diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
commit | 1109132f09d75da9a28b649c7677bb6ce07c40c0 (patch) | |
tree | 0dd8b084480983cf9f9680e8aedb92782a921b13 /files/es/web/api/canvas_api | |
parent | 4b1a9203c547c019fc5398082ae19a3f3d4c3efe (diff) | |
download | translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.gz translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.bz2 translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.zip |
initial commit
Diffstat (limited to 'files/es/web/api/canvas_api')
-rw-r--r-- | files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html | 295 | ||||
-rw-r--r-- | files/es/web/api/canvas_api/tutorial/compositing/index.html | 117 |
2 files changed, 412 insertions, 0 deletions
diff --git a/files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html b/files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html new file mode 100644 index 0000000000..b85b83238c --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html @@ -0,0 +1,295 @@ +--- +title: Ejemplo de composición +slug: Web/API/Canvas_API/Tutorial/Compositing/Ejemplo +tags: + - Canvas + - Ejemplo + - HTML + - HTML5 + - Tutorial + - graficos +translation_of: Web/API/Canvas_API/Tutorial/Compositing/Example +--- +<div>{{CanvasSidebar}}</div> + +<p>Este programa de ejemplo muestra una cantidad de <a href="/es/docs/Web/API/CanvasRenderingContext2D.globalCompositeOperation">operaciones de composición</a>. La salida se ve así:</p> + +<p>{{EmbedLiveSample("Ejemplo_de_composición", "100%", 7250)}}</p> + +<h2 id="Ejemplo_de_composición">Ejemplo de composición</h2> + +<p>Este código establece los valores globales utilizados por el resto del programa.</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 = [ +'Esta es la configuración predeterminada y dibuja nuevas formas sobre el contenido del canvas existente.', +'La nueva forma se dibuja solo donde la nueva forma y el canvas de destino se superponen. Todo lo demás se hace transparente.', +'La nueva forma se dibuja donde no se superpone al contenido del canvas existente.', +'La nueva forma solo se dibuja donde se solapa con el contenido del canvas existente.', +'Se dibujan nuevas formas detrás del contenido del canvas existente', +'El contenido del canvas existente se conserva donde la nueva forma y el contenido del canvas existente se superponen. Todo lo demás se hace transparente.', +'El contenido existente se mantiene donde no se superpone a la nueva forma.', +'El canvas existente solo se conserva donde se solapa con la nueva forma. La nueva forma se dibuja detrás del contenido del canvas.', +'Donde ambas formas se superponen, el color se determina agregando valores de color.', +'Solo se muestra la nueva forma.', +'Las formas se hacen transparentes donde ambas se superponen y se dibujan de manera normal en cualquier otro lugar.', +'Los píxeles de la capa superior se multiplican con el píxel correspondiente de la capa inferior. El resultado es una imagen más oscura. ', +'Los píxeles están invertidos, multiplicados e invertidos nuevamente. Una imagen más clara es el resultado (opuesto a multiplicar).', +'Una combinación de multiplicar y pantalla. Las partes oscuras en la capa base se oscurecen y las partes claras se vuelven más claras.', +'Conserva los píxeles más oscuros de ambas capas.', +'Conserva los píxeles más claros de ambas capas.', +'Divide la capa inferior por la capa superior invertida.', +'Divide la capa inferior invertida por la capa superior, y luego invierte el resultado.', +'Una combinación de multiplicar y pantalla como superposición, pero con la parte superior y la capa inferior intercambiado.', +'Una versión más suave de la luz dura. Negro puro o blanco no da como resultado negro o blanco puro.', +'Resta la capa inferior de la capa superior o viceversa para obtener siempre un valor positivo.', +'Al igual que la diferencia, pero con menor contraste.', +'Conserva la luma y el croma de la capa inferior, mientras adopta el tono de la capa superior.', +'Conserva la luma y el tono de la capa inferior, mientras adopta el croma de la capa superior.', +'Conserva la luma de la capa inferior, mientras adopta el matiz y el croma de la capa superior.', +'Conserva el tono y el croma de la capa inferior, mientras adopta la luma de la capa superior.' + ].reverse(); +var width = 320; +var height = 340; +</pre> + +<h3 id="Programa_principal">Programa principal</h3> + +<p>Cuando se carga la página, este código se ejecuta para configurar y ejecutar el ejemplo:</p> + +<pre class="brush: js">window.onload = function() { + // lum en sRGB + var lum = { + r: 0.33, + g: 0.33, + b: 0.33 + }; + // redimensionar canvas + canvas1.width = width; + canvas1.height = height; + canvas2.width = width; + canvas2.height = height; + lightMix() + colorSphere(); + runComposite(); + return; +}; +</pre> + +<p>Y este código, <code>runComposite()</code>, maneja la mayor parte del trabajo, dependiendo de una serie de funciones de utilidad para hacer las partes difíciles.</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('existing content', 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('new content', 5, height/2 - 5); + ctx.restore(); + + dd.appendChild(canvasToDrawOn); + dd.appendChild(canvasToDrawFrom); + dd.appendChild(canvasToDrawResult); + + dl.appendChild(dd); + } +}; +</pre> + +<h3 id="Funciones_de_utilidad">Funciones de utilidad</h3> + +<p>El programa se basa en una serie de funciones de utilidad.</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; // por grado + 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/es/web/api/canvas_api/tutorial/compositing/index.html b/files/es/web/api/canvas_api/tutorial/compositing/index.html new file mode 100644 index 0000000000..1d45712fd4 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/compositing/index.html @@ -0,0 +1,117 @@ +--- +title: Compositing and clipping +slug: Web/API/Canvas_API/Tutorial/Compositing +tags: + - Canvas + - Graphics + - HTML + - HTML5 + - Intermediate + - Lienzo + - NeedsTranslation + - Recorte + - TopicStub + - 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>En todos nuestros <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations">ejemplos a</a>nteriores, las formas siempre fueron dibujadas una encima de la anterior. Estos es más que adecuado para la mayoría de las situaciones pero se limita al orden compuesto de las figuras. Podemos, sin embargo, cambiar este comportamiento estableciendo el valor de la propiedad <code>globalCompositeOperation</code>. Además, la proeidad <code>clip</code> nos permite ocultar partes de figuras que no queremos mostrar.</p> +</div> + +<h2 id="globalCompositeOperation" name="globalCompositeOperation"><code>globalCompositeOperation</code></h2> + +<p>No solo podemos dibujar formas nuevas detrás de las ya existentes sino que las podemos utilizar para enmascarar ciertas áreas, limpiar secciones del lienzo (canvas no se limita a utilizar rectángulos como en el método {{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}}) y algunas cosas más.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.globalCompositeOperation", "globalCompositeOperation = type")}}</dt> + <dd>Esto establece el tipo de operación compuesta a aplicar cuando se dibujan nuevas figuras, en donde tipo (type) es una cadena de caracteres que identifica cual de las doce operaciones compuestas se utilizará.</dd> +</dl> + +<p>Vea <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing/Example">ejemplos de composición</a> para el código de los siguientes ejemplos.</p> + +<p>{{EmbedLiveSample("Compositing_example", 750, 6750, "" ,"Web/API/Canvas_API/Tutorial/Compositing/Example")}}</p> + +<h2 id="Clipping_paths" name="Clipping_paths">Trazado de Recorte</h2> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/209/Canvas_clipping_path.png" style="float: right;">Un trazado de recoirte es como una figura normal en el lienzo pero actúa como una máscara para ocultar las partes de la misma que no se quieren mostrar. Este efecto se muestra en la figura de la derecha. La estrella roja es nuestro trazado de recorte. Todo lo que cae fuera de este trazado no se dibujará en el lienzo.</p> + +<p>Si comparamos el trazado de recorte con la propiedad <code>globalCompositeOperation</code> que hemos visto antes, vemos dos modos compuestos que logran mas o menos los mismos efectos en <code>source-in</code> y <code>source-atop</code>. Las diferencias mas importantes entre éstos dos son que el trazado de recorte no dibujan nunca en el lienzo y que nunca se afecta por agregar nuevas figuras. Esto vuelve al trazado de recorte ideal para dibujar múltiples figuras en un área delimitada.</p> + +<p>En el capítulo acerca de <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes" title="Web/Guide/HTML/Canvas_tutorial/Drawing_shapes#Drawing_paths">dibujo de figuras</a> solo menciono a los métodos <code>stroke()</code> y <code>fill()</code> pero existe un tercer método que se usa para trazados llamado <code>clip()</code>.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.clip", "clip()")}}</dt> + <dd>Convierte al trazado en ejecución a un trazado de recorte.</dd> +</dl> + +<p>Se utiliza <code>clip()</code> en lugar de <code>closePath()</code> para cerrar el trazado y volverlo uno de recorte, en vez de marcar (stroke) o rellenar el trazado.</p> + +<p>Por edfecto el elemento {{HTMLElement("canvas")}} tiene un trazado de recorte que es de extacamente el mismo tamaño del propio lienzo. En otras palabras, la máscara de recorte (clipping) no se da.</p> + +<h3 id="A_clip_example" name="A_clip_example">Un ejemplo de <code>clip</code></h3> + +<p>En este ejemplo, utilizamos un trazado de recorte de forma circular para restringir el dibujo de un conjunto de estrellas aleatorias dentro de una región particular del lienzo.</p> + +<pre class="brush: js;highlight[9] notranslate">function dibuja() { + var ctx = document.getElementById('lienzo').getContext('2d'); + ctx.fillRect(0, 0, 150, 150); + ctx.translate(75, 75); + + // crear un trazado de corte de forma circular + ctx.beginPath(); + ctx.arc(0, 0, 60, 0, Math.PI * 2, true); + ctx.clip(); + + // pinta el fondo + 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); + + // dibuja las estrellas + 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)); + dibulaEstrella(ctx, Math.floor(Math.random() * 4) + 2); + ctx.restore(); + } + +} + +function dibujaEstrella(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 notranslate"><canvas id="lienzo" width="150" height="150"></canvas></pre> + +<pre class="brush: js notranslate">dibuja();</pre> +</div> + +<p>En las primeras líneas de código, dibujamos un rectángulo negro del tamaño del lienzo como telón de fondo, luego trasladamos el origen del mismo al centro. A continuación, creamos un trazado de recorte de forma circular, a través de dibujar un arco y mediante la llamada a <code>clip()</code>. El recorte también es parte del estado guardado del lienzo. Si queremos mantener el recorte original, podríamos haber guardado el estado anterior del lienzo justo antes de que creamos el nuevo.</p> + +<p>Todo lo que se dibuja después de crear un recorte aparecerá dentro de su trazado. Se puede ver claramente esto en el dibujo de gradiente lineal que realizamos a continuación. Después se ubican estrellas en 50 posiciones alteatorias y escaladas utilizando la función <code>drawStar()</code>. Una vez más, las estrellas solo aparecen dentro del recorte trazado en el lienzo.</p> + +<p>{{EmbedLiveSample("A_clip_example", "180", "180", "https://mdn.mozillademos.org/files/208/Canvas_clip.png")}}</p> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Transformations", "Web/API/Canvas_API/Tutorial/Basic_animations")}}</p> |