简体   繁体   English

绘制多条路径时 react-native-canvas 的性能优化

[英]Performance optimization for react-native-canvas when drawing many paths

I want to mirror an analog segment display in my React Native app.我想在我的 React Native 应用程序中镜像模拟段显示。 The segment display is quite complicated, it consists of more than 100 different segments.段显示相当复杂,它由 100 多个不同的段组成。 It contains three 7-segment displays for numbers and a progress bar with 20 elements.它包含三个 7 段数字显示和一个包含 20 个元素的进度条。 The rest are custom shapes and symbols that provide information about the current state of the machine it is attached to.其余的是自定义形状和符号,提供有关它所连接的机器的当前状态的信息。 I have some experience with the HTML canvas and found the React Native module react-native-canvas and wanted to give it a try.我对 HTML 画布有一些经验,发现了 React Native 模块 react-native-canvas 并想尝试一下。 However, drawing on the react-native-canvas seems to be quite slow compared to the HTML canvas that I can use in a web-browser.但是,与我可以在网络浏览器中使用的 HTML 画布相比,在 react-native-canvas 上绘图似乎相当慢。

Here is what I do:这是我所做的:

  1. I import the module in my component:我在我的组件中导入模块:

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

  1. Add a canvas element to my render function:向我的渲染函数添加一个画布元素:

<Canvas ref={this.handleCanvas}/>

  1. store a reference to the canvas and set its size:存储对画布的引用并设置其大小:
handleCanvas = (canvas) => {
    if (this.myCanvas === null && canvas !== null){
      canvas.width = 250;
      canvas.height = 250;
      this.myCanvas = canvas;
    }
  }
  1. Then i can call for each segment a "draw" function that draws a 2D-path:然后我可以为每个段调用一个绘制二维路径的“绘制”函数:
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();
}

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

I made a prototype with 13 segments.我制作了一个包含 13 个部分的原型。 Each segment has around 50 nodes and I draw all 13 segments at once.每个段有大约 50 个节点,我一次绘制所有 13 个段。 In my React Native app, this takes almost one second to draw which is way too slow (and there are 90 more segments that I do not render yet...).在我的 React Native 应用程序中,这几乎需要一秒钟的时间来绘制,这太慢了(还有 90 个部分我还没有渲染......)。 If I draw the same paths on a HTML canvas on Google Chrome, it only takes 2-5 milliseconds.如果我在 Google Chrome 的 HTML 画布上绘制相同的路径,只需要 2-5 毫秒。

Does anyone have an idea, how I can improve the performance?有没有人有想法,我如何提高性能? Or is there another library that is more performant for my purposes?`还是有另一个库对我的目的来说性能更好?`

Thanks in advance!提前致谢!

Iddans answer was correct, since I can not post a detailed solution of how exactly we solved the problem as comment to his answer, I'm posting a new answer myself. Iddans 的回答是正确的,因为我无法发布我们如何准确解决问题的详细解决方案作为对他的回答的评论,所以我自己发布了一个新答案。

As Iddan stated, the correct solution was indeed to minimize the numbers of instructions sent to the canvas.正如 Iddan 所说,正确的解决方案确实是尽量减少发送到画布的指令数量。 We changed point 4 of my question.我们改变了我的问题的第 4 点。 Instead of directly drawing a path with ctx.lineTo(...) statements, we extracted all SVG paths as strings and stored them in an array:我们没有直接使用ctx.lineTo(...)语句绘制路径,而是将所有 SVG 路径提取为字符串并将它们存储在一个数组中:

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

For each render cycle, we decide, what subset of all SVG paths we want to be rendered and store them in a new array, then we create a single Path2D object of all the desired svg Paths对于每个渲染周期,我们决定要渲染所有 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)

This is very fast and takes just a few milliseconds.这非常快,只需几毫秒。

thank you for posting your question with such detail.感谢您发布如此详细的问题。 React Native Canvas is fairly slow compared to the HTML canvas as each instruction is being communicated to a WebView.与 HTML 画布相比,React Native Canvas 相当慢,因为每条指令都被传送到 WebView。 One potential way to improve performance that I can think of is to use Path2D as the object holds multiple instructions before it renders.我能想到的一种提高性能的潜在方法是使用Path2D,因为对象在呈现之前包含多个指令。 Can you try that and check if it improved the performance?您可以尝试一下并检查它是否提高了性能?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM