diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/ja/web/api/canvas_api/tutorial/compositing | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/ja/web/api/canvas_api/tutorial/compositing')
-rw-r--r-- | files/ja/web/api/canvas_api/tutorial/compositing/example/index.html | 260 | ||||
-rw-r--r-- | files/ja/web/api/canvas_api/tutorial/compositing/index.html | 113 |
2 files changed, 373 insertions, 0 deletions
diff --git a/files/ja/web/api/canvas_api/tutorial/compositing/example/index.html b/files/ja/web/api/canvas_api/tutorial/compositing/example/index.html new file mode 100644 index 0000000000..65e56da8d4 --- /dev/null +++ b/files/ja/web/api/canvas_api/tutorial/compositing/example/index.html @@ -0,0 +1,260 @@ +--- +title: Compositing example +slug: Web/API/Canvas_API/Tutorial/Compositing/Example +tags: + - Canvas + - Example + - Graphics + - HTML + - HTML5 + - Tutorial +translation_of: Web/API/Canvas_API/Tutorial/Compositing/Example +--- +<div>{{CanvasSidebar}}</div> + +<p>This sample program demonstrates a number of <a href="/en-US/docs/Web/API/CanvasRenderingContext2D.globalCompositeOperation" title="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Compositing">compositing operations</a>. The output looks like this:</p> + +<p>{{EmbedLiveSample("Compositing_example", "100%", 7250)}}</p> + +<h2 id="Compositing_example">Compositing example</h2> + +<p>This code sets up the global values used by the rest of the program.</p> + +<pre class="brush: js">var canvas1 = document.createElement("canvas"); +var canvas2 = document.createElement("canvas"); +var gco = [ 'source-over','source-in','source-out','source-atop', + 'destination-over','destination-in','destination-out','destination-atop', + 'lighter', 'copy','xor', 'multiply', 'screen', 'overlay', 'darken', + 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', + 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity' + ].reverse(); +var gcoText = [ +'デフォルトの設定です。新たな図形をすでにあるCanvasの内容の上に描きます。', +'新たな図形は、その図形と描画先 Canvas の内容が重なり合う部分のみが描かれます。重なり合わない領域は透明になります。', +'新たな図形は、その図形と描画先 Canvas の内容と重なり合わない部分のみが描画されます。他の領域は透明になります。', +'新たな図形は、その図形と描画先 Canvas の内容と重なり合う部分のみが描かれます。', +'新たな図形は、描画先 Canvas の内容の背後に描かれます。', +'描画先 Canvas の内容は、新たな図形と重なり合う部分だけが残ります。新たな図形も含めて、他の領域は透明になります。', +'描画先 Canvas の内容は、新たな図形と重なり合わない部分だけが残ります。新たな図形も含めて、他の領域は透明になります。', +'描画先 Canvas の内容は、新たな図形と重なり合う部分だけが残ります。新たな図形は、その背後に描かれます。', +'新たな図形と描画先 Canvas の内容が重なる部分は、カラー値が加算されます。', +'新たな図形だけが描かれて、描画先 Canvas の内容は透明になります。', +'新たな図形と描画先 Canvas の内容が重なり合う部分は透明になります。他の領域はともに描画されます。', +'新たな図形のピクセルは、対応する描画先 Canvas のピクセルとカラー値が乗算されます。その結果、各ピクセルのカラーは暗くなります。', +'新たな図形のピクセルと対応する描画先 Canvas のピクセルとカラー値をそれぞれ一旦反転して、乗算したうえで、改めて反転します。その結果、各ピクセルのカラーは明るくなります (multiply の逆)。', +'multiply と screen を組み合わせます。新たな図形のピクセルより対応する描画先 Canvas のピクセルが、それぞれ暗いときは暗くし、明るければ明るくします。', +'新たな図形のピクセルは、対応する描画先 Canvas のピクセルとカラー値を比べて、それぞれ暗い方のピクセルを残します。', +'新たな図形のピクセルは、対応する描画先 Canvas のピクセルとカラー値を比べて、それぞれ明るい方のピクセルを残します。', +'描画先 Canvas の内容のピクセルのカラー値を、対応する新たな図形の反転したピクセルのカラー値でそれぞれ除算します。', +'描画先 Canvas の内容のピクセルの反転したカラー値を、対応する新たな図形のピクセルのカラー値でそれぞれ除算し、改めて各ピクセルのカラー値を反転させます。', +'multiply と screen を組み合わせます。描画先 Canvas のピクセルより対応する新たな図形のピクセルが、それぞれ暗いときは暗くし、明るければ明るくします (overlay と比較対象が逆)。', +'hard-light の効果を柔らかくしたカラー合成になります。純粋な黒と白は、真っ黒や真っ白にはなりません。', +'新たな図形のピクセルと対応する描画先 Canvas のピクセルとカラー値の差の絶対値をそれぞれのピクセルに定めます。', +'difference よりもコントラストを弱めたカラー合成になります(いわゆる「除外」)。', +'描画先 Canvas の内容のピクセルの輝度と彩度は保ち、対応する新たな図形のピクセルの色相をそれぞれ与えます。', +'描画先 Canvas の内容のピクセルの輝度と色相は保ち、対応する新たな図形のピクセルの彩度をそれぞれ与えます。', +'描画先 Canvas の内容のピクセルの輝度は保ち、対応する新たな図形のピクセルの色相と彩度をそれぞれ与えます。', +'描画先 Canvas の内容のピクセルの色相と彩度は保ち、対応する新たな図形のピクセルの輝度をそれぞれ与えます。' + ].reverse(); +var width = 320; +var height = 340; +</pre> + +<h3 id="Main_program">Main program</h3> + +<p>When the page loads, this code runs to set up and run the example:</p> + +<pre class="brush: js">window.onload = function() { + // lum in sRGB + var lum = { + r: 0.33, + g: 0.33, + b: 0.33 + }; + // resize canvas + canvas1.width = width; + canvas1.height = height; + canvas2.width = width; + canvas2.height = height; + lightMix() + colorSphere(); + runComposite(); + return; +}; +</pre> + +<p>And this code, <code>runComposite()</code>, handles the bulk of the work, relying on a number of utility functions to do the hard parts.</p> + +<pre class="brush: js">function runComposite() { + var dl = document.createElement("dl"); + document.body.appendChild(dl); + while(gco.length) { + var pop = gco.pop(); + var dt = document.createElement("dt"); + dt.textContent = pop; + dl.appendChild(dt); + var dd = document.createElement("dd"); + var p = document.createElement("p"); + p.textContent = gcoText.pop(); + dd.appendChild(p); + var canvas = document.createElement("canvas"); + canvas.style.background = "url("+op_8x8.data+")"; + canvas.style.border = "1px solid #000"; + canvas.style.margin = "10px"; + canvas.width = width/2; + canvas.height = height/2; + var ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, width, height) + ctx.save(); + ctx.drawImage(canvas1, 0, 0, width/2, height/2); + ctx.globalCompositeOperation = pop; + ctx.drawImage(canvas2, 0, 0, width/2, height/2); + ctx.globalCompositeOperation = "source-over"; + ctx.fillStyle = "rgba(0,0,0,0.8)"; + ctx.fillRect(0, height/2 - 20, width/2, 20); + ctx.fillStyle = "#FFF"; + ctx.font = "14px arial"; + ctx.fillText(pop, 5, height/2 - 5); + ctx.restore(); + dd.appendChild(canvas); + dl.appendChild(dd); + } +}; +</pre> + +<h3 id="Utility_functions">Utility functions</h3> + +<p>The program relies on a number of utility functions.</p> + +<pre class="brush: js">var lightMix = function() { + var ctx = canvas2.getContext("2d"); + ctx.save(); + ctx.globalCompositeOperation = "lighter"; + ctx.beginPath(); + ctx.fillStyle = "rgba(255,0,0,1)"; + ctx.arc(100, 200, 100, Math.PI*2, 0, false); + ctx.fill() + ctx.beginPath(); + ctx.fillStyle = "rgba(0,0,255,1)"; + ctx.arc(220, 200, 100, Math.PI*2, 0, false); + ctx.fill() + ctx.beginPath(); + ctx.fillStyle = "rgba(0,255,0,1)"; + ctx.arc(160, 100, 100, Math.PI*2, 0, false); + ctx.fill(); + ctx.restore(); + ctx.beginPath(); + ctx.fillStyle = "#f00"; + ctx.fillRect(0,0,30,30) + ctx.fill(); +}; +</pre> + +<pre class="brush: js">var colorSphere = function(element) { + var ctx = canvas1.getContext("2d"); + var width = 360; + var halfWidth = width / 2; + var rotate = (1 / 360) * Math.PI * 2; // per degree + var offset = 0; // scrollbar offset + var oleft = -20; + var otop = -20; + for (var n = 0; n <= 359; n ++) { + var gradient = ctx.createLinearGradient(oleft + halfWidth, otop, oleft + halfWidth, otop + halfWidth); + var color = Color.HSV_RGB({ H: (n + 300) % 360, S: 100, V: 100 }); + gradient.addColorStop(0, "rgba(0,0,0,0)"); + gradient.addColorStop(0.7, "rgba("+color.R+","+color.G+","+color.B+",1)"); + gradient.addColorStop(1, "rgba(255,255,255,1)"); + ctx.beginPath(); + ctx.moveTo(oleft + halfWidth, otop); + ctx.lineTo(oleft + halfWidth, otop + halfWidth); + ctx.lineTo(oleft + halfWidth + 6, otop); + ctx.fillStyle = gradient; + ctx.fill(); + ctx.translate(oleft + halfWidth, otop + halfWidth); + ctx.rotate(rotate); + ctx.translate(-(oleft + halfWidth), -(otop + halfWidth)); + } + ctx.beginPath(); + ctx.fillStyle = "#00f"; + ctx.fillRect(15,15,30,30) + ctx.fill(); + return ctx.canvas; +}; +</pre> + +<pre class="brush: js">// HSV (1978) = H: Hue / S: Saturation / V: Value +Color = {}; +Color.HSV_RGB = function (o) { + var H = o.H / 360, + S = o.S / 100, + V = o.V / 100, + R, G, B; + var A, B, C, D; + if (S == 0) { + R = G = B = Math.round(V * 255); + } else { + if (H >= 1) H = 0; + H = 6 * H; + D = H - Math.floor(H); + A = Math.round(255 * V * (1 - S)); + B = Math.round(255 * V * (1 - (S * D))); + C = Math.round(255 * V * (1 - (S * (1 - D)))); + V = Math.round(255 * V); + switch (Math.floor(H)) { + case 0: + R = V; + G = C; + B = A; + break; + case 1: + R = B; + G = V; + B = A; + break; + case 2: + R = A; + G = V; + B = C; + break; + case 3: + R = A; + G = B; + B = V; + break; + case 4: + R = C; + G = A; + B = V; + break; + case 5: + R = V; + G = A; + B = B; + break; + } + } + return { + R: R, + G: G, + B: B + }; +}; + +var createInterlace = function (size, color1, color2) { + var proto = document.createElement("canvas").getContext("2d"); + proto.canvas.width = size * 2; + proto.canvas.height = size * 2; + proto.fillStyle = color1; // top-left + proto.fillRect(0, 0, size, size); + proto.fillStyle = color2; // top-right + proto.fillRect(size, 0, size, size); + proto.fillStyle = color2; // bottom-left + proto.fillRect(0, size, size, size); + proto.fillStyle = color1; // bottom-right + proto.fillRect(size, size, size, size); + var pattern = proto.createPattern(proto.canvas, "repeat"); + pattern.data = proto.canvas.toDataURL(); + return pattern; +}; + +var op_8x8 = createInterlace(8, "#FFF", "#eee");</pre> diff --git a/files/ja/web/api/canvas_api/tutorial/compositing/index.html b/files/ja/web/api/canvas_api/tutorial/compositing/index.html new file mode 100644 index 0000000000..723509fa9c --- /dev/null +++ b/files/ja/web/api/canvas_api/tutorial/compositing/index.html @@ -0,0 +1,113 @@ +--- +title: 合成とクリッピング +slug: Web/API/Canvas_API/Tutorial/Compositing +tags: + - Canvas + - Graphics + - HTML + - HTML5 + - Intermediate + - Tutorial +translation_of: Web/API/Canvas_API/Tutorial/Compositing +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Transformations", "Web/API/Canvas_API/Tutorial/Basic_animations")}}</div> + +<div class="summary"> +<p><a href="/ja/docs/Web/API/Canvas_API/Tutorial/Transformations">これまでの例</a>はすべて、常にほかの図形より手前に図形が描かれました。これはほとんどの状況において十分以上ですが、合成した図形を構築する順序を制限します。しかし、<code>globalCompositeOperation</code> プロパティを設定すると、この動作を変更できます。さらに <code>clip</code> プロパティで、図形の不要な部分を隠すことができます。</p> +</div> + +<h2 id="globalCompositeOperation" name="globalCompositeOperation"><code>globalCompositeOperation</code></h2> + +<p>新しい図形を既存の図形の後ろに描くだけでなく、特定の領域を覆う、一部分を canvas から消去する ({{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}} メソッドのように矩形に限定されません) などが可能です。</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.globalCompositeOperation", "globalCompositeOperation = type")}}</dt> + <dd>これは、新しい図形を描くときに適用する合成処理の種類を設定します。type は、12種類の合成処理から使用するものを特定する文字列です。</dd> +</dl> + +<p>以下の例のコードについては、<a href="/ja/docs/Web/API/Canvas_API/Tutorial/Compositing/Example">合成のサンプル</a>をご覧ください。</p> + +<p>{{EmbedLiveSample("Compositing_example", 750, 6750, "" ,"Web/API/Canvas_API/Tutorial/Compositing/Example")}}</p> + +<h2 id="Clipping_paths" name="Clipping_paths">クリッピングパス</h2> + +<p><img alt="" src="https://mdn.mozillademos.org/files/209/Canvas_clipping_path.png" style="float: right;">クリッピングパスは通常の canvas の図形に似ていますが、図形の不要な部分を隠すマスクとして作用します。これを右の画像で視覚化しました。赤い星型の図形は、クリッピングパスです。このパスの外側にあるものはすべて、canvas で描画されません。</p> + +<p>クリッピングパスと先ほどの <code>globalCompositeOperation</code> プロパティを比較すると、おおむね同じ効果をもたらす合成モードとして <code>source-in</code> と <code>source-atop</code> の 2 つがあることがわかります。これら 2 つとのもっとも重要な違いは、クリッピングパスは実際に canvas に描かれるものではないことと、クリッピングパスは新しい図形による影響を受けないことです。これは制限された領域に複数の図形を描くという、クリッピングパスの目標を表しています。</p> + +<p><a href="/ja/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes" title="Web/Guide/HTML/HTML/Canvas/Tutorial/Drawing_shapes#Drawing_paths">図形を描く</a> の章では <code>stroke()</code> および <code>fill()</code> メソッドのみ言及しましたが、パスを扱う第 3 のメソッドとして <code>clip()</code> があります。</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.clip", "clip()")}}</dt> + <dd>現在構築しているパスを、現在のクリッピングパスに変換します。</dd> +</dl> + +<p><code>closePath()</code> の代わりに <code>clip()</code> を使用して、パスの輪郭を描いたり塗りつぶすのではなく、パスを閉じてクリッピングパスに変換します。</p> + +<p>デフォルトで {{HTMLElement("canvas")}} 要素には、canvas 自体とまったく同じサイズのクリッピングパスが存在します。言い換えると、クリッピングは行われません。</p> + +<h3 id="A_clip_example" name="A_clip_example"><code>clip</code> の例</h3> + +<p>この例では、ランダムな星の集団の描画先を特定の領域に制限するために、円形のクリッピングパスを使用しています。</p> + +<pre class="brush: js;highlight[9]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + ctx.fillRect(0,0,150,150); + ctx.translate(75,75); + + // 円形のクリッピングパスを作成 + ctx.beginPath(); + ctx.arc(0,0,60,0,Math.PI*2,true); + ctx.clip(); + + // 背景を描く + var lingrad = ctx.createLinearGradient(0,-75,0,75); + lingrad.addColorStop(0, '#232256'); + lingrad.addColorStop(1, '#143778'); + + ctx.fillStyle = lingrad; + ctx.fillRect(-75,-75,150,150); + + // 星を描く + for (var j=1;j<50;j++){ + ctx.save(); + ctx.fillStyle = '#fff'; + ctx.translate(75-Math.floor(Math.random()*150), + 75-Math.floor(Math.random()*150)); + drawStar(ctx,Math.floor(Math.random()*4)+2); + ctx.restore(); + } + +} + +function drawStar(ctx,r){ + ctx.save(); + ctx.beginPath(); + ctx.moveTo(r,0); + for (var i=0;i<9;i++){ + ctx.rotate(Math.PI/5); + if(i%2 === 0) { + ctx.lineTo((r/0.525731)*0.200811,0); + } else { + ctx.lineTo(r,0); + } + } + ctx.closePath(); + ctx.fill(); + ctx.restore(); +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>コードの始めの数行で、背景として canvas と同サイズの黒い背景を描いて、原点を中央に移動します。次に、円弧を描いて <code>clip()</code> を呼び出すことで、円形のクリッピングパスを作成します。クリッピングパスは、canvas の状態として保存されるもののひとつでもあります。元のクリッピングパスを維持したい場合は、新しいクリッピングパスを作成する前に保存した canvas の状態があるとよいでしょう。</p> + +<p>クリッピングパスを作成した後に描いたものはすべて、パスの内部にあるものだけが見える状態になります。これは、次に描いている線形グラデーションで明らかです。この後に独自の <code>drawStar()</code> 関数を使用して、位置や大きさがランダムな星を 50 個描きます。星もまた、クリッピングパスの内部で定義されたものしか見えません。</p> + +<p>{{EmbedLiveSample("A_clip_example", "180", "180", "https://mdn.mozillademos.org/files/208/Canvas_clip.png")}}</p> + +<div>{{PreviousNext("Web/API/Canvas_API/Tutorial/Transformations", "Web/API/Canvas_API/Tutorial/Basic_animations")}}</div> |