Html canvas 元素过多 canvas 绘图速度变慢
Html canvas drawing slows with too many canvas elements
我正在开发带有幻灯片预览条的幻灯片编辑器。我正在使用电子并做出反应。我的每张幻灯片都包含用于 images/text 的背景 canvas 和用于绘图的前景 canvas。我的绘图性能很好,直到我的预览条中有大约 20 张幻灯片,然后绘图速度变得非常慢。我正在绘制鼠标移动事件,以便用户看到它拖着他们的光标。
我想我在预览幻灯片上绘图时已将问题缩小到 ctx.stroke() 行。预览幻灯片要小得多,但与用户实际绘制的主 canvas 具有相同的分辨率。
当屏幕上显示 >40 canvas 时,有什么方法可以提高性能吗?
apply(ctx, pointIndex) {
let points = this.path.getPoints().slice(pointIndex);
ctx.lineWidth = this.getLineWidth();
if(points.length === 1){
ctx.fillRect(points[0].x - (this.getLineWidth() / 2), points[0].y - (this.getLineWidth() / 2), this.getLineWidth(), this.getLineWidth());
return;
}
ctx.beginPath();
ctx.moveTo(Math.floor(points[0].x), Math.floor(points[0].y));
points.slice(1).forEach(function(point) {
ctx.lineTo(Math.floor(point.x), Math.floor(point.y));
});
ctx.stroke();
ctx.closePath();
ctx.lineWidth = 1;
pointIndex = this.path.getPoints().length - 1;
return pointIndex;
}
回答您的问题: 是的,随着总 canvas 大小的增加,重绘需要更长的时间。通过添加完整大小的 canvases,即使那些 canvases 被缩小为 "slide size",您也会显着增加总 canvas 大小。顺便说一句,.stroke
不是你的问题——它呈现得非常快。
您的每张幻灯片 canvases 都与您的主幻灯片 canvas 具有相同的分辨率。 DOM 必须记住原始大小,因此每张新幻灯片总 canvas 大小都会显着增加。
解决方法是使每张幻灯片 canvas 更小(== 显示大小),而不是保持与主幻灯片相同的分辨率 canvas。如果用户想要重新绘制一张幻灯片,则从 points
为该幻灯片动态创建一个全尺寸的 canvas。更少的总数 canvas 大小 == 更好的性能。
Canvas 有一个缩放命令,可让您轻松获取全尺寸 canvas 内容并将其缩放到较小的显示尺寸:
var c=document.createElement('canvas');
var cctx=c.getContext('2d');
c.width=smallSlideWidth;
c.height=smallSlideHeight;
var scale=Math.min((slideWidth/mainCanvasWidth),(slideHeight/mainCanvasHeight));
cctx.scale(scale,scale);
... now draw your slide using the same coordinates as your main canvas
我们没有您的更多代码,但是如果您一直都在重新绘制每张幻灯片 canvas - 请不要那样做!
我正在开发带有幻灯片预览条的幻灯片编辑器。我正在使用电子并做出反应。我的每张幻灯片都包含用于 images/text 的背景 canvas 和用于绘图的前景 canvas。我的绘图性能很好,直到我的预览条中有大约 20 张幻灯片,然后绘图速度变得非常慢。我正在绘制鼠标移动事件,以便用户看到它拖着他们的光标。
我想我在预览幻灯片上绘图时已将问题缩小到 ctx.stroke() 行。预览幻灯片要小得多,但与用户实际绘制的主 canvas 具有相同的分辨率。
当屏幕上显示 >40 canvas 时,有什么方法可以提高性能吗?
apply(ctx, pointIndex) {
let points = this.path.getPoints().slice(pointIndex);
ctx.lineWidth = this.getLineWidth();
if(points.length === 1){
ctx.fillRect(points[0].x - (this.getLineWidth() / 2), points[0].y - (this.getLineWidth() / 2), this.getLineWidth(), this.getLineWidth());
return;
}
ctx.beginPath();
ctx.moveTo(Math.floor(points[0].x), Math.floor(points[0].y));
points.slice(1).forEach(function(point) {
ctx.lineTo(Math.floor(point.x), Math.floor(point.y));
});
ctx.stroke();
ctx.closePath();
ctx.lineWidth = 1;
pointIndex = this.path.getPoints().length - 1;
return pointIndex;
}
回答您的问题: 是的,随着总 canvas 大小的增加,重绘需要更长的时间。通过添加完整大小的 canvases,即使那些 canvases 被缩小为 "slide size",您也会显着增加总 canvas 大小。顺便说一句,.stroke
不是你的问题——它呈现得非常快。
您的每张幻灯片 canvases 都与您的主幻灯片 canvas 具有相同的分辨率。 DOM 必须记住原始大小,因此每张新幻灯片总 canvas 大小都会显着增加。
解决方法是使每张幻灯片 canvas 更小(== 显示大小),而不是保持与主幻灯片相同的分辨率 canvas。如果用户想要重新绘制一张幻灯片,则从 points
为该幻灯片动态创建一个全尺寸的 canvas。更少的总数 canvas 大小 == 更好的性能。
Canvas 有一个缩放命令,可让您轻松获取全尺寸 canvas 内容并将其缩放到较小的显示尺寸:
var c=document.createElement('canvas');
var cctx=c.getContext('2d');
c.width=smallSlideWidth;
c.height=smallSlideHeight;
var scale=Math.min((slideWidth/mainCanvasWidth),(slideHeight/mainCanvasHeight));
cctx.scale(scale,scale);
... now draw your slide using the same coordinates as your main canvas
我们没有您的更多代码,但是如果您一直都在重新绘制每张幻灯片 canvas - 请不要那样做!