Flechas (markers)

La etiqueta <marker>


La etiqueta <marker> permite dibujar flechas en trayectos o trazos específicos. Observa el siguiente ejemplo, donde a grandes rasgos, utilizamos una etiqueta <marker> con un trayecto en su interior que define la cabeza de la flecha y donde podemos personalizarla a nuestro gusto. Esta cabeza de flecha debe ser indicada dentro de una etiqueta denominada <defs> (definiciones).

Un poco más adelante, definimos la forma o trayecto a la que queremos ponerle las flechas, y le indicamos mediante el atributo marker-end la función url() donde indicamos el ID de la flecha a utilizar, precedido de un #. Aquí un ejemplo inicial:

<svg viewBox="0 0 100 100" height="250">
  <defs>
    <marker id="arrow" markerWidth="5" markerHeight="5"
            viewBox="0 0 10 10" refX="0" refY="5"
            orient="auto-start-reverse">
      <path d="M0 0 L10 5 L0 10 Z" />
    </marker>
  </defs>
  <path d="M5 10 L50 90 L50 50 L90 50 L90 10"
        stroke="black" fill="none"
        marker-end="url(#arrow)" />
</svg>
svg {
  background: grey;
}

Una vez visto este primer ejemplo donde utilizamos esta etiqueta <marker>, echemos un vistazo a los atributos que podemos utilizar en ella:

AtributoPor defectoDescripción
id-Indica un nombre para la flecha, mediante el cuál posteriormente haremos referencia.
markerWidth3Indica el tamaño de ancho de la flecha, en unidades del viewBox.
markerHeight3Indica el tamaño de alto de la flecha, en unidades del viewBox.
markerUnitsstrokeWidthIndica las unidades de los valores anteriores. El valor userSpaceOnUse o strokeWidth.
viewBoxnoneIndica el viewBox de la flecha. Tiene relación con el <path> de su interior.
refX0Posición de partida de la flecha (horizontal). Valores: left, center, right o .
refY0Posición de partida de la flecha (vertical). Valores: left, center, right o .
orient0Indica la orientación de la flecha: auto, auto-start-reverse o un valor de .

Expliquemos cada uno de ellos.

Tamaño de la flecha

Mediante los atributos markerWidth, markerHeight y markerUnits se puede modificar el tamaño de la cabeza de la flecha. Observa en el ejemplo anterior, que hemos indicado un valor de 5 en markerWidth y markerHeight. Vamos a modificarlo:

<svg viewBox="0 0 100 100" height="250">
  <defs>
    <marker id="arrow" markerWidth="5" markerHeight="5"
            viewBox="0 0 10 10" refX="0" refY="5"
            orient="auto-start-reverse">
      <path d="M0 0 L10 5 L0 10 Z" />
    </marker>
  </defs>
  <path d="M5 10 L50 90 L50 50 L90 50 L90 10"
        stroke="black" fill="none"
        marker-end="url(#arrow)" />
</svg>
svg {
  background: grey;
}

Observa que el tamaño de la cabeza de la flecha es ahora el doble de grande, ya que lo hemos modificado de 5 a 10. Además, también podemos añadir el atributo markerUnits con los valores strokeWidth(por defecto) o userSpaceOnUse. El primero de ellos nos indica que el tamaño especificado depende del grosor del trazo del elemento, de modo que si le añadimos un stroke-width al <path> del final, estaremos modificando el grosor de ese trayecto y, consecuentemente, el tamaño de la flecha.

En el caso de utilizar userSpaceOnUse, el tamaño de las flechas se determina en relación al tamaño del sistema y no depende directamente del grosor del trazo.

Orientación

El atributo orient indica la rotación para orientar la flecha según la posición de la forma donde se coloca.

ValoresDescripción
autoLa flecha se coloca en una orientación automática (dirección del trayecto).
auto-start-reverseIgual a auto, pero la flecha inicial hacia el lado contrario (180 grados).
0 | [angulo] | [número]Indica la orientación de la flecha en grados. Por defecto, 0.

Veamos un ejemplo donde utilizamos esto.

<svg viewBox="0 0 100 100" height="250">
  <defs>
    <marker id="arrow" markerWidth="5" markerHeight="5"
            viewBox="0 0 10 10" refX="0" refY="5"
            orient="auto">
      <path d="M0 0 L10 5 L0 10 Z" />
    </marker>
  </defs>
  <path d="M5 10 L50 10 L50 50" stroke="black" fill="none"
        marker-end="url(#arrow)"
        marker-mid="url(#arrow)"
        marker-start="url(#arrow)" />
</svg>
<p>Valor de <code>orient</code>:</p>
<input type="range" min="0" max="360" value="0">
<output>1</output>
const marker = document.querySelector("marker");
const input = document.querySelector("input");

input.addEventListener("input", () => {
  input.nextElementSibling.value = input.value;
  marker.setAttribute("orient", input.value);
});
svg {
  background: grey;
  display: block;
}

Los atributos refX y refY

Mediante los atributos refX y refY establecemos las coordenadas de referencia para la flecha. Para entender esto, observemos el ejemplo anterior y analicemos los atributos:

<defs>
  <marker id="arrow" markerWidth="5" markerHeight="5"
          viewBox="0 0 10 10" refX="0" refY="5"
          orient="auto">
    <path d="M0 0 L10 5 L0 10 Z" />
  </marker>
</defs>

Observemos el viewBox de 10x10 que tenemos, por lo que todo ocurrirá dentro de ese rectángulo (viewbox). Si nos fijamos en el parámetro d del <path> definido, encontraremos que el trayecto va desde el punto (0,0) hasta el punto (10,5) y luego hasta el punto (0,10), cerrándose en su punto de inicio (0,0). Al indicar unas referencias de (0,5) con los atributos refX y refY, lo que estamos haciendo es decirle que el punto central de la flecha estará posicionado en ese punto (0,5).

Por otro lado, observa que tenemos un atributo viewBox para establecer una subregión independiente del viewBox del SVG, donde se creará la flecha que utilizaremos.

Utilizando las flechas

Una vez llegados a este punto, hemos definido la flecha con la etiqueta <marker>. Ahora sólo nos queda elegir el elemento donde vamos a añadirlas visualmente. Para ello, utilizaremos elementos basados en trayectos como <path>, <line>, <polyline> o <polygon>. Para indicar que dichos elementos tienen flechas, podemos utilizar los siguientes atributos:

AtributoPor defectoDescripción
marker-startnoneIndica la flecha a utilizar en el extremo inicial.
marker-midnoneIndica la flecha a utilizar en las uniones intermedias.
marker-endnoneIndica la flecha a utilizar en el extremo final.

El atributo marker-start indica una flecha en el extremo inicial del trayecto. El atributo marker-end indica una flecha en el extremo final del trayecto. Por último, el atributo marker-mid establece flechas en los puntos de unión del trayecto.

El valor que podemos utilizar en dichos atributos será el uso de una función url() donde en su interior, haremos referencia a un id que pertenece al elemento <marker> que queremos utilizar:

<path d="M5 10 L50 90 L50 50 L90 50 L90 10"
        stroke="black" fill="none"
        marker-end="url(#arrow)" />

Recuerda que el elemento <marker> debe estar dentro de la región de definiciones <defs>, y que para definir su forma, se utilizará una forma SVG en el interior del <marker>.

¿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