Recortar con clipPath

facebook-svg gplus-svg twitter-svg

Podemos recortar un trozo de una imagen generada en el lienzo SVG utilizando el elemento <clipPath>. El trazado que aparece dentro del elemento <clipPath> define la región de recorte.
Como siempre cuando se trata de un elemento que no aparece en pantalla, podemos poner el elemento <clipPath> dentro de un elemento <defs> ( definiciones ) y le asignamos una identificación id para poder referenciarlo más tarde.

Un ejemplo básico

En el siguiente ejemplo dentro del elemento <clipPath> aparece un circulo que define la región de recorte.

<clipPath id="clipCirculo"">
       <circle cx="120" cy="125" r="70"></circle>     
</clipPath>

La imagen insertada ( <image xlink:href = "images/arboc.jpg" ) cubre prácticamente todo el lienzo SVG. Para recortar de esta imagen solo la parte central, la del madroño, utilizamos el atributo clip-path = "url(#clipCirculo)". Lo que aparece entre paréntesis es una referencia al elemento <clipPath id="clipCirculo"> definido anteriormente.

<image clip-path="url(#clipCirculo)" . . . . 


  
    
      
    
  
 

Algunos atributos del elemento clipPath

El id es el único atributo imprescindible del elemento <clipPath> ya que se utiliza para referenciarlo mas tarde:

<clipPath id="el_id ">
     <circle cx="120" cy="125" r="70"></circle>
</clipPath>
<image xlink:href="img.jpg" clip-path = "url(#el_id)" height="240" width="250" ></image>

Además del id podemos utilizar varios atributos presentacionales entre los cuales cabe destacar: clipPathUnits y clip-rule.

El atributo clipPathUnits

El atributo clipPathUnits es un atributo especifico utilizado solo con <clipPath> y define el sistema de coordenadas utilizadas para el trazado de recorte. Puede tomar uno de estos dos valores: objectBoundingBox o userSpaceOnUse.

clipPathUnits="userSpaceOnUse"

El valor por defecto del atributo clipPathUnits es userSpaceOnUse. Si clipPathUnits no está definido o si clipPathUnits="userSpaceOnUse" el sistema de coordenadas utilizado para el trazado de recorte coincide con el sistema de coordenadas definido por el valor del atributo viewBox del elemento <svg> o del elemento <symbol>, <marker>, <pattern> o <view> que alberga el objeto.

Por ejemplo si el trazado de recorte es un circulo vamos a escribir:

<circle cx="120" cy="125" r="70"/>

Esto significa que el centro del circulo se encuentra en el punto cuyas coordenadas són: {x:120,y:125} y el radio del circulo es de 20 unidades.

clipPathUnits="objectBoundingBox"

El sistema de coordenadas de referencia para objectBoundingBox es un cuadrado de 1x1 con el origen en la esquina superior izquierda, y es redimensionado para llenar la caja delimitadora del trazado SVG.

Por ejemplo si el trazado de recorte es un circulo:

<circle cx=".5" cy=".5" r=".45" />

Esto significa que el centro del circulo de recorte se encuentra justo en el medio del trazado que queremos recortar cx=".5" cy=".5".
En lo que concierne el radio... es algo más complicado.

Conque el sistema de coordenadas de referencia para objectBoundingBox es un cuadrado de 1x1, pero la caja delimitadora del trazado svg que queremos recortar es un rectángulo que puede tener cualquier tamaño. Esto quiere decir que el cuadrado de 1x1 será redimensionado de manera diferente a lo largo del eje x e y, y la imagen será estirada o comprimida según el caso.

Por ejemplo si el trazado de recorte es un circulo y lo queremos utilizar para cortar un cuadrado, el resultado será un circulo. Si lo utilizamos para recortar un rectángulo el resultado será una elipse.

See the Pen clipPathUnits="objectBoundingBox" by Gabi (@enxaneta) on CodePen.

El atributo clip-rule

Podemos crear trazados perforados (con huecos) utilizando la regla de llenado fill-rule. Por ejemplo el atributo d del path #agujero dibuja primero un rectángulo más grande (M10,5v50h100v-50h-100z). A continuación aparece el comando move to m y a partir de este punto el trazado dibuja un rectángulo interior más pequeño (m10,10v30h80v-30h-80z). El atributo fill-rule="evenodd" hace que el rectángulo interior aparesca como un agujero en el primer rectángulo

<svg viewBox="0 0 120 60">
    <path id="agujero" fill-rule="evenodd" 
    d="M10,5v50h100v-50h-100z
       m10,10v30h80v-30h-80z"/>
  </svg>

La mala noticia es que la regla de llenado fill-rule no afecta los trazados dentro de <clipPath>.

<svg viewBox="0 0 120 60"> 
    <clipPath id="clip" >
      <use xlink:href="#agujero" />
    </clipPath>   
    <image xlink:href="imagen.jpg" x="0" y="0" width="120" height="160" clip-path="url(#clip)" />
  </svg>

Para crear el mismo efecto con <clipPath> necesitamos utilizar el atributo clip-rule, que, exactamente como fill-rule, puede tomar como valor una de estas dos palabras clave: evenodd y nonzero.

<svg viewBox="0 0 120 60"> 
    <clipPath id="clip1" clip-rule="evenodd" >
      <use xlink:href="#agujero" />
    </clipPath>
    <image xlink:href="imagen.jpg" x="0" y="0" width="120" height="160" clip-path="url(#clip1)" />
  </svg>

See the Pen test clipPath & fill-rule by Gabi (@enxaneta) on CodePen.

Varios trazados como región de recorte

No todos los elementos SVG pueden ser utilizados como trazado de recorte. Podemos utilizar  <rect>, <circle>, <ellipse>, <polygon> y <path>.
También podemos utilizar el elemento <text> aunque dejará de comportarse como texto.
Asimismo podemos utilizar <use> pero solo si utiliza uno de los elementos mencionados anteriormente.
Dentro de <clipPath> no podemos utilizar grupos <g> de objetos pero sí pueden aparecer varios trazados que se suman para definir una sola región de recorte. No podemos agrupar estos trazados en un grupo <g>.

See the Pen SVG clipPath*** by Gabi (@enxaneta) on CodePen.

Sin embargo podemos recortar varios objetos SVG a la vez agrupándolos dentro de un elemento <g> al cual recortamos con clip-path.

Texto como región de recorte

Cimo ya he mencionado podemos utilizar texto como región de recorte aunque dejará de comportarse como texto. En el siguiente ejemplo dibujamos un rectángulo que ocupa todo el llienzo SVG. El relleno de este rectángulo es un degradado lineal id="deRojoAamarillo". Utilizamos TEXTO <clipPath id= "texto" > como región de recorte.



  
    
      
      
    
    
      TEXTO
    		
  
 
TEXTO

Intersección de trazados

A veces necesitamos llenar de color la intersección de dos o varios trazados. Una posible solución a este problema es utilizar <clipPath>. En el siguiente ejemplo tengo 3 círculos #c1, #c2 y #c3. Para encontrar la intersección de los 3 círculos voy a utilizar #c2 y #c3 como trazados de recorte.

Primero voy a recortar #c1 con el #clipC2. Después voy a poner el resultado en un grupo <g> y voy a recortar este grupo con el #clipC3.

See the Pen Intersección de trazados con clipPath by Gabi (@enxaneta) on CodePen.