aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/api/canvas_api/tutorial/compositing/index.html
blob: 1cdf1d3f1518be0a12fc2bd724bff61663e4619d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
---
title: 合成效果
slug: Web/API/Canvas_API/Tutorial/Compositing
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>

<p>在前述的範例中,新繪製的圖形總會覆蓋在之前的圖形上,對大多數情況來說這相當正常,不過它也限制了圖形繪製的順序。其實我們可以透過 globalCompositeOperation 屬性來改變這項預設行為。</p>

<h2 id="globalCompositeOperation" name="globalCompositeOperation"><code>globalCompositeOperation</code></h2>

<p>利用 globalCompositeOperation,我們可以將新圖形繪製在舊圖形之下、遮蓋部分區域、清除畫布部分區域 (不同於 clearRect() 函式只能清除矩形區域)。</p>

<dl>
 <dt><code>globalCompositeOperation = <em>type</em></code></dt>
 <dt>type 字串可指定為以下 12 種合成設定之一,每一種合成設定均將套用到新繪製的圖形上。</dt>
</dl>

<div class="note">
<p><strong>Note:</strong> 下列圖例的藍色矩形是舊圖形,紅色圓形是新圖形。</p>
</div>

<table style="width: 100%;">
 <tbody>
  <tr>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>source-over</strong> 預設值。將新圖形畫在舊圖形之上。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_srcovr.png" class="internal" src="https://mdn.mozillademos.org/files/220/Canvas_composite_srcovr.png"></p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>destination-over</strong><br>
     將新圖形畫在舊圖形之下。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_destovr.png" class="internal" src="https://mdn.mozillademos.org/files/215/Canvas_composite_destovr.png"></p>
   </td>
  </tr>
  <tr>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>source-in</strong><br>
     只保留新、舊圖形重疊的新圖形區域,其餘皆變為透明。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_srcin.png" class="internal" src="https://mdn.mozillademos.org/files/218/Canvas_composite_srcin.png"></p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>destination-in</strong><br>
     只保留新、舊圖形重疊的舊圖形區域,其餘皆變為透明。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_destin.png" class="internal" src="https://mdn.mozillademos.org/files/213/Canvas_composite_destin.png"></p>
   </td>
  </tr>
  <tr>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>source-out</strong><br>
     只保留新、舊圖形非重疊的新圖形區域,其餘皆變為透明。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_srcout.png" class="internal" src="https://mdn.mozillademos.org/files/219/Canvas_composite_srcout.png"></p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>destination-out</strong><br>
     只保留新、舊圖形非重疊的舊圖形區域,其餘皆變為透明。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_destout.png" class="internal" src="https://mdn.mozillademos.org/files/214/Canvas_composite_destout.png"></p>
   </td>
  </tr>
  <tr>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>source-atop</strong><br>
     新圖形只繪製在新、舊圖形重疊的新圖形區域,然後蓋在舊圖形之上。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_srcatop.png" class="internal" src="https://mdn.mozillademos.org/files/217/Canvas_composite_srcatop.png"></p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>destination-atop</strong><br>
     舊圖形只保留在新、舊圖形重疊的舊圖形區域,然後蓋在新圖形之上。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_destatop.png" class="internal" src="https://mdn.mozillademos.org/files/212/Canvas_composite_destatop.png"></p>
   </td>
  </tr>
  <tr>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>lighter</strong><br>
     新舊圖形重疊區域的顏色,由新、舊圖形的顏色碼相加而得。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_lighten.png" class="internal" src="https://mdn.mozillademos.org/files/216/Canvas_composite_lighten.png"></p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>darker</strong> {{obsolete_inline}}</p>

    <p>新舊圖形重疊區域的顏色,由新、舊圖形的顏色碼相減而得。此屬性值已經從畫布規格中移除了,不再支援。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_darken.png" class="internal" src="https://mdn.mozillademos.org/files/211/Canvas_composite_darken.png"></p>
   </td>
  </tr>
  <tr>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>xor</strong><br>
     新舊圖形重疊區域設為透明。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_xor.png" class="internal" src="https://mdn.mozillademos.org/files/221/Canvas_composite_xor.png"></p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><strong>copy</strong><br>
     移除其他圖形,只保留新圖形。</p>
   </td>
   <td style="padding: 5px; vertical-align: top;">
    <p><img alt="Image:Canvas_composite_copy.png" class="internal" src="https://mdn.mozillademos.org/files/210/Canvas_composite_copy.png"></p>
   </td>
  </tr>
 </tbody>
</table>

<p>這裡有這些構圖組合的<a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Compositing/Example" title="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Compositing/Example">實際範例</a><a href="https://mdn.mozillademos.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Compositing/Example$samples/Compositing_example" title="https://mdn.mozillademos.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Compositing/Example$samples/Compositing_example">輸出結果</a>在此。</p>

<p>See <a href="/zh-TW/docs/Web/API/Canvas_API/Tutorial/Compositing/Example">compositing examples</a> for the code of the following examples.</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="" class="internal" src="canvas_clipping_path.png" style="float: right;">裁剪路徑就像是一般畫布圖形繪圖,但就如同遮罩一樣,會蓋掉不需要的部分,如右圖所示。紅邊星星是我們的裁剪路徑,在路徑區域以外部分都不會出現在畫布上。</p>

<p>和上述 globalCompositeOperation 相比,可以發現 source-in 和 source-atop 這兩種構圖組合所達到的效果,和裁剪路徑類似,而其中最大差異在於裁剪路徑不需加入新圖形,消失的部分也不會出現在畫布上,所以,如果想要限定繪圖區域,裁剪路徑會是更理想的作法。</p>

<p><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes#Drawing_paths" title="Web/Guide/HTML/Canvas_tutorial/Drawing_shapes#Drawing_paths">繪畫圖形</a>一章中,我們只提到 stroke() 和 fill() 函式,但其實還有第三個函式,那就是 clip() 函式。</p>

<dl>
 <dt><code>clip()</code></dt>
 <dd>轉換目前繪圖路徑為裁剪路徑。</dd>
</dl>

<p>呼叫 clip() 除了會替代 closePath() 來關閉路徑之外,還會轉換目前填滿或勾勒繪圖路徑為裁剪路徑。</p>

<p> {{HTMLElement("canvas")}} 畫布預設有一個等同於本身大小的裁剪路徑,等同於無裁剪效果。</p>

<h3 id="A_clip_example" name="A_clip_example"><code>clip</code> 範例</h3>

<p>本範例使用了圓形的裁剪路徑,來限定畫星星時的繪圖區域。</p>

<pre class="brush: js">function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  ctx.fillRect(0,0,150,150);
  ctx.translate(75,75);

  // Create a circular clipping path
  ctx.beginPath();
  ctx.arc(0,0,60,0,Math.PI*2,true);
  ctx.clip();

  // draw background
  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);

  // draw stars
  for (var j=1;j&lt;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&lt;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">&lt;canvas id="canvas" width="150" height="150"&gt;&lt;/canvas&gt;</pre>

<pre class="brush: js">draw();</pre>
</div>

<p>一開始我們先畫了一個黑色矩形作為畫布背景,然後移動畫布原點到中央,接著我們繪製弧線並呼叫 clip(),藉以建立圓形的裁剪路徑。畫布儲存狀態亦可儲存裁剪路徑。若要保留原本的裁剪路徑,則可於繪製新的裁剪路徑之前,先行儲存畫布狀態。</p>

<p>繪製裁剪路徑之後,所產生的所有圖形都只會出現在路徑以內,從後來繪製的漸層背景中可看出此特性。我們用自訂的 drawStar() 函數產生 50 個隨機散佈、大小不一的星星。這些星星同樣只會出現在裁剪路徑的範圍之內。</p>

<p>{{EmbedLiveSample("A_clip_example", "180", "180", "canvas_clip.png")}}</p>

<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial/Transformations", "Web/Guide/HTML/Canvas_tutorial/Basic_animations")}}</p>