Transformaciones SVG

Funciones de transformación


En SVG, existe un atributo denominado transform mediante el cuál se pueden hacer transformaciones a las formas, figuras y trazos dibujados. Las transformaciones SVG son muy similares a las transformaciones CSS, sin embargo tienen algunas diferencias sustanciales.

Estas son las funciones que podemos utilizar para realizar transformaciones:

Función Descripción
translate(x y) Traslada (mueve) el elemento x unidades en horizontal, y y unidades en vertical.
rotate(a x y) Rota el elemento a grados, utilizando el punto de origen (x, y).
scale(x y) Escala el elemento x unidades en horizontal y y unidades en vertical.
scale(s) Escala el elemento s unidades en horizontal y vertical.
skewX(x) Deforma el elemento x unidades en horizontal.
skewY(y) Deforma el elemento y unidades en vertical.

Una diferencia importante respecto a HTML/CSS, es que en SVG los valores por parámetro no se separan por comas, ni se utilizan unidades como px, ya que indicamos las unidades del viewbox.

Observa la siguiente imagen SVG con fondo gris, donde tenemos un cuadrado color violeta del tamaño de la mitad del lienzo, colocado al inicio.

<svg viewBox="0 0 100 100" height="300" style="background:grey">
  <rect x="0" y="0" width="50" height="50" fill="indigo">
</svg>

En los siguientes ejemplos, vamos a añadirle un atributo transform al elemento <rect> para realizar transformaciones. En las demostraciones interactivas puedes variar los valores de la función de transformación y observar la diferencia visual.

La función translate()

Mediante la transformación translate() podemos realizar movimientos o desplazamientos en horizontal y vertical. Observa que los parámetros, aunque pueden ir separados por comas, es más habitual separarlo únicamente con espacios.

<svg viewBox="0 0 100 100" height="300" style="background:grey">
  <rect x="0" y="0" width="50" height="50" fill="indigo" transform="translate(50 50)">
</svg>

<p>Valor de <code>X</code>: <input class="x" type="range" min="-25" max="75" value="50"></p>
<p>Valor de <code>Y</code>: <input class="y" type="range" min="-25" max="75" value="50"></p>

<code>transform="translate(</code><output>50 50</output><code>)"</code>
const x = document.querySelector(".x");
const y = document.querySelector(".y");
const rect = document.querySelector("rect");
const output = document.querySelector("output");

const update = () => {
  output.value = `${x.value} ${y.value}`;
  rect.setAttribute("transform", `translate(${x.value} ${y.value})`);
}

x.addEventListener("input", () => update());
y.addEventListener("input", () => update());

La función rotate()

Mediante la función rotate() debemos indicar tres parámetros: el ángulo (de 0 a 360), el punto de referencia de x y el punto de referencia de y. El único obligatorio es el ángulo, ya que si no indicamos valores x e y, ambos valdrán 0.

<svg viewBox="0 0 100 100" height="300" style="background:grey">
  <rect x="0" y="0" width="50" height="50" fill="indigo" transform="rotate(45 50 50)">
</svg>

<p>Angulo de rotación: <input class="a" type="range" min="0" max="360" value="45"></p>
<p>Valor de <code>X</code>: <input class="x" type="range" min="0" max="50" value="50"></p>
<p>Valor de <code>Y</code>: <input class="y" type="range" min="0" max="50" value="50"></p>

<code>transform="rotate(</code><output>45 50 50</output><code>)"</code>
const a = document.querySelector(".a");
const x = document.querySelector(".x");
const y = document.querySelector(".y");
const rect = document.querySelector("rect");
const output = document.querySelector("output");

const update = () => {
  output.value = `${a.value} ${x.value} ${y.value}`;
  rect.setAttribute("transform", `rotate(${a.value} ${x.value} ${y.value})`);
}

a.addEventListener("input", () => update());
x.addEventListener("input", () => update());
y.addEventListener("input", () => update());

La función scale()

La transformación scale() nos permite escalar nuestro objeto, y hacerlo más pequeño (valores inferiores a 1) o más grande (valores superiores a 1). Observa el siguiente ejemplo, que tiene un scale(1) por defecto. Esto significa que el elemento no estará alterado, sino que estará a su tamaño real.

Si indicamos un scale(2), el elemento tendrá el doble de tamaño, si indicamos un scale(0.5) tendrá la mitad de su tamaño real.

<svg viewBox="0 0 100 100" height="300" style="background:grey">
  <rect x="0" y="0" width="50" height="50" fill="indigo" transform="scale(1)">
</svg>

<p>Escala: <input class="s" type="range" min="0" max="2" step="0.1" value="1"></p>

<code>transform="scale(</code><output>1</output><code>)"</code>
const s = document.querySelector(".s");
const rect = document.querySelector("rect");
const output = document.querySelector("output");

const update = () => {
  output.value = `${s.value}`;
  rect.setAttribute("transform", `scale(${s.value})`);
}

s.addEventListener("input", () => update());

También es posible indicar dos parámetros, de modo que si indicamos scale(1 2), significa que el elemento tendrá el mismo tamaño en horizontal, pero el doble en vertical.

La función skewX() / skewY()

Por último, las funciones de transformación skewX() y skewY() permiten deformar o torcer un elemento. Juega un poco con los controles de la demo y observarás el resultado de deformar elementos en los diferentes ejes.

<svg viewBox="0 0 100 100" height="300" style="background:grey">
  <rect x="0" y="0" width="50" height="50" fill="indigo" transform="skewX(45) skewY(0)">
</svg>

<p>Valor de <code>X</code>: <input class="x" type="range" min="-45" max="45" value="45"></p>
<p>Valor de <code>Y</code>: <input class="y" type="range" min="-45" max="45" value="0"></p>

<code>transform="</code><output>skewX(45) skewY(0)</output><code>"</code>
const x = document.querySelector(".x");
const y = document.querySelector(".y");
const rect = document.querySelector("rect");
const output = document.querySelector("output");

const update = () => {
  output.value = `skewX(${x.value}) skewY(${y.value})`;
  rect.setAttribute("transform", `skewX(${x.value}) skewY(${y.value})`);
}

x.addEventListener("input", () => update());
y.addEventListener("input", () => update());

Como habrás visto, ten en cuenta que es posible aplicar múltiples transformaciones simplemente separando por espacio las funciones de transformación.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev