2017-06-30 109 views
0

我正在对付一个金融库,需要我提供实时更新到画布中的折线图。为了优化更新图表的过程,我想只更新了最新的数据点,而不是清理和重新绘制整个画布。部分渲染HTML5画布 - 性能

当只重新渲染最新的数据点时,我注意到线条不清晰(图像中有一个点)。

这里的线看起来如何开始(没有重绘)

Inital

及后致电 “partial_rerender” 的一些更新,这是该行的样子: Redraw

请注意两条线的“连接”在较暗的阴影下可见

有没有办法实现只为最新数据点部分重画线条&没有完全画出整条线?

参考代码

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(); 
} 
+1

在clearRect(这是一个好主意)的顶部,你也应该使用[片段](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip)。在那之后结局不会“泄漏”。 – tevemadar

+0

你并没有在'partial_rerender'中调用'beginPath' ...''ctx.save'保存**所有**你的上下文的属性,但是**不**你的路径声明的当前状态。 (即这里没有什么重要的要求)。对于这样的情况,只需重绘一切;对于非常复杂和沉重的绘制形状,将其存储在屏幕外画布中,并且在每一帧清除所有内容时,绘制屏幕外画布beginPath(),moveTo(theLastPoint),partial_rerender()。但通过一切手段,删除这些保存并恢复... – Kaiido

+0

可能重复[为什么忽略beginPath()重绘一切?](https://stackoverflow.com/questions/21869609/why-does-omitting-beginpath-redraw - 一切) – Kaiido

回答

1

您需要在每次渲染时创建一个新路径,或者最终重新渲染相同的内容。

ctx.save()ctx.restore()从堆栈中压入和弹出,对于每次恢复,您需要有一个匹配的保存。 ctx.save()ctx.restore()ctx.restore()第二次恢复不做任何事情,因为没有匹配的保存。

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 
} 
+1

为什么在这里剪辑? – Kaiido

+1

@Kaiido停止与现有像素混淆的边缘。从100,50到100,60的宽度为2(或1或更小)的线将呈现为(99,50),(99,49),(100,49) – Blindman67

+0

@ Blindman67上的像素:如果线宽度是10ps,它会渲染像素89? (总是比总体位置少1)? – Akash

0

当你画到你覆盖了必要的像素的画布。但其余的保持不变。 你试图实现的是不可能的。您必须清除画布(canvas.clear()),然后重新绘制所有元素以从先前的绘制调用中移除这些工件并实现所需的结果。