【问题标题】:Html5 canvas issue on MacOS chromeMacOS chrome上的HTML5画布问题
【发布时间】:2023-05-13 23:02:01
【问题描述】:

我正在尝试使用 HTML5 画布绘制散点图。我的散点图需要有很多点。当我尝试在画布上绘制大量点时,比如说 (7700000) 个点,它适用于 Firefox 和 Safari。

Very large number of points (JS fiddle)

但由于某种原因,MacOS 上的 Google Chrome 上的画布是空白的。但是它适用于 Windows 和 Linux 的 Google Chrome。如果要绘制的点数较少,它可以在 MacOS 上工作,但当点数增加时就不行。我试图搜索相关问题,但找不到任何问题。是我做错了什么还是 Google Chrome for MacOS 的问题?

Small number of points (JS Fiddle)

我正在使用以下函数在画布上绘图:

function drawPoint(scaleX, scaleY, point, k) {
    context.beginPath();
    context.fillStyle = pointColor;
    const px = scaleX(point[0]);
    const py = scaleY(point[1]);
    const arc_width = width/1000;
    const arc_height = height/1000;
    // context.arc(px, py, arc_width * k, 0, 2 * Math.PI, true);
    context.strokeRect(px, py, arc_width * k, arc_height * k)
    context.stroke();
}

【问题讨论】:

  • 您的真实数据点是否真的像您的示例中一样?如果是这样,那么画那么多点是没有意义的。您的网格只能包含 900 x 900 点。过滤掉所有重复项。另外,不要单独绘制每个点,创建一条大路径并在一次调用中绘制它。最后,避免中风,它超级慢,尽可能选择填充。
  • 我的真实数据点没有被填充,它可以根据绘图的某些属性是动态的。点也可以是随机的,它可能不在一条路径中。
  • 使用填充代替描边解决了我的问题。感谢您的回复。
  • 是的,如果您的所有点都使用相同的颜色绘制,您可以将它们绘制在一条路径中。为此,请在循环积分之前在draw 中调用一次context.beginPath(),然后在drawPoint 中只调用context.rect(...)(或moveTo(x+radius,y); arc(...),之后,在draw 中调用一次@ 987654330@.

标签: javascript html d3.js canvas html5-canvas


【解决方案1】:

你有一些用于 svg/canvas 的时髦 d3 动画(我不确定你为什么同时使用这两种动画)。这是一个影响性能的转换延迟。我可以在 Android 手机上加载小点,但是当我旋转或调整大小时,它会重新绘制它们,它们看起来完全不同。然后页面崩溃。

【讨论】:

  • SVG 只是画布上的一个叠加层,以使绘图具有交互性并添加一些功能。如果我尝试使用 SVG 绘制这些大量点,它会使浏览器崩溃,所以我使用画布绘制点并使用 svg 进行交互。在缩放或调整大小的情况下,我有另一个代码只绘制该窗口中的点。现在这是一个实际实现的虚拟代码,向你们询问我面临的问题。
  • 我的意思是画布的第一层油漆是单色噪点的洗涤,但在旋转时它是更大的描边圆圈。你说你为了性能而同步两者。在交互方面,svg 通常会更新特定元素(快),而 canvas 会重绘整个上下文(慢)。在这样的布局转换期间,浏览器会显着减慢或崩溃。绘制焦点/缩放细节的分层分组系统会更加用户友好。
【解决方案2】:

使用填充而不是描边解决了我的问题。我不知道实际原因,但是当您尝试在画布上绘制大量点时,使用填充会更快,并且可以在 chrome MacOS 上解决此问题。

【讨论】: