Javascript HTML画布间隔,画布模式消失

Javascript HTML画布间隔,画布模式消失,javascript,html,canvas,Javascript,Html,Canvas,在创建HTML画布时,我计划制作这些圆柱体,并为其中移动的大理石设置动画。然而,当尝试这样做时,它只会删除所有内容。在搞乱了我的代码之后,我发现问题是由于图像中的CanvasPattern填充样式造成的 这段代码完全模拟了我的经历。矩形绘制得非常精细,但是,在1秒后,当间隔运行时,它消失,并且没有绘制圆弧或“大理石”。控制台中也没有错误 有间隔(不工作): let canv=document.getElementById(“canvas”); 设ctx=canv.getContext('2d')

在创建HTML画布时,我计划制作这些圆柱体,并为其中移动的大理石设置动画。然而,当尝试这样做时,它只会删除所有内容。在搞乱了我的代码之后,我发现问题是由于图像中的
CanvasPattern
填充样式造成的

这段代码完全模拟了我的经历。矩形绘制得非常精细,但是,在1秒后,当间隔运行时,它消失,并且没有绘制圆弧或“大理石”。控制台中也没有错误

有间隔(不工作):
let canv=document.getElementById(“canvas”);
设ctx=canv.getContext('2d');
设蒙版=新图像(canv.width,canv.height);
matte.onload=函数(){
var pattern=ctx.createPattern(无光,“重复”);
ctx.globalCompositeOperation='source in';
ctx.rect(0,0,canv.width,canv.height);
ctx.fillStyle=图案;
ctx.fill();
};
matte.src=”https://www.muralswallpaper.com/app/uploads/classic-red-marble-textures-plain-820x532.jpg"; // 图像src
ctx.lineWidth=“5”;
ctx.fillRect(0,0,50,50);//当setInterval运行时,这将消失????大理石连画都不画
设x=60,
y=20;
var draw=setInterval(函数(){//绘制大理石
ctx.beginPath();
弧(x,y,10,0,2*Math.PI);
ctx.closePath();
ctx.fill();
y+=1;
}, 1 * 1000);


问题在于您的
ctx.globalCompositeOperation
指令。使用
中的
源代码,您明确地告诉画布制作任何与您正在绘制的新事物不同的颜色(基于每像素)。由于每个像素都是不同的,因此所有内容都变得透明,剩下的看起来像是一个空画布(即使
ImageData
将显示RGB通道中有意义内容的RGBA数据,但A为0)

删除
globalCompositeOperation
规则,您就可以开始了,但是您可能需要一些时间来重写这里的逻辑,这样在加载映像之前不会发生任何事情,因为您的代码非常依赖于现有的模式:等待映像加载,构建模式,将其分配给上下文,然后开始绘制循环

const canv=document.getElementById(“canvas”);
const ctx=canv.getContext('2d');
设x=60,y=20;
函数start(){
常量蒙版=新图像(canv.宽度、canv.高度);
matte.addEventListener(`load`,evt=>
startDrawing(ctx.createPattern(无光,“重复”))
);
matte.addEventListener(`load`,evt=>
错误(`无法加载${matte.src}…`);
);
matte.src=”https://www.muralswallpaper.com/app/uploads/classic-red-marble-textures-plain-820x532.jpg“;//图像src
}
功能开始绘图(模式){
ctx.strokeStyle=`red`;
ctx.fillStyle=图案;
设置间隔(()=>{
draw();
y+=10;
}, 1 * 1000);  
}
函数绘图(){
ctx.beginPath();
弧(x,y,10,0,2*Math.PI);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
//然后开始一切
start();
尽管另一方面,通常setInterval不是动画的最佳选择:您通常希望使用“墙时间”检查(例如,根据实际时钟进行操作,而不是信任间隔):


注意,您的
ctx.rect(0,0,canv.width,canv.height)
什么都不做:它是整个画布的大小,不填充/笔划任何东西(
rect()
本身不为任何像素着色)。然后,您的第一个
fillRect(0,0,50,50)
将在保证有模式之前运行,draw()代码也将在保证加载图像之前开始运行,因此这里有各种不确定的逻辑。从加载处理程序中的“启动一切”开始,例如@Kamermans我在加载图像时对模式进行填充样式后立即填充该矩形。运行代码段,你所说的是错误的,所以你是:无论如何,看看这个jsbin。@Mike'Pomax'Kamermans谢谢你!这很有效。如果您有想法,我仍然想知道为什么我的方法没有?重温代码:您的GlobalComposite操作告诉上下文(出于好奇,您为什么在
中选择
源代码?)
...

function startDrawing(pattern) {
  ctx.strokeStyle = `red`;
  ctx.fillStyle = pattern;
  startAnimation();
}

let playing, lastTime;

function startAnimation() {
  playing = true;
  lastTime = Date.now();
  requestAnimationFrame(nextFrame);
}

function stopAnimation() {
  playing = false;
}

function nextFrame() {
  let newTime = Date.now();
  if (newTime - lastTime >= 1000) {
    draw();
  }
  if (playing) {
    lastTime = newTime;
    requestAnimationFrame(nextFrame);
  }
}

...