react-konvakonva

Konva free drawing slows down on large screens


I am developing a free drawing module using React-Konva. When testing on a PC, there was no significant decrease in speed. However, when we tested the page on a 55-inch Interactive Whiteboard, we saw a huge slowdown. There is also a function that allows you to enlarge the Stage and write, and we found that writing on the Whiteboard using this function becomes even slower. What part of my code should I modify to prevent writing speed from being slow on large-sized Canvas?

        <Stage
                width={width}
                height={height}
                style={{ pointerEvents: "all" }}
                onPointerDown={handleMouseDown}
                onPointerMove={handleMouseMove}
                onPointerUp={handleMouseUp}
                ref={stageRef}
                scaleX={zoom}
                scaleY={zoom}
                id={page}
            >
                <Layer>
                    {items.map((line, index) => (
                        <Line
                            name="object"
                            key={index}
                            id={line.id}
                            x={line.x}
                            y={line.y}
                            points={line.points}
                            stroke={line.color}
                            strokeWidth={line.width}
                            tension={0.5}
                            lineCap="round"
                            lineJoin="round"
                            globalCompositeOperation="source-over"
                        />
                    ))}
                </Layer>
            </Stage>

Solution

  • There are many ways to improve the performance. Take a look here for some tips: https://konvajs.org/docs/performance/All_Performance_Tips.html

    If you have a drawing application, you should try to isolate the current drawing line. Every change on the canvas will trigger for layer redraw.

    Instead of redrawing every line on user input, you can put the last (current) line into a separate layer.

    <Stage>
      <Layer>
        {lines.map(line => <Line {...line} />)}
      </Layer>
      <Layer>
        {currentLine && <Line {...currentLine} />}
      </Layer>
    </Stage>
    

    As soon as a user finish drawing (on mouseup or touchend) you can clear "currentLine" and add into array of "lines".