2011-01-31 8 views
7

私は、OpenHeatMapオープンソースプロジェクト用に、FlashとHTML5/Canvasのレンダラを並列に保ちます。私は2つのバージョン間の分数座標で塗りつぶされたポリゴンのレンダリングに矛盾があります。エッジを共有する2つのポリゴンをレンダリングすると、Canvasはそのエッジに沿って目に見える結合を表示しますが、Flashは同じ色であれば違いを目にすることなく2つのフレームをシームレスに融合します。HTML5キャンバスでポリゴンのエッジステッチのアーチファクトを回避するにはどうすればよいですか?

http://web.mailana.com/labs/stitchingbug/

[ガクは、スパム防止の画像であることから、これを停止しますが、スクリーンショットのweb.mailana.com/labs/stitchingbugについてはこちらを参照してください。私はこの問題を示すために、ここでは最小限のページを一緒に入れています.PNG]

ソースは、同じことをやってFlashプロジェクトと一緒に、ここにある:

github.com/petewarden/stitchingbug

根本的な問題は、それがどんな複雑な多角形を行うことは不可能だということですr縫い目なしでポリゴンをつなぎ合わせることができない場合は、 Flashの塗りつぶしルールは正確には分かりませんが、3Dレンダラーと同様に正しい結果が得られます。この問題を回避するには、誰でもクライアント側の修正がありますか?それはクロスブラウザーなので、故意に見えるようになっているので、使用されるルールへの参照も高く評価されます。キャンバスコードは次のとおりです。

var ctx = canvas.getContext('2d'); 
    ctx.fillStyle = 'rgb(0,0,0)'; 

    ctx.beginPath() 
    ctx.moveTo(0, 0); 
    ctx.lineTo(50.5, 0); 
    ctx.lineTo(50.5, 100); 
    ctx.lineTo(0, 100); 
    ctx.closePath(); 
    ctx.fill(); 

    ctx.beginPath() 
    ctx.moveTo(50.5, 0); 
    ctx.lineTo(100, 0); 
    ctx.lineTo(100, 100); 
    ctx.lineTo(50.5, 100); 
    ctx.closePath(); 
    ctx.fill(); 
+0

ストーミング:各ポリゴンの中心を計算して描画するときに、中心から外側に向かってポイントをプッシュ少量(たぶん0.5)。アンチエイリアシングをわずかにオーバードローします。 – Phrogz

+0

[ハックなしでこの問題を解決できない理由を理解するには、[この回答](http://stackoverflow.com/questions/15631426/svg-fill-not-filling-boundary/15638764#comment22224474_15638764)の後半を参照してください。アンチエイリアシングが関与している場合は、ストロークやアンダーフィルのようになります。 – Phrogz

答えて

1

すべての描画コードを切り捨てると考えましたか?品質を低下させるべきではなく、問題を解決する可能性があります。

問題を目立たないようにするために、問題のある領域に線を描くこともできます。

他のすべてが失敗した場合、それはうまくいくはずです。

+1

残念ながら座標を切り捨てるのは、静的なポリゴンセットの単純なケースでのみ機能します。たとえばマップをズームまたはパンすると、トランケーションは整数座標間で前後にスナップするので、かなり激しい「ダンスエッジ」を引き起こします。また、浅いグレードの大きなポリゴンのエッジが目立ちます。 –

3

これは古い質問ですが、同じ問題がありました。

2つのポリゴン(またはそれらの周りの輪郭)の間に1本の線があると、問題が解決されます(少なくともfirefoxとchromeでは)。

少なくとも、クロムとファイアフォックスの隙間を埋めるようです。

ctx.beginPath() 
ctx.moveTo(50.5, 0); 
ctx.lineTo(50.5, 100); 
ctx.stroke(); 

そしてもちろんstrokeStyleを設定してください:ctx.fill()ctx.stroke()を呼び出す、または次のように単一線を引くのに十分です。

+0

あなたが描いている線がイメージパターンの場合、クロムでは何らかの理由でパフォーマンスが著しく低下します。 – shoosh

+1

また、このソリューションは半透明のポリゴンでは機能しません。 –

+0

lineWidthが.5のポリゴンの周りにストロークを追加すると、私にとってはうまくいきました。私がズームインしたときに気づくまでは、ポリゴンのコーナーは互いに劇的にオーバーシュートしていました。だから、代わりにlineWidthを.5/zoomに設定します(ズームは100%で0.5、50%で0.5、%200から2など)。これで美しく動作します。残念ながら、半透明のポリゴンは目立つエッジでレンダリングされます。理論的には、ポリゴンを完全に不透明にして別のキャンバスに描画し、そのキャンバスを透明にしてターゲットキャンバスにレンダリングすることでこれを克服することができます。 – CodeAndCats

1

私は、座標はすべて整数である場合でも、クローム41.0.2272.89メートルで同じ問題を見ることができます:http://jsfiddle.net/xgd03fyb/

var canvas = document.getElementById('myCanvas'); 
var context = canvas.getContext('2d'); 
context.lineWidth = 0; 
context.fillStyle = 'black'; 

context.beginPath(); 
context.moveTo(100, 100); 
context.lineTo(200, 200); 
context.lineTo(200, 100); 
context.closePath(); 
context.fill(); 

context.beginPath(); 
context.moveTo(100, 100); 
context.lineTo(100, 200); 
context.lineTo(200, 200); 
context.closePath(); 
context.fill(); 

私はのような問題は、時計回り/反時計回りの不一致が原因で発生する可能性があることを疑わ過去に私が使っていたライブラリの中には、どの辺が透明であるか、そしてアンチエイリアスとして描かれているかに影響します。 しかし、2番目の三角形のlineTo()呼び出しの順番を変更しても効果はないようです。

fillStyle(fill()に渡された引数)を"evenodd"からデフォルトの"nonzero"に変更しようとしました。

それはので、私はより多くを学ぶためにバグを提出してきましたこれは動作するはずですどのように仕様https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-fillから私にとっては明らかではありません。https://www.w3.org/Bugs/Public/show_bug.cgi?id=28217

関連する問題