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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
---
title: Exemplo de Composição
slug: Web/API/Canvas_API/Tutorial/Compositing/Example
tags:
- Canvas
- Example
- HTML5
- Tutorial
translation_of: Web/API/Canvas_API/Tutorial/Compositing/Example
original_slug: Web/Guide/HTML/Canvas_tutorial/Compositing/Exemplo
---
<div>{{CanvasSidebar}}</div>
<p>Esse exemplo demonstra várias <a href="/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation">operações de composição</a>. A saída se parece assim:</p>
<p>{{ EmbedLiveSample('Exemplo_de_composição', '', '7240px', '', 'Web/Guide/HTML/Canvas_tutorial/Compositing/Exemplo') }}</p>
<h2 id="Exemplo_de_composição">Exemplo de composição</h2>
<p><span id="result_box" lang="pt"><span>Este código configura os valores globais usados pelo restante do programa.</span></span></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 = [
'<span id="result_box" lang="pt"><span>Essa é a configuração padrão e desenha novas formas sobre o conteúdo da tela (canvas) existente</span></span>.',
'<span id="result_box" lang="pt"><span class="alt-edited">A nova forma é desenhada apenas onde a nova forma e a tela (canvas) de destino se sobrepõem.</span> <span class="alt-edited">Todo o resto é transparente.</span></span> ',
'A nova forma é desenhada onde ela não sobrepõe o conteúdo da tela (canvas) existente.',
'A nova forma é somente desenahda onde ela sobrepõe o conteúdo da tela (canvas) existente.',
'Novas formas são desenhadas por trás do conteúdo da tela (canvas) existente.',
'O conteúdo da tela (canvas) existente é mantido onde ambos, a nova forma e o conteúdo da tela (canvas) existente, se sobrepõe. Todo o resto é transparente.',
'O conteúdo existente é mantido onde ele não sobrepõe a nova forma.',
'A tela (canvas) existente só é mantida onde ela sobrepõe a nova forma. A nova forma é desenahda por trás do conteúdo canvas.',
'Onde ambas formas se sebrepõem a cor é determinada adicionando seus respectivos valores de cores.',
'Somente a nova forma é mostrada.',
'Formas são feitas transparentes onde ambos se sobrepõem e todo o resto é desenhado normalmente.',
'<span id="result_box" lang="pt"><span>Os pixels da camada superior são multiplicados pelo pixel correspondente da camada inferior.</span> <span>Uma imagem mais escura é o resultado.</span></span> ',
'<span id="result_box" lang="pt"><span>Os pixels são invertidos, multiplicados e invertidos novamente.</span> <span>Uma imagem mais clara é o resultado (oposto de multiplicar)</span></span>',
'<span id="result_box" lang="pt"><span>Uma combinação de multiplicação e tela.</span> <span>As partes escuras na camada base tornam-se mais escuras e as partes claras tornam-se mais claras.</span></span>',
'Mantêm os pixels mais escuro de ambas camadas.',
'Mantêm os pixels mais claro de ambas camadas.',
'<span id="result_box" lang="pt"><span>Divide a camada inferior pela camada superior invertida.</span></span>',
'<span id="result_box" lang="pt"><span>Divide a camada inferior invertida pela camada superior e, em seguida, inverte o resultado.</span></span>',
'<span id="result_box" lang="pt"><span>Uma combinação de multiplicação e tela como sobreposição, mas com a camada superior e inferior trocada.</span></span>',
'<span id="result_box" lang="pt"><span>Uma versão mais suave da luz.</span> <span>Preto ou branco puro não resulta em preto ou branco puro.</span></span>',
'<span id="result_box" lang="pt"><span>Subtrai a camada inferior da camada superior ou vice-versa para obter sempre um valor positivo.</span></span>',
'<span class="short_text" id="result_box" lang="pt"><span>Como diferença, mas com menor contraste.</span></span>',
'<span id="result_box" lang="pt"><span>Preserva o luma e o croma da camada inferior, enquanto adota a tonalidade da camada superior.</span></span>',
'<span id="result_box" lang="pt"><span>Preserva o luma e a tonalidade da camada inferior, enquanto adota o croma da camada superior.</span></span>',
'<span id="result_box" lang="pt"><span>Preserva a luma da camada inferior, enquanto adota a tonalidade e o croma da camada superior.</span></span>',
'<span id="result_box" lang="pt"><span>Preserva a tonalidade e o croma da camada inferior, enquanto adota a luma da camada superior.</span></span>'
].reverse();
var width = 320;
var height = 340;</pre>
<h3 id="Programa_principal">Programa principal</h3>
<p><span id="result_box" lang="pt"><span>Quando a página é carregada, esse código é executado para configurar e executar o exemplo:</span></span></p>
<pre class="brush: js">window.onload = function() {
// lum em sRGB
var lum = {
r: 0.33,
g: 0.33,
b: 0.33
};
// redimensiona canvas
canvas1.width = width;
canvas1.height = height;
canvas2.width = width;
canvas2.height = height;
lightMix();
colorSphere();
runComposite();
return;
};
</pre>
<p><span id="result_box" lang="pt"><span>E esse código, <code>runComposite ()</code>, manipula a maior parte do trabalho, contando com várias funções utilitárias para fazer as partes difíceis.</span></span></p>
<pre class="brush: js">function createCanvas() {
var canvas = document.createElement("canvas");
canvas.style.background = "url("+op_8x8.data+")";
canvas.style.border = "1px solid #000";
canvas.style.margin = "5px";
canvas.width = width/2;
canvas.height = height/2;
return canvas;
}
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 canvasToDrawOn = createCanvas();
var canvasToDrawFrom = createCanvas();
var canvasToDrawResult = createCanvas();
var ctx = canvasToDrawResult.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();
var ctx = canvasToDrawOn.getContext('2d');
ctx.clearRect(0, 0, width, height)
ctx.save();
ctx.drawImage(canvas1, 0, 0, width/2, height/2);
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('Conteúdo existente', 5, height/2 - 5);
ctx.restore();
var ctx = canvasToDrawFrom.getContext('2d');
ctx.clearRect(0, 0, width, height)
ctx.save();
ctx.drawImage(canvas2, 0, 0, width/2, height/2);
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('Novo conteúdo', 5, height/2 - 5);
ctx.restore();
dd.appendChild(canvasToDrawOn);
dd.appendChild(canvasToDrawFrom);
dd.appendChild(canvasToDrawResult);
dl.appendChild(dd);
}
};
</pre>
<h3 id="Funções_Utilitárias">Funções Utilitárias</h3>
<p><span id="result_box" lang="pt"><span>O programa depende de várias funções utilitárias.</span></span></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 (tom)
// S: Saturation (Saturação)
// V: Value (Valor)
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>
|