【问题标题】:Manipulating pixels in canvas操作画布中的像素
【发布时间】:2017-09-29 01:26:12
【问题描述】:

我正在尝试使用基于网格的地图编写简单的 2D 自上而下游戏,但在某些画布区域中处理像素时遇到问题。我有以下功能:

changeCellBackground(x, y, r, g, b){

    let cell = this.context.getImageData(x * this.TILE_SIZE, y * this.TILE_SIZE, this.TILE_SIZE, this.TILE_SIZE);

    for(let i=0; i<cell.data.length; i+=4){

        cell.data[i] += r;
        cell.data[i+1] += g;
        cell.data[i+2] += b;
    }

    this.context.putImageData(cell, x * this.TILE_SIZE, y * this.TILE_SIZE);
}

context 是 canvas 2d 上下文:

this.screen = $('#game');
this.context = this.screen[0].getContext('2d');

和有 src 链接的 Img 标签:

let tileSet = $('<img></img>').attr('src', '../assets/tiles.png');

但是,当我尝试使用上述功能时,我得到了SecurityError: The operation is insecure.。据我了解,这是由于 CORS 限制而发生的,所以我尝试将 add crossOrigin="anonymous" 属性设置为 Img

let tileSet = $('<img></img>').attr('crossOrigin', 'anonymous').attr('src', '../assets/tiles.png');

但现在我收到了NS_ERROR_NOT_AVAILABLE:。我猜这是因为当脚本的其余部分开始执行时图像尚未加载。我该如何解决?我试过这个:

let tileSet = $('<img></img>');

    tileSet.onload = function(){

        tileSet.attr('crossOrigin', 'anonymous').attr('src', '../assets/tiles.png');

        gameScreen.drawAnimatedImage(0, 0, 'waterfall');
        gameScreen.drawAnimatedImage(2, 2, 'fountain');
        gameScreen.drawAnimatedImage(11, 5, 'street_lamp');
        gameScreen.drawAnimatedImage(10, 5, 'street_lamp');
        gameScreen.changeCellBackground(10, 15, -30, -30, -30);
    };

但它也不起作用 - 当我在 onload 函数的末尾设置 console.log(tileSet) 时,控制台上没有任何记录。似乎没有触发 onload 功能。为什么会发生这种情况,我该如何解决?

【问题讨论】:

  • 您正在设置 src 属性 inside 您的加载事件处理程序,这需要设置 src 以便在某天触发... 将此行放在这个处理程序。国际海事组织这个问题应该作为错字关闭......

标签: javascript html image image-processing canvas


【解决方案1】:

这是向画布上的像素添加值的一种更简单的方法。

你的功能

changeCellBackground(x, y, r, g, b){

将 r,g,b 添加到图块上 x,y 处的每个像素

可以用

function changeCellBackground(x, y, r, g, b){
     this.context.fillStyle = "rgb(" + Math.floor(r) + ","  + Math.floor(g) + "," + Math.floor(b) + ")";
     this.context.globalCompositeOperation = "lighter"; // adds the fill color to existing pixels
     this.context.fillRect(x * this.TILE_SIZE, y * this.TILE_SIZE, this.TILE_SIZE, this.TILE_SIZE);
     this.context.globalCompositeOperation = "source-over"; // restore default composite operation
 }

上述函数与您的函数相同,但无需访问像素数据。这意味着您不必担心不安全的图像,并且可以在没有跨域标头的情况下加载它。

作为猜测,如果您正在使用硬盘驱动器(即../assets/tiles.png 在您的硬盘驱动器上),您将不会获得 CORS 映像,因为这需要服务器。

您可以在您的计算机上设置一个服务器(有很多选项),然后使用域 localhost 在这种情况下,图像不是跨域的并且不需要标头。或者您可以查看浏览器安全开关并关闭跨域安全性,这样您也可以访问图像数据。

【讨论】:

    【解决方案2】:

    changeCellBackground() 和您的问题中的tileset 之间没有链接,所以我不确定前面是否还有更多问题,但是要等待图像加载,您实际上需要将 src 部分从功能:

    let tileSet = $('<img></img>');
    
    tileSet.onload = function(){
        gameScreen.drawAnimatedImage(0, 0, 'waterfall');
        gameScreen.drawAnimatedImage(2, 2, 'fountain');
        gameScreen.drawAnimatedImage(11, 5, 'street_lamp');
        gameScreen.drawAnimatedImage(10, 5, 'street_lamp');
        gameScreen.changeCellBackground(10, 15, -30, -30, -30);
    };
    
    tileSet.attr('crossOrigin', 'anonymous').attr('src', '../assets/tiles.png');
    

    就目前而言,onload 事件没有被触发,因为没有 src 可供加载。

    【讨论】:

      猜你喜欢
      • 2021-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-12
      • 1970-01-01
      • 2012-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多