简体   繁体   中英

Partial render html5 canvas - Performance

I was working against a financial library that requires me to provide realtime updates to a line chart in canvas. To optimize the process of updating the chart, I thought of just updated the latest data-point rather than clearing and re-drawing the entire canvas.

When re-rendering only the latest datapoint frequently, I'm noticing that the line is not clear(there's a spot in the image).

Here's how the line looks initially(no redraw)

初始

And after a few updates of calling "partial_rerender", this is how the line looks: 重画

Notice the "joining" of the 2 lines is visible with a darker shade .

Is there a way to achieve partial re-drawing of lines only for the latest data point & not drawing the entire line completely?

Reference code

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.lineWidth = 2;
ctx.lineJoin = "miter";
ctx.moveTo(20, 50);
ctx.lineTo(100, 50);
ctx.save();
ctx.lineTo(150, 60);
ctx.stroke();

/*Call this every second to re-draw only the latest data point*/
function partial_rerender(){
ctx.clearRect(100,50, 400,400);
ctx.restore();
ctx.lineTo(150, 60);
ctx.stroke();
}

You need to create a new path each time you render or you end up re- rendering the same content over and over.

ctx.save() and ctx.restore() push and pop from a stack, for every restore you need to have a matching save. ctx.save() , ctx.restore() , ctx.restore() the second restore does nothing as there is no matching save.

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.lineWidth = 2;
ctx.lineJoin = "miter";
ctx.moveTo(20, 50);
ctx.lineTo(100, 50);
ctx.save();
ctx.lineTo(150, 60);
ctx.stroke();

// Your function should look more like this
function partial_rerender(){
   ctx.lineWidth = 2;
   ctx.lineJoin = "miter";
   ctx.save();  // needed to remove clip
   ctx.beginPath(); // removes old path ready to create a new one
   ctx.rect(100,50, 400,400); // create a clip area
   ctx.clip(); // activate the clip area
   ctx.clearRect(100,50, 400,400);
   ctx.beginPath(); // needed to draw the new path 
   ctx.moveTo(100,50)
   ctx.lineTo(150, 60);
   ctx.stroke();
   ctx.restore(); // remove the clip area
}

When you draw onto the canvas you do override the necessary pixels. But the rest stays the same. What you are trying to achieve is not possible. You have to clear the canvas (canvas.clear()) and then redraw all elements to remove these artifacts from previous draw calls and to achieve your desired result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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