HTML Canvas 滞后
HTML Canvas Lag
所以我创建了一个 canvas,当您将鼠标悬停在它上面时,会出现一个绿色的 32x32 框。 canvas 非常大,因此您可以绘制大量肖像,问题是绘制绿色框会使 canvas 和我的整个浏览器变得迟钝。
我添加的部分使其变得迟钝:
function makeTileCover(mousex, mousey) {
ctx.strokeStyle = "green";
ctx.strokeRect(mousex, mousey, 32, 32);
ctx.stroke();
}
我猜想有一些简单的答案可以解决这个问题,似乎它可能绘制了太多次,因为当你将鼠标悬停在它上面的次数越多,正方形就会变得越暗,尽管我不确定这是否会解决无论如何。
var canvas = document.getElementById("MapEditor");
var ctx = canvas.getContext("2d");
function updateCanvas() {
container = document.getElementById("container");
if (container.width != window.innerWidth) {
container.style.width = window.innerWidth - 250;
}
if (container.height != window.innerHeight) {
container.style.height = window.innerHeight;
}
}
//Destroy mouse on canvas exit.
canvas.addEventListener('mouseout', function() {
document.body.style.cursor = 'auto';
});
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
var mousex = Math.round(mousePos.x / 32) * 32;
var mousey = Math.round(mousePos.y / 32) * 32;
var cursor = document.createElement('canvas'),
cursorctx = cursor.getContext('2d');
cursor.width = 32;
cursor.height = 32;
makeTileCover(mousex, mousey);
document.body.style.cursor = 'url(' + cursor.toDataURL() + '), auto';
document.getElementById('mousePosLocation').innerHTML = "Mouse location:" + "<b id='mousex'>" + mousex + "</b>" + "," + "<b id='mousey'>" + mousey + "</b>";
}, false);
function makeTileCover(mousex, mousey) {
ctx.strokeStyle = "green";
ctx.strokeRect(mousex, mousey, 32, 32);
ctx.stroke();
}
canvas {
background-color: black;
}
<div id="container">
<canvas width="16384" height="16384" id="MapEditor"></canvas>
</div>
您在 MouseMove 上做的太多了,它可能每帧触发很多次,并且可能在帧的任何时间发生。
关于输入事件,您想尽可能少地做。
我认为您只需执行以下操作就可以逃脱惩罚:
canvas.addEventListener('mousemove', function(evt) {
//I'm attaching it to Window for now. Ideally, you'd use a private namespace.
window.mousePos = getMousePos(canvas, evt);
}, false);
只需设置一个变量并继续。
其他所有内容都应与 requestAnimationFrame()
触发的回调相关联。这样,鼠标位置会随着鼠标的每次移动而更新,但每帧绘制只会发生一次,即采用最近的鼠标位置。
function draw() {
window.requestAnimationFrame(draw);
var mousex = Math.round(mousePos.x / 32) * 32;
var mousey = Math.round(mousePos.y / 32) * 32;
var cursor = document.createElement('canvas'),
cursorctx = cursor.getContext('2d');
cursor.width = 32;
cursor.height = 32;
makeTileCover(mousex, mousey);
document.body.style.cursor = 'url(' + cursor.toDataURL() + '), auto';
document.getElementById('mousePosLocation').innerHTML = "Mouse location:" + "<b id='mousex'>" + mousex + "</b>" + "," + "<b id='mousey'>" + mousey + "</b>";
}
作为一个额外的好处,好的浏览器也会在浏览器可以管理的框架中尽早出现。这意味着您的长 运行 代码将尽可能远离正在呈现的帧(在监视器需要它之前为这段繁重的代码提供最长的计算时间,这与 mousemove 事件可能发生的一小部分不同)在监视器需要它之前一毫秒)。
问题是您的 canvas 太大了,chrome 无法处理它所需的内存。你真的不希望 canvas 比屏幕上可以容纳的更大。 (通常约为 1080x1920)。结合@ScottMichaud 的回答我们得到
HTML
<div id="container">
<canvas width="1638" height="900" id="MapEditor"></canvas>
</div>
JS
var canvas = document.getElementById("MapEditor");
var ctx = canvas.getContext("2d");
var MousePos = {x:0, y:0};
function updateCanvas() {
container = document.getElementById("container");
if (container.width != window.innerWidth) {
container.style.width = window.innerWidth - 250;
}
if (container.height != window.innerHeight) {
container.style.height = window.innerHeight;
}
}
//Destroy mouse on canvas exit.
canvas.addEventListener('mouseout', function() {
document.body.style.cursor = 'auto';
});
function Update(){
window.requestAnimationFrame(Update);
var mousex = Math.round(MousePos.x / 32) * 32;
var mousey = Math.round(MousePos.y / 32) * 32;
ctx.fillRect(0,0,canvas.width,canvas.height);
makeTileCover(ctx, mousex, mousey);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
MousePos = getMousePos(canvas, evt);
// var cursor = document.createElement('canvas'),
// cursorctx = cursor.getContext('2d');
// cursor.width = 32;
// cursor.height = 32;
// makeTileCover(mousex, mousey);
// document.body.style.cursor = 'url(' + cursor.toDataURL() + '), auto';
// document.getElementById('mousePosLocation').innerHTML = "Mouse location:" + "<b id='mousex'>" + mousex + "</b>" + "," + "<b id='mousey'>" + mousey + "</b>";
}, false);
function makeTileCover(ctx, mousex, mousey) {
ctx.strokeStyle = "green";
ctx.strokeRect(mousex, mousey, 32, 32);
ctx.stroke();
}
Update();
我还更改了 canvas,因此每一帧都会将 canvas 重新填充为黑色,这样您就不会在视图中看到一堆方块,而只有光标所在的方块.
所以我创建了一个 canvas,当您将鼠标悬停在它上面时,会出现一个绿色的 32x32 框。 canvas 非常大,因此您可以绘制大量肖像,问题是绘制绿色框会使 canvas 和我的整个浏览器变得迟钝。
我添加的部分使其变得迟钝:
function makeTileCover(mousex, mousey) {
ctx.strokeStyle = "green";
ctx.strokeRect(mousex, mousey, 32, 32);
ctx.stroke();
}
我猜想有一些简单的答案可以解决这个问题,似乎它可能绘制了太多次,因为当你将鼠标悬停在它上面的次数越多,正方形就会变得越暗,尽管我不确定这是否会解决无论如何。
var canvas = document.getElementById("MapEditor");
var ctx = canvas.getContext("2d");
function updateCanvas() {
container = document.getElementById("container");
if (container.width != window.innerWidth) {
container.style.width = window.innerWidth - 250;
}
if (container.height != window.innerHeight) {
container.style.height = window.innerHeight;
}
}
//Destroy mouse on canvas exit.
canvas.addEventListener('mouseout', function() {
document.body.style.cursor = 'auto';
});
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
var mousex = Math.round(mousePos.x / 32) * 32;
var mousey = Math.round(mousePos.y / 32) * 32;
var cursor = document.createElement('canvas'),
cursorctx = cursor.getContext('2d');
cursor.width = 32;
cursor.height = 32;
makeTileCover(mousex, mousey);
document.body.style.cursor = 'url(' + cursor.toDataURL() + '), auto';
document.getElementById('mousePosLocation').innerHTML = "Mouse location:" + "<b id='mousex'>" + mousex + "</b>" + "," + "<b id='mousey'>" + mousey + "</b>";
}, false);
function makeTileCover(mousex, mousey) {
ctx.strokeStyle = "green";
ctx.strokeRect(mousex, mousey, 32, 32);
ctx.stroke();
}
canvas {
background-color: black;
}
<div id="container">
<canvas width="16384" height="16384" id="MapEditor"></canvas>
</div>
您在 MouseMove 上做的太多了,它可能每帧触发很多次,并且可能在帧的任何时间发生。
关于输入事件,您想尽可能少地做。
我认为您只需执行以下操作就可以逃脱惩罚:
canvas.addEventListener('mousemove', function(evt) {
//I'm attaching it to Window for now. Ideally, you'd use a private namespace.
window.mousePos = getMousePos(canvas, evt);
}, false);
只需设置一个变量并继续。
其他所有内容都应与 requestAnimationFrame()
触发的回调相关联。这样,鼠标位置会随着鼠标的每次移动而更新,但每帧绘制只会发生一次,即采用最近的鼠标位置。
function draw() {
window.requestAnimationFrame(draw);
var mousex = Math.round(mousePos.x / 32) * 32;
var mousey = Math.round(mousePos.y / 32) * 32;
var cursor = document.createElement('canvas'),
cursorctx = cursor.getContext('2d');
cursor.width = 32;
cursor.height = 32;
makeTileCover(mousex, mousey);
document.body.style.cursor = 'url(' + cursor.toDataURL() + '), auto';
document.getElementById('mousePosLocation').innerHTML = "Mouse location:" + "<b id='mousex'>" + mousex + "</b>" + "," + "<b id='mousey'>" + mousey + "</b>";
}
作为一个额外的好处,好的浏览器也会在浏览器可以管理的框架中尽早出现。这意味着您的长 运行 代码将尽可能远离正在呈现的帧(在监视器需要它之前为这段繁重的代码提供最长的计算时间,这与 mousemove 事件可能发生的一小部分不同)在监视器需要它之前一毫秒)。
问题是您的 canvas 太大了,chrome 无法处理它所需的内存。你真的不希望 canvas 比屏幕上可以容纳的更大。 (通常约为 1080x1920)。结合@ScottMichaud 的回答我们得到
HTML
<div id="container">
<canvas width="1638" height="900" id="MapEditor"></canvas>
</div>
JS
var canvas = document.getElementById("MapEditor");
var ctx = canvas.getContext("2d");
var MousePos = {x:0, y:0};
function updateCanvas() {
container = document.getElementById("container");
if (container.width != window.innerWidth) {
container.style.width = window.innerWidth - 250;
}
if (container.height != window.innerHeight) {
container.style.height = window.innerHeight;
}
}
//Destroy mouse on canvas exit.
canvas.addEventListener('mouseout', function() {
document.body.style.cursor = 'auto';
});
function Update(){
window.requestAnimationFrame(Update);
var mousex = Math.round(MousePos.x / 32) * 32;
var mousey = Math.round(MousePos.y / 32) * 32;
ctx.fillRect(0,0,canvas.width,canvas.height);
makeTileCover(ctx, mousex, mousey);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
MousePos = getMousePos(canvas, evt);
// var cursor = document.createElement('canvas'),
// cursorctx = cursor.getContext('2d');
// cursor.width = 32;
// cursor.height = 32;
// makeTileCover(mousex, mousey);
// document.body.style.cursor = 'url(' + cursor.toDataURL() + '), auto';
// document.getElementById('mousePosLocation').innerHTML = "Mouse location:" + "<b id='mousex'>" + mousex + "</b>" + "," + "<b id='mousey'>" + mousey + "</b>";
}, false);
function makeTileCover(ctx, mousex, mousey) {
ctx.strokeStyle = "green";
ctx.strokeRect(mousex, mousey, 32, 32);
ctx.stroke();
}
Update();
我还更改了 canvas,因此每一帧都会将 canvas 重新填充为黑色,这样您就不会在视图中看到一堆方块,而只有光标所在的方块.