画布,矩形:图案的图像显示错误

时间:2013-08-02 16:55:25

标签: html5 canvas

我正在开发一个小地图编辑器,只是为了有趣地了解HTML5 Canvas并且更好一些。

我想做什么

我正在尝试加载3项:

  • 2个岩石
  • 1 goblin

我写了一个函数“drawItem(item)”,它应该在画布上绘制一个项目:

drawItem = function(item) {
    var imageObj = new Image();
    imageObj.onload = function() {
        var pattern = context.createPattern(imageObj, 'repeat');
        context.rect(gridSize*item.position[0], gridSize*item.position[1], gridSize, gridSize);
        context.fillStyle = pattern;
        context.fill();
    };
    imageObj.src = item.img;
};

项目对象是什么样的:

itemOne = {
    img : 'https://lh3.googleusercontent.com/ZX4Zl7JT1gkgOVA9FbMFnMAw7TC9bBCVMSGWKFTmOW88vDTgcCOb7tBBo60nxoSdHQ=s190',
    position : [0, 0] //these get multiplied with "gridSize" in the drawItem-function
};

现在问题出在这里:

如果我使用item-object调用此函数,则会正确绘制对象。

如果我使用3个不同的物品对象调用此功能3次(参见JS-Fiddle),那么2个摇滚物品似乎在它上面有一个妖精。那是错的。

JS-小提琴

http://jsfiddle.net/rSVkb/1/

“问题”

有谁知道这个问题?我一直在谷歌搜索几个小时,但由于我不确定要搜索什么,所以很难找到。

非常感谢! 鲍里斯

3 个答案:

答案 0 :(得分:2)

您可以使用drawImage

简化整个过程
drawItem = function(item) {
    var imageObj = new Image();
    imageObj.onload = function() {
        context.drawImage(imageObj, gridSize*item.position[0], gridSize*item.position[1])
    };
    imageObj.src = item.img;
};

http://jsfiddle.net/rSVkb/2/

答案 1 :(得分:2)

你可能应该使用drawImage作为另一个回答者说,但为了完整起见,让我告诉你为什么你的原始代码是错误的。

在此代码中:

var pattern = context.createPattern(imageObj, 'repeat');
context.rect(gridSize*item.position[0], gridSize*item.position[1], gridSize, gridSize);
context.fillStyle = pattern;
context.fill();

您正在向当前路径添加rect,然后填充当前路径。

当您致电rect然后fill,然后使用不同的矩形调用rect然后再次调用fill时,第二个fill命令正在填充<你所定义的rects> strong 。

这是因为rect总是在当前路径上添加一个额外的矩形。

因此修复代码的一种方法是添加一行,调用beginPath(),这将重置路径,这样每次绘制时都不会继续添加代码:

var pattern = context.createPattern(imageObj, 'repeat');
context.beginPath();
context.rect(gridSize*item.position[0], gridSize*item.position[1], gridSize, gridSize);
context.fillStyle = pattern;
context.fill();

所以看起来应该是这样的: http://jsfiddle.net/rSVkb/6/

答案 2 :(得分:1)

如果您确实想继续使用模式,则需要切换为使用fillRect而不是创建矩形并使用fill

drawItem = function(item) {
    var imageObj = new Image();
    imageObj.onload = function() {
        var pattern = context.createPattern(imageObj, 'repeat');
        context.fillStyle = pattern;
        context.fillRect(gridSize*item.position[0], gridSize*item.position[1], gridSize, gridSize);
    };
    imageObj.src = item.img;
};

See it in action

.fill将当前模式应用于已经填充的整个上下文。继续使用模式将允许您连续绘制多个像:

itemOne = {
    img : 'https://lh3.googleusercontent.com/ZX4Zl7JT1gkgOVA9FbMFnMAw7TC9bBCVMSGWKFTmOW88vDTgcCOb7tBBo60nxoSdHQ=s190',
    position : [0, 0], //these get multiplied with "gridSize" in the drawItem-function
    howManyX: 2,
    howManyY: 1
};

// And then in drawImage
context.fillRect(gridSize*item.position[0], gridSize*item.position[1], gridSize*(item.howManyX || 1), gridSize*(item.howManyY || 1));

并将其用作fillRect中最后两个参数的修饰符。

或者,您可以对this等项目执行多次positions。您也可以使用.drawImage执行此操作,但模式只需要进行一次。这个jsperf表明使用模式可以更快。