diff options
author | Florian Merz <me@fiji-flo.de> | 2021-02-11 14:46:50 +0100 |
---|---|---|
committer | Florian Merz <me@fiji-flo.de> | 2021-02-11 14:46:50 +0100 |
commit | a55b575e8089ee6cab7c5c262a7e6db55d0e34d6 (patch) | |
tree | 5032e6779a402a863654c9d65965073f09ea4182 /files/es/web/api/canvas_api | |
parent | 8260a606c143e6b55a467edf017a56bdcd6cba7e (diff) | |
download | translated-content-a55b575e8089ee6cab7c5c262a7e6db55d0e34d6.tar.gz translated-content-a55b575e8089ee6cab7c5c262a7e6db55d0e34d6.tar.bz2 translated-content-a55b575e8089ee6cab7c5c262a7e6db55d0e34d6.zip |
unslug es: move
Diffstat (limited to 'files/es/web/api/canvas_api')
14 files changed, 3000 insertions, 0 deletions
diff --git a/files/es/web/api/canvas_api/a_basic_ray-caster/index.html b/files/es/web/api/canvas_api/a_basic_ray-caster/index.html new file mode 100644 index 0000000000..7917541554 --- /dev/null +++ b/files/es/web/api/canvas_api/a_basic_ray-caster/index.html @@ -0,0 +1,59 @@ +--- +title: A basic ray-caster +slug: Web/HTML/Canvas/A_basic_ray-caster +tags: + - Avanzado + - Canvas + - Ejemplo + - Espanol(2) + - Gráficos(2) + - HTML + - Necesita traducción + - Web +translation_of: Web/API/Canvas_API/A_basic_ray-caster +--- +<div>{{CanvasSidebar}}</div> + +<div class="summary"> +<p>Este artículo proporciona un interesante ejemplo de la vida real usando el elemento {{HTMLElement("canvas")}} para renderizar un sencillo entorno 3D usando una técnica de render llamada ray-casting.</p> +</div> + +<p>{{EmbedGHLiveSample("canvas-raycaster/index.html", 900, 300)}}</p> + +<p><strong><a href="http://mdn.github.io/canvas-raycaster/">Abrir en una nueva ventana</a></strong></p> + +<h2 id="Why.3F" name="Why.3F">¿Por qué?</h2> + +<p> </p> + +<p>Después de darme cuenta, para mi satisfacción, de que el ingenioso elemento <canvas> sobre el que había estado leyendo, no sólo iba a recibir soporte por parte de Firefox, sino que <strong>ya estaba</strong> soportado por la versión actual de Safari, así que tenía que ponerme manos a la obra y hacer un pequeño experimento.</p> + +<p>El <a href="https://developer.mozilla.org/en-US/docs/Canvas_tutorial">tutorial</a> y el <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">resumen</a> que encontré en la MDN son geniales, pero nadie había escrito nada (todavía) sobre animación, así que pensé que sería una buena oportunidad para portar un sencillo raycaster en el que había trabajado hacía tiempo y comprobar qué tipo de rendimiento podía esperar de un buffer de pixeles controlado por JavaScript.</p> + +<h2 id="How.3F" name="How.3F">¿Cómo?</h2> + +<p>La idea es sencilla, usar {{domxref("WindowTimers.setInterval","setInterval()")}} con un retraso arbitrario que se corresponde con la velocidad de fotogramas deseada. Por cada llamada al intervalo se ejecutará una función que volverá a pintar el elemento <canvas> en el que se muestra la vista actual del usuario. Sé que podría haber empezado con un ejemplo más simple, pero creo que el <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">tutorial</a> sobre <canvas> vale para eso, y quería ver si podía hacer esto.</p> + +<p>Continuemos, por cada actualización, el raycaster comprueba si has presionado alguna tecla, si no has presionado ninguna se mantendrán los cálculos para ahorrar tiempo de ejecución. Si se ha presionado alguna tecla, el <canvas> es borrado, el suelo y el cielo son pintados, la posición y la orientación de la cámara son actualizados, y los rayos son lanzados. Según van intersectando los rayos con las paredes se van pintando líneas verticales de pared del color de la pared con la que han colisionado, mezcladas con una versión más oscura del color en función de la distancia a la que se encuentra la pared. La altura de la línea vertical depende directamente de la distancia a la que el rayo es interesectado, dibujándose centrada con respecto la línea del horizonte.</p> + +<p>El código que he terminado usando es una amalgama regurgitada del código que aparece en los capítulos sobre raycasting del libro de André LaMothe <em>Tricks of the Game Programming Gurus</em> y una <a class="external" href="http://www.shinelife.co.uk/java-maze/">versión en java de un raycaster</a> que encontré online, a su vez pasado por el filtro de mi pulsión a renombrar todo para que tenga sentido para mí y todo el chapuceo necesario para que las cosas funcionen bien.</p> + +<h2 id="Results" name="Results">Resultados</h2> + +<p>El <canvas> en Safari 2.0.1 rindió sorprendentemente bien. Renderizando columnas de 8 pixeles de ancho, puedo correr una ventana de 320 x 240 a 24 FPS en mi Apple Mini. Firefox 1.5 Beta 1 es incluso más rápido; puedo correr una ventana de 320 x 240 a 24 FPS con columnas de 4 píxeles de ancho. No es exactamente un nuevo miembro de la familia de ID Software, pero es bastante decente teniendo en cuenta que es un entorno completamente interpretado, y que no me he tenido que preocupar de reservar memoria, ni modos de vídeo o escribir rutinas en ensamblador. Aún así el código intenta ser lo más eficiente posible, usando tablas de acceso rápido para valores precalculados, pero no soy ningún gurú de la optimización, así que seguramente haya varias cosas que se puedan escribir más rápido.</p> + +<p>Además, deja bastante que desear en términos de intentar convertir esto en un motor de juego - no hay texturas en las paredes, no hay sprites, no hay puertas, ni siquiera hay teletransportadores que te permitan ir a otro nivel. Pero tengo bastante confianza en que todas esas cosas se podrían añadir con el suficiente tiempo disponible. La API de canvas soporta copiado de píxeles de imágenes, así que tener texturas parece bastante factible. Dejaré esto para otro artículo, seguramente para otra persona. =)</p> + +<h2 id="The_RayCaster" name="The_RayCaster">El ray-caster</h2> + +<p>El gente tan maravillosa que hay aquí han copiado manualmente mis archivos así vosotros podéis echarle un <a href="http://mdn.github.io/canvas-raycaster/">vistazo</a>, y para vuestro disfrute he puesto los archivos individuales como listados de código (ver abajo).</p> + +<p>¡Así que aquí lo tenéis, arrancad Safari 1.3+ o Firefox 1.5+ o cualquier otro navegador que soporte el elemento <code><canvas></code> y a disfrutar!<br> + <br> + <small><a href="https://github.com/mdn/canvas-raycaster/blob/master/input.js">input.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/Level.js">Level.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/Player.js">Player.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/index.html">RayCaster.html</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/RayCaster.js">RayCaster.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/trace.css">trace.css</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/trace.js">trace.js</a> </small></p> + +<h2 id="See_also" name="See_also">Ver también</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Canvas_API/Tutorial">Tutorial de canvas</a></li> +</ul> diff --git a/files/es/web/api/canvas_api/index.html b/files/es/web/api/canvas_api/index.html new file mode 100644 index 0000000000..dfdde2bf63 --- /dev/null +++ b/files/es/web/api/canvas_api/index.html @@ -0,0 +1,170 @@ +--- +title: API Canvas +slug: Web/HTML/Canvas +tags: + - API + - Canvas + - JavaScript + - Referencia + - introducción +translation_of: Web/API/Canvas_API +--- +<div>{{CanvasSidebar}}</div> + +<p class="summary">Añadido en <a href="/es/docs/HTML/HTML5">HTML5</a>, el <strong>elemento HTML {{HTMLElement("canvas")}}</strong> se puede usar para dibujar gráficos mediante scripting en <a href="/es/docs/Web/JavaScript">JavaScript</a>. Por ejemplo, se puede usar para hacer gráficas, composiciones fotográficas, crear animaciones, o incluso procesado o renderizado de vídeo en tiempo real.</p> + +<p>Las aplicaciones de Mozilla soportan <code><canvas></code> desde Gecko 1.8 (es decir, <a href="/es/docs/Mozilla/Firefox/Releases/1.5">Firefox 1.5</a>). El elemento fue inicialmenmte presentado por Apple para el Dashboard de OS X y Safari. Internet Explorer soporta <code><canvas></code> desde la versión 9 en adelante; para versiones anteriores de IE, se puede añadir soporte para <code><canvas></code> a una página incluyendo un script del proyecto de Google <a href="https://github.com/arv/explorercanvas">Explorer Canvas</a>. Google Chrome y Opera 9 también soportan <code><canvas></code>.</p> + +<p>El elemento <code><canvas></code> también se usa en <a href="/es/docs/Web/WebGL">WebGL</a> para dibujar gráficos 3D con aceleración por hardware en páginas web.</p> + +<h2 id="Ejemplo">Ejemplo</h2> + +<p>Esto es un trozo de código que usa el método {{domxref("CanvasRenderingContext2D.fillRect()")}}.</p> + +<h3 id="HTML">HTML</h3> + +<pre class="brush: html"><canvas id="canvas"></canvas> +</pre> + +<h3 id="JavaScript">JavaScript</h3> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); + +ctx.fillStyle = 'green'; +ctx.fillRect(10, 10, 100, 100); +</pre> + +<p>Edita este código para ver tus cambios en tiempo real en este canvas:</p> + +<div class="hidden"> +<h6 id="Código_editable">Código editable</h6> + +<pre class="brush: html"><canvas id="canvas" width="400" height="200" class="playable-canvas"></canvas> +<div class="playable-buttons"> + <input id="edit" type="button" value="Edit" /> + <input id="reset" type="button" value="Reset" /> +</div> +<textarea id="code" class="playable-code"> +ctx.fillStyle = 'green'; +ctx.fillRect(10, 10, 100, 100);</textarea> +</pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext("2d"); +var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var edit = document.getElementById('edit'); +var code = textarea.value; + +function drawCanvas() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + drawCanvas(); +}); + +edit.addEventListener('click', function() { + textarea.focus(); +}) + +textarea.addEventListener('input', drawCanvas); +window.addEventListener('load', drawCanvas); +</pre> +</div> + +<p>{{ EmbedLiveSample('Código_editable', 700, 360) }}</p> + +<h2 id="Referencia">Referencia</h2> + +<div class="index"> +<ul> + <li>{{domxref("HTMLCanvasElement")}}</li> + <li>{{domxref("CanvasRenderingContext2D")}}</li> + <li>{{domxref("CanvasGradient")}}</li> + <li>{{domxref("CanvasImageSource")}}</li> + <li>{{domxref("CanvasPattern")}}</li> + <li>{{domxref("ImageBitmap")}}</li> + <li>{{domxref("ImageData")}}</li> + <li>{{domxref("RenderingContext")}}</li> + <li>{{domxref("TextMetrics")}}</li> + <li>{{domxref("OffscreenCanvas")}}{{experimental_inline}}</li> + <li>{{domxref("Path2D")}} {{experimental_inline}}{{domxref("ImageBitmapRenderingContext")}}{{experimental_inline}}</li> +</ul> +</div> + +<p>Las interfaces relacionadas con <code>WebGLRenderingContext</code> están en <a href="/es/docs/Web/WebGL" title="/en-US/docs/Web/WebGL">WebGL</a>.</p> + +<p>{{domxref("CanvasCaptureMediaStream")}} está relacionado..</p> + +<h2 id="Guías_y_tutoriales">Guías y tutoriales</h2> + +<dl> + <dt><a href="/es/docs/Web/API/Canvas_API/Tutorial">Tutorial Canvas</a></dt> + <dd>Tutorial exhaustivo que cubre tanto el uso básico de <code><canvas></code> como sus características avanzadas.</dd> + <dt><a href="/es/Add-ons/Code_snippets/Canvas">Fragmentos de código: Canvas</a></dt> + <dd>Algunos fragmentos de código orientados al desarrollador de extensiones usando <code><canvas></code>.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/A_basic_ray-caster">Demo: Un laberinto básico</a></dt> + <dd>Una demo de una animación de laberinto usando canvas.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas">Dibujar objetos DOM en un canvas</a></dt> + <dd>Cómo dibujar contenido DOM, como elementos HTML, en un canvas.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/Manipulating_video_using_canvas">Manipulación de vídeo usando canvas</a></dt> + <dd>Combinando {{HTMLElement("video")}} y {{HTMLElement("canvas")}} para manipular datos de vídeo en tiempo real.</dd> +</dl> + +<h2 id="Recursos">Recursos</h2> + +<h3 id="Genéricos">Genéricos</h3> + +<ul> + <li><a href="http://joshondesign.com/p/books/canvasdeepdive/title.html">Profundizando en HTML5 Canvas</a></li> + <li><a href="http://bucephalus.org/text/CanvasHandbook/CanvasHandbook.html">Manual de Canvas</a></li> +</ul> + +<h3 id="Librerías">Librerías</h3> + +<ul> + <li><a href="http://fabricjs.com">Fabric.js</a> es una librería open-source para canvas con capacidad de parsear SVG.</li> + <li><a href="https://github.com/ericdrowell/KineticJS">Kinetic.js</a> es una librería open-source de canvas enfocada en la interactividad para aplicaciones móviles y de escritorio.</li> + <li><a href="http://paperjs.org/">Paper.js</a> es un framework para gráficos vectoriales open source que funciona sobre Canvas HTML5.</li> + <li><a href="http://origamijs.com/docs/">Origami.js</a> es una librería ligera open-source para canvas.</li> + <li><a href="http://libcanvas.github.com/">libCanvas</a> es un framework ligero y potente para canvas.</li> + <li><a href="http://processingjs.org">Processing.js</a> es un port de PVL (Processing visualization language).</li> + <li><a href="https://playcanvas.com/">PlayCanvas</a> es un motor open source de juegos.</li> + <li><a href="http://www.pixijs.com/">Pixi.js</a> es un motor open source de juegos.</li> + <li><a href="http://www.liquidx.net/plotkit/">PlotKit</a> es una librería para hacer gráficas.</li> + <li><a class="link-https" href="https://github.com/jeremyckahn/rekapi">Rekapi</a> es una API para animación por frames para Canvas.</li> + <li><a href="http://senchalabs.github.com/philogl/">PhiloGL</a> es un framework WebGL para visualización de datos, programación creativa y desarrollo de juegos.</li> + <li><a href="http://thejit.org/">JavaScript InfoVis Toolkit</a> crea visualizaciones de datos 2D interactivas para Web.</li> + <li><a href="http://www.createjs.com/easeljs">EaselJS</a> es una librería open source/libre que facilita el uso de canvas para arte y juegos</li> + <li><a href="http://scrawl.rikweb.org.uk/">Scrawl-canvas</a> es otra librería open-source javascript para crear y manipular elementos canvas en 2D</li> + <li><a href="https://www.patrick-wied.at/static/heatmapjs/">heatmap.js</a> es una librería open-source para crear mapas (heatmaps)</li> +</ul> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado</th> + <th scope="col">Comentarios</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('HTML WHATWG', 'scripting.html#the-canvas-element', '<canvas>')}}</td> + <td>{{Spec2('HTML WHATWG')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="/es/docs/Web/WebGL">WebGL</a></li> +</ul> diff --git a/files/es/web/api/canvas_api/manipulating_video_using_canvas/index.html b/files/es/web/api/canvas_api/manipulating_video_using_canvas/index.html new file mode 100644 index 0000000000..a3ae61673d --- /dev/null +++ b/files/es/web/api/canvas_api/manipulating_video_using_canvas/index.html @@ -0,0 +1,126 @@ +--- +title: Manipular video por medio de canvas +slug: Web/HTML/anipular_video_por_medio_de_canvas +tags: + - Canvas + - Firefox 3.5 + - Video + - para_revisar +translation_of: Web/API/Canvas_API/Manipulating_video_using_canvas +--- +<p><span class="goog-gtc-unit" id="goog-gtc-unit-2"><span class="goog-gtc-translatable goog-gtc-from-tm goog-gtc-from-tm-score-100" dir="ltr" style="">{{ fx_minversion_header (3.5) }}</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-3"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Al combinar las capacidades del elemento </span></span><a class="internal" href="/En/HTML/Element/Video" title="En/HTML/Element/Video"><code>video</code></a><span class="goog-gtc-unit" id="goog-gtc-unit-3"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style=""> introducido en Firefox 3.5 con un elemento </span></span><a class="internal" href="/en/HTML/Canvas" title="En/Canvas"><code>canvas</code></a><span class="goog-gtc-unit" id="goog-gtc-unit-3"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style=""> , puedes manipular los datos de video en tiempo real para incorporar una variedad de efectos visuales que se mostrarán en el video.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-4"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Este artículo, adaptado de <a class="external" href="http://blog.mozbox.org/post/2009/02/25/video-canvas%3A-special-effects" title="http://blog.mozbox.org/post/2009/02/25/video-canvas:-special-effects">esta entrada del blog</a> de Paul Rouget, muestra cómo realizar una inserción croma (también conocida como el "efecto pantalla verde") utilizando el código JavaScript.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-5"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style=""><a href="/samples/video/chroma-key/index.xhtml" title="samples/video/chroma-key/index.xhtml">Ver este ejemplo en vivo</a> .</span></span></p> +<h2 id="El_contenido_del_documento"><span class="goog-gtc-unit" id="goog-gtc-unit-6"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El contenido del documento</span></span></h2> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-7"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El documento XHTML que se utiliza para representar este contenido se muestra a continuación.</span></span></p> +<pre class="brush: html"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <style> + body { + background: black; + color:#CCCCCC; + } + #c2 { + background-image: url(foo.png); + background-repeat: no-repeat; + } + div { + float: left; + border :1px solid #444444; + padding:10px; + margin: 10px; + background:#3B3B3B; + } + </style> + <script type="text/javascript;version=1.8" src="main.js"></script> + </head> + + <body onload="processor.doLoad()"> + <div> + <video id="video" src="video.ogv" controls="true"/> + </div> + <div> + <canvas id="c1" width="160" height="96"/> + <canvas id="c2" width="160" height="96"/> + </div> + </body> +</html> +</pre> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-42"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Los puntos clave a tener en cuenta son:</span></span></p> +<ol> + <li><span class="goog-gtc-unit" id="goog-gtc-unit-43"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Este documento establece dos elemento <a class="internal"><code>canvas</code></a> , con los identificadores de <code>c1</code> y <code>c2</code> .</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-44"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Canvas <code>c1</code> se utiliza para mostrar la imagen actual del video original, mientras que <code>c2</code> se utiliza para mostrar el video después de realizar la manipulación con el efecto croma; <code>c2</code> se carga previamente con la imagen fija que se utilizará para sustituir el fondo verde en el video.</span></span></li> + <li><span class="goog-gtc-unit" id="goog-gtc-unit-45"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El código JavaScript es importado de un script llamado <code>main.js</code> ; este script utiliza JavaScript 1.8 características, de modo que la versión se especifica en la línea 22 al importar la secuencia de comandos.</span></span></li> + <li><span class="goog-gtc-unit" id="goog-gtc-unit-46"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Cuando se carga el documento, se ejecuta el método <code>processor.doLoad()</code> de <code>main.js</code>.</span></span></li> +</ol> +<h2 id="El_código_JavaScript"><span class="goog-gtc-unit" id="goog-gtc-unit-47"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El código JavaScript</span></span></h2> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-48"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El código JavaScript en <code>main.js</code> consta de tres métodos.</span></span></p> +<h3 id="Inicializar_el_reproductor_de_croma"><span class="goog-gtc-unit" id="goog-gtc-unit-49"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Inicializar el reproductor de croma</span></span></h3> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-50"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El método <code>doLoad()</code> se llama cuando el documento XHTML se carga inicialmente.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-51"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">La función de este método es preparar las variables necesarias para el código de procesamiento del croma y la creación de un detector de eventos para que podamos detectar cuándo inicia el usuario la reproducción del video.</span></span></p> +<pre class="brush: js"> doLoad: function() { + this.video = document.getElementById("video"); + this.c1 = document.getElementById("c1"); + this.ctx1 = this.c1.getContext("2d"); + this.c2 = document.getElementById("c2"); + this.ctx2 = this.c2.getContext("2d"); + let self = this; + this.video.addEventListener("play", function() { + self.width = self.video.videoWidth / 2; + self.height = self.video.videoHeight / 2; + self.timerCallback(); + }, false); + }, +</pre> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-65"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Este código obtiene referencias a los elementos del documento XHTML que son de particular interés, a saber, el elemento <code>video</code> y los dos elementos <code>canvas</code>.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-66"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">También recupera las referencias a los contextos gráficos para cada uno de los dos elementos canvas.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-67"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Estos serán utilizados cuando estamos haciendo de verdad el efecto croma.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-68"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Luego <code>addEventListener()</code> es llamado para empezar a ver el elemento <code>video</code> de forma que podamos obtener una notificación cuando el usuario presione el botón de reproducción en el video.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-69"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">En respuesta al usuario que inicia la reproducción, el código obtiene la anchura y la altura de video, reduciendo a la mitad cada uno (vamos a reducir a la mitad el tamaño del video, cuando llevamos a cabo la manipulación efecto croma). A continuación, llama al método <code>timerCallback()</code> para iniciar el visionado del video y la computación del efecto visual.</span></span></p> +<h3 id="La_devolución_de_llamada_del_temporizador"><span class="goog-gtc-unit" id="goog-gtc-unit-70"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">La devolución de llamada del temporizador</span></span></h3> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-71"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">La devolución de llamada del temporizador se llama inicialmente cuando el video comienza a reproducirse (cuando tiene lugar el evento "reproducir"), a continuación, toma la responsabilidad por la que se establece a sí mismo para ser llamado periódicamente, a fin de poner en marcha el efecto croma para cada imagen.</span></span></p> +<pre class="brush: js"> timerCallback: function() { + if (this.video.paused || this.video.ended) { + return; + } + this.computeFrame(); + let self = this; + setTimeout(function () { + self.timerCallback(); + }, 0); + }, +</pre> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-82"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Lo primero que la devolución de llamada hace es comprobar si el video se está aún reproduciendo, y si no lo está, la devolución de llamada regresa inmediatamente sin hacer nada.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-83"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">A continuación, llama al método <code>computeFrame()</code>, que lleva a cabo la manipulación del efecto croma en la imagen de video actual.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-84"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Lo último que la devolución de llamada hace es llamar a <code>setTimeout()</code> para programarse para ser llamado lo más pronto posible.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-85"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">En el mundo real, es probable que programes esto en función de la velocidad de fotogramas del video.</span></span></p> +<h3 id="Manipulación_de_los_datos_de_la_imagen_del_video"><span class="goog-gtc-unit" id="goog-gtc-unit-86"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Manipulación de los datos de la imagen del video</span></span></h3> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-87"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El método <code>computeFrame()</code>, que se muestra a continuación, se encarga de ir a buscar realmente un fotograma de datos y realizar el efecto croma.</span></span></p> +<pre class="brush: js"> computeFrame: function() { + this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); + let frame = this.ctx1.getImageData(0, 0, this.width, this.height); + let l = frame.data.length / 4; + + for (let i = 0; i < l; i++) { + let r = frame.data[i * 4 + 0]; + let g = frame.data[i * 4 + 1]; + let b = frame.data[i * 4 + 2]; + if (g > 100 && r > 100 && b < 43) + frame.data[i * 4 + 3] = 0; + } + this.ctx2.putImageData(frame, 0, 0); + return; + } +</pre> +<p>Cuando esta rutina es llamada, el elemento video muestra el fotograma de datos de video más reciente, que tiene este aspecto:</p> +<p><img alt="video.png" class="internal default" src="/@api/deki/files/3282/=video.png" style="width: 320px; height: 192px;"></p> +<p>En la línea 2, ese fotograma de video se copia al contexto gráfico <code>ctx1</code> del primer lienzo, especificando como alto y ancho los valores que previamente guardamos para dibujar el fotograma a mitad de tamaño. <span class="goog-gtc-unit" id="goog-gtc-unit-104"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Ten en cuenta que puedes pasar simplemente el elemento de video al método <code>drawImage()</code> del contexto para dibujar el fotograma de video actual en dicho contexto.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-105"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El resultado es:</span></span></p> +<p><img alt="sourcectx.png" class="internal default" src="/@api/deki/files/3284/=sourcectx.png" style="width: 160px; height: 96px;"></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-106"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Línea 3 obtiene una copia de los datos gráficos del actual fotograma de video llamando al método <code>getImageData()</code> en el primer contexto.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-107"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Esto proporciona los datos de imagen en píxeles de 32 bits sin procesar que podemos después manipular.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-108"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Línea 4 calcula el número de píxeles de la imagen al dividir entre cuatro el tamaño total de los datos de la imagen del fotograma.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-109"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El bucle <code>for</code> que comienza en la línea 6 explora a través de los píxeles del fotograma, extrayendo los valores rojo, verde y azul para cada píxel, y compara los valores frente a números predeterminados que se utilizan para detectar la pantalla verde que se reemplazará por la imagen de fondo fija importada de <code>foo.png</code> .</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-110"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Cada píxel de datos de imagen del fotograma que se encuentra que está dentro de los parámetros que se consideran parte de la pantalla verde tiene su valor alfa reemplazado por un cero, lo que indica que el píxel es totalmente transparente.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-111"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Como resultado, la imagen final tiene toda el área de pantalla verde 100% transparente, de modo que cuando se dibuja en el contexto de destino en la línea 13, el resultado es una superposición sobre el fondo estático.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-112"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">La imagen resultante tiene este aspecto:</span></span></p> +<p><img alt="output.png" class="internal default" src="/@api/deki/files/3283/=output.png" style="width: 161px; height: 96px;"></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-113"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Esto se hace en varias ocasiones mientras el video se reproduce, de manera que fotograma tras fotograma se procesa y se muestra con el efecto de croma.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-114"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style=""><a href="/samples/video/chroma-key/index.xhtml" title="samples/video/chroma-key/index.xhtml">Ver este ejemplo en vivo</a> .</span></span></p> +<h2 id="Consulta_también"><span class="goog-gtc-unit" id="goog-gtc-unit-115"><span class="goog-gtc-translatable goog-gtc-from-tm goog-gtc-from-tm-score-100" dir="ltr" style="">Consulta también</span></span></h2> +<ul> + <li><a class="internal" href="/es/Usando_audio_y_video_en_Firefox" title="es/Usando audio y video en Firefox"><span class="goog-gtc-unit" id="goog-gtc-unit-116"><span class="goog-gtc-translatable goog-gtc-from-tm goog-gtc-from-tm-score-100" dir="ltr" style="">Usar audio y video en Firefox</span></span></a></li> +</ul> +<p>{{ languages ( { "en": "En/Manipulating_video_using_canvas" } ) }}</p> diff --git a/files/es/web/api/canvas_api/tutorial/advanced_animations/index.html b/files/es/web/api/canvas_api/tutorial/advanced_animations/index.html new file mode 100644 index 0000000000..15ab72ee7f --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/advanced_animations/index.html @@ -0,0 +1,380 @@ +--- +title: Advanced animations +slug: Web/Guide/HTML/Canvas_tutorial/Advanced_animations +tags: + - Canvas + - Tutoria + - graficos +translation_of: Web/API/Canvas_API/Tutorial/Advanced_animations +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Basic_animations", "Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas")}}</div> + +<div class="summary"> +<p>En el último capítulo hicimos unas <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">animaciones básicas</a> y nos familiarizamos con varias maneras de mover cosas. En esta parte examinaremos la moción misma y agregaremos la física para hacer nuestras animaciones más avanzadas.</p> +</div> + +<h2 id="Dibujar_una_bola">Dibujar una bola</h2> + +<p>Vamos a usar una bola para nuestro estudio de la animación, entonces primero dibujamos la bola dentro del canvas. El siguente código lo configurará.</p> + +<pre class="brush: html"><canvas id="canvas" width="600" height="300"></canvas> +</pre> + +<p>Como siempre, necesitamos un entorno para dibujar. Para dibujar la bola, creamos un contenido <code>ball</code> lo cual contiene propiedades y un método <code>draw()</code>.</p> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); + +var ball = { + x: 100, + y: 100, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +ball.draw();</pre> + +<p>Nada especial aquí; la bola es en realidad un circulo sencillo y se dibuja con el método {{domxref("CanvasRenderingContext2D.arc()", "arc()")}}.</p> + +<h2 id="Agregar_velocidad">Agregar velocidad</h2> + +<p>Ya que tenemos una bola, estamos listos agregar una animación básica así como aprendimos en el <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">último capítulo</a> de esta tutoría. De nuevo, {{domxref("window.requestAnimationFrame()")}} nos ayuda controlar la animación. La bola empieza moverse por agregar un vector de velocidad a la posición. Para cada fotograma, también {{domxref("CanvasRenderingContext2D.clearRect", "clear", "", 1)}} el canvas para quitar los circulos viejos de los fotogramas anteriores.</p> + +<pre class="brush: js; highlight:[8,9,24,25]">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.clearRect(0,0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw(); +</pre> + +<h2 id="Límites">Límites</h2> + +<p>Si no probamos los límites, de repente nuestra bola se agota el canvas. Necesitamos verificar si las posiciones <code>x</code> e <code>y</code> están fuera de las dimensiones del canvas y invertir la direción de los vectores de velocidad. Para hacer eso, agregamos los siguentes pasos al método <code>draw</code>:</p> + +<pre class="brush: js">if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { + ball.vy = -ball.vy; +} +if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { + ball.vx = -ball.vx; +}</pre> + +<h3 id="Primera_demo">Primera demo</h3> + +<p>Veamos como se ve en acción hasta este punto. Dirige el ratón dentro del canvas para empezar la animación.</p> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.clearRect(0,0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + + if (ball.y + ball.vy > canvas.height || + ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || + ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw();</pre> +</div> + +<p>{{EmbedLiveSample("First_demo", "610", "310")}}</p> + +<h2 id="Aceleración">Aceleración</h2> + +<p>Para convertir la moción en más auténtica, puedes jugar con la velocidad, así por ejemplo:</p> + +<pre class="brush: js">ball.vy *= .99; +ball.vy += .25;</pre> + +<p>Esto reduce el vector vertical de velocidad para cada fotograma para que la bola termina rebotando en el suelo.</p> + +<div class="hidden"> +<h6 id="Second_demo">Second demo</h6> + +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.clearRect(0,0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + ball.vy *= .99; + ball.vy += .25; + + if (ball.y + ball.vy > canvas.height || + ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || + ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw();</pre> +</div> + +<p>{{EmbedLiveSample("Second_demo", "610", "310")}}</p> + +<h2 id="Efecto_de_rezagar">Efecto de rezagar</h2> + +<p>Hasta este punto hemos limpiado los fotogramas anteriores con el método {{domxref("CanvasRenderingContext2D.clearRect", "clearRect")}}. Si reemplazas este método con un semi-transparente {{domxref("CanvasRenderingContext2D.fillRect", "fillRect")}}, puedes facilmente crear un efecto de rezagar.</p> + +<pre class="brush: js">ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; +ctx.fillRect(0, 0, canvas.width, canvas.height);</pre> + +<div class="hidden"> +<h6 id="Third_demo">Third demo</h6> + +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + ball.vy *= .99; + ball.vy += .25; + + if (ball.y + ball.vy > canvas.height || + ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || + ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw();</pre> +</div> + +<p>{{EmbedLiveSample("Third_demo", "610", "310")}}</p> + +<h2 id="Agregar_control_de_ratón">Agregar control de ratón</h2> + +<p>Para controlar la bola, podemos hacerla seguir nuestro ratón usando el evento <code><a href="/en-US/docs/Web/Reference/Events/mousemove">mousemove</a></code>, por ejemplo. El evento <code><a href="/en-US/docs/Web/Events/click">click</a></code> solta la bola y la deja rebotar de nuevo.</p> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> +</div> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; +var running = false; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 1, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function clear() { + ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; + ctx.fillRect(0,0,canvas.width,canvas.height); +} + +function draw() { + clear(); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + + if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mousemove', function(e) { + if (!running) { + clear(); + ball.x = e.clientX; + ball.y = e.clientY; + ball.draw(); + } +}); + +canvas.addEventListener('click', function(e) { + if (!running) { + raf = window.requestAnimationFrame(draw); + running = true; + } +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); + running = false; +}); + +ball.draw(); +</pre> + +<p>Mueve la bola usando el ratón y suéltala haciendo click.</p> + +<p>{{EmbedLiveSample("Adding_mouse_control", "610", "310")}}</p> + +<h2 id="Breakout">Breakout</h2> + +<p>Este capítulo corto sólo explica algunas técnicas para crear animaciones más avanzadas. ¡Hay muchos más! ¿Qué tal agregar una raqueta, algunos ladrillos, y convertir esta demo en un partido <a href="http://en.wikipedia.org/wiki/Breakout_%28video_game%29">Breakout</a>? Visita nuestra área de <a href="/en-US/docs/Games">Game development</a> para mayor información.</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li>{{domxref("window.requestAnimationFrame()")}}</li> + <li><a href="/en-US/docs/Games/Techniques/Efficient_animation_for_web_games">Efficient animation for web games</a></li> +</ul> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Basic_animations", "Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/applying_styles_and_colors/index.html b/files/es/web/api/canvas_api/tutorial/applying_styles_and_colors/index.html new file mode 100644 index 0000000000..ab76918132 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/applying_styles_and_colors/index.html @@ -0,0 +1,726 @@ +--- +title: Applying styles and colors +slug: Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors +translation_of: Web/API/Canvas_API/Tutorial/Applying_styles_and_colors +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_shapes", "Web/API/Canvas_API/Tutorial/Drawing_text")}}</div> + +<div class="summary"> +<p>En el capítulo acerca de dibujar formas, usamos unicamente los estilos de linea y de relleno por defecto. Aqui exploraremos las opciones del canvas que tenemos a nuestra disposición para hacer los dibujos un tanto más atractivos. Aprenderas como agregar diferentes colores, estilos de linea, gradiantes, patrones y sombras a tus dibujos.</p> +</div> + +<h2 id="Colors" name="Colors">Colors</h2> + +<p>Hasta ahrora nosotros solo me hemos visto metodos en el contexto de dibujo. Si quisieramos aplicar colores a las formas, hay dos importantes propiedades que podemos usar: <code>fillStyle</code> y <code>strokeStyle</code>.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle = color")}}</dt> + <dd>Configura el estilo cuando se rellenan las formas.</dd> + <dt>{{domxref("CanvasRenderingContext2D.strokeStyle", "strokeStyle = color")}}</dt> + <dd>Configura el estilo al contorno perimetral de las formas.</dd> +</dl> + +<p><code>color</code> es una cadena que representa un CSS {{cssxref("<color>")}}, un objeto gradiante, o un objeto patron. Miraremos en objetos de gradientes y patrones mas tarde. Por defecto, el color del trazo y del relleno son configurados en negro (valor de color CSS <code>#000000</code>).</p> + +<div class="note"> +<p><strong>Nota: </strong> Cuando configuras la propiedad <code>strokeStyle</code> y/o <code>fillStyle</code>, el nuevo valor llega a ser el vador por defecto para los dibujos posteriores. Para cada forma que tu quieras en un color difrente, necesitaras reasignar las propiedades anteriores.</p> +</div> + +<p>Las cadenas validas que tu pueden entrar deberian, segun la especificación, ser valores de {{cssxref("<color>")}} CSS. En el siguiente ejemplo, describimos en mismo color.</p> + +<pre class="brush: js">// these all set the fillStyle to 'orange' + +ctx.fillStyle = 'orange'; +ctx.fillStyle = '#FFA500'; +ctx.fillStyle = 'rgb(255, 165, 0)'; +ctx.fillStyle = 'rgba(255, 165, 0, 1)'; +</pre> + +<h3 id="A_fillStyle_example" name="A_fillStyle_example">A <code>fillStyle</code> example</h3> + +<p>En este ejemplo, usamos dos bucles for para dibujar una cuadrícula de rectangulos, cada uno de diferente color. La imagen resultante deberia ser similar a la de la screenhot. No hay nada demasiado espectacular en el proceso. Usamos dos variables i y j para generar un unico color RGB para cada celda cuadrada, modificando las componentes rojo y verde. El canal azul tiene un valor fijo. Modificando los canales, puedes generar todo tipo de paletas. Incrementando los paos, puedes lograr algo similar que se parezca a las paletas de colores que Photoshop usa.</p> + +<pre class="brush: js;highlight[5,6]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + for (var i = 0; i < 6; i++) { + for (var j = 0; j < 6; j++) { + ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ', ' + + Math.floor(255 - 42.5 * j) + ', 0)'; + ctx.fillRect(j * 25, i * 25, 25, 25); + } + } +}</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>The result looks like this:</p> + +<p>{{EmbedLiveSample("A_fillStyle_example", 160, 160, "https://mdn.mozillademos.org/files/5417/Canvas_fillstyle.png")}}</p> + +<h3 id="A_strokeStyle_example" name="A_strokeStyle_example">A <code>strokeStyle</code> example</h3> + +<p>Este ejemplo es similar al de arriba, pero usa la propiedad <code>strokeStyle</code> para cambiar el color del contorno de las formas. Usamos el método <code>arc()</code> para dibujar circulos en lugar de celdas cuadradas.</p> + +<pre class="brush: js;highlight[5,6]"> function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + for (var i = 0; i < 6; i++) { + for (var j = 0; j < 6; j++) { + ctx.strokeStyle = 'rgb(0, ' + Math.floor(255 - 42.5 * i) + ', ' + + Math.floor(255 - 42.5 * j) + ')'; + ctx.beginPath(); + ctx.arc(12.5 + j * 25, 12.5 + i * 25, 10, 0, Math.PI * 2, true); + ctx.stroke(); + } + } + } +</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>The result looks like this:</p> + +<p>{{EmbedLiveSample("A_strokeStyle_example", "180", "180", "https://mdn.mozillademos.org/files/253/Canvas_strokestyle.png")}}</p> + +<h2 id="Transparency" name="Transparency">Transparency</h2> + +<p>Ademas de dibujar formas opacas en el canvas, podemos dibujar formas semi-transparentes(o translucidas). Esto se logra bien configurando la propiedad <code>globalAlpha</code> o asignando un color semi-transparente al estilo del trazo u u/y al de relleno.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.globalAlpha", "globalAlpha = transparencyValue")}}</dt> + <dd>Applies the specified transparency value to all future shapes drawn on the canvas. The value must be between 0.0 (fully transparent) to 1.0 (fully opaque). This value is 1.0 (fully opaque) by default.</dd> +</dl> + +<p>The <code>globalAlpha</code> property can be useful if you want to draw a lot of shapes on the canvas with similar transparency, but otherwise it's generally more useful to set the transparency on individual shapes when setting their colors.</p> + +<p>Debido qaque las propiedades <code>strokeStyle</code> y <code>fillStyle</code> aceptan valores de color rgba de CSS, podemos usar la siguiente notacion para asignar una color transparente a ellos.</p> + +<pre class="brush: js">// Assigning transparent colors to stroke and fill style + +ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)'; +ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; +</pre> + +<p>The <code>rgba()</code> function is similar to the <code>rgb()</code> function but it has one extra parameter. The last parameter sets the transparency value of this particular color. The valid range is again between 0.0 (fully transparent) and 1.0 (fully opaque).</p> + +<h3 id="A_globalAlpha_example" name="A_globalAlpha_example">A <code>globalAlpha</code> example</h3> + +<p>In this example, we'll draw a background of four different colored squares. On top of these, we'll draw a set of semi-transparent circles. The <code>globalAlpha</code> property is set at <code>0.2</code> which will be used for all shapes from that point on. Every step in the <code>for</code> loop draws a set of circles with an increasing radius. The final result is a radial gradient. By overlaying ever more circles on top of each other, we effectively reduce the transparency of the circles that have already been drawn. By increasing the step count and in effect drawing more circles, the background would completely disappear from the center of the image.</p> + +<pre class="brush: js;highlight[15]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + // draw background + ctx.fillStyle = '#FD0'; + ctx.fillRect(0, 0, 75, 75); + ctx.fillStyle = '#6C0'; + ctx.fillRect(75, 0, 75, 75); + ctx.fillStyle = '#09F'; + ctx.fillRect(0, 75, 75, 75); + ctx.fillStyle = '#F30'; + ctx.fillRect(75, 75, 75, 75); + ctx.fillStyle = '#FFF'; + + // set transparency value + ctx.globalAlpha = 0.2; + + // Draw semi transparent circles + for (var i = 0; i < 7; i++) { + ctx.beginPath(); + ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true); + ctx.fill(); + } +}</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>{{EmbedLiveSample("A_globalAlpha_example", "180", "180", "https://mdn.mozillademos.org/files/232/Canvas_globalalpha.png")}}</p> + +<h3 id="An_example_using_rgba" name="An_example_using_rgba()">An example using <code>rgba()</code></h3> + +<p>In this second example, we do something similar to the one above, but instead of drawing circles on top of each other, I've drawn small rectangles with increasing opacity. Using <code>rgba()</code> gives you a little more control and flexibility because we can set the fill and stroke style individually.</p> + +<pre class="brush: js;highlight[16]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Draw background + ctx.fillStyle = 'rgb(255, 221, 0)'; + ctx.fillRect(0, 0, 150, 37.5); + ctx.fillStyle = 'rgb(102, 204, 0)'; + ctx.fillRect(0, 37.5, 150, 37.5); + ctx.fillStyle = 'rgb(0, 153, 255)'; + ctx.fillRect(0, 75, 150, 37.5); + ctx.fillStyle = 'rgb(255, 51, 0)'; + ctx.fillRect(0, 112.5, 150, 37.5); + + // Draw semi transparent rectangles + for (var i = 0; i < 10; i++) { + ctx.fillStyle = 'rgba(255, 255, 255, ' + (i + 1) / 10 + ')'; + for (var j = 0; j < 4; j++) { + ctx.fillRect(5 + i * 14, 5 + j * 37.5, 14, 27.5); + } + } +}</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>{{EmbedLiveSample("An_example_using_rgba()", "180", "180", "https://mdn.mozillademos.org/files/246/Canvas_rgba.png")}}</p> + +<h2 id="Line_styles" name="Line_styles">Line styles</h2> + +<p>There are several properties which allow us to style lines.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.lineWidth", "lineWidth = value")}}</dt> + <dd>Sets the width of lines drawn in the future.</dd> + <dt>{{domxref("CanvasRenderingContext2D.lineCap", "lineCap = type")}}</dt> + <dd>Sets the appearance of the ends of lines.</dd> + <dt>{{domxref("CanvasRenderingContext2D.lineJoin", "lineJoin = type")}}</dt> + <dd>Sets the appearance of the "corners" where lines meet.</dd> + <dt>{{domxref("CanvasRenderingContext2D.miterLimit", "miterLimit = value")}}</dt> + <dd>Establishes a limit on the miter when two lines join at a sharp angle, to let you control how thick the junction becomes.</dd> + <dt>{{domxref("CanvasRenderingContext2D.getLineDash", "getLineDash()")}}</dt> + <dd>Returns the current line dash pattern array containing an even number of non-negative numbers.</dd> + <dt>{{domxref("CanvasRenderingContext2D.setLineDash", "setLineDash(segments)")}}</dt> + <dd>Sets the current line dash pattern.</dd> + <dt>{{domxref("CanvasRenderingContext2D.lineDashOffset", "lineDashOffset = value")}}</dt> + <dd>Specifies where to start a dash array on a line.</dd> +</dl> + +<p>You'll get a better understanding of what these do by looking at the examples below.</p> + +<h3 id="A_lineWidth_example" name="A_lineWidth_example">A <code>lineWidth</code> example</h3> + +<p>This property sets the current line thickness. Values must be positive numbers. By default this value is set to 1.0 units.</p> + +<p>The line width is the thickness of the stroke centered on the given path. In other words, the area that's drawn extends to half the line width on either side of the path. Because canvas coordinates do not directly reference pixels, special care must be taken to obtain crisp horizontal and vertical lines.</p> + +<p>In the example below, 10 straight lines are drawn with increasing line widths. The line on the far left is 1.0 units wide. However, the leftmost and all other odd-integer-width thickness lines do not appear crisp, because of the path's positioning.</p> + +<pre class="brush: js;highlight[4]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + for (var i = 0; i < 10; i++) { + ctx.lineWidth = 1 + i; + ctx.beginPath(); + ctx.moveTo(5 + i * 14, 5); + ctx.lineTo(5 + i * 14, 140); + ctx.stroke(); + } +} +</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>{{EmbedLiveSample("A_lineWidth_example", "180", "180", "https://mdn.mozillademos.org/files/239/Canvas_linewidth.png")}}</p> + +<p>Obtaining crisp lines requires understanding how paths are stroked. In the images below, the grid represents the canvas coordinate grid. The squares between gridlines are actual on-screen pixels. In the first grid image below, a rectangle from (2,1) to (5,5) is filled. The entire area between them (light red) falls on pixel boundaries, so the resulting filled rectangle will have crisp edges.</p> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/201/Canvas-grid.png"></p> + +<p>If you consider a path from (3,1) to (3,5) with a line thickness of <code>1.0</code>, you end up with the situation in the second image. The actual area to be filled (dark blue) only extends halfway into the pixels on either side of the path. An approximation of this has to be rendered, which means that those pixels being only partially shaded, and results in the entire area (the light blue and dark blue) being filled in with a color only half as dark as the actual stroke color. This is what happens with the <code>1.0</code> width line in the previous example code.</p> + +<p>To fix this, you have to be very precise in your path creation. Knowing that a <code>1.0</code> width line will extend half a unit to either side of the path, creating the path from (3.5,1) to (3.5,5) results in the situation in the third image—the <code>1.0</code> line width ends up completely and precisely filling a single pixel vertical line.</p> + +<div class="note"> +<p><strong>Note:</strong> Be aware that in our vertical line example, the Y position still referenced an integer gridline position—if it hadn't, we would see pixels with half coverage at the endpoints (but note also that this behavior depends on the current <code>lineCap</code> style whose default value is <code>butt</code>; you may want to compute consistent strokes with half-pixel coordinates for odd-width lines, by setting the <code>lineCap</code> style to <code>square</code>, so that the outer border of the stroke around the endpoint will be automatically extended to cover the whole pixel exactly).</p> + +<p>Note also that only start and final endpoints of a path are affected: if a path is closed with <code>closePath()</code>, there's no start and final endpoint; instead, all endpoints in the path are connected to their attached previous and next segment using the current setting of the <code>lineJoin</code> style, whose default value is <code>miter</code>, with the effect of automatically extending the outer borders of the connected segments to their intersection point, so that the rendered stroke will exactly cover full pixels centered at each endpoint if those connected segments are horizontal and/or vertical). See the next two sections for demonstrations of these additional line styles.</p> +</div> + +<p>For even-width lines, each half ends up being an integer amount of pixels, so you want a path that is between pixels (that is, (3,1) to (3,5)), instead of down the middle of pixels.</p> + +<p>While slightly painful when initially working with scalable 2D graphics, paying attention to the pixel grid and the position of paths ensures that your drawings will look correct regardless of scaling or any other transformations involved. A 1.0-width vertical line drawn at the correct position will become a crisp 2-pixel line when scaled up by 2, and will appear at the correct position.</p> + +<h3 id="A_lineCap_example" name="A_lineCap_example">A <code>lineCap</code> example</h3> + +<p>The <code>lineCap</code> property determines how the end points of every line are drawn. There are three possible values for this property and those are: <code>butt</code>, <code>round</code> and <code>square</code>. By default this property is set to <code>butt</code>.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/236/Canvas_linecap.png" style="float: right; height: 190px; width: 190px;"></p> + +<dl> + <dt><code>butt</code></dt> + <dd>The ends of lines are squared off at the endpoints.</dd> + <dt><code>round</code></dt> + <dd>The ends of lines are rounded.</dd> + <dt><code>square</code></dt> + <dd>The ends of lines are squared off by adding a box with an equal width and half the height of the line's thickness.</dd> +</dl> + +<p>In this example, we'll draw three lines, each with a different value for the <code>lineCap</code> property. I also added two guides to see the exact differences between the three. Each of these lines starts and ends exactly on these guides.</p> + +<p>The line on the left uses the default <code>butt</code> option. You'll notice that it's drawn completely flush with the guides. The second is set to use the <code>round</code> option. This adds a semicircle to the end that has a radius half the width of the line. The line on the right uses the <code>square</code> option. This adds a box with an equal width and half the height of the line thickness.</p> + +<pre class="brush: js;highlight[18]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + var lineCap = ['butt', 'round', 'square']; + + // Draw guides + ctx.strokeStyle = '#09f'; + ctx.beginPath(); + ctx.moveTo(10, 10); + ctx.lineTo(140, 10); + ctx.moveTo(10, 140); + ctx.lineTo(140, 140); + ctx.stroke(); + + // Draw lines + ctx.strokeStyle = 'black'; + for (var i = 0; i < lineCap.length; i++) { + ctx.lineWidth = 15; + ctx.lineCap = lineCap[i]; + ctx.beginPath(); + ctx.moveTo(25 + i * 50, 10); + ctx.lineTo(25 + i * 50, 140); + ctx.stroke(); + } +} +</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>{{EmbedLiveSample("A_lineCap_example", "180", "180", "https://mdn.mozillademos.org/files/236/Canvas_linecap.png")}}</p> + +<h3 id="A_lineJoin_example" name="A_lineJoin_example">A <code>lineJoin</code> example</h3> + +<p>The <code>lineJoin</code> property determines how two connecting segments (of lines, arcs or curves) with non-zero lengths in a shape are joined together (degenerate segments with zero lengths, whose specified endpoints and control points are exactly at the same position, are skipped).</p> + +<p>There are three possible values for this property: <code>round</code>, <code>bevel</code> and <code>miter</code>. By default this property is set to <code>miter</code>. Note that the <code>lineJoin</code> setting has no effect if the two connected segments have the same direction, because no joining area will be added in this case.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/237/Canvas_linejoin.png" style="float: right; height: 190px; width: 190px;"></p> + +<dl> + <dt><code>round</code></dt> + <dd>Rounds off the corners of a shape by filling an additional sector of disc centered at the common endpoint of connected segments. The radius for these rounded corners is equal to half the line width.</dd> + <dt><code>bevel</code></dt> + <dd>Fills an additional triangular area between the common endpoint of connected segments, and the separate outside rectangular corners of each segment.</dd> + <dt><code>miter</code></dt> + <dd>Connected segments are joined by extending their outside edges to connect at a single point, with the effect of filling an additional lozenge-shaped area. This setting is effected by the <code>miterLimit</code> property which is explained below.</dd> +</dl> + +<p>The example below draws three different paths, demonstrating each of these three <code>lineJoin</code> property settings; the output is shown above.</p> + +<pre class="brush: js;highlight[6]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + var lineJoin = ['round', 'bevel', 'miter']; + ctx.lineWidth = 10; + for (var i = 0; i < lineJoin.length; i++) { + ctx.lineJoin = lineJoin[i]; + ctx.beginPath(); + ctx.moveTo(-5, 5 + i * 40); + ctx.lineTo(35, 45 + i * 40); + ctx.lineTo(75, 5 + i * 40); + ctx.lineTo(115, 45 + i * 40); + ctx.lineTo(155, 5 + i * 40); + ctx.stroke(); + } +} +</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>{{EmbedLiveSample("A_lineJoin_example", "180", "180", "https://mdn.mozillademos.org/files/237/Canvas_linejoin.png")}}</p> + +<h3 id="A_demo_of_the_miterLimit_property" name="A_demo_of_the_miterLimit_property">A demo of the <code>miterLimit</code> property</h3> + +<p>As you've seen in the previous example, when joining two lines with the <code>miter</code> option, the outside edges of the two joining lines are extended up to the point where they meet. For lines which are at large angles with each other, this point is not far from the inside connection point. However, as the angles between each line decreases, the distance (miter length) between these points increases exponentially.</p> + +<p>The <code>miterLimit</code> property determines how far the outside connection point can be placed from the inside connection point. If two lines exceed this value, a bevel join gets drawn instead. Note that the maximum miter length is the product of the line width measured in the current coordinate system, by the value of this <code>miterLimit</code> property (whose default value is 10.0 in the HTML {{HTMLElement("canvas")}}), so the <code>miterLimit</code> can be set independently from the current display scale or any affine transforms of paths: it only influences the effectively rendered shape of line edges.</p> + +<p>More exactly, the miter limit is the maximum allowed ratio of the extension length (in the HTML canvas, it is measured between the outside corner of the joined edges of the line and the common endpoint of connecting segments specified in the path) to half the line width. It can equivalently be defined as the maximum allowed ratio of the distance between the inside and outside points of jonction of edges, to the total line width. It is then equal to the cosecant of half the minimum inner angle of connecting segments below which no miter join will be rendered, but only a bevel join:</p> + +<ul> + <li><code>miterLimit</code> = <strong>max</strong> <code>miterLength</code> / <code>lineWidth</code> = 1 / <strong>sin</strong> ( <strong>min</strong> <em>θ</em> / 2 )</li> + <li>The default miter limit of 10.0 will strip all miters for sharp angles below about 11 degrees.</li> + <li>A miter limit equal to √2 ≈ 1.4142136 (rounded up) will strip miters for all acute angles, keeping miter joins only for obtuse or right angles.</li> + <li>A miter limit equal to 1.0 is valid but will disable all miters.</li> + <li>Values below 1.0 are invalid for the miter limit.</li> +</ul> + +<p>Here's a little demo in which you can set <code>miterLimit</code> dynamically and see how this effects the shapes on the canvas. The blue lines show where the start and endpoints for each of the lines in the zig-zag pattern are.</p> + +<p>If you specify a <code>miterLimit</code> value below 4.2 in this demo, none of the visible corners will join with a miter extension, but only with a small bevel near the blue lines; with a <code>miterLimit</code> above 10, most corners in this demo should join with a miter far away from the blue lines, and whose height is decreasing between corners from left to right because they connect with growing angles; with intermediate values, the corners on the left side will only join with a bevel near the blue lines, and the corners on the right side with a miter extension (also with a decreasing height).</p> + +<pre class="brush: js;highlight[18]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Clear canvas + ctx.clearRect(0, 0, 150, 150); + + // Draw guides + ctx.strokeStyle = '#09f'; + ctx.lineWidth = 2; + ctx.strokeRect(-5, 50, 160, 50); + + // Set line styles + ctx.strokeStyle = '#000'; + ctx.lineWidth = 10; + + // check input + if (document.getElementById('miterLimit').value.match(/\d+(\.\d+)?/)) { + ctx.miterLimit = parseFloat(document.getElementById('miterLimit').value); + } else { + alert('Value must be a positive number'); + } + + // Draw lines + ctx.beginPath(); + ctx.moveTo(0, 100); + for (i = 0; i < 24 ; i++) { + var dy = i % 2 == 0 ? 25 : -25; + ctx.lineTo(Math.pow(i, 1.5) * 2, 75 + dy); + } + ctx.stroke(); + return false; +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><table> + <tr> + <td><canvas id="canvas" width="150" height="150"></canvas></td> + <td>Change the <code>miterLimit</code> by entering a new value below and clicking the redraw button.<br><br> + <form onsubmit="return draw();"> + <label>Miter limit</label> + <input type="number" size="3" id="miterLimit"/> + <input type="submit" value="Redraw"/> + </form> + </td> + </tr> +</table></pre> + +<pre class="brush: js">document.getElementById('miterLimit').value = document.getElementById('canvas').getContext('2d').miterLimit; +draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_demo_of_the_miterLimit_property", "400", "180", "https://mdn.mozillademos.org/files/240/Canvas_miterlimit.png")}}</p> + +<h3 id="Using_line_dashes">Using line dashes</h3> + +<p>The <code>setLineDash</code> method and the <code>lineDashOffset</code> property specify the dash pattern for lines. The <code>setLineDash</code> method accepts a list of numbers that specifies distances to alternately draw a line and a gap and the <code>lineDashOffset</code> property sets an offset where to start the pattern.</p> + +<p>In this example we are creating a marching ants effect. It is an animation technique often found in <span class="new">selection</span> tools of computer graphics programs. It helps the user to distinguish the selection border from the image background by animating the border. In a later part of this tutorial, you can learn how to do this and other <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">basic animations</a>.</p> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="110" height="110"></canvas></pre> +</div> + +<pre class="brush: js;highlight[6]">var ctx = document.getElementById('canvas').getContext('2d'); +var offset = 0; + +function draw() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.setLineDash([4, 2]); + ctx.lineDashOffset = -offset; + ctx.strokeRect(10, 10, 100, 100); +} + +function march() { + offset++; + if (offset > 16) { + offset = 0; + } + draw(); + setTimeout(march, 20); +} + +march();</pre> + +<p>{{EmbedLiveSample("Using_line_dashes", "120", "120", "https://mdn.mozillademos.org/files/9853/marching-ants.png")}}</p> + +<h2 id="Gradients" name="Gradients">Gradients</h2> + +<p>Just like any normal drawing program, we can fill and stroke shapes using linear and radial gradients. We create a {{domxref("CanvasGradient")}} object by using one of the following methods. We can then assign this object to the <code>fillStyle</code> or <code>strokeStyle</code> properties.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.createLinearGradient", "createLinearGradient(x1, y1, x2, y2)")}}</dt> + <dd>Creates a linear gradient object with a starting point of (<code>x1</code>, <code>y1</code>) and an end point of (<code>x2</code>, <code>y2</code>).</dd> + <dt>{{domxref("CanvasRenderingContext2D.createRadialGradient", "createRadialGradient(x1, y1, r1, x2, y2, r2)")}}</dt> + <dd>Creates a radial gradient. The parameters represent two circles, one with its center at (<code>x1</code>, <code>y1</code>) and a radius of <code>r1</code>, and the other with its center at (<code>x2</code>, <code>y2</code>) with a radius of <code>r2</code>.</dd> +</dl> + +<p>For example:</p> + +<pre class="brush: js">var lineargradient = ctx.createLinearGradient(0, 0, 150, 150); +var radialgradient = ctx.createRadialGradient(75, 75, 0, 75, 75, 100); +</pre> + +<p>Once we've created a <code>CanvasGradient</code> object we can assign colors to it by using the <code>addColorStop()</code> method.</p> + +<dl> + <dt>{{domxref("CanvasGradient.addColorStop", "gradient.addColorStop(position, color)")}}</dt> + <dd>Creates a new color stop on the <code>gradient</code> object. The <code>position</code> is a number between 0.0 and 1.0 and defines the relative position of the color in the gradient, and the <code>color</code> argument must be a string representing a CSS {{cssxref("<color>")}}, indicating the color the gradient should reach at that offset into the transition.</dd> +</dl> + +<p>You can add as many color stops to a gradient as you need. Below is a very simple linear gradient from white to black.</p> + +<pre class="brush: js">var lineargradient = ctx.createLinearGradient(0, 0, 150, 150); +lineargradient.addColorStop(0, 'white'); +lineargradient.addColorStop(1, 'black'); +</pre> + +<h3 id="A_createLinearGradient_example" name="A_createLinearGradient_example">A <code>createLinearGradient</code> example</h3> + +<p>In this example, we'll create two different gradients. As you can see here, both the <code>strokeStyle</code> and <code>fillStyle</code> properties can accept a <code>canvasGradient</code> object as valid input.</p> + +<pre class="brush: js;highlight[5,11]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Create gradients + var lingrad = ctx.createLinearGradient(0, 0, 0, 150); + lingrad.addColorStop(0, '#00ABEB'); + lingrad.addColorStop(0.5, '#fff'); + lingrad.addColorStop(0.5, '#26C000'); + lingrad.addColorStop(1, '#fff'); + + var lingrad2 = ctx.createLinearGradient(0, 50, 0, 95); + lingrad2.addColorStop(0.5, '#000'); + lingrad2.addColorStop(1, 'rgba(0, 0, 0, 0)'); + + // assign gradients to fill and stroke styles + ctx.fillStyle = lingrad; + ctx.strokeStyle = lingrad2; + + // draw shapes + ctx.fillRect(10, 10, 130, 130); + ctx.strokeRect(50, 50, 50, 50); + +} +</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>The first is a background gradient. As you can see, we assigned two colors at the same position. You do this to make very sharp color transitions—in this case from white to green. Normally, it doesn't matter in what order you define the color stops, but in this special case, it does significantly. If you keep the assignments in the order you want them to appear, this won't be a problem.</p> + +<p>In the second gradient, we didn't assign the starting color (at position 0.0) since it wasn't strictly necessary, because it will automatically assume the color of the next color stop. Therefore, assigning the black color at position 0.5 automatically makes the gradient, from the start to this stop, black.</p> + +<p>{{EmbedLiveSample("A_createLinearGradient_example", "180", "180", "https://mdn.mozillademos.org/files/235/Canvas_lineargradient.png")}}</p> + +<h3 id="A_createRadialGradient_example" name="A_createRadialGradient_example">A <code>createRadialGradient</code> example</h3> + +<p>In this example, we'll define four different radial gradients. Because we have control over the start and closing points of the gradient, we can achieve more complex effects than we would normally have in the "classic" radial gradients we see in, for instance, Photoshop (that is, a gradient with a single center point where the gradient expands outward in a circular shape).</p> + +<pre class="brush: js;highlight[5,10,15,20]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Create gradients + var radgrad = ctx.createRadialGradient(45, 45, 10, 52, 50, 30); + radgrad.addColorStop(0, '#A7D30C'); + radgrad.addColorStop(0.9, '#019F62'); + radgrad.addColorStop(1, 'rgba(1, 159, 98, 0)'); + + var radgrad2 = ctx.createRadialGradient(105, 105, 20, 112, 120, 50); + radgrad2.addColorStop(0, '#FF5F98'); + radgrad2.addColorStop(0.75, '#FF0188'); + radgrad2.addColorStop(1, 'rgba(255, 1, 136, 0)'); + + var radgrad3 = ctx.createRadialGradient(95, 15, 15, 102, 20, 40); + radgrad3.addColorStop(0, '#00C9FF'); + radgrad3.addColorStop(0.8, '#00B5E2'); + radgrad3.addColorStop(1, 'rgba(0, 201, 255, 0)'); + + var radgrad4 = ctx.createRadialGradient(0, 150, 50, 0, 140, 90); + radgrad4.addColorStop(0, '#F4F201'); + radgrad4.addColorStop(0.8, '#E4C700'); + radgrad4.addColorStop(1, 'rgba(228, 199, 0, 0)'); + + // draw shapes + ctx.fillStyle = radgrad4; + ctx.fillRect(0, 0, 150, 150); + ctx.fillStyle = radgrad3; + ctx.fillRect(0, 0, 150, 150); + ctx.fillStyle = radgrad2; + ctx.fillRect(0, 0, 150, 150); + ctx.fillStyle = radgrad; + ctx.fillRect(0, 0, 150, 150); +} +</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>In this case, we've offset the starting point slightly from the end point to achieve a spherical 3D effect. It's best to try to avoid letting the inside and outside circles overlap because this results in strange effects which are hard to predict.</p> + +<p>The last color stop in each of the four gradients uses a fully transparent color. If you want to have a nice transition from this to the previous color stop, both colors should be equal. This isn't very obvious from the code because it uses two different CSS color methods as a demonstration, but in the first gradient <code>#019F62 = rgba(1,159,98,1)</code>.</p> + +<p>{{EmbedLiveSample("A_createRadialGradient_example", "180", "180", "https://mdn.mozillademos.org/files/244/Canvas_radialgradient.png")}}</p> + +<h2 id="Patterns" name="Patterns">Patterns</h2> + +<p>In one of the examples on the previous page, we used a series of loops to create a pattern of images. There is, however, a much simpler method: the <code>createPattern()</code> method.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.createPattern", "createPattern(image, type)")}}</dt> + <dd>Creates and returns a new canvas pattern object. <code>image</code> is a {{domxref("CanvasImageSource")}} (that is, an {{domxref("HTMLImageElement")}}, another canvas, a {{HTMLElement("video")}} element, or the like. <code>type</code> is a string indicating how to use the image.</dd> +</dl> + +<p>The type specifies how to use the image in order to create the pattern, and must be one of the following string values:</p> + +<dl> + <dt><code>repeat</code></dt> + <dd>Tiles the image in both vertical and horizontal directions.</dd> + <dt><code>repeat-x</code></dt> + <dd>Tiles the image horizontally but not vertically.</dd> + <dt><code>repeat-y</code></dt> + <dd>Tiles the image vertically but not horizontally.</dd> + <dt><code>no-repeat</code></dt> + <dd>Doesn't tile the image. It's used only once.</dd> +</dl> + +<p>We use this method to create a {{domxref("CanvasPattern")}} object which is very similar to the gradient methods we've seen above. Once we've created a pattern, we can assign it to the <code>fillStyle</code> or <code>strokeStyle</code> properties. For example:</p> + +<pre class="brush: js">var img = new Image(); +img.src = 'someimage.png'; +var ptrn = ctx.createPattern(img, 'repeat'); +</pre> + +<div class="note"> +<p><strong>Note:</strong> Like with the <code>drawImage()</code> method, you must make sure the image you use is loaded before calling this method or the pattern may be drawn incorrectly.</p> +</div> + +<h3 id="A_createPattern_example" name="A_createPattern_example">A <code>createPattern</code> example</h3> + +<p>In this last example, we'll create a pattern to assign to the <code>fillStyle</code> property. The only thing worth noting is the use of the image's <code>onload</code> handler. This is to make sure the image is loaded before it is assigned to the pattern.</p> + +<pre class="brush: js;highlight[10]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // create new image object to use as pattern + var img = new Image(); + img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png'; + img.onload = function() { + + // create pattern + var ptrn = ctx.createPattern(img, 'repeat'); + ctx.fillStyle = ptrn; + ctx.fillRect(0, 0, 150, 150); + + } +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> + +<p>The result looks like this:</p> +</div> + +<p>{{EmbedLiveSample("A_createPattern_example", "180", "180", "https://mdn.mozillademos.org/files/222/Canvas_createpattern.png")}}</p> + +<h2 id="Shadows">Shadows</h2> + +<p>Using shadows involves just four properties:</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.shadowOffsetX", "shadowOffsetX = float")}}</dt> + <dd>Indicates the horizontal distance the shadow should extend from the object. This value isn't affected by the transformation matrix. The default is 0.</dd> + <dt>{{domxref("CanvasRenderingContext2D.shadowOffsetY", "shadowOffsetY = float")}}</dt> + <dd>Indicates the vertical distance the shadow should extend from the object. This value isn't affected by the transformation matrix. The default is 0.</dd> + <dt>{{domxref("CanvasRenderingContext2D.shadowBlur", "shadowBlur = float")}}</dt> + <dd>Indicates the size of the blurring effect; this value doesn't correspond to a number of pixels and is not affected by the current transformation matrix. The default value is 0.</dd> + <dt>{{domxref("CanvasRenderingContext2D.shadowColor", "shadowColor = color")}}</dt> + <dd>A standard CSS color value indicating the color of the shadow effect; by default, it is fully-transparent black.</dd> +</dl> + +<p>The properties <code>shadowOffsetX</code> and <code>shadowOffsetY</code> indicate how far the shadow should extend from the object in the X and Y directions; these values aren't affected by the current transformation matrix. Use negative values to cause the shadow to extend up or to the left, and positive values to cause the shadow to extend down or to the right. These are both 0 by default.</p> + +<p>The <code>shadowBlur</code> property indicates the size of the blurring effect; this value doesn't correspond to a number of pixels and is not affected by the current transformation matrix. The default value is 0.</p> + +<p>The <code>shadowColor</code> property is a standard CSS color value indicating the color of the shadow effect; by default, it is fully-transparent black.</p> + +<div class="note"> +<p><strong>Note:</strong> Shadows are only drawn for <code>source-over</code> <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing" title="Web/Guide/HTML/Canvas_tutorial/Compositing">compositing operations</a>.</p> +</div> + +<h3 id="A_shadowed_text_example">A shadowed text example</h3> + +<p>This example draws a text string with a shadowing effect.</p> + +<pre class="brush: js;highlight[4,5,6,7]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + ctx.shadowOffsetX = 2; + ctx.shadowOffsetY = 2; + ctx.shadowBlur = 2; + ctx.shadowColor = 'rgba(0, 0, 0, 0.5)'; + + ctx.font = '20px Times New Roman'; + ctx.fillStyle = 'Black'; + ctx.fillText('Sample String', 5, 30); +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="80"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_shadowed_text_example", "180", "100", "https://mdn.mozillademos.org/files/2505/shadowed-string.png")}}</p> + +<p>We will look at the <code>font</code> property and <code>fillText</code> method in the next chapter about <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text">drawing text</a>.</p> + +<h2 id="Canvas_fill_rules">Canvas fill rules</h2> + +<p>When using <code>fill</code> (or {{domxref("CanvasRenderingContext2D.clip", "clip")}} and {{domxref("CanvasRenderingContext2D.isPointInPath", "isPointinPath")}}) you can optionally provide a fill rule algorithm by which to determine if a point is inside or outside a path and thus if it gets filled or not. This is useful when a path intersects itself or is nested.<br> + <br> + Two values are possible:</p> + +<ul> + <li><code><strong>"nonzero</strong></code>": The <a class="external external-icon" href="http://en.wikipedia.org/wiki/Nonzero-rule">non-zero winding rule</a>, which is the default rule.</li> + <li><code><strong>"evenodd"</strong></code>: The <a class="external external-icon" href="http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule">even-odd winding rule</a>.</li> +</ul> + +<p>In this example we are using the <code>evenodd</code> rule.</p> + +<pre class="brush: js;highlight[6]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + ctx.beginPath(); + ctx.arc(50, 50, 30, 0, Math.PI * 2, true); + ctx.arc(50, 50, 15, 0, Math.PI * 2, true); + ctx.fill('evenodd'); +}</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="100" height="100"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("Canvas_fill_rules", "110", "110", "https://mdn.mozillademos.org/files/9855/fill-rule.png")}}</p> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_shapes", "Web/API/Canvas_API/Tutorial/Drawing_text")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/basic_animations/index.html b/files/es/web/api/canvas_api/tutorial/basic_animations/index.html new file mode 100644 index 0000000000..94c66fb05d --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/basic_animations/index.html @@ -0,0 +1,333 @@ +--- +title: Animaciones básicas +slug: Web/Guide/HTML/Canvas_tutorial/Basic_animations +tags: + - Canvas + - HTML5 + - Intermedio + - Tutorial + - graficos +translation_of: Web/API/Canvas_API/Tutorial/Basic_animations +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}</div> + +<div class="summary"> +<p>Ya que estamos usando JavaScript para controlar elementos {{HTMLElement("canvas")}} , también es muy fácil hacer animaciones (interactivas). En este capitulo veremos como hacer algunas animaciones básicas.</p> +</div> + +<p>Probablemente la mayor limitación es que una vez que se dibuja una forma, se mantiene de esa manera. Si necesitamos moverlo tenemos que volver a dibujarlo y todo lo que se dibujó antes. Se necesita mucho tiempo para volver a dibujar estructuras complejas y el rendimiento depende en gran medida de la velocidad de la computadora en la que se ejecuta.</p> + +<h2 id="Basic_animation_steps" name="Basic_animation_steps">Pasos básicos de animación</h2> + +<p>Estos son los pasos que necesitas para dibujar un cuadro:</p> + +<ol> + <li><strong>Limpiar el canvas</strong><br> + A menos que las formas que vas a dibujar llenen el canvas completo (por ejemplo, una imagen de fondo), debes borrar cualquier forma que haya dibujado previamente. La forma más fácil de hacerlo es usar el método {{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}}.</li> + <li><strong>Guardar el estado del canvas</strong><br> + Si estás cambiando alguna configuración (como estilos, transformaciones, etc.) que afecte el estado del canvas y deseas asegurarte de que se utiliza el estado original cada vez que se dibuja una figura, debes guardar ese estado original. </li> + <li><strong>Dibujar formas animadas</strong><br> + El paso en el que realizas el renderizado del cuadro actual.</li> + <li><strong>Restaurar el estado del canvas</strong><br> + Si has guardado el estado, restáuralo antes de dibujar un nuevo cuadro.</li> +</ol> + +<h2 id="Controlling_an_animation" name="Controlling_an_animation">Controlando una animación</h2> + +<p>Las formas se dibujan en el canvas utilizando los métodos de canvas directamente o llamando a funciones personalizadas. En circunstancias normales, solo vemos que estos resultados aparecen en el canvas cuando el script termina de ejecutarse. Por ejemplo, no es posible hacer una animación desde un bucle <code>for</code>.</p> + +<p>Eso significa que necesitamos una forma de ejecutar nuestras funciones de dibujo durante un período de tiempo. Hay dos formas de controlar una animación como esta.</p> + +<h3 id="Actualizaciones_Programadas">Actualizaciones Programadas</h3> + +<p>Primero {{domxref("window.setInterval()")}}, {{domxref("window.setTimeout()")}}, y {{domxref("window.requestAnimationFrame()")}} son funciones que pueden ser usadas para llamar una función especifica en un periodo de tiempo establecido.</p> + +<dl> + <dt>{{domxref("WindowTimers.setInterval", "setInterval(function, delay)")}}</dt> + <dd>Ejecuta una función especificada por <code>function</code> cada <code>delay</code> milisegundos.</dd> + <dt>{{domxref("WindowTimers.setTimeout", "setTimeout(function, delay)")}}</dt> + <dd>Ejecuta una función especificada por <code>function</code> dentro de <code>delay</code> milisegundos.</dd> + <dt>{{domxref("Window.requestAnimationFrame()", "requestAnimationFrame(callback)")}}</dt> + <dd>Comunica al navegador que deseas iniciar una animación y requieres que el navegador llame a las funciones especificas para actualizar la misma antes de la siguiente escena.</dd> +</dl> + +<p>Si no quieres ninguna interacción del usuario puedes usar la función <code>setInterval()</code> que repite la ejecución del código suministrado. Si lo que queremos es hacer un juego, podríamos usar eventos de teclado o el mouse para controlar la animación y usar <code>setTimeout()</code>. Al establecer los {{domxref("EventListener")}}, capturamos cualquier interacción del usuario y ejecutamos nuestras funciones de animación.</p> + +<div class="note"> +<p>En los siguiente ejemplo,usaremos el método para controlar animaciones {{domxref("window.requestAnimationFrame()")}}. El método <code>requestAnimationFrame</code> provee formas amigables y mas eficientes para animar llamando cada marco de animación cuando el sistema esta listo para dibujar. La cantidad de devoluciones de llamadas suele ser 60 veces por segundo y podría ser reducido a menor periodo cuando se corre en un segundo plano. Para mas información acerca de los ciclos de animación, especialmente para juegos, Ver el Articulo <a href="/es/docs/Games/Anatomy">Anatomía de un videojuego</a> en nuestra <a href="/en-US/docs/Games">GameZona de desarrollo de Juegos</a>.</p> +</div> + +<h2 id="Un_sistema_solar_animado">Un sistema solar animado</h2> + +<p>Este ejemplo animado es un pequeño modelo de nuestro sistema solar.</p> + +<pre class="brush: js">var sun = new Image(); +var moon = new Image(); +var earth = new Image(); +function init(){ + sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png'; + moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png'; + earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png'; + window.requestAnimationFrame(draw); +} + +function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + ctx.globalCompositeOperation = 'destination-over'; + ctx.clearRect(0,0,300,300); // limpiar canvas + + ctx.fillStyle = 'rgba(0,0,0,0.4)'; + ctx.strokeStyle = 'rgba(0,153,255,0.4)'; + ctx.save(); + ctx.translate(150,150); + + // La tierra + var time = new Date(); + ctx.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() ); + ctx.translate(105,0); + ctx.fillRect(0,-12,50,24); // Sombra + ctx.drawImage(earth,-12,-12); + + // La luna + ctx.save(); + ctx.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() ); + ctx.translate(0,28.5); + ctx.drawImage(moon,-3.5,-3.5); + ctx.restore(); + + ctx.restore(); + + ctx.beginPath(); + ctx.arc(150,150,105,0,Math.PI*2,false); // Órbita terrestre + ctx.stroke(); + + ctx.drawImage(sun,0,0,300,300); + + window.requestAnimationFrame(draw); +} + +init(); +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="300" height="300"></canvas></pre> +</div> + +<p>{{EmbedLiveSample("Un_sistema_solar_animado", "310", "310", "https://mdn.mozillademos.org/files/202/Canvas_animation1.png")}}</p> + +<h2 id="Un_reloj_animado">Un reloj animado</h2> + +<p>Este ejemplo dibuja una reloj animado, mostrando la hora actual.</p> + +<pre class="brush: js">function clock(){ + var now = new Date(); + var ctx = document.getElementById('canvas').getContext('2d'); + ctx.save(); + ctx.clearRect(0,0,150,150); + ctx.translate(75,75); + ctx.scale(0.4,0.4); + ctx.rotate(-Math.PI/2); + ctx.strokeStyle = "black"; + ctx.fillStyle = "white"; + ctx.lineWidth = 8; + ctx.lineCap = "round"; + + // Aguja de la hora + ctx.save(); + for (var i=0;i<12;i++){ + ctx.beginPath(); + ctx.rotate(Math.PI/6); + ctx.moveTo(100,0); + ctx.lineTo(120,0); + ctx.stroke(); + } + ctx.restore(); + + // Aguja del minuto + ctx.save(); + ctx.lineWidth = 5; + for (i=0;i<60;i++){ + if (i%5!=0) { + ctx.beginPath(); + ctx.moveTo(117,0); + ctx.lineTo(120,0); + ctx.stroke(); + } + ctx.rotate(Math.PI/30); + } + ctx.restore(); + + var sec = now.getSeconds(); + var min = now.getMinutes(); + var hr = now.getHours(); + hr = hr>=12 ? hr-12 : hr; + + ctx.fillStyle = "black"; + + // Escribimos la hora + ctx.save(); + ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec ) + ctx.lineWidth = 14; + ctx.beginPath(); + ctx.moveTo(-20,0); + ctx.lineTo(80,0); + ctx.stroke(); + ctx.restore(); + + // escribimos los minutos + ctx.save(); + ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec ) + ctx.lineWidth = 10; + ctx.beginPath(); + ctx.moveTo(-28,0); + ctx.lineTo(112,0); + ctx.stroke(); + ctx.restore(); + + // escribimos los segundos + ctx.save(); + ctx.rotate(sec * Math.PI/30); + ctx.strokeStyle = "#D40000"; + ctx.fillStyle = "#D40000"; + ctx.lineWidth = 6; + ctx.beginPath(); + ctx.moveTo(-30,0); + ctx.lineTo(83,0); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(0,0,10,0,Math.PI*2,true); + ctx.fill(); + ctx.beginPath(); + ctx.arc(95,0,10,0,Math.PI*2,true); + ctx.stroke(); + ctx.fillStyle = "rgba(0,0,0,0)"; + ctx.arc(0,0,3,0,Math.PI*2,true); + ctx.fill(); + ctx.restore(); + + ctx.beginPath(); + ctx.lineWidth = 14; + ctx.strokeStyle = '#325FA2'; + ctx.arc(0,0,142,0,Math.PI*2,true); + ctx.stroke(); + + ctx.restore(); + + window.requestAnimationFrame(clock); +} + +window.requestAnimationFrame(clock);</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> +</div> + +<p>{{EmbedLiveSample("Un_reloj_animado", "180", "180", "https://mdn.mozillademos.org/files/203/Canvas_animation2.png")}}</p> + +<h2 id="Un_panorama_en_bucle">Un panorama en bucle</h2> + +<p>En este ejemplo, una foto panorámica avanza de izquierda a derecha. Donde usaremos <a href="http://commons.wikimedia.org/wiki/File:Capitan_Meadows,_Yosemite_National_Park.jpg" title="http://commons.wikimedia.org/wiki/File:Capitan_Meadows,_Yosemite_National_Park.jpg">una imagen del Parque Nacional de Yosemite</a> que tomamos de Wikipedia, pero tu podrías usar cualquier imagen que sea mas grande que el canvas.</p> + +<pre class="brush: js">var img = new Image(); + +// Variables de usuario - personalizar estas para cambiar la imagen cuando inicie el desplazamiento +// dirección y velocidad. + +img.src = 'https://mdn.mozillademos.org/files/4553/Capitan_Meadows,_Yosemite_National_Park.jpg'; +var CanvasXSize = 800; +var CanvasYSize = 200; +var speed = 30; //más bajo es más rápido +var scale = 1.05; +var y = -4.5; //desplazamiento vertical + +// Programa principal + +var dx = 0.75; +var imgW; +var imgH; +var x = 0; +var clearX; +var clearY; +var ctx; + +img.onload = function() { + imgW = img.width * scale; + imgH = img.height * scale; + + if (imgW > CanvasXSize) { + // imagen más grande que canvas + x = CanvasXSize - imgW; + } + if (imgW > CanvasXSize) { + // ancho de imagen más grande que canvas + clearX = imgW; + } else { + clearX = CanvasXSize; + } + if (imgH > CanvasYSize) { + // altura de la imagen más grande que canvas + clearY = imgH; + } else { + clearY = CanvasYSize; + } + + // obtener contexto de canvas + ctx = document.getElementById('canvas').getContext('2d'); + + // establecer frecuencia de actualización + return setInterval(draw, speed); +} + +function draw() { + ctx.clearRect(0, 0, clearX, clearY); // clear the canvas + + // si la imagen es <= tamaño de Canvas + if (imgW <= CanvasXSize) { + // reiniciar, comenzar desde el principio + if (x > CanvasXSize) { + x = -imgW + x; + } + // dibujar image1 adicional + if (x > 0) { + ctx.drawImage(img, -imgW + x, y, imgW, imgH); + } + // dibujar image2 adicional + if (x - imgW > 0) { + ctx.drawImage(img, -imgW * 2 + x, y, imgW, imgH); + } + } + + // la imagen es > tamaño de Canvas + else { + // reiniciar, comenzar desde el principio + if (x > (CanvasXSize)) { + x = CanvasXSize - imgW; + } + // dibujar image adicional + if (x > (CanvasXSize-imgW)) { + ctx.drawImage(img, x - imgW + 1, y, imgW, imgH); + } + } + // dibujar imagen + ctx.drawImage(img, x, y,imgW, imgH); + // cantidad para moverse + x += dx; +}</pre> + +<p>Debajo esta el elemento {{HTMLElement("canvas")}} en el cual va la imagen se va ha desplazar. Nota que el ancho y el alto especificado aquí son las variables <code>CanvasXZSize</code> y <code>CanvasYSize</code>.</p> + +<pre class="brush: html"><canvas id="canvas" width="800" height="200"></canvas></pre> + +<p>{{EmbedLiveSample("Un_panorama_en_bucle", "830", "230")}}</p> + +<h2 id="Other_examples" name="Other_examples">Otros ejemplos</h2> + +<dl> + <dt><a href="/es/docs/Web/API/Canvas_API/A_basic_ray-caster" title="/en-US/docs/Web/Guide/HTML/A_basic_ray-caster">Un ray-caster básico</a></dt> + <dd>Un buen ejemplo de como hacer animaciones usando como control el teclado.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/Tutorial/Advanced_animations">Animaciones avanzadas</a></dt> + <dd>Vamos a echar un vistazo a algunas técnicas de animación avanzadas y física en el próximo capítulo.</dd> +</dl> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/basic_usage/index.html b/files/es/web/api/canvas_api/tutorial/basic_usage/index.html new file mode 100644 index 0000000000..17136d7a7e --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/basic_usage/index.html @@ -0,0 +1,146 @@ +--- +title: Uso básico de Canvas +slug: Web/Guide/HTML/Canvas_tutorial/Basic_usage +translation_of: Web/API/Canvas_API/Tutorial/Basic_usage +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial", "Web/API/Canvas_API/Tutorial/Dibujando_formas")}}</div> + +<div class="summary"> +<p>Comenzamos este tutorial observando el elemento {{HTMLElement("canvas")}}. Al final de esta página, sabrás como configurar el entorno 2D de canvas y habrás dibujado el primer ejemplo en tu navegador.</p> +</div> + +<h2 id="El_elemento_<canvas>">El elemento <code><canvas></code></h2> + +<pre class="brush: html"><canvas id="tutorial" width="150" height="150"></canvas> +</pre> + +<p>A primera vista, un elemento {{HTMLElement("canvas")}} es parecido al elemento {{HTMLElement("img")}}, con la diferencia que este no tiene los atributos <code>src</code> y <code>alt</code>. El elemento <code><canvas></code> tiene solo dos atributos - {{htmlattrxref("width", "canvas")}} y {{htmlattrxref("height", "canvas")}}. Ambos son opcionales y pueden ser definidos usando propiedades <a href="/en-US/docs/DOM" rel="internal" title="en/DOM">DOM</a>. Cuando los atributos ancho y alto no estan especificados, el lienzo se inicializara con <strong>300 pixels</strong> ancho y <strong>150 pixels</strong> de alto. El elemento puede ser arbitrariamente redimensionado por CSS, pero durante el renderizado la imagen es escalada para ajustarse al tamaño de su layout. Si el tamaño del CSS no respeta el ratio del canvas inicial, este aparecerá distorsionado.</p> + +<div class="note"> +<p><strong>Nota:</strong> Si su renderizado se ve distorsionado, pruebe especificar los atributos width y height explícitamente en los atributos del <code><canvas></code> , y no usando CSS.</p> +</div> + +<p>El atributo <a href="/es/docs/Web/HTML/Atributos_Globales/id">id</a> no está especificado para el elemento <code><canvas></code> pero es uno de los <a href="/es/docs/Web/HTML/Atributos_Globales">atributos globales de HTML</a> el cual puede ser aplicado a cualquier elemento HTML (como <a href="en-US/docs/Web/HTML/Global_attributes/class">class</a> por ejemplo). Siempre es buena idea proporcionar un <code>id</code> porque esto hace más fácil identificarlo en un script.</p> + +<p>El elemento <code><canvas></code> puede ser estilizado como a cualquier imagen normal (margin, border, background, etc). Estas reglas, sin embargo, no afectan a lo dibujado sobre el canvas. Mas adelante veremos cómo se hace esto en un <a href="en-US/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors">capítulo dedicado</a> en este tutorial. Cuando no tenemos reglas de estilo aplicadas al canvas, este será completamente transparente.</p> + +<div id="section_2"> +<h3 id="Contenido_alternativo">Contenido alternativo</h3> + +<p>El elemento <canvas> se diferencia de un tag {{HTMLElement("img")}} en que, como los elementos {{HTMLElement("video")}}, {{HTMLElement("audio")}} o {{HTMLElement("picture")}}, es fácil definir contenido alternativo (fallback content) para mostrarse en navegadores viejos que no soporten el elemento <canvas>, como versiones de Internet Explorer previas a la versión 9 o navegadores de texto. Siempre debes proporcionar contenido alternativo para mostrar en estos navegadores.</p> + +<p>Proporcionar contenido alternativo es muy explicito: solo debemos insertar el contenido alterno dentro del elemento <canvas>. Los navegadores que no soporten <code><canvas></code> ignoraran el contenedor y mostrarán el contenido indicado dentro de este. Navegadores que soporten <code><canvas></code> ignorarán el contenido en su interior (de las etiquetas), y mostrarán el canvas normalmente.</p> + +<p>Por ejemplo, podremos proporcionar un texto descriptivo del contenido del canvas o proveer una imagen estática del contenido rederizado. Nos podría quedar algo así:</p> + +<pre class="brush: html"><canvas id="stockGraph" width="150" height="150"> + current stock price: $3.15 +0.15 +</canvas> + +<canvas id="clock" width="150" height="150"> + <img src="images/clock.png" width="150" height="150" alt=""/> +</canvas> +</pre> + +<h2 id="Etiqueta_<canvas>_requerida">Etiqueta <code></canvas></code> requerida</h2> + +<p>De manera distinta al elemento {{HTMLElement("img")}}, el elemento {{HTMLElement("canvas")}} requiere cerrar la etiqueta (<code></canvas></code>).</p> + +<div class="note"> +<p><strong>Note:</strong> Aunque las versiones anteriores del navegador Safari de Apple no requeria el cierre de la etiqueta, la especificacion indica que es necesaria, asi que tu deberias incluir esta para asegurarte la compatibilidad. Aquellas versiones de Safari (anteriores versiones a 2.0) renderizaran el contenido de regreso agregandolo al canvas mismo a no ser que utilice trucos de CSS para enmascararlo. Afortunadamente, los usuarios de aquellas versiones de Safari son raros hoy en dia.</p> +</div> + +<p>Si el contenido alternativo no se necesita, un simple <code><canvas id="foo" ...></canvas></code> es completamente compatible con todos los navegadores que soportan canvas.</p> + +<h2 id="El_contexto_de_renderización">El contexto de renderización</h2> + +<p>{{HTMLElement("canvas")}} crea un lienzo de dibujo fijado que expone uno o mas contextos renderizados, los cuales son usados para crear y manipular el contenido mostrado. Nos enfocaremos en renderizacion de contextos 2D. Otros contextos deberan proveer diferentes tipos de renderizaciones; por ejemplo, <a href="/en-US/docs/Web/WebGL" title="/en-US/docs/Web/WebGL">WebGL</a> usa un 3D contexto ("experimental-webgl") basado sobre <a class="external" href="http://www.khronos.org/opengles/" rel="external" title="http://en.wikipedia.org/wiki/OpenGL_ES">OpenGL ES</a>.</p> + +<p>El canvas esta inicialmente en blanco. Para mostrar alguna cosa, un script primero necesita acceder al contexto a renderizar y dibujar sobre este. El elemento {{HTMLElement("canvas")}} tiene un <a href="/en-US/docs/Web/API/HTMLCanvasElement#Methods" title="/en-US/docs/Web/API/HTMLCanvasElement#Methods">method</a> llamado <code>getContext()</code>, usado para obtener el contexto a renderizar y sus funciones de dibujo. <code>getContext()</code> toma un parametro, el tipo de contexto. Para graficos 2D, como los que cubre este tutorial, su especificacion es "2d".</p> + +<pre class="brush: js">var canvas = document.getElementById('tutorial'); +var ctx = canvas.getContext('2d'); +</pre> + +<p>La primera linea regresa el nodo DOM para el elemento {{HTMLElement("canvas")}} llamando al metodo {{domxref("document.getElementById()")}}. Una vez tu tienes el elemento nodo, tu puedes acceder al contexto de dibujo usando su metodo <code>getContext()</code>.</p> + +<div id="section_5"> +<h2 id="Comprobando_soporte">Comprobando soporte</h2> + +<p>El contenido de regreso que es mostrado en navegadores los cuales no soportan {{HTMLElement("canvas")}}. Para los Scripts puede tambien comprobarse su soporte desde la programacion por un simple test para la presencia del metodo <code>getContext()</code>. Con un trozo de codigo parecido al que viene debajo:</p> + +<pre class="brush: js">var canvas = document.getElementById('tutorial'); + +if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + // drawing code here +} else { + // canvas-unsupported code here +} +</pre> +</div> +</div> + +<h2 id="Un_esqueleto_de_plantilla">Un esqueleto de plantilla</h2> + +<p>Aqui esta una plantilla minimalista, la cual usaremos como punto de partida para posteriores ejemplos.</p> + +<pre class="brush: html"><html> + <head> + <title>Canvas tutorial</title> + <script type="text/javascript"> + function draw(){ + var canvas = document.getElementById('tutorial'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + } + } + </script> + <style type="text/css"> + canvas { border: 1px solid black; } + </style> + </head> + <body onload="draw();"> + <canvas id="tutorial" width="150" height="150"></canvas> + </body> +</html> +</pre> + +<p>El script incluye una funcion llamada draw(), la cual es ejecutada una vez finalizada la carga de la pagina; este esta hecho usando el evento load del documento. Esta funcion, o una parecida, podria tambien ser llamada usando {{domxref("window.setTimeout()")}}, {{domxref("window.setInterval()")}}, o cualquier otro manejador de evento, a lo largo de que la pagina esta siendo cargada la primera vez.</p> + +<p>Aqui esta como la plantilla se ve en acción:</p> + +<p>{{EmbedLiveSample("Un_esqueleto_de_plantilla", 160, 160)}}</p> + +<h2 id="Un_simple_ejemplo">Un simple ejemplo</h2> + +<p>Para comenzar, daremos un vistazo a un simple ejemplo que dibuja dos rectangulos que se intersectan, uno de los cuales tiene alpha transparencia. Exploraremos como esto trabaja en mas detalle en posteriores ejemplos.</p> + +<pre class="brush: html"><html> + <head> + <script type="application/javascript"> + function draw() { + var canvas = document.getElementById("canvas"); + if (canvas.getContext) { + var ctx = canvas.getContext("2d"); + + ctx.fillStyle = "rgb(200,0,0)"; + ctx.fillRect (10, 10, 55, 50); + + ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; + ctx.fillRect (30, 30, 55, 50); + } + } + </script> + </head> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> + +<p>Este ejemplo quedaría así:</p> + +<p>{{EmbedLiveSample("Un_simple_ejemplo", 160, 160, "https://mdn.mozillademos.org/files/228/canvas_ex1.png")}}</p> + +<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial", "Web/Guide/HTML/Canvas_tutorial/Dibujando_formas")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html b/files/es/web/api/canvas_api/tutorial/compositing/example/index.html index b85b83238c..b85b83238c 100644 --- a/files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html +++ b/files/es/web/api/canvas_api/tutorial/compositing/example/index.html diff --git a/files/es/web/api/canvas_api/tutorial/drawing_shapes/index.html b/files/es/web/api/canvas_api/tutorial/drawing_shapes/index.html new file mode 100644 index 0000000000..3467533e93 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/drawing_shapes/index.html @@ -0,0 +1,513 @@ +--- +title: Dibujando formas con canvas +slug: Web/Guide/HTML/Canvas_tutorial/Dibujando_formas +tags: + - Canvas + - HTML + - HTML Canvas + - HTML5 + - Intermedio + - Tutorial + - graficos +translation_of: Web/API/Canvas_API/Tutorial/Drawing_shapes +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Basic_usage", "Web/API/Canvas_API/Tutorial/Applying_styles_and_colors")}}</div> + +<div class="summary"> +<p>Ahora que hemos preparado nuestro <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_usage">entorno canvas</a>, podemos entrar en detalles de como dibujar en el canvas. Al final de este artículo, habrás aprendido como dibujar rectángulos, triángulos, líneas, arcos y curvas, dándote familiaridad con algunas figuras básicas. Trabajar con rutas es esencial cuando dibujamos objetos sobre el canvas y veremos como se puede hacer eso.</p> +</div> + +<h2 id="La_cuadrícula">La cuadrícula</h2> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/224/Canvas_default_grid.png" style="float: right; height: 220px; width: 220px;">Antes de que podamos empezar a dibujar, necesitamos hablar sobre la cuadrícula del canvas o el <strong>espacio de coordenadas</strong>. La plantilla HTML de la página anterior tenía un elemento canvas con un 'height' y un 'width' de 150 píxeles. A la derecha, puedes ver este canvas con la cuadrícula por defecto superpuesta. Normalmente una unidad en la cuadrícula corresponde a un píxel en el elemento canvas. El origen de esta cuadrícula está posicionado en la esquina superior izquierda (coordenada (0,0)). Todos los elementos estan posicionados de manera relativa a este punto, así que la posición de la esquina superior izquierda del cuadrado azul es de 'x' pixeles desde la izquierda y 'y' pixeles desde arriba (coordenada (x,y)). Mas tarde en este tutorial veremos como trasladar el punto de origen a una posicion diferente, girar la cuadrícula e incluso darle una escala diferente. Por ahora nos dedicaremos a lo mas común.</p> + +<h2 id="Dibujando_rectángulos">Dibujando rectángulos</h2> + +<p>A diferencia de <a href="/en-US/docs/SVG" rel="internal" title="en/SVG">SVG</a>, {{HTMLElement("canvas")}} solo soporta una forma primitiva: rectangulos. Todas las otras formas deben ser creadas por la combinación de uno o más trazos, listas de puntos conectados por líneas. Afortunadamente, tenemos una variedad de funciones para dibujar trazos que hacen posible componer formas muy complejas.</p> + +<div id="section_3"> +<p>Primero veamos el rectángulo. Aquí hay tres funciones que podemos usar en el canvas para dibujarlos:</p> + +<dl> + <dt><code>fillRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Dibuja un rectángulo relleno.</dd> + <dt><code>strokeRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Dibuja el contorno de un rectángulo.</dd> + <dt><code>clearRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Borra un área rectangular especificada, dejándola totalmente transparente.</dd> +</dl> + +<p>Cada una de estas tres funciones toma los mismos parámetros. X e Y especifican la posición del canvas (en relación con el origen) desde la esquina superior izquierda del rectángulo. Tambien especifica los parámetros de anchura y altura que proporcionan el tamaño del rectángulo.</p> + +<p>A continuación se muestra la función draw() de la página anterior, pero ahora haciendo uso de estas tres funciones.</p> + +<h3 id="Ejemplo_de_forma_rectangular">Ejemplo de forma rectangular</h3> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + + ctx.fillRect(25,25,100,100); + ctx.clearRect(45,45,60,60); + ctx.strokeRect(50,50,50,50); + } +}</pre> + +<p>El resultado de este ejemplo se muestra a continuación.</p> + +<p>{{EmbedLiveSample("Rectangular_shape_example", 160, 160, "https://mdn.mozillademos.org/files/245/Canvas_rect.png")}}</p> + +<p>La función fillRect() dibuja un cuadrado grande negro de 100 píxeles en cada lado. La función clearRect() luego borra un cuadrado de 60x60 píxeles del centro, y luego strokeRect() es llamado para crear un contorno rectangular de 50x50 píxeles dentro del cuadrado borrado.</p> + +<p>En las próximas páginas veremos dos métodos alternativos para clearRect(), y también veremos cómo cambiar el color y el trazo de diferentes formas.</p> + +<p>A diferencia de las funciones de trazo que veremos en la próxima sección, las tres funciones del rectángulo dibujan inmediatamente en el canvas.</p> + +<h2 id="Dibujando_trazos">Dibujando trazos</h2> + +<p>Crear formas mediante trazos requiere algunos pasos adicionales.</p> + +<ol> + <li>Primero, se crea el trazo.</li> + <li>A continuación, se usan <a href="/es/docs/Web/API/CanvasRenderingContext2D#Paths">comandos de dibujo</a> para dibujar dentro del trazo.</li> + <li>Después, se cierra el trazo.</li> + <li>Una vez el trazo ha sido creado, se le puede dar contorno o relleno para renderizarlo.</li> +</ol> + +<p>Estas son las funciones que se usan para llevar a cabo estos pasos:</p> + +<dl> + <dt><code>beginPath()</code></dt> + <dd>Crea un nuevo trazo. Una vez creado, los comandos de dibujo futuros son aplicados dentro del trazo y usados para construir el nuevo trazo hacia arriba.</dd> + <dt><code>closePath()</code></dt> + <dd>Cierra el trazo de tal forma que los comandos de dibujo futuros son, una vez más redireccionados al contexto.</dd> + <dt><code>stroke()</code></dt> + <dd>Dibuja el contorno de la forma.</dd> + <dt><code>fill()</code></dt> + <dd>Dibuja una forma solida rellenando el área del trazo.</dd> +</dl> + +<p>El primer paso para crear un trazo es llamar la función <code>beginPath()</code>. Internamente, los trazos son guardados como una lista de subtrazos (lineas, arcos, etc) los cuales juntos crean una forma. Todo tiempo que sea llamado este método la lista es reseteada y podemos empezar a dibujar nuevas formas.</p> + +<div class="note"><strong>Nota:</strong> Cuando el trazo actual este vacio, como aparece inmediatamente despues de llamar la función <code>beginPath()</code>, o en un canvas nuevo, el primer comando para la construcción del trazo es siempre tratada como un <code>moveTo()</code>, independientemente de cual es el trazo actual. Por esta razón casi siempre querrás específicamente setear tu posición de inicio despues de resetear un trazo.</div> + +<p>El segundo paso es llamar los métodos que específican los trazos a crear. Los veremos en seguida.</p> + +<p>El tercero, y un paso opcional, es llamar a la función <code>closePath()</code>. Este método trata de cerrar la forma dibujando una linea recta desde el punto actual al inicio. Si la forma ya ha sido cerrada o hay solamente un punto en la lista, la función hace nada.</p> + +<div class="note"><strong>Nota:</strong> Cuando llamas a la función <code>fill()</code>, cualquier forma abierta es cerrada automaticamente, de tal forma que no tendrás que llamar a la función <code>closePath()</code>. Este no es el caso cuando llamas a la función <code>stroke()</code>.</div> + +<h3 id="Dibujando_un_triangulo">Dibujando un triangulo</h3> + +<p>Por ejemplo, el código para dibujar un triangulo luciría como el siguiente:</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + ctx.beginPath(); + ctx.moveTo(75,50); + ctx.lineTo(100,75); + ctx.lineTo(100,25); + ctx.closePath(); + ctx.fill(); + } +} +</pre> + +<p>El resultado lucirá así:</p> + +<p>{{EmbedLiveSample("Drawing_a_triangle", 160, 160)}}</p> + +<h3 id="Moviendo_la_pluma">Moviendo la pluma</h3> + +<p>Una función muy útil, la cual realmente no dibuja algo pero convierte parte de la lista de trazos descrita arriba, es la función <code>moveTo()</code>. Puedes, probablemente, pensar mejor de esta como levantar el lápiz o la pluma de un punto en un pedazo de papel y ponerlo en el siguiente punto.</p> + +<dl> + <dt><code>moveTo(<em>x</em>, <em>y</em>)</code></dt> + <dd>Mueve la pluma a las coordenadas específicadas por <code>x</code> e <code>y</code>.</dd> +</dl> + +<p>Cuando el canvas es inicializado ó la función <code>beginPath()</code> es llamada, querrás usar la función <code>moveTo()</code> para colocar el punto de inicio en alguna otra parte. Podríamos usar <code>moveTo()</code> para dibujar trazos sin conectar. Toma un vistazo a la cara sonriente de abajo. He marcado los lugares donde use el método <code>moveTo()</code> (las líneas rojas).</p> + +<p>Para intentar esto por tí mismo, puedes usar el pequeño código de abajo. Solo pégalo dentro de la función <code>draw()</code> que vimos antes.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + ctx.beginPath(); + ctx.arc(75,75,50,0,Math.PI*2,true); // Círculo externo + ctx.moveTo(110,75); + ctx.arc(75,75,35,0,Math.PI,false); // Boca (contra reloj) + ctx.moveTo(65,65); + ctx.arc(60,65,5,0,Math.PI*2,true); // Ojo izquierdo + ctx.moveTo(95,65); + ctx.arc(90,65,5,0,Math.PI*2,true); // Ojo derecho + ctx.stroke(); + } +} +</pre> + +<p>El resultado luce así:</p> + +<p>{{EmbedLiveSample("Moving_the_pen", 160, 160, "https://mdn.mozillademos.org/files/252/Canvas_smiley.png")}}</p> + +<p>Si quisieras ver las líneas conectadas, puedes remover las líneas de código que llaman <code>moveTo()</code>.</p> + +<div class="note"> +<p><strong>Nota:</strong> Para aprender más sobre la función <code>arc()</code>, vea los {{anch("Arcs")}} a continuación.</p> +</div> + +<h3 id="Líneas">Líneas</h3> + +<p>Para dibujar lineas rectas usa el método <code>lineTo()</code>.</p> + +<dl> + <dt><code>lineTo(<em>x</em>, <em>y</em>)</code></dt> + <dd>Dibuja una línea desde la posición actual del dibujo a la posición específicada por <code>x</code> e <code>y</code>.</dd> +</dl> + +<p>Este método toma dos argumentos <code>x</code> e <code>y</code>, los cuales son las coordenadas del punto final de la linea. El punto de inicio es dependiente de los trazos previamente dibujados, donde el punto final del trazo anterior es el punto inicial para el siguiente, etc. El punto de inicio también puede ser cambiado usando el método <code>moveTo()</code>.</p> + +<p>El ejemplo siguiente dibuja dos triángulos, uno rellenado y el otro contorneado.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + // Triángulo rellenado + ctx.beginPath(); + ctx.moveTo(25,25); + ctx.lineTo(105,25); + ctx.lineTo(25,105); + ctx.fill(); + + // Triángulo contorneado + ctx.beginPath(); + ctx.moveTo(125,125); + ctx.lineTo(125,45); + ctx.lineTo(45,125); + ctx.closePath(); + ctx.stroke(); + } +} +</pre> + +<p>Esto comienza llamando a <code>beginPath()</code> para empezar una nueva forma. Entonces usamos el método <code>moveTo()</code> para mover el punto de inicio a la posición deseada. Debajo de esto dos líneas son dibujadas lo cual pinta dos lados del triángulo.</p> + +<p>{{EmbedLiveSample("Lines", 160, 160, "https://mdn.mozillademos.org/files/238/Canvas_lineTo.png")}}</p> + +<p>Te darás cuenta de la diferencia entre el triángulo rellenado y el contorneado. Esto es, como se menciona arriba, porque las formas son automáticamente cerradas cuando un trazo es rellenado, pero no cuando esta contorneado. Si sacamos el <code>closePath()</code> para el triángulo contorneado, solamente dos líneas serian dibujadas, no un triángulo completo.</p> + +<h3 id="Arcos">Arcos</h3> + +<p>Para dibujar arcos o circulos usamos el método <code>arc()</code>. También puedes usar <code>arcTo()</code>, pero su implementación es un poco menos confiable, así que no lo cubriremos aquí.</p> + +<dl> + <dt><code>arc(<em>x</em>, <em>y</em>, <em>radius</em>, <em>startAngle</em>, <em>endAngle</em>, <em>anticlockwise</em>)</code></dt> + <dd>Dibuja un arco.</dd> +</dl> + +<p>Este método toma cinco parámetros: <code>x</code> e <code>y</code> son las coordenadas del centro del círculo en el cual el arco debería ser dibujado. <code>radius</code> se explica por sí solo. Los parámetros <code>startAngle</code> y <code>endAngle</code> definen el punto de inicio y punto final del arco en radianes a lo largo de la curva del círculo. Estos son medidos desde el eje x. El parámetro <code>anticlockwise</code> es un valor Booleano el cual cuando es verdadero (<code>true</code>) dibuja el arco al contrario de las manecillas del reloj, de lo contrario el arco es dibujado al sentido de las manecillas del reloj.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los ángulos en la función del arco (<code>arc</code>) son medidos en radianes, no en grados. Para convertir grados a radianes puedes usar la siguiente expresión en Javascript: <code>radians = (Math.PI/180)*degrees</code>.</p> +</div> + +<p>El siguiente ejemplo es un poco más complejo que otros que hemos visto arriba. Esto dibuja 12 diferentes arcos, todos con diferentes ángulos y rellenos.</p> + +<p>Las dos sentencias <code>for</code> son para iterar a través de las filas y columnas de los arcos. Para cada arco, empezamos un nuevo trazo llamando <code>beginPath()</code>. En el código, cada uno de los parámetros para el arco estan en una variable para su entendimiento, pero no es necesario esto en la vida real.</p> + +<p>Las coordenadas <code>x</code> e <code>y</code> deberían ser suficientemente claras. <code>radius</code> y <code>startAngle</code> estan arreglados. El <code>endAngle</code> inicia en 180 grados (la mitad de un círculo) en la primera columna y es incrementado por pasos de 90 grados, culminando en un círculo completo en la última columna.</p> + +<p>El parámetro <code>clockwise</code> resulta, en la primera y tercera fila siendo dibujado como un arco al sentido de las manecillas de reloj y la segunda y cuarta fila como arcos al contrario de las manecillas de reloj. Finalmente, la estructura <code>if</code> hace los arcos contorneados a la mitad desde arriba y los arcos hacia abajorellenados a la mitad.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="200"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + for(var i=0;i<4;i++){ + for(var j=0;j<3;j++){ + ctx.beginPath(); + var x = 25+j*50; // Coordenada x + var y = 25+i*50; // Coordenada y + var radius = 20; // Radio del arco + var startAngle = 0; // Punto inicial del círculo + var endAngle = Math.PI+(Math.PI*j)/2; // Punto final del círculo + var anticlockwise = i%2==0 ? false : true; // Sentido de las manecillas del reloj y contrario a ellas + + ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise); + + if (i>1){ + ctx.fill(); + } else { + ctx.stroke(); + } + } + } + } +} +</pre> +{{EmbedLiveSample("Arcs", 160, 210, "https://mdn.mozillademos.org/files/204/Canvas_arc.png")}} + +<h3 id="Curvas_Bezier_curvas_cuadráticas">Curvas Bezier curvas cuadráticas</h3> + +<p>El siguiente tipo de trazos disponibles son las <a class="external" href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve" rel="external" title="http://en.wikipedia.org/wiki/B%C3%A9zier_curve">curvas Bézier</a>, en sus dos variantes, cúbicas y cuadráticas. Son usadas generalmente para dibujar complejas formas orgánicas.</p> + +<dl> + <dt><code>quadraticCurveTo(cp1x, cp1y, x, y)</code></dt> + <dd><span id="result_box" lang="es"><span>Dibuja una curva cuadrática de Bézier desde la posición actual de la pluma hasta el punto final especificado por <code>x</code> e <code>y</code>, utilizando el punto de control especificado por <code>cp1x</code> y <code>cp1y</code>.</span></span></dd> + <dt><code>bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)</code></dt> + <dd>Dibuja una curva cúbica de Bézier desde la posición actual de la pluma hasta el punto final especificado por <code>x</code> e <code>y</code>, utilizando los puntos de control especificados por (<code>cp1x</code>, <code>cp1y</code>) y (<code>cp2x</code>, <code>cp2y</code>).</dd> +</dl> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/223/Canvas_curves.png" style="float: right; height: 190px; width: 190px;">La diferencia entre estos puede describirse mejor utilizando la imagen de la derecha. Una curva cuadrática de Bézier tiene un punto inicial y un punto final (puntos azules) y un solo <strong>punto de control</strong> (indicado por el punto rojo), mientras que una curva cúbica de Bézier utiliza dos puntos de control.</p> + +<p>Los parámetros <code>x</code> e <code>y</code> de ambos métodos son las coordenadas del punto final. <code>cp1x</code> y <code>cp1y</code> son las coordenadas del primer punto de control, y <code>cp2x</code> y <code>cp2y</code> son las coordenadas del segundo punto de control.</p> + +<p>El uso de curvas cuadráticas y cúbicas Bézier puede ser bastante difícil, ya que a diferencia del software de dibujo vectorial como Adobe Illustrator, no tenemos respuesta visual directa en cuanto a lo que estamos haciendo. Esto hace bastante difícil dibujar formas complejas. En el siguiente ejemplo, vamos a dibujar algunas formas orgánicas simples, pero si tienes el tiempo y, sobre todo, la paciencia, se pueden crear formas mucho más complejas.</p> + +<p>No hay nada muy difícil en estos ejemplos. En ambos casos vemos una sucesión de curvas que se dibujan que finalmente dan lugar a una forma completa.</p> + +<h4 id="Curvas_de_Bezier_cuadraticas">Curvas de Bezier cuadraticas</h4> + +<p>Este ejemplo usa multiples curvas cuadraticas de Bézier para renderizar un globo de voz.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + + // Quadratric curves example + ctx.beginPath(); + ctx.moveTo(75,25); + ctx.quadraticCurveTo(25,25,25,62.5); + ctx.quadraticCurveTo(25,100,50,100); + ctx.quadraticCurveTo(50,120,30,125); + ctx.quadraticCurveTo(60,120,65,100); + ctx.quadraticCurveTo(125,100,125,62.5); + ctx.quadraticCurveTo(125,25,75,25); + ctx.stroke(); + } +} +</pre> + +<p>{{EmbedLiveSample("Quadratic_Bezier_curves", 160, 160, "https://mdn.mozillademos.org/files/243/Canvas_quadratic.png")}}</p> + +<h4 id="Curvas_cúbicas_Bezier">Curvas cúbicas Bezier</h4> + +<p>Este ejemplo dibuja un corazon usanco curvas cúbicas de Bézier.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + // Quadratric curves example + ctx.beginPath(); + ctx.moveTo(75,40); + ctx.bezierCurveTo(75,37,70,25,50,25); + ctx.bezierCurveTo(20,25,20,62.5,20,62.5); + ctx.bezierCurveTo(20,80,40,102,75,120); + ctx.bezierCurveTo(110,102,130,80,130,62.5); + ctx.bezierCurveTo(130,62.5,130,25,100,25); + ctx.bezierCurveTo(85,25,75,37,75,40); + ctx.fill(); + } +} +</pre> + +<p>{{EmbedLiveSample("Cubic_Bezier_curves", 160, 160, "https://mdn.mozillademos.org/files/207/Canvas_bezier.png")}}</p> + +<h3 id="Rectangles">Rectangles</h3> + +<p>In addition to the three methods we saw in {{anch("Drawing rectangles")}}, which draw rectangular shapes directly to the canvas, there's also the <code>rect()</code> method, which adds a rectangular path to a currently open path.</p> + +<dl> + <dt><code>rect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Draws a rectangle whose top-left corner is specified by (<code>x</code>, <code>y</code>) with the specified <code>width</code> and <code>height</code>.</dd> +</dl> + +<p>When this method is executed, the <code>moveTo()</code> method is automatically called with the parameters (0,0). In other words, the current pen position is automatically reset to the default coordinates.</p> + +<h3 id="Making_combinations">Making combinations</h3> + +<p>So far, each example on this page has used only one type of path function per shape. However, there's no limitation to the number or types of paths you can use to create a shape. So in this final example, let's combine all of the path functions to make a set of very famous game characters.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + roundedRect(ctx,12,12,150,150,15); + roundedRect(ctx,19,19,150,150,9); + roundedRect(ctx,53,53,49,33,10); + roundedRect(ctx,53,119,49,16,6); + roundedRect(ctx,135,53,49,33,10); + roundedRect(ctx,135,119,25,49,10); + + ctx.beginPath(); + ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false); + ctx.lineTo(31,37); + ctx.fill(); + + for(var i=0;i<8;i++){ + ctx.fillRect(51+i*16,35,4,4); + } + + for(i=0;i<6;i++){ + ctx.fillRect(115,51+i*16,4,4); + } + + for(i=0;i<8;i++){ + ctx.fillRect(51+i*16,99,4,4); + } + + ctx.beginPath(); + ctx.moveTo(83,116); + ctx.lineTo(83,102); + ctx.bezierCurveTo(83,94,89,88,97,88); + ctx.bezierCurveTo(105,88,111,94,111,102); + ctx.lineTo(111,116); + ctx.lineTo(106.333,111.333); + ctx.lineTo(101.666,116); + ctx.lineTo(97,111.333); + ctx.lineTo(92.333,116); + ctx.lineTo(87.666,111.333); + ctx.lineTo(83,116); + ctx.fill(); + + ctx.fillStyle = "white"; + ctx.beginPath(); + ctx.moveTo(91,96); + ctx.bezierCurveTo(88,96,87,99,87,101); + ctx.bezierCurveTo(87,103,88,106,91,106); + ctx.bezierCurveTo(94,106,95,103,95,101); + ctx.bezierCurveTo(95,99,94,96,91,96); + ctx.moveTo(103,96); + ctx.bezierCurveTo(100,96,99,99,99,101); + ctx.bezierCurveTo(99,103,100,106,103,106); + ctx.bezierCurveTo(106,106,107,103,107,101); + ctx.bezierCurveTo(107,99,106,96,103,96); + ctx.fill(); + + ctx.fillStyle = "black"; + ctx.beginPath(); + ctx.arc(101,102,2,0,Math.PI*2,true); + ctx.fill(); + + ctx.beginPath(); + ctx.arc(89,102,2,0,Math.PI*2,true); + ctx.fill(); + } +} + +// A utility function to draw a rectangle with rounded corners. + +function roundedRect(ctx,x,y,width,height,radius){ + ctx.beginPath(); + ctx.moveTo(x,y+radius); + ctx.lineTo(x,y+height-radius); + ctx.quadraticCurveTo(x,y+height,x+radius,y+height); + ctx.lineTo(x+width-radius,y+height); + ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius); + ctx.lineTo(x+width,y+radius); + ctx.quadraticCurveTo(x+width,y,x+width-radius,y); + ctx.lineTo(x+radius,y); + ctx.quadraticCurveTo(x,y,x,y+radius); + ctx.stroke(); +} +</pre> + +<div id="section_18"> +<p>The resulting image looks like this:</p> + +<p>{{EmbedLiveSample("Making_combinations", 160, 160)}}</p> + +<p>We won't go over this in detail, since it's actually surprisingly simple. The most important things to note are the use of the <code>fillStyle</code> property on the drawing context, and the use of a utility function (in this case <code>roundedRect()</code>). Using utility functions for bits of drawing you do often can be very helpful and reduce the amount of code you need, as well as its complexity.</p> + +<p>We'll take another look at <code>fillStyle</code>, in more detail, later in this tutorial. Here, all we're doing is using it to change the fill color for paths from the default color of black to white, and then back again.</p> + +<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial/Basic_usage", "Web/Guide/HTML/Canvas_tutorial/Using_images")}}</p> +</div> +</div> + +<p> </p> diff --git a/files/es/web/api/canvas_api/tutorial/drawing_text/index.html b/files/es/web/api/canvas_api/tutorial/drawing_text/index.html new file mode 100644 index 0000000000..10a5970824 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/drawing_text/index.html @@ -0,0 +1,67 @@ +--- +title: Dibujar texto usando canvas +slug: Dibujar_texto_usando_canvas +tags: + - 'HTML:Canvas' +translation_of: Web/API/Canvas_API/Tutorial/Drawing_text +--- +<p>{{ Gecko_minversion_header(1.9) }} +{{ Fx_minversion_header(3) }} +El elemento <code><a href="es/HTML/Canvas"><canvas></a></code> permite dibujar texto en él a través de una API experimental de Mozilla. +</p> +<h3 id="API" name="API"> API </h3> +<pre class="eval">attribute DOMString mozTextStyle; +void mozDrawText(in DOMString textToDraw); +float mozMeasureText(in DOMString textToMeasure); +void mozPathText(in DOMString textToPath); +void mozTextAlongPath(in DOMString textToDraw, in boolean stroke); +</pre> +<h3 id="Notas" name="Notas"> Notas </h3> +<ul><li> El tipo de letra predeterminado es sans-serif 12pt. +</li><li> Estas extensiones de texto no están aún estandarizadas por WHATWG. +</li><li> No necesitas un contexto especial para usarlas; el contexto 2D funciona bien. +</li><li> Todos los dibujos se realizan usando la transformación actual. +</li><li> Revisa el {{ Bug(339553) }} si quieres leer más sobre las implementaciones específicas. +</li></ul> +<h3 id="Demostraciones" name="Demostraciones"> Demostraciones </h3> +<p>Mira algunos ejemplos <a class="link-https" href="https://bugzilla.mozilla.org/attachment.cgi?id=273497">aquí</a>, <a class="link-https" href="https://bugzilla.mozilla.org/attachment.cgi?id=273498">aquí</a>, y <a class="link-https" href="https://bugzilla.mozilla.org/attachment.cgi?id=273499">aquí</a>. +</p> +<h3 id="Cambiar_el_tipo_de_letra_actual" name="Cambiar_el_tipo_de_letra_actual"> Cambiar el tipo de letra actual </h3> +<p>El atributo <code>mozTextStyle</code> contiene el estilo de texto actual. Usa la misma sintaxis que el especificado para las <a href="es/CSS/font">tipografías CSS</a>. +</p><p>Ej: +</p> +<pre class="eval">ctx.mozTextStyle = "20pt Arial" +</pre> +<h3 id="Dibujar_texto" name="Dibujar_texto"> Dibujar texto </h3> +<p>Dibujar es muy sencillo. <code>mozDrawText</code> usa el estilo de texto actual, cualquiera que sea éste. Se usa el color de relleno del contexto como color del texto. +</p> +<pre class="eval">ctx.translate(10, 50); +ctx.fillStyle = "Red"; +ctx.mozDrawText("Sample String"); +</pre> +<h3 id="Medir_texto" name="Medir_texto"> Medir texto </h3> +<p>A veces es útil saber qué tan ancho es un trozo de texto en particular (para centrarlo en una ventana, por ejemplo). +</p> +<pre class="eval">var text = "Sample String"; +var width = ctx.canvas.width; +var len = ctx.mozMeasureText(text); +ctx.translate(len/2, 0); +ctx.mozDrawText(text); +</pre> +<h3 id="Interacci.C3.B3n_texto.2Ftrazo" name="Interacci.C3.B3n_texto.2Ftrazo"> Interacción texto/trazo </h3> +<p>Si quieres tachar un texto, <code>mozDrawText</code> no te lo permite. En cambio, <code>mozPathText</code> agrega el tachado de texto al trazo actual. +</p> +<pre class="eval">ctx.fillStyle = "green"; +ctx.strokeStyle = "black"; +ctx.mozPathText("Sample String"); +ctx.fill() +ctx.stroke() +</pre> +<p>Supongamos ahora que quieres agregar un texto que se acomode a un trazo que dibujaste (una línea curva o algo parecido) es donde aparece <code>mozTextAlongPath</code>. Al contrario de otras funciones de texto, <code>mozTextAlongPath</code> necesita dos argumentos: el texto y qué se quiere hacer con él. <code>mozTextAlongPath</code> aproxima el trazo actual como una serie de segmentos de línea y ubica cada carácter encima de ese trazo. Los caracteres no son cambiados de tamaño o transformados de acuerdo a la curvatura de la base; toman la orientación del trazo a la mitad del carácter. +</p><p>Una vez que <code>mozTextAlongPath</code> sabe dónde está el carácter, busca el segundo parámetro para decidir qué hacer con él. Si el segundo parámetro es <code>false</code>, entonces dibuja el carácter como lo haría <code>mozDrawText</code>. Si es <code>true</code>, agrega el carácter al trazo actual, como lo hace <code>mozPathText</code>. Esto puede usarse para crear efectos únicos. +</p><p><br> +</p><p><br> +</p> +<div class="noinclude"> +</div> +{{ languages( { "en": "en/Drawing_text_using_a_canvas", "fr": "fr/Dessin_de_texte_avec_canvas", "ja": "ja/Drawing_text_using_a_canvas", "pl": "pl/Rysowanie_tekstu_przy_u\u017cyciu_canvas" } ) }} diff --git a/files/es/web/api/canvas_api/tutorial/hit_regions_and_accessibility/index.html b/files/es/web/api/canvas_api/tutorial/hit_regions_and_accessibility/index.html new file mode 100644 index 0000000000..967710de49 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/hit_regions_and_accessibility/index.html @@ -0,0 +1,99 @@ +--- +title: Hit regions and accessibility +slug: Web/Guide/HTML/Canvas_tutorial/Hit_regions_and_accessibility +translation_of: Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility +--- +<div>{{CanvasSidebar}} {{ PreviousNext("Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas", "Web/API/Canvas_API/Tutorial/Optimizing_canvas") }}</div> + +<div class="summary">The {{HTMLElement("canvas")}} element on its own is just a bitmap and does not provide information about any drawn objects. Canvas content is not exposed to accessibility tools like semantic HTML is. In general, you should avoid using canvas in an accessible website or app. The following guidelines can help to make it more accessible.</div> + +<div class="summary">El elemento {{HTMLElement ("canvas")}} por sí solo es solo un mapa de bits y no proporciona información sobre ningún objeto dibujado. El contenido del lienzo no está expuesto a herramientas de accesibilidad como el HTML semántico. En general, debe evitar usar canvas en un sitio web o aplicación accesible. Las siguientes pautas pueden ayudar a que sea más accesible.</div> + +<h2 id="Fallback_content">Fallback content</h2> + +<p>The content inside the <code><canvas> ... </canvas></code> tags can be used as a fallback for browsers which don't support canvas rendering. It's also very useful for assistive technology users (like screen readers) which can read and interpret the sub DOM in it. A good example at <a href="http://www.html5accessibility.com/tests/canvas.html">html5accessibility.com</a> demonstrates how this can be done:</p> + +<pre class="brush: html"><canvas> + <h2>Shapes</h2> + <p>A rectangle with a black border. + In the background is a pink circle. + Partially overlaying the <a href="http://en.wikipedia.org/wiki/Circle" onfocus="drawCircle();" onblur="drawPicture();">circle</a>. + Partially overlaying the circle is a green + <a href="http://en.wikipedia.org/wiki/Square" onfocus="drawSquare();" onblur="drawPicture();">square</a> + and a purple <a href="http://en.wikipedia.org/wiki/Triangle" onfocus="drawTriangle();" onblur="drawPicture();">triangle</a>, + both of which are semi-opaque, so the full circle can be seen underneath.</p> +</canvas> </pre> + +<p>See the <a href="https://www.youtube.com/watch?v=ABeIFlqYiMQ">video how NVDA reads this example by Steve Faulkner</a>.</p> + +<h2 id="ARIA_rules">ARIA rules</h2> + +<p>Accessible Rich Internet Applications <strong>(<a href="/en-US/docs/Web/Accessibility/ARIA">ARIA</a>)</strong> defines ways to make Web content and Web applications more accessible to people with disabilities. You can use ARIA attributes to describe the behavior and purpose of the canvas element. See <a href="/en-US/docs/Web/Accessibility/ARIA">ARIA</a> and <a href="/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques">ARIA techniques</a> for more information.</p> + +<pre class="brush: html"><canvas id="button" tabindex="0" role="button" aria-pressed="false" aria-label="Start game"></canvas> +</pre> + +<h2 id="Hit_regions">Hit regions</h2> + +<p>Whether the mouse coordinates are within a particular area on the canvas, is a common problem to solve. The hit region API allows you to define an area of your canvas and provides another possibility to expose interactive content on a canvas to accessibility tools. It allows you to make hit detection easier and lets you route events to DOM elements. The API has the following three methods (which are still experimental in current web browsers; check the browser compatibility tables).</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.addHitRegion()")}} {{experimental_inline}}</dt> + <dd>Adds a hit region to the canvas.</dd> + <dt>{{domxref("CanvasRenderingContext2D.removeHitRegion()")}} {{experimental_inline}}</dt> + <dd>Removes the hit region with the specified <code>id</code> from the canvas.</dd> + <dt>{{domxref("CanvasRenderingContext2D.clearHitRegions()")}} {{experimental_inline}}</dt> + <dd>Removes all hit regions from the canvas.</dd> +</dl> + +<p>You can add a hit region to your path and check for the {{domxref("MouseEvent.region")}} property to test if your mouse is hitting your region, for example.</p> + +<pre class="brush: html"><canvas id="canvas"></canvas> +<script> +var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); + +ctx.beginPath(); +ctx.arc(70, 80, 10, 0, 2 * Math.PI, false); +ctx.fill(); +ctx.addHitRegion({id: 'circle'}); + +canvas.addEventListener('mousemove', function(event) { + if (event.region) { + alert('hit region: ' + event.region); + } +}); +</script></pre> + +<p>The <code>addHitRegion()</code> method also takes a <code>control</code> option to route events to an element (that is a descendant of the canvas):</p> + +<pre class="brush: js">ctx.addHitRegion({control: element});</pre> + +<p>This can be useful for routing to {{HTMLElement("input")}} elements, for example. See also this <a href="https://codepen.io/peterj35/pen/PEdLKx">codepen demo</a>.</p> + +<h2 id="Focus_rings">Focus rings</h2> + +<p>When working with the keyboard, focus rings are a handy indicator to help navigating on a page. To draw focus rings on a canvas drawing, the <code>drawFocusIfNeeded</code> property can be used.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.drawFocusIfNeeded()")}} {{experimental_inline}}</dt> + <dd>If a given element is focused, this method draws a focus ring around the current path.</dd> +</dl> + +<p>Additionally, the <code>scrollPathIntoView()</code> method can be used to make an element visible on the screen if focused, for example.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.scrollPathIntoView()")}} {{experimental_inline}}</dt> + <dd>Scrolls the current path or a given path into the view.</dd> +</dl> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://www.w3.org/WAI/PF/HTML/wiki/Canvas_Accessibility_Use_Cases">Canvas accessibility use cases</a></li> + <li><a href="https://www.w3.org/html/wg/wiki/AddedElementCanvas">Canvas element accessibility issues</a></li> + <li><a href="http://www.paciellogroup.com/blog/2012/06/html5-canvas-accessibility-in-firefox-13/">HTML5 Canvas Accessibility in Firefox 13 – by Steve Faulkner</a></li> + <li><a href="https://html.spec.whatwg.org/multipage/scripting.html#best-practices">Best practices for interactive canvas elements</a></li> +</ul> + +<div>{{ PreviousNext("Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas", "Web/API/Canvas_API/Tutorial/Optimizing_canvas") }}</div> diff --git a/files/es/web/api/canvas_api/tutorial/index.html b/files/es/web/api/canvas_api/tutorial/index.html new file mode 100644 index 0000000000..da5b0b3cc9 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/index.html @@ -0,0 +1,61 @@ +--- +title: Tutorial Canvas +slug: Web/Guide/HTML/Canvas_tutorial +tags: + - Canvas + - HTML5 + - graficos +translation_of: Web/API/Canvas_API/Tutorial +--- +<p><a href="/en-US/docs/HTML/Canvas" title="HTML/Canvas"><img alt="" src="https://mdn.mozillademos.org/files/257/Canvas_tut_examples.jpg" style="float: right; height: 450px; width: 200px;"></a></p> + +<p><a href="/en-US/docs/HTML/Canvas" title="HTML/Canvas"><strong><code><canvas></code></strong></a> es un elemento <a href="/en-US/docs/HTML" title="HTML">HTML</a> el cual puede ser usado para dibujar gráficos usando scripts (normalmente <a href="/en-US/docs/JavaScript" title="JavaScript">JavaScript</a>). Este puede, por ejemplo, ser usado para dibujar gráficos, realizar composición de fotos o simples (y <a href="/en-US/docs/HTML/Canvas/A_Basic_RayCaster" title="A_Basic_RayCaster">no tan simples</a>) animaciones. Las imágenes a la derecha muestran algunos ejemplos de implementaciones <code><canvas></code> las cuales se verán en un futuro en este tutorial.</p> + +<p><code><canvas></code> fue introducido primero por Apple para el Mac OS X Dashboard y después implementado en Safari y Google Chrome. Navegadores basados en <a href="/en-US/docs/Gecko" title="Gecko">Gecko</a> 1.8, tal como Firefox 1.5, que también soportan este elemento. El <code><canvas></code> es un elemento parte de las especificaciones de la <a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/">WhatWG Web applications 1.0</a> mejor conocida como HTML5.</p> + +<p><span class="seoSummary">En este tutorial se describe cómo usar el elemento <code><canvas></code> para dibujar gráficos en 2D, empezando con lo básico. Los ejemplos le proveerán mayor claridad a las ideas que pueda tener referentes al canvas, así como los códigos que necesita para crear su propio contenido.</span></p> + +<h2 id="Before_you_start" name="Before_you_start">Antes de Empezar</h2> + +<p>Usar el elemento <code><canvas></code> no es algo muy díficil pero necesita saber y entender los aspectos básicos del <a href="/en-US/docs/HTML" title="HTML">HTML</a> y <a href="/en-US/docs/JavaScript" title="JavaScript">JavaScript</a>. El elemento <code><canvas></code> no está soportado en navegadores viejos, pero están soportado en la mayoría de las versiones más recientes de los navegadores. El tamaño por defecto del canvas es 300px * 150px [ancho (width) * alto (height)]. Pero se puede personalizar el tamaño usando las propiedades height y width de CSS.<span id="result_box" lang="es"><span class="hps"> Con el fin de</span> <span class="hps">dibujar gráficos</span> <span class="hps">en el lienzo</span> <span class="hps"><canvas> se utiliza un</span> <span class="hps">objeto de contexto de</span> <span class="hps">JavaScript</span> <span class="hps">que crea</span> <span class="hps">gráficos</span> <span class="hps">sobre la marcha.</span></span></p> + +<h2 id="In_this_tutorial" name="In_this_tutorial">En este Tutorial</h2> + +<ul> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Basic_usage" title="Canvas_tutorial/Basic_usage">Usos Básicos</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes" title="Canvas_tutorial/Drawing_shapes">Dibujando Formas</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images" title="Canvas_tutorial/Using_images">Usando Imágenes</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors" title="Canvas_tutorial/Applying_styles_and_colors">Aplicando estilos y colores</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations" title="Canvas_tutorial/Transformations">Transformaciones</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Compositing" title="Canvas_tutorial/Compositing">Composiciones</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Basic_animations" title="Canvas_tutorial/Basic_animations">Animaciones Básicas</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Optimizing_canvas" title="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Optimizing_canvas">Optimización de Canvas</a></li> +</ul> + +<h2 id="See_also" name="See_also">Vea también</h2> + +<ul> + <li><a href="/en-US/docs/HTML/Canvas" title="HTML/Canvas">Canvas topic page</a></li> + <li><a href="/en-US/docs/HTML/Canvas/Drawing_Graphics_with_Canvas" title="Drawing_Graphics_with_Canvas">Drawing Graphics with Canvas</a></li> + <li><a href="/en-US/docs/tag/Canvas_examples" title="tag/Canvas_examples">Canvas examples</a></li> + <li><a href="http://www.html5andcss3.org">HTML5 Tutorial</a></li> + <li><a href="/en-US/docs/Drawing_text_using_a_canvas" title="Drawing_text_using_a_canvas">Drawing Text Using a Canvas</a></li> + <li><a class="external" href="http://developer.apple.com/library/safari/#documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingText/AddingText.html#//apple_ref/doc/uid/TP40010542-CH6-SW4" title="Adding Text to Canvas">Adding Text to Canvas</a></li> + <li><a class="external" href="http://www.canvasdemos.com/" title="Canvas Demos">Canvas Demos - Games, applications, tools and tutorials</a></li> + <li><a class="external" href="http://canvimation.github.com/" title="http://canvimation.github.com/">Canvas Drawing and Animation Application</a></li> + <li><a class="external" href="http://billmill.org/static/canvastutorial/" title="http://billmill.org/static/canvastutorial/">Interactive canvas tutorial</a></li> + <li><a class="external" href="http://blog.nihilogic.dk/2009/02/html5-canvas-cheat-sheet.html" title="http://blog.nihilogic.dk/2009/02/html5-canvas-cheat-sheet.html">Canvas Cheat Sheet with all attributes and methods</a></li> + <li><a class="external" href="http://visitmix.com/labs/ai2canvas/" title="http://visitmix.com/labs/ai2canvas/">Adobe Illustrator to Canvas plug-in</a></li> + <li><a class="external" href="http://www.html5canvastutorials.com/" title="http://www.html5canvastutorials.com/">HTML5CanvasTutorials</a></li> + <li><a class="external" href="http://html5tutorial.com/how-to-draw-n-grade-bezier-curve-with-canvas-api" title="http://html5tutorial.com/how-to-draw-n-grade-bezier-curve-with-canvas-api">How to draw N grade Bézier curves with the Canvas API</a></li> + <li><a class="external" href="http://creativejs.com/2011/08/31-days-of-canvas-tutorials/" title="http://creativejs.com/2011/08/31-days-of-canvas-tutorials/">31 days of canvas tutorials</a></li> + <li><a href="http://www.w3.org/TR/2dcontext/" title="http://www.w3.org/TR/2dcontext/">W3C Standard</a></li> + <li><a href="http://www.tutorialspark.com/html5/HTML5_canvas_Intro.php" title="http://www.tutorialspark.com/html5/HTML5_canvas_Intro.php">HTML5 Canvas tutorials and reference</a></li> + <li><a href="http://davidwalsh.name/convert-canvas-image">JavaScript Canvas Image Conversion</a></li> +</ul> + +<h2 id="Nota_a_los_contribuyentes">Nota a los contribuyentes</h2> + +<p>Debido a un desafortunado error técnico que ocurrió el 17 de junio del 2013, perdimos la historia de este tutorial, incluyendo atribuciones a todos los contribuyentes del pasado a su contenido. Pedimos disculpas por esto, y esperamos que perdone este desafortunado percance.</p> + +<div>{{ Next("Web/Guide/HTML/Canvas_tutorial/Basic_usage") }}</div> diff --git a/files/es/web/api/canvas_api/tutorial/optimizing_canvas/index.html b/files/es/web/api/canvas_api/tutorial/optimizing_canvas/index.html new file mode 100644 index 0000000000..145e2734f0 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/optimizing_canvas/index.html @@ -0,0 +1,19 @@ +--- +title: Optimizing canvas +slug: Web/Guide/HTML/Canvas_tutorial/Optimizing_canvas +translation_of: Web/API/Canvas_API/Tutorial/Optimizing_canvas +--- +<p>{{HTMLElement("canvas")}} es uno de los estándares más utilizados para la representación de gráficos 2D en la Web. Se utiliza ampliamente en los juegos y visualizaciones complejas. Sin embargo, as Web sites and apps push canvas to the limits, el rendimiento comienza a sufrir. <span class="seoSummary">This article aims to provide suggestions for optimizing your use of the canvas element, to ensure that your Web site or app performs well.</span></p> +<p>A continuación una lista de tips par mejorar el rendimiento:</p> +<ul> + <li>Repintar primitives similares o objetos repetidos dentro y fuera de la pantalla canvas.</li> + <li>Batch canvas calls together (for example, draw a poly-line instead of multiple separate lines).</li> + <li>Avoid floating-point coordinates and use integers instead.</li> + <li>Avoid unnecessary canvas state changes.</li> + <li>Render screen differences only, not the whole new state.</li> + <li>Utilice varios lienzos en capas para escenas complejas.</li> + <li>Evite la propiedad <code>shadowBlur</code> siempre que sea posible.</li> + <li>Con las animaciones, use {{domxref("window.requestAnimationFrame()")}}.</li> + <li>Probar el rendimiento con <a href="http://jsperf.com" title="http://jsperf.com">JSPerf</a>.</li> +</ul> +<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial/Basic_animations")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/pixel_manipulation_with_canvas/index.html b/files/es/web/api/canvas_api/tutorial/pixel_manipulation_with_canvas/index.html new file mode 100644 index 0000000000..14ccc9c4a5 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/pixel_manipulation_with_canvas/index.html @@ -0,0 +1,301 @@ +--- +title: Pixel manipulation with canvas +slug: Web/Guide/HTML/Canvas_tutorial/Pixel_manipulation_with_canvas +translation_of: Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Advanced_animations", "Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility")}}</div> + +<div class="summary"> +<p>Hasta ahora, no habíamos mirado los píxeles reales de nuestro <em>canvas</em>. Con el objeto <code>ImageData</code>, puedes leer y escribir directamente un <em>array</em> de datos para manipular píxeles.</p> + +<p>También veremos cómo se puede controlar el suavizado de la imagen (antialiasing) y cómo guardar imágenes de tu <em>canvas</em>.</p> +</div> + +<h2 id="El_objeto_ImageData">El objeto <code>ImageData</code></h2> + +<p>El objeto {{domxref("ImageData")}} representa los datos pixelados subyacentes de un área de un objeto lienzo. Contiene los siguientes atributos de sólo lectura:</p> + +<dl> + <dt><code>width</code></dt> + <dd>El ancho de la imagen en píxeles.</dd> + <dt><code>height</code></dt> + <dd>La altura de la imagen en píxeles.</dd> + <dt><code>data</code></dt> + <dd>Un objeto {{jsxref("Uint8ClampedArray")}} que representa un array unidimensional, contiene información en formato RGBA, con valores desde <code>0</code> hasta <code>255</code> (incluído).</dd> +</dl> + +<p>La propiedad <code>data</code> devuelve un {{jsxref("Uint8ClampedArray")}}, al que se puede acceder para ver los datos originales del pixel; cada pixel está representado por cuatro valores (rojo, verde, azul, y alfa, en ese orden; esto es, formato "RGBA"). Cada componente de color se representa con un valor entero entre 0 y 255. Dentro del array, cada componente ocupa un índice consecutivo, comenzando con 0 desde el punto superior izquierdo, continuando de izquierda a derecha y de arriba hacia abajo, a través del array.</p> + +<p>El {{jsxref("Uint8ClampedArray")}} contiene <code>alto</code> × <code>ancho</code> × 4 bytes de datos, con valores de índice en el rango entre 0 y (<code>alto</code>×<code>ancho</code>×4)-1.</p> + +<p>Por ejemplo, para leer el valor del componente azul del pixel en la columna 200, fila 50 de una imagen, deberías hacer lo siguiente:</p> + +<p>blueComponent = imageData.data[((50 * (imageData.width * 4)) + (200 * 4)) + 2];</p> + +<p>Si se le da un conjunto de coordenadas (X e Y), puede que termine haciendo algo así:</p> + +<pre class="brush: js">var xCoord = 50; +var yCoord = 100; +var canvasWidth = 1024; + +function getColorIndicesForCoord(x, y, width) { + var red = y * (width * 4) + x * 4; + return [red, red + 1, red + 2, red + 3]; +} + +var colorIndices = getColorIndicesForCoord(xCoord, yCoord, canvasWidth); + +var redIndex = colorIndices[0]; +var greenIndex = colorIndices[1]; +var blueIndex = colorIndices[2]; +var alphaIndex = colorIndices[3]; + +var redForCoord = imageData.data[redIndex]; +var greenForCoord = imageData.data[greenIndex]; +var blueForCoord = imageData.data[blueIndex]; +var alphaForCoord = imageData.data[alphaIndex]; +</pre> + +<p>O, en ES6 sería algo así:</p> + +<pre class="brush: js">const xCoord = 50; +const yCoord = 100; +const canvasWidth = 1024; + +const getColorIndicesForCoord = (x, y, width) => { + const red = y * (width * 4) + x * 4; + return [red, red + 1, red + 2, red + 3]; +}; + +const colorIndices = getColorIndicesForCoord(xCoord, yCoord, canvasWidth); + +const [redIndex, greenIndex, blueIndex, alphaIndex] = colorIndices; +</pre> + +<p>You may also access the size of the pixel array in bytes by reading the <code>Uint8ClampedArray.length</code> attribute:</p> + +<pre class="brush: js">var numBytes = imageData.data.length; +</pre> + +<h2 id="Creando_un_objeto_ImageData">Creando un objeto <code>ImageData</code></h2> + +<p>Para crear un objeto nuevo y vacío tipo <code>ImageData</code>, debes usar el método {{domxref("CanvasRenderingContext2D.createImageData", "createImageData()")}}. Hay dos versiones del método <code>createImageData()</code>:</p> + +<pre class="brush: js">var myImageData = ctx.createImageData(width, height);</pre> + +<p>Esto crea un nuevo objeto <code>ImageData</code> con las dimensiones especificadas. Todos los pixels tienen valor correspondiente a negro - transparente (0,0,0,0).</p> + +<p>También puedes crear un nuevo objeto <code>ImageData</code> con las mismas dimensiones que otro objeto, especificado por <code>anotherImageData</code>. Los píxels del nuevo objeto tienen valor negro - transparente. <strong>¡Esto no es una copia de los datos de la imagen!</strong></p> + +<pre class="brush: js">var myImageData = ctx.createImageData(anotherImageData);</pre> + +<h2 id="Getting_the_pixel_data_for_a_context">Getting the pixel data for a context</h2> + +<p>To obtain an <code>ImageData</code> object containing a copy of the pixel data for a canvas context, you can use the <code>getImageData()</code> method:</p> + +<pre class="brush: js">var myImageData = ctx.getImageData(left, top, width, height);</pre> + +<p>This method returns an <code>ImageData</code> object representing the pixel data for the area of the canvas whose corners are represented by the points (<code>left</code>,<code>top</code>), (<code>left+width</code>, <code>top</code>), (<code>left</code>, <code>top+height</code>), and (<code>left+width</code>, <code>top+height</code>). The coordinates are specified in canvas coordinate space units.</p> + +<div class="note"> +<p><strong>Note</strong>: Any pixels outside the canvas are returned as transparent black in the resulting <code>ImageData</code> object.</p> +</div> + +<p>This method is also demonstrated in the article <a href="/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas">Manipulating video using canvas</a>.</p> + +<h3 id="A_color_picker">A color picker</h3> + +<p>In this example we are using the <a href="/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData">getImageData() </a>method to display the color under the mouse cursor. For this, we need the current position of the mouse with <code>layerX</code> and <code>layerY</code>, then we look up the pixel data on that position in the pixel array that <a href="/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData">getImageData()</a> provides us. Finally, we use the array data to set a background color and a text in the <code><div></code> to display the color.</p> + +<div class="hidden"> +<pre class="brush: html;"><canvas id="canvas" width="300" height="227" style="float:left"></canvas> +<div id="color" style="width:200px;height:50px;float:left"></div> +</pre> +</div> + +<pre class="brush: js;">var img = new Image(); +img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg'; +var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +img.onload = function() { + ctx.drawImage(img, 0, 0); + img.style.display = 'none'; +}; +var color = document.getElementById('color'); +function pick(event) { + var x = event.layerX; + var y = event.layerY; + var pixel = ctx.getImageData(x, y, 1, 1); + var data = pixel.data; + var rgba = 'rgba(' + data[0] + ', ' + data[1] + + ', ' + data[2] + ', ' + (data[3] / 255) + ')'; + color.style.background = rgba; + color.textContent = rgba; +} +canvas.addEventListener('mousemove', pick); +</pre> + +<p>{{ EmbedLiveSample('A_color_picker', 610, 240) }}</p> + +<h2 id="Painting_pixel_data_into_a_context">Painting pixel data into a context</h2> + +<p>You can use the<a href="/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData"> putImageData() </a>method to paint pixel data into a context:</p> + +<pre class="brush: js">ctx.putImageData(myImageData, dx, dy); +</pre> + +<p>The <code>dx</code> and <code>dy</code> parameters indicate the device coordinates within the context at which to paint the top left corner of the pixel data you wish to draw.</p> + +<p>For example, to paint the entire image represented by <code>myImageData</code> to the top left corner of the context, you can simply do the following:</p> + +<pre class="brush: js">ctx.putImageData(myImageData, 0, 0); +</pre> + +<h3 id="Grayscaling_and_inverting_colors">Grayscaling and inverting colors</h3> + +<p>In this example we iterate over all pixels to change their values, then we put the modified pixel array back to the canvas using <a href="/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData">putImageData()</a>. The invert function simply subtracts each color from the max value 255. The grayscale function simply uses the average of red, green and blue. You can also use a weighted average, given by the formula <code>x = 0.299r + 0.587g + 0.114b</code>, for example. See <a href="http://en.wikipedia.org/wiki/Grayscale">Grayscale</a> on Wikipedia for more information.</p> + +<div class="hidden"> +<pre class="brush: html;"><canvas id="canvas" width="300" height="227"></canvas> +<div> + <input id="grayscalebtn" value="Grayscale" type="button"> + <input id="invertbtn" value="Invert" type="button"> +</div> +</pre> +</div> + +<pre class="brush: js">var img = new Image(); +img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg'; +img.onload = function() { + draw(this); +}; + +function draw(img) { + var canvas = document.getElementById('canvas'); + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + img.style.display = 'none'; + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + var data = imageData.data; + + var invert = function() { + for (var i = 0; i < data.length; i += 4) { + data[i] = 255 - data[i]; // red + data[i + 1] = 255 - data[i + 1]; // green + data[i + 2] = 255 - data[i + 2]; // blue + } + ctx.putImageData(imageData, 0, 0); + }; + + var grayscale = function() { + for (var i = 0; i < data.length; i += 4) { + var avg = (data[i] + data[i + 1] + data[i + 2]) / 3; + data[i] = avg; // red + data[i + 1] = avg; // green + data[i + 2] = avg; // blue + } + ctx.putImageData(imageData, 0, 0); + }; + + var invertbtn = document.getElementById('invertbtn'); + invertbtn.addEventListener('click', invert); + var grayscalebtn = document.getElementById('grayscalebtn'); + grayscalebtn.addEventListener('click', grayscale); +} +</pre> + +<p>{{ EmbedLiveSample('Grayscaling_and_inverting_colors', 330, 270) }}</p> + +<h2 id="Zooming_and_anti-aliasing">Zooming and anti-aliasing</h2> + +<p>With the help of the {{domxref("CanvasRenderingContext2D.drawImage", "drawImage()")}} method, a second canvas and the {{domxref("CanvasRenderingContext2D.imageSmoothingEnabled", "imageSmoothingEnabled")}} property, we are able to zoom into our picture and see the details.</p> + +<p>We get the position of the mouse and crop an image of 5 pixels left and above to 5 pixels right and below. Then we copy that one over to another canvas and resize the image to the size we want it to. In the zoom canvas we resize a 10×10 pixel crop of the original canvas to 200×200.</p> + +<pre class="brush: js">zoomctx.drawImage(canvas, + Math.abs(x - 5), Math.abs(y - 5), + 10, 10, 0, 0, 200, 200);</pre> + +<p>Because anti-aliasing is enabled by default, we might want to disable the smoothing to see clear pixels. You can toggle the checkbox to see the effect of the <code>imageSmoothingEnabled</code> property (which needs prefixes for different browsers).</p> + +<h6 class="hidden" id="Zoom_example">Zoom example</h6> + +<div class="hidden"> +<pre class="brush: html;"><canvas id="canvas" width="300" height="227"></canvas> +<canvas id="zoom" width="300" height="227"></canvas> +<div> +<label for="smoothbtn"> + <input type="checkbox" name="smoothbtn" checked="checked" id="smoothbtn"> + Enable image smoothing +</label> +</div> +</pre> +</div> + +<pre class="brush: js">var img = new Image(); +img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg'; +img.onload = function() { + draw(this); +}; + +function draw(img) { + var canvas = document.getElementById('canvas'); + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + img.style.display = 'none'; + var zoomctx = document.getElementById('zoom').getContext('2d'); + + var smoothbtn = document.getElementById('smoothbtn'); + var toggleSmoothing = function(event) { + zoomctx.imageSmoothingEnabled = this.checked; + zoomctx.mozImageSmoothingEnabled = this.checked; + zoomctx.webkitImageSmoothingEnabled = this.checked; + zoomctx.msImageSmoothingEnabled = this.checked; + }; + smoothbtn.addEventListener('change', toggleSmoothing); + + var zoom = function(event) { + var x = event.layerX; + var y = event.layerY; + zoomctx.drawImage(canvas, + Math.abs(x - 5), + Math.abs(y - 5), + 10, 10, + 0, 0, + 200, 200); + }; + + canvas.addEventListener('mousemove', zoom); +}</pre> + +<p>{{ EmbedLiveSample('Zoom_example', 620, 490) }}</p> + +<h2 id="Guardando_las_imágenes">Guardando las imágenes</h2> + +<p>The {{domxref("HTMLCanvasElement")}} provides a <code>toDataURL()</code> method, which is useful when saving images. It returns a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs">data URI</a> containing a representation of the image in the format specified by the <code>type</code> parameter (defaults to <a class="external external-icon" href="https://en.wikipedia.org/wiki/Portable_Network_Graphics">PNG</a>). The returned image is in a resolution of 96 dpi.</p> + +<dl> + <dt>{{domxref("HTMLCanvasElement.toDataURL", "canvas.toDataURL('image/png')")}}</dt> + <dd>Default setting. Creates a PNG image.</dd> + <dt>{{domxref("HTMLCanvasElement.toDataURL", "canvas.toDataURL('image/jpeg', quality)")}}</dt> + <dd>Creates a JPG image. Optionally, you can provide a quality in the range from 0 to 1, with one being the best quality and with 0 almost not recognizable but small in file size.</dd> +</dl> + +<p>Once you have generated a data URI from you canvas, you are able to use it as the source of any {{HTMLElement("image")}} or put it into a hyper link with a <a href="/en-US/docs/Web/HTML/Element/a#attr-download">download attribute</a> to save it to disc, for example.</p> + +<p>You can also create a {{domxref("Blob")}} from the canvas.</p> + +<dl> + <dt>{{domxref("HTMLCanvasElement.toBlob", "canvas.toBlob(callback, type, encoderOptions)")}}</dt> + <dd>Creates a <code>Blob</code> object representing the image contained in the canvas.</dd> +</dl> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{domxref("ImageData")}}</li> + <li><a href="/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas">Manipulating video using canvas</a></li> + <li><a href="https://codepo8.github.io/canvas-images-and-pixels/">Canvas, images and pixels – by Christian Heilmann</a></li> +</ul> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Advanced_animations", "Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility")}}</p> |