diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:15 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:15 -0500 |
commit | 4b1a9203c547c019fc5398082ae19a3f3d4c3efe (patch) | |
tree | d4a40e13ceeb9f85479605110a76e7a4d5f3b56b /files/ca/web/api/canvas_api/tutorial/transformacions | |
parent | 33058f2b292b3a581333bdfb21b8f671898c5060 (diff) | |
download | translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.gz translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.tar.bz2 translated-content-4b1a9203c547c019fc5398082ae19a3f3d4c3efe.zip |
initial commit
Diffstat (limited to 'files/ca/web/api/canvas_api/tutorial/transformacions')
-rw-r--r-- | files/ca/web/api/canvas_api/tutorial/transformacions/index.html | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/files/ca/web/api/canvas_api/tutorial/transformacions/index.html b/files/ca/web/api/canvas_api/tutorial/transformacions/index.html new file mode 100644 index 0000000000..2958d40498 --- /dev/null +++ b/files/ca/web/api/canvas_api/tutorial/transformacions/index.html @@ -0,0 +1,290 @@ +--- +title: Transformacions +slug: Web/API/Canvas_API/Tutorial/Transformacions +tags: + - Canvas + - Graphics + - Guide + - HTML + - HTML5 + - Intermediate + - Web +translation_of: Web/API/Canvas_API/Tutorial/Transformations +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Using_images", "Web/API/Canvas_API/Tutorial/Compositing")}}</div> + +<div class="summary">Anteriorment en aquest tutorial hem après sobre la graella de canvas i l'<strong>espai de coordenades</strong>. Fins ara, només usàvem la graella per defecte i canviàvem la grandària del llenç per a les nostres necessitats. Amb les transformacions, hi ha formes més poderoses de traslladar l'origen a una posició diferent, girar la graella i fins i tot escalar-la.</div> + +<h2 id="Saving_and_restoring_state" name="Saving_and_restoring_state">Guardar i restaurar l'estat</h2> + +<p>Abans de veure els mètodes de transformació, vegem altres dos mètodes que són indispensables una vegada que comencem a generar dibuixos cada vegada més complexos.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.save", "save()")}}</dt> + <dd>Guarda tot l'estat del llenç.</dd> + <dt>{{domxref("CanvasRenderingContext2D.restore", "restore()")}}</dt> + <dd>Restaura l'estat del llenç guardat més recent.</dd> +</dl> + +<p>Els estats del llenç s'emmagatzemen en una pila. Cada vegada que es crida al mètode <code>save()</code> l'estat del dibuix actual es mou a la pila. L'estat d'un dibuix consisteix de</p> + +<ul> + <li>Les transformacions que s'han aplicat (i.e. <code>translate</code>, <code>rotate</code> i <code>scale</code> – vegeu a continuació).</li> + <li>Els valors actuals dels següents atributs: {{domxref("CanvasRenderingContext2D.strokeStyle", "strokeStyle")}}, {{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle")}}, {{domxref("CanvasRenderingContext2D.globalAlpha", "globalAlpha")}}, {{domxref("CanvasRenderingContext2D.lineWidth", "lineWidth")}}, {{domxref("CanvasRenderingContext2D.lineCap", "lineCap")}}, {{domxref("CanvasRenderingContext2D.lineJoin", "lineJoin")}}, {{domxref("CanvasRenderingContext2D.miterLimit", "miterLimit")}}, {{domxref("CanvasRenderingContext2D.lineDashOffset", "lineDashOffset")}}, {{domxref("CanvasRenderingContext2D.shadowOffsetX", "shadowOffsetX")}}, {{domxref("CanvasRenderingContext2D.shadowOffsetY", "shadowOffsetY")}}, {{domxref("CanvasRenderingContext2D.shadowBlur", "shadowBlur")}}, {{domxref("CanvasRenderingContext2D.shadowColor", "shadowColor")}}, {{domxref("CanvasRenderingContext2D.globalCompositeOperation", "globalCompositeOperation")}}, {{domxref("CanvasRenderingContext2D.font", "font")}}, {{domxref("CanvasRenderingContext2D.textAlign", "textAlign")}}, {{domxref("CanvasRenderingContext2D.textBaseline", "textBaseline")}}, {{domxref("CanvasRenderingContext2D.direction", "direction")}}, {{domxref("CanvasRenderingContext2D.imageSmoothingEnabled", "imageSmoothingEnabled")}}.</li> + <li>La <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing#Clipping_paths">trajectòria de retall</a> actual, que veurem a la següent secció.</li> +</ul> + +<p>Es pot cridar al mètode <code>save()</code> tantes vegades com es vulgui. Cada vegada que es crida al mètode <code>restore()</code> l'últim estat desat s'elimina de la pila i es restauren tots les configuracions guardades.</p> + +<h3 id="A_save_and_restore_canvas_state_example" name="A_save_and_restore_canvas_state_example">Un exemple de <code>save</code> i <code>restore</code> de l'estat del llenç</h3> + +<p>Aquest exemple intenta il·lustrar com funciona la pila d'estats del dibuix en dibuixar un conjunt de rectangles consecutius.</p> + +<pre class="brush: js; highlight:[5,10,15,18]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + ctx.fillRect(0, 0, 150, 150); // Dibuixa un rectangle amb la configuració per defecte + ctx.save(); // Guarda el estat predeterminat + + ctx.fillStyle = '#09F'; // Es fan canvis a la configuració + ctx.fillRect(15, 15, 120, 120); // Es dibuixa un rectangle amb la nova configuració + + ctx.save(); // Es guarda el estat actual + ctx.fillStyle = '#FFF'; // Es fan canvis a la configuració + ctx.globalAlpha = 0.5; + ctx.fillRect(30, 30, 90, 90); // Es dibuixa un rectangle amb la nova configuració + + ctx.restore(); // Es restaura el estat anterior + ctx.fillRect(45, 45, 60, 60); // Es dibuixa un rectangle amb la configuració restaurada + + ctx.restore(); // Es restaura el estat original + ctx.fillRect(60, 60, 30, 30); // Es dibuixa un rectangle amb la configuració restaurada</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>El primer pas és dibuixar un gran rectangle amb la configuració predeterminada. A continuació guardem aquest estat i fem canvis en el color de farcit. Després dibuixem el segon rectangle blau i més petit i guardem l'estat. De nou canviem algunes configuracions de dibuix i dibuixem el tercer rectangle blanc semitransparent.</p> + +<p>Fins ara, això és bastant similar al que hem fet en les seccions anteriors. No obstant això, una vegada que cridem a la primera instrucció <code>restore()</code> l'estat del dibuix superior s'elimina de la pila i es restaura la configuració. Si no haguéssim guardat l'estat usant <code>save()</code>, hauríem de canviar el color de farcit i la transparència manualment, per tornar a l'estat anterior. Això seria fàcil per a dues propietats, però si tenim més que això, el nostre codi es faria molt llarg, molt ràpid.</p> + +<p>Quan es crida a la segona instrucció <code>restore()</code>, es restaura l'estat original (el que hem configurat abans de la primera crida <code>save</code>) i l'últim rectangle es dibuixa de nou en negre.</p> + +<p>{{EmbedLiveSample("A_save_and_restore_canvas_state_example", "180", "180", "https://mdn.mozillademos.org/files/249/Canvas_savestate.png")}}</p> + +<h2 id="Translating" name="Translating">Traslladar</h2> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/234/Canvas_grid_translate.png" style="float: right;">El primer dels mètodes de transformació que veurem és <code>translate()</code>. Aquest mètode s'utilitza per moure el llenç i el seu origen a un punt diferent de la graella.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.translate", "translate(x, y)")}}</dt> + <dd>Mou el llenç i el seu origen en la graella. <code>x</code> indica la distància horitzontal a moure, i <code>y</code> indica quanta distància s'ha de moure la graella verticalment.</dd> +</dl> + +<p>És una bona idea guardar l'estat del llenç abans de fer qualsevol transformació. En la majoria dels casos, és més fàcil cridar al mètode <code>restore</code>, que haver de fer una traslació inversa per tornar a l'estat original. També, si estem trasladant dins d'un bucle i no guardem i restaurem l'estat del llenç, pot ser que acabem perdent part del dibuix, ja que es va dibuixar fora de la vora del llenç.</p> + +<h3 id="A_translate_example" name="A_translate_example">Un exemple de <code>translate</code></h3> + +<p>Aquest exemple demostra alguns dels beneficis de traslladar l'origen del llenç. Sense el mètode <code>translate()</code>, tots els rectangles es dibuixarien en la mateixa posició (0,0). El mètode <code>translate()</code>, també ens dóna la llibertat de col·locar el rectangle en qualsevol lloc del llenç, sense haver d'ajustar manualment les coordenades en la funció <code>fillRect()</code>. Això fa que sigui una mica més fàcil d'entendre i usar.</p> + +<p>En la funció <code>draw()</code>, cridem a la funció <code>fillRect()</code> nou vegades, usant dos bucles <code>for</code>. En cada bucle, el llenç es trasllada, es dibuixa el rectangle i el llenç torna al seu estat original. Observem com la crida a <code>fillRect()</code> usa les mateixes coordenades cada vegada, confiant en <code>translate()</code> per ajustar la posició del dibuix.</p> + +<pre class="brush: js; highlight:[7]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + for (var i = 0; i < 3; i++) { + for (var j = 0; j < 3; j++) { + ctx.save(); + ctx.fillStyle = 'rgb(' + (51 * i) + ', ' + (255 - 51 * i) + ', 255)'; + ctx.translate(10 + j * 50, 10 + i * 50); + ctx.fillRect(0, 0, 25, 25); + ctx.restore(); + } + } +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_translate_example", "160", "160", "https://mdn.mozillademos.org/files/9857/translate.png")}}</p> + +<h2 id="Rotating" name="Rotating">Girar</h2> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/233/Canvas_grid_rotate.png" style="float: right;">El segon mètode de transformació és <code>rotate()</code>. Se usa per girar el llenç al voltant de l'origen actual.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.rotate", "rotate(angle)")}}</dt> + <dd>Gira el llenç en sentit horari, al voltant de l'origen actual pel nombre d'<code>angle</code> de radiants.</dd> +</dl> + +<p>El punt central de gir és sempre l'origen del llenç. Per canviar el punt central, necessitarem moure el llenç usant el mètode <code>translate()</code>.</p> + +<h3 id="A_rotate_example" name="A_rotate_example">Un exemple de <code>rotate</code></h3> + +<p>En aquest exemple, usarem el mètode <code>rotate()</code> para girar primer un rectangle des de l'origen del llenç, i després des del centre del rectangle mateix amb l'ajuda de <code>translate()</code>.</p> + +<div class="note"> +<p><strong>Recordatori</strong>: Els angles estan en radiants, no en graus. Per fer la conversació, estem usant: <code>radians = (Math.PI/180)*degrees</code>.</p> +</div> + +<pre class="brush: js; highlight:[9, 23]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // <span class="s3gt_translate_tooltip_variant" id="s3gt_translate_tooltip_variant_to_id_0">rectangles esquerra, giren a partir d'origen del llenç</span> + ctx.save(); + // rect blau + ctx.fillStyle = '#0095DD'; + ctx.fillRect(30, 30, 100, 100); + ctx.rotate((Math.PI / 180) * 25); + // grey rect + ctx.fillStyle = '#4D4E53'; + ctx.fillRect(30, 30, 100, 100); + ctx.restore(); + + // <span class="s3gt_translate_tooltip_variant" id="s3gt_translate_tooltip_variant_to_id_0">rectangles drets, giren des del centre del rectangle</span> + // dibuixa rect blau + ctx.fillStyle = '#0095DD'; + ctx.fillRect(150, 30, 100, 100); + + ctx.translate(200, 80); // trasllada al rectangle central + // x = x + 0.5 * width + // y = y + 0.5 * height + ctx.rotate((Math.PI / 180) * 25); // gira + ctx.translate(-200, -80); // traslladar de nou + + // dibuixa rect gris + ctx.fillStyle = '#4D4E53'; + ctx.fillRect(150, 30, 100, 100); +} +</pre> + +<p>Per girar el rectangle al voltant del seu propi centre, traslladem el llenç al centre del rectangle, després girem el llenç i tornem a traslladar el llenç a 0,0, i a continuació dibuixem el rectangle.</p> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="300" height="200"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_rotate_example", "310", "210", "https://mdn.mozillademos.org/files/9859/rotate.png")}}</p> + +<h2 id="Scaling" name="Scaling">Escalar</h2> + +<p>El següent mètode de transformació és l'escalat. Ho usem per augmentar o disminuir les unitats en la graella del llenç. Això es pot utilitzar per dibuixar formes i mapes de bits reduïts o ampliats.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.scale", "scale(x, y)")}}</dt> + <dd>Escala les unitats del llenç, per x horitzontalment i per y verticalment. Tots dos paràmetres són nombres reals. Els valors inferiors a 1.0 redueixen la grandària de la unitat i els valors superiors a 1.0 augmenten la grandària de la unitat. Els valors a 1.0 deixen les unitats de la mateixa grandària.</dd> +</dl> + +<p>Usant nombres negatius es pot fer la replica d'eixos (per exemple, usant <code>translate(0,canvas.height); scale(1,-1);</code> tindrem el conegut sistema de coordenades cartesianes, amb l'origen en la cantonada inferior esquerra).</p> + +<p>Per defecte, una unitat en el llenç és exactament un píxel. Si apliquem, per exemple, un factor d'escala de 0.5, la unitat resultant es convertirà en 0.5 píxels i per tant les formes es dibuixaran a meitat de la seva grandària. De manera similar, si s'ajusta el factor d'escala a 2.0, la grandària de la unitat augmentarà i una unitat ara es converteix en dos píxels. Això dona com a resultat que les formes es dibuixin dues vegades més grans.</p> + +<h3 id="A_scale_example" name="A_scale_example">Un exemple de <code>scale</code></h3> + +<p><span class="s3gt_translate_tooltip_variant" id="s3gt_translate_tooltip_variant_to_id_0">En aquest últim exemple, dibuixarem formes amb diferents factors d'escala.</span></p> + +<pre class="brush: js; highlight:[6,11]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // <span class="short_text" id="result_box" lang="ca"><span>dibuixar un rectangle senzill, però escalar-lo</span></span>. + ctx.save(); + ctx.scale(10, 3); + ctx.fillRect(1, 10, 10, 10); + ctx.restore(); + + // mirror horizontally + ctx.scale(-1, 1); + ctx.font = '48px serif'; + ctx.fillText('MDN', -135, 120); +} + +</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_scale_example", "160", "160", "https://mdn.mozillademos.org/files/9861/scale.png")}}</p> + +<h2 id="Transforms" name="Transforms">Transformar</h2> + +<p>Finalment, els següents mètodes de transformació permeten modificar directament la matriu de transformació.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.transform", "transform(a, b, c, d, e, f)")}}</dt> + <dd>Multiplica la matriu de transformació actual amb la matriu descrita pels seus arguments. La matriu de transformació és descrita per: <math><semantics><mrow><mo>[</mo><mtable columnalign="center center center" rowspacing="0.5ex"><mtr><mtd><mi>a</mi></mtd><mtd><mi>c</mi></mtd><mtd><mi>e</mi></mtd></mtr><mtr><mtd><mi>b</mi></mtd><mtd><mi>d</mi></mtd><mtd><mi>f</mi></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable><mo>]</mo></mrow><annotation encoding="TeX">\left[ \begin{array}{ccc} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{array} \right]</annotation></semantics></math></dd> +</dl> + +<dl> + <dd>Si qualsevol dels arguments és <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity">Infinity</a></code>, la matriu de transformació ha de ser marcada com a infinita en lloc que el mètode llanci una excepció.</dd> +</dl> + +<p>Els paràmetres d'aquesta funció són:</p> + +<dl> + <dt><code>a (m11)</code></dt> + <dd>Escalat horitzontal.</dd> + <dt><em><code>b (m12)</code></em></dt> + <dd>Desviació Horizontal.</dd> + <dt><code>c (m21)</code></dt> + <dd>Desviació Vertical.</dd> + <dt><code>d (m22)</code></dt> + <dd>Escalat Vertical.</dd> + <dt><code>e (dx)</code></dt> + <dd>Moviment Horizontal.</dd> + <dt><code>f (dy)</code></dt> + <dd>Moviment Vertical.</dd> + <dt>{{domxref("CanvasRenderingContext2D.setTransform", "setTransform(a, b, c, d, e, f)")}}</dt> + <dd>Reinicia la transformació actual a la matriu d'identitat i, a continuació, invoca el mètode <code>transform()</code> amb els mateixos arguments. Això, bàsicament, desfà la transformació actual, i després estableix la transformació especificada, tot en un sol pas.</dd> + <dt>{{domxref("CanvasRenderingContext2D.resetTransform", "resetTransform()")}}</dt> + <dd>Reinicia la transformació actual a la matriu d'identitat. Això és el mateix que cridar: <code>ctx.setTransform(1, 0, 0, 1, 0, 0);</code></dd> +</dl> + +<h3 id="Exemple_de_transform_i_setTransform">Exemple de <code>transform</code> i <code>setTransform</code></h3> + +<pre class="brush: js; highlight:[12,15]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + var sin = Math.sin(Math.PI / 6); + var cos = Math.cos(Math.PI / 6); + ctx.translate(100, 100); + var c = 0; + for (var i = 0; i <= 12; i++) { + c = Math.floor(255 / 12 * i); + ctx.fillStyle = 'rgb(' + c + ', ' + c + ', ' + c + ')'; + ctx.fillRect(0, 0, 100, 10); + ctx.transform(cos, sin, -sin, cos, 0, 0); + } + + ctx.setTransform(-1, 0, 0, 1, 100, 100); + ctx.fillStyle = 'rgba(255, 128, 255, 0.5)'; + ctx.fillRect(0, 50, 100, 100); +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="200" height="250"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("Example_for_transform_and_setTransform", "230", "280", "https://mdn.mozillademos.org/files/255/Canvas_transform.png")}}</p> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Using_images", "Web/API/Canvas_API/Tutorial/Compositing")}}</p> + +<div class="s3gt_translate_tooltip_mini_box" id="s3gt_translate_tooltip_mini" style="position: absolute; left: 224px; top: 1401px; opacity: 0;"> +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_logo" title="Traducir texto seleccionado"> </div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_sound" title="Reproducir"> </div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_copy" title="Copy text to Clipboard"> </div> +</div> |