2017-06-30 147 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()),然後重新繪製所有元素以從先前的繪製調用中移除這些工件並實現所需的結果。