0

問題

不透明ジッターを使用してブラシ ツールを作成しようとしています (Photoshop のように)。具体的な問題は次のとおりです。

さまざまなレベルの不透明度を使用して、HTML キャンバスにストロークを描画します。不透明度の高いピクセルは、不透明度の低いピクセルに置き換わる必要があります。それ以外の場合、ピクセルは変更されません。

その過程で透明性が失われてはなりません。ストロークは別のキャンバスに描画され、後で背景のキャンバスと結合されます。

結果は次のようになります。すべてのコードと対応する出力は、こちら(JSFiddle) にあります。

異なるレベルの不透明度で 1 つのパスをストロークすることはできないため (間違っている場合は訂正してください)、私のコードではセグメントごとに異なる不透明度のパスを作成します。

非解決策 1、「暗い」ブレンド モードの使用

暗いブレンド モードでは、不透明なピクセルを使用すると望ましい結果が得られますが、透明度では機能しないようです。透明性を失うことは取引の破綻です。

不透明なピクセルの場合:

ここに画像の説明を入力

透明ピクセルの場合:

ここに画像の説明を入力

非解決策 2、'destination-out' 合成演算子を使用する

新しいストローク セグメントを描画する前に、'destination-out' 合成演算子を使用して、下にあるピクセルからその不透明度を減算します。次に、「source-over」で新しいストローク セグメントを追加します。これはほとんど機能しますが、少しずれています。

ここに画像の説明を入力

解決策を探しています

各ピクセルを手動で操作することは避けたいです (過去に行ったことがあります)。明らかな何かが欠けていますか?この問題の簡単な解決策はありますか?

"Links to jsfiddle.net must be accompanied by code."
4

3 に答える 3

3

不透明度の異なる単一のパスをストロークすることはできないため(間違っている場合は修正してください)

あなたは間違っています=)

globalCompositeOperation = 'destination-out'(あなたがいる)を使用するときは、不透明度をに設定してすべてを削除するlineDestinationOut必要があります。strokeStyle1

ただし、フィドルでそれを変更するだけでは、パスビルドの順序が原因で必要な効果が得られません。最初に 10% 透明のものを全長にわたって構築し、次に 2 つの 40% 透明ビットを削除して描画します。

以下のコードの jsfiddle を次に示します。

var canvas = document.getElementById('canvas');
var cx = canvas.getContext('2d');
cx.lineCap = 'round';
cx.lineJoin = 'round';
cx.lineWidth = 40;

// Create the first line, 10% transparency, the whole length of the shape.
cx.strokeStyle = 'rgba(0,0,255,0.1)';
cx.beginPath();
cx.moveTo(20,20);
cx.lineTo(260,20);
cx.lineTo(220,60);
cx.stroke();
cx.closePath();

// Create the first part of the second line, first by clearing the first
// line, then 40% transparency.
cx.strokeStyle = 'black';
cx.globalCompositeOperation = 'destination-out';
cx.beginPath();
cx.moveTo(20,20);
cx.lineTo(100,20);
cx.stroke();
cx.strokeStyle = 'rgba(0,0,255,0.4)';
cx.globalCompositeOperation = 'source-over';
cx.stroke();
cx.closePath();

// Create the second part of the second line, same as above.
cx.strokeStyle = 'black';
cx.globalCompositeOperation = 'destination-out';
cx.beginPath();
cx.moveTo(180,20);
cx.lineTo(260,20);
cx.stroke();
cx.strokeStyle = 'rgba(0,0,255,0.4)';
cx.globalCompositeOperation = 'source-over';
cx.stroke();
cx.closePath();
于 2014-01-04T20:55:50.967 に答える