【问题标题】:Performance optimization for react-native-canvas when drawing many paths绘制多条路径时 react-native-canvas 的性能优化
【发布时间】:2020-03-02 08:09:02
【问题描述】:

我想在我的 React Native 应用程序中镜像模拟段显示。段显示相当复杂,它由100多个不同的段组成。它包含三个 7 段数字显示和一个包含 20 个元素的进度条。其余的是自定义形状和符号,提供有关它所连接的机器当前状态的信息。我对 HTML 画布有一些经验,发现了 React Native 模块 react-native-canvas 并想尝试一下。但是,与我可以在网络浏览器中使用的 HTML 画布相比,在 react-native-canvas 上绘图似乎相当慢。

这是我的工作:

  1. 我在我的组件中导入模块:

import Canvas, {Image as CanvasImage, Path2D, ImageData} from 'react-native-canvas';

  1. 在我的渲染函数中添加一个画布元素:

<Canvas ref={this.handleCanvas}/>

  1. 存储对画布的引用并设置其大小:
handleCanvas = (canvas) => {
    if (this.myCanvas === null && canvas !== null){
      canvas.width = 250;
      canvas.height = 250;
      this.myCanvas = canvas;
    }
  }
  1. 然后我可以为每个段调用一个绘制 2D 路径的“绘制”函数:
draw(ctx){
  ctx.save();
  ctx.strokeStyle="#000000";
  ctx.lineWidth=2;
  ctx.lineJoin="round";
  ctx.font="   10px sans-serif";
  ctx.beginPath();
  ctx.moveTo(158.108112514019,24.324327290058136);
  ctx.lineTo(159.45946389436722,24.324327290058136);
  ctx.lineTo(160.13513958454132,25.67567867040634);
  ...
  ctx.lineTo(162.16216665506363,25.00000298023224);
  ctx.fill("nonzero");
  ctx.stroke();
  ctx.restore();
}

我得到这样的上下文: var ctx = this.myCanvas.getContext('2d');

我制作了一个包含 13 段的原型。每个段大约有 50 个节点,我一次绘制所有 13 个段。在我的 React Native 应用程序中,这需要将近一秒钟的时间来绘制,这太慢了(还有 90 多个片段我还没有渲染......)。如果我在 Google Chrome 上的 HTML 画布上绘制相同的路径,只需要 2-5 毫秒。

有人知道如何提高性能吗?或者是否有其他库对我来说性能更高?`

提前致谢!

【问题讨论】:

    标签: typescript react-native canvas react-native-android react-native-ios


    【解决方案1】:

    Iddans 的回答是正确的,因为我无法发布关于我们如何准确解决问题的详细解决方案作为对他的回答的评论,所以我自己发布了一个新的答案。

    正如 Iddan 所说,正确的解决方案确实是尽量减少发送到画布的指令数量。 我们改变了我的问题的第 4 点。我们没有使用ctx.lineTo(...) 语句直接绘制路径,而是将所有 SVG 路径提取为字符串并将它们存储在一个数组中:

    const svgPaths = [
       'M713.33,497.34a38.67 ... ',
       ...
    ]
    
    

    对于每个渲染周期,我们决定要渲染所有 SVG 路径的哪个子集并将它们存储在一个新数组中,然后我们创建一个包含所有所需 svg 路径的单个 Path2D 对象

    const svgPathsSubset = [svgPaths[1], svgPaths[7], ... ]
    const pathToRender = new Path2D(this.myCanvas, svgPathsSubset)
    const ctx = this.myCanvas.getContext('2d')
    ctx.fill(pathToRender)
    

    这非常快,只需几毫秒。

    【讨论】:

      【解决方案2】:

      感谢您如此详细地发布您的问题。与 HTML 画布相比,React Native Canvas 相当慢,因为每条指令都在与 WebView 进行通信。我能想到的一种提高性能的潜在方法是使用Path2D,因为对象在呈现之前包含多个指令。你可以试试看它是否提高了性能?

      【讨论】:

      • 您好 Iddan,非常感谢您的宝贵意见!我设法解决了这个问题。对于任何感兴趣的人,我自己发布了一个答案,其中包含更详细的步骤。我有一个小的后续问题:如果我想更改画布的内容,您认为正确的方法是什么?目前,我在“render”函数中调用一个函数,如下所示:“render(){ if(isCanvasInitialized === true) {this.redrawCanvas()} ...”。这是正确的做法吗?
      猜你喜欢
      • 1970-01-01
      • 2020-08-04
      • 2012-05-21
      • 2022-10-17
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-04
      相关资源
      最近更新 更多