2017-09-22 61 views
0

我正在使用HTML5畫布元素,我正在處理一個項目,同時呈現一堆東西,我遇到了一個非常奇怪的工件,我想知道如果有人曾經見過。基本上,在這個特定的場景中(這是我見過的唯一產生這種行爲的情況),我恰好在平移/縮放應用程序,並注意到在畫布的一部分上出現了一種奇怪的渲染效果。經進一步檢查,我能夠重現一個非常簡單的例子效果:奇怪的HTML5畫布關閉路徑渲染神器

Strange HTML5 Canvas Rendering Artifact

在這種情況下,我有一個路徑(其座標不改變)和所有從改變第一個截圖到第二個截圖是應用的變換矩陣(數量非常少)。

您可以訪問的jsfiddle我用來產生這些截圖在https://jsfiddle.net/ynsv66g8/,這裏是相關的渲染代碼:

// Clear context 
context.setTransform(1, 0, 0, 1, 0, 0); 
context.fillStyle = "#000000"; 
context.fillRect(0, 0, 500, 500); 

if (showArtifact) { // This transformation causes the artifact 
    context.transform(0.42494658722537976, 0, 0, -0.42494658722537976, 243.95776291868646, 373.14630356628857); 
} else { // This transformation does not 
    context.transform(0.4175650109545749, 0, 0, -0.4175650109545749, 243.70987992043368, 371.06797574381795); 
} 

// Draw path 
context.lineWidth = 3.488963446543301; 
context.strokeStyle = 'red'; 
context.beginPath(); 
var p = path[0]; 
context.moveTo(p[0], p[1]); 
for (var i = 1; i < path.length; ++i) { 
    p = path[i]; 
    context.lineTo(p[0], p[1]); 
} 
context.closePath(); 
context.stroke(); 

看起來,因爲如果去掉調用context.closePath()可能與調用canvas.closePath()

p = path[0]; 
context.lineTo(p[0], p[1]); 

(因此手動「關閉」路徑)一切正常(當然,這真的沒有,因爲我靠解決我的具體問題上的多個閉合路徑爲:將其替換爲填寫規則)。

可以使問題消失的另一個有趣的變化是將path數組倒轉(即在其定義之後立即添加對path.reverse()的調用)。

所有這些似乎都加在某種與路徑特徵有關的瀏覽器渲染錯誤上,尤其是因爲在我的Mac上,Chrome(v61.0.3163.91)和Firefox(v55.0.3),而不是Safari(v11)。我已經做了一些廣泛的搜索,試圖找到這個問題(或者類似的東西),但是到目前爲止已經空了。

任何洞察什麼可能會導致此(或正確的方式來報告這個問題,如果共識是它是由一些瀏覽器錯誤引起)將不勝感激。

+0

這是由兩個線段之間的一個非常小的角度引起的斜角僞影,並且可以通過將'context'的'lineJoin'屬性設置爲''round''或''斜角''來消除。默認的'lineJoin'是''miter'',它有一個限制。通過「miterLimit」屬性設置斜接限制,雖然它並不總是能夠消除僞像。由於從雙打(64位浮點JS數)轉換爲浮點(GPU使用32Bit)時得到的舍入誤差,您的問題會加劇。給定的答案將解決您的問題,並值得一票。 – Blindman67

+0

@ blindman67只是想報告,也'斜角'失敗在我的Firefox;看着alpha混合的神器三角形,我被說服了,這完全是一個着色器問題,而不是定向邏輯中的一個bug。 –

+0

@ Blindman67在將'lineJoin'設置爲''bevel''時,我也看到失敗,但是,當將'lineJoin'設置爲'「round」'時,問題似乎得到解決。 – Sanuden

回答

3

它似乎是一個線路問題;也就是說,當寬度相對於片段大小/方向過大時,渲染器無法正確連接線條。

這似乎不受路徑關閉影響(我可以重現與開放路徑的神器);請注意,手動關閉路徑與closePath()不同,因爲在前一種情況下不執行行連接。

據我所知,似乎通過設置lineJoin解決了「圓」或減少線寬...無論如何,似乎呈現錯誤給我...只是我的兩分錢:)