为了账号安全,请及时绑定邮箱和手机立即绑定

Canvas drawImage在拉伸时绘制不需要的像素

Canvas drawImage在拉伸时绘制不需要的像素

梦里花落0921 2023-10-17 17:40:47
我使用 drawImage 将 1x2 像素精灵拉伸为 300x2 水平线。这曾经工作得很好,但最近我注意到 Chrome、Firefox 和 Edge 上有一个问题,drawImage 函数将开始包含 1x2 定义框之外的精灵数据。(顺便说一句,这不会发生在移动设备上)在下面的链接中,绘制线条对于小长度来说效果很好,但是一旦长度超过 255 像素,它将开始绘制不需要的颜色(蓝色)。JSFiddle;https://jsfiddle.net/y6bo1zfu/1/任何人都知道这可能是什么原因造成的?这可能是一个已知的错误还是通过优化添加的意外功能?尝试将图像拉伸为其默认宽度 256 倍是禁忌吗?
查看完整描述

1 回答

?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

这是由硬件加速 (HWA)(即 GPU)引起的。您可以在自己的浏览器上禁用它,您会看到它会按预期工作。


遗憾的是,您无法要求所有用户禁用 HWA。


解决这个问题的一种简单方法是创建一个仅包含图像所需部分的 ImageBitmap。

这非常简单,因为该createImageBitmap()方法接受 5 个参数版本


createImageBitmap( source, sourceX, sourceY, sourceWidth, sourceHeight );

并且drawImage()接受 5 参数版本


drawImage( source, destinationX, destinationY, destinationWidth, destinationHeight );

因此,您可以将 9 个参数版本重写drawImage()为


drawImage( 

  await createImageBitmap( source, sourceX, sourceY, sourceWidth, sourceHeight ),

  destinationX, destinationY, destinationWidth, destinationHeight

)

var rawImage = false;


var testCanvas = document.createElement('canvas');

testCanvas.width = 300;

testCanvas.height = 20;

var testContext = testCanvas.getContext("2d");

testContext.imageSmoothingEnabled = false;

document.body.appendChild( testCanvas );


function loadImage()

{

  rawImage = new Image();

  rawImage.onload = function(){

    // Create the sprite image

    createSpriteImage();

    

    document.body.appendChild( rawImage );

  }

  rawImage.src = "data:image/png;base64,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";

}


async function createSpriteImage()

{

  testContext.drawImage(

    await createImageBitmap(rawImage,

      2,     // Source X for this part of the Sprite

      1 ,    // Source Y for this part of the Sprite

      1 ,    // Width of this part of the Sprite

      2      // Height of this part of the Sprite

    ),

    0,        // The X position where to draw

    0,        // The Y position where to draw

    300 ,     // Width of the line

    2      // Height of the line

  );

  

  testContext.drawImage(

    await createImageBitmap(rawImage,

      2,    // Source X for this part of the Sprite

      1 ,   // Source Y for this part of the Sprite

      1 ,   // Width of this part of the Sprite

      2     // Height of this part of the Sprite

    ) ,  

    0 ,       // The X position where to draw

    3 ,       // The Y position where to draw

    298 ,     // Width of the line

    2    // Height of the line

  );

  

  testContext.drawImage(

    await createImageBitmap(rawImage,

      2,    // Source X for this part of the Sprite

      1 ,   // Source Y for this part of the Sprite

      1 ,   // Width of this part of the Sprite

      2     // Height of this part of the Sprite

    ) ,

    0,        // The X position where to draw

    6,        // The Y position where to draw

    264 ,     // Width of the line

    2         // Height of the line

  );

  

  testContext.drawImage(

    await createImageBitmap(rawImage,

      2,    // Source X for this part of the Sprite

      1 ,   // Source Y for this part of the Sprite

      1 ,   // Width of this part of the Sprite

      2     // Height of this part of the Sprite

    ),

    0,        // The X position where to draw

    9,        // The Y position where to draw

    256 ,     // Width of the line

    2         // Height of the line

  );

  

  testContext.drawImage(

    await createImageBitmap(rawImage,

      2,     // Source X for this part of the Sprite

      1 ,    // Source Y for this part of the Sprite

      1 ,    // Width of this part of the Sprite

      2      // Height of this part of the Sprite

    ),

    0,       // The X position where to draw

    12,      // The Y position where to draw

    255 ,    // Width of the line

    2 ,      // Height of the line

  );

  

  testContext.drawImage(

    await createImageBitmap(rawImage,

      2,     // Source X for this part of the Sprite

      1 ,    // Source Y for this part of the Sprite

      1 ,    // Width of this part of the Sprite

      2      // Height of this part of the Sprite

    ),

    0,       // The X position where to draw

    15,      // The Y position where to draw

    100 ,    // Width of the line

    2 ,      // Height of the line

  );

  

  testContext.drawImage(

    await createImageBitmap(rawImage,

      2,     // Source X for this part of the Sprite

      1 ,    // Source Y for this part of the Sprite

      1 ,    // Width of this part of the Sprite

      2      // Height of this part of the Sprite

    ),

    0,       // The X position where to draw

    18,      // The Y position where to draw

    10 ,     // Width of the line

    2 ,      // Height of the line

  );

}


//

loadImage();

body,html {

    margin: 0px;

    background-color: #4f4f4f;

}

img

{

    display: block;

    width: 50px;

    height: 50px;

    margin: 0px auto;

  image-rendering: pixelated;

}

canvas

{

  display: block;

    width: 300px;

    height: 20px;

    box-shadow: 1px 1px 4px black;

    margin: 15px auto;

    background-color: white;

    border: 1px solid white;

}

而对于不支持 ImageBitmap 接口的浏览器,至少可以通过使用其他画布来对这种用法进行猴子修补。



查看完整回答
反对 回复 2023-10-17
  • 1 回答
  • 0 关注
  • 82 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信