HTML5 Canvas ~ 使用绘制元素平滑快速缩放,而不是图像 ~ 如何?

Posted

技术标签:

【中文标题】HTML5 Canvas ~ 使用绘制元素平滑快速缩放,而不是图像 ~ 如何?【英文标题】:HTML5 Canvas ~ Smooth Rapid Scaling with Drawn Elements, Not Images ~ How to? 【发布时间】:2019-07-27 10:30:30 【问题描述】:

有一些关于缩放图像的帖子(例如,html5 Canvas Image Scaling Issue);但是,我需要深入了解如何以平滑的方式快速缩放数百个简单的绘制元素(正方形、线条、弧线等)。我希望它看起来像一个动画,并且现在使用鼠标滚轮缩放(以 0.05 为增量缩放)过渡是不稳定的。

Optimizing Canvas 有一个有趣的见解,它建议在屏幕外画布上进行预渲染,但这可能会导致浏览器出现内存问题(我们已经在突破极限)。

这是一个包含数百个绘制元素的工程示意图示例:

谢谢!

【问题讨论】:

this answer 能让你更接近吗? 缩放和定位图像不是主要任务。基本问题是所有元素(数百个,有时数千个)在每个比例点处重新绘制,结果不稳定。企业主想要平滑的缩放体验,就像他们正在缩放图像一样(因此等待鼠标滚轮停止不是一种选择)。一种可能是创建画布的 png 图像叠加层,使用鼠标滚轮缩放该图像,然后在鼠标滚轮停止时进行重绘。 “一种可能的方法是创建画布的 png 图像叠加层,用鼠标滚轮缩放该图像,然后在鼠标滚轮停止时进行重绘。” 你能至少展示一下你正在做什么来绘制这个模式吗?您应该能够每帧绘制几次,没有繁重的过滤,也许是文本最慢的部分,但我觉得您做错了什么(可能一次抚摸每一行?)并且这有问题有一个简单的解决方案(批处理所有路径命令并尽可能少地调用描边和填充)。 在这种情况下,滚动去抖动会有所帮助。另外,如果我们计算缩放后可以看到哪些对象/形状,然后只在画布上绘制它们呢?您是否尝试过按照here 的建议使用屏幕外画布? 【参考方案1】:

问题是每帧重新绘制所有元素。一种简单的方法是将整个图像绘制到 Canvas 上。然后每次要在图像上绘制图片时,都将画布绘制到另一个画布上。

const imgCanvas = document.createElement('canvas');
const imgCtx = imgCanvas.getContext('2d');

// Draw the each elements to imgCtx
// ...

在执行缩放时重新绘制:

// Scale the canvas
ctx.scale(x, y);
// Draw the pre-drew image onto screen
ctx.drawImage(imgCanvas);

【讨论】:

【参考方案2】:

有多种技术可以提高性能,但归根结底,这一切都取决于您在画布中放置的元素数量,因此在重构代码时,请考虑如何做到:

绘制更少的元素,例如在缩小的图片中无需绘制那些小标签

group/cluster stuff 这样您就可以绘制组中所有元素的表示,谷歌地图做得很好:https://cloud.google.com/blog/products/maps-platform/how-cluster-map-markers

使用 JavaScript 游戏引擎性能这是游戏引擎非常了解的,您可以利用其中之一:https://github.com/collections/javascript-game-engines

...请记住,没有一种灵丹妙药可以解决网络性能问题;如果性能对您的应用至关重要,那么它可能不应该出现在浏览器上。

【讨论】:

以上是关于HTML5 Canvas ~ 使用绘制元素平滑快速缩放,而不是图像 ~ 如何?的主要内容,如果未能解决你的问题,请参考以下文章

html5 canvas怎么画

H5 Canvas

canvas 元素用于在网页上绘制图形。

使用canvas绘制时钟

HTML5 - Canvas标签<使用;

HTML5 中的 canvas 画布