web-dev-qa-db-ja.com

HTML5で塗りつぶされたストロークの透明度

HTML5の落書きアプリに取り組んでおり、一種のバケット機能を実行したいと思います。パスを描画すると、パスが閉じられ、選択した色(ストロークの色)で塗りつぶされます。単色で非常にうまく機能しますが、透明なストロークと塗りつぶしが必要な場合は、次の問題が発生します: http://imgur.com/0N3MW

塗りつぶしはストロークの中央(パスの実際のサンプリングポイント)まで行われるため、塗りとストロークの交点であるため、図形の内側にストロークの半分のサイズの線があります。

これに対する回避策はありますか?

残念ながら、JSFiddleは読み取り専用モードであるため、現在JSFiddleに投稿できません。しかし、あなたは私が話していることをこのサンドボックスでライブで見ることができるはずです: http://bit.ly/AbaMLl (ウェブサイトとライブラリは私が使用しているものとは無関係です、それはただです私が見つけたキャンバスサンボックス)

どんなアイデア/リードも歓迎します:)

8
Mathieu

サイモンの答えは当時は正しかったのですが、Chrome 36が彼のソリューションに影響するバグを修正し、機能しなくなったようです。Firefoxではすでに機能していなかったようです。予想される動作: https://bugzilla.mozilla.org/show_bug.cgi?id=898375

では、どうやってこれを成し遂げるのですか?
最初に別のキャンバスが必要です。
塗りつぶされたストロークの形状を不透明なしでこのキャンバスに描画します(カラーではなく、globalAlphaもありません)。
次に、globalAlphaをメインキャンバスで必要なものに描画設定します。
メインのキャンバスに最初のキャンバスを描画します。
globalAlphaをメインキャンバスにあるものに設定します。
完了。

4
Mathieu

確かに、ctx.globalCompositeOperation = 'destination-atop';を使用すると、期待どおりに表示されるはずです。

そのように: http://jsfiddle.net/UcyX4/

(あなたが抱えている問題を見るためにその行を取り出してください)

キャンバスに描画されるのはそれだけではないと仮定すると、おそらくこれを一時的なキャンバスに描画してから、そのキャンバスを通常のキャンバスに描画する必要があります。そうしないと、以前に描画されたすべての形状が台無しになる可能性があります。したがって、次のようなシステムが必要になります。 http://jsfiddle.net/dATfj/

編集:jsfiddleが失敗した場合に貼り付けられたコード:

html:

<canvas id="canvas1" width="500" height="500"></canvas>

脚本:

var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');

var can2 = document.createElement('canvas');
can2.width = can.width;
can2.height = can.height;
ctx2 = can2.getContext('2d');

ctx.strokeStyle = 'rgba(0,0,0,0.7)';
ctx.fillStyle = 'rgba(0,0,0,0.7)';
ctx.lineWidth = 10;


// Stuff drawn normally before
// Here I draw one rect in the old way just to show the old way
// and show something on the canvas before:
ctx.beginPath();
ctx.rect(50,50,100,100);
ctx.fill();
ctx.stroke();


// Draw on can2 then draw can2 to can
ctx2.strokeStyle = 'rgba(0,0,0,0.7)';
ctx2.fillStyle = 'rgba(0,0,0,0.7)';
ctx2.lineWidth = 10;
ctx2.beginPath();
ctx2.rect(50,250,100,100);
ctx2.globalCompositeOperation = 'destination-atop';
ctx2.fill();
ctx2.stroke();

ctx.drawImage(can2, 0, 0);
11
Simon Sarris

2018年の回答:context.globalAlphaを使用

例:context.globalAlpha = 0.2;

5
PhilMaGeo