2011-10-25 5 views
6

私は奇妙な問題を突き詰めました。次のコードは、半不透明な矩形で何度も何度も上書きされるため、イメージがぼやけてしまいます。複数回適用するとアルファ付きrgba fillStyleが完全に不透明にならない

少なくとも10回目の繰り返しがdraw();の場合、イメージは完全にオーバードラングする必要があります。これは、rectが完全に不透明であるべきであるからです。しかし、実際に完全に消えてしまうことはありません。

この影響は、Firefoxの場合よりもChromeの方が悪いです。しかし、注意してください:悪い画面がこの不具合を隠すかもしれません=)

私はまたjsFiddleでdemoを作った。

$(function() { 
var canvas = $("#mycanvas"), 
    ctx = canvas[0].getContext("2d"), 
    imgUrl = "http://it-runde.de/dateien/2009/august/14/25.png"; 


var image = new Image(); 
image.src = imgUrl ; 
$(image).load(function() { 
    ctx.drawImage(image, 0, 0, canvas.width(), canvas.height()); 
    draw(); 
}); 

function draw() {   
    ctx.fillStyle = "rgba(255, 255, 255, 0.1)"; 
    ctx.fillRect(0,0,canvas.width(),canvas.height()); 
    setTimeout(draw, 100); 

}  
}); 

1が達成したいことの効果は、オブジェクトがすべてのキャンバス上で動いていると言うと、すでに描かれた位置はアフターグロー後のフェード効果のように、わずかに誇張得る、ということです。しかし、この結果はちょうど醜いです。

これには解決策がありますか?

+1

に道を作る例は、キャンバスは以前の状態を「覚える」なしで動作を覚えておいてください。したがって、0.1のアルファは、10回後に完全に不透明になりましたが、不透明度は実際には決して到達しない '(1 - 0.1)*(1 - 0.1)* ...' 「0」。 – pimvdb

答えて

4

矩形はわずか10%しか不透明ではないため、イメージの上に描画すると、イメージの90%と10%の白が合成されます。あなたがそれを描くたびに、イメージの以前の反復の10%を失います。矩形自体はより不透明になることはありません。 (その効果を得るには、別のオブジェクトをイメージの上に置き、その不透明度をアニメーション化する必要があります)。10回反復した後も、(0.9^10)または元のイメージの約35%が残っています。丸め誤差は約30回の反復後に設定されることに注意してください。

+0

あなたはそれに私を打つ! – gthmb

+0

私はまだそれを取得しません。これは内部的な画像処理計算ですか?それは私には論理的ではない。私がPhotoshopの位置にある10個のレイヤーで、あるコンテンツに対して10%の不透明度があると言うと、レイヤーは完全にそれをカバーします。これは実生活にも適用されますね。私はあなたの答えを理解していますが、それはなぜですか?あなたの説明によれば、実際には100%の不透明度の画像を配置し、その反復ごとに現在の不透明度は10%ですが、ここでは起こっていません... =(と:30回の反復後に画像は消えません。 – owzim

+0

新しいレイヤーごとに透明度を10%減らすと考えると、1つのレイヤーの後では100%から90%に減らし、残りのレイヤーでは90%を10%減らします。あなたは約81%であり、3番目の層では81%が8.1%減少し、約72.9%などとなります。 – gthmb

3

私はこれが古いことを知っていますが、私は以前に受け入れられた答えが正しいとは思わない。私はこれが浮動小数点からバイトに切り捨てられたピクセル値の結果として起こっていると思います。 Windows 7ではChromeバージョン39.0.2171.95mを使用していますが、しばらくの間あなたのフィドルを実行しても、画像はまだ見えますが軽くても、それ以上は変化していないようです。

:あなたはのRGBAとその上に四角形を描画するとき

(246、246、246)

:私は、スクリーンショットを撮る場合は、私は、画像の上に、次のピクセル値を参照してください

(255、255、255、0.1)

とソースオーバーのデフォルトの合成モードを使用してアルファブレンディングを適用するには、バイトに変換する前に、あなたが得る:

(255 * 0.1 + 246 * 0.9)= 246.9

ですから、ブラウザは、単にバイトに浮動小数点値を切り捨てると仮定すると、それを見ることができ、それは246の値を書き出します描画操作を繰り返すたびに、常に同じ値になります。

このブログ投稿hereに問題に関する大きな議論があります。

回避策として、継続的にキャンバスを消去して、減少するglobalAlpha値でイメージを再描画することができます。例:

// Clear the canvas 
    ctx.globalAlpha = 1.0; 
    ctx.fillStyle = "rgb(255, 255, 255)"; 
    ctx.fillRect(0,0,canvas.width(),canvas.height()); 

    // Decrement the alpha and draw the image 
    alpha -= 0.1; 
    if (alpha < 0) alpha = 0; 
    ctx.globalAlpha = alpha; 
    console.log(alpha); 
    ctx.drawImage(image, 0, 0, 256, 256); 
    setTimeout(draw, 100); 

フィドルはhereです。

0

理由は前に完全に述べられました。 を取り除くことはできません。それを消去せずに@Samのように再描画することは既に言われています。

少し補うためにできることは、globalCompositeOperationを設定することです。

さまざまな操作があります。私のテストでは、暗い背景にはhard-light、明るい背景にはlighterが最適です。しかし、これはあなたのシーンに非常に依存します。

「近い」黒

ctx.globalCompositeOperation = 'hard-light' 
ctx.fillStyle = 'rgba(20,20,20,0.2)' // The closer to black the better 
ctx.fillRect(0, 0, width, height) 

ctx.globalCompositeOperation = 'source-over' // reset to default value 
関連する問題