Animación de máscaras CSS.
Tags: webdev, javascript, css, spanish
Published: 2022-06-07 21:13:55

Hoy aprenderemos a animar máscaras css, apoyándonos en la posición del cursor para crear un efecto único para tu próximo proyecto web.

![Imagen de una mujer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/git711shkw0e6hssbkfh.png)

Demo
https://css-mask-effect.netlify.app/

Github
https://github.com/JairDev/css-mask-effect

***

El enmascaramiento en css, nos permite “cortar” (enmascarar ) un elemento, ya sea a través de una imagen, un svg o un degradado pudiendo establecer que parte serán o no visibles de ese elemento de acuerdo a la transparencia en la imagen, svg o degradado.

Como podemos ver en este ejemplo, nuestra imagen que servirá de máscara es el logo de apple, es totalmente negra con un fondo transparente y nuestro elemento a enmascarar tiene un fondo de color rosa.

![tres imágenes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/07k8tkbgc2t2slzslq6s.png)

*La imagen se aplica como máscara al elemento rosa, lo ilustré de esta manera para ver como actúa el fondo transparente de la imagen, solo serían dos elementos, mas adelante lo veremos.

***

**Máscara aplicada**

![imagen de manzana sobre imagen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rio8cij0k1tayeutn7j9.png)

La parte mas oscura de nuestra imagen, svg o degradado hacen visible el elemento mientras que la parte mas trasparente ocultan el elemento.

![gif de asombro](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkbjg8h1f1y2wqwpn2s5.gif)

{% codesandbox https://codesandbox.io/embed/black-hill-9pkco7?fontsize=14&hidenavigation=1&theme=dark %}

###Propiedad css mask:

La propiedad css mask es un shorthand para mask-image, mask-repeat, mask-position entre otras propiedades, https://developer.mozilla.org/es/docs/Web/CSS/mask. 

```
.element {
  mask-image: url("image-link");
  mask-repeat: no-repeat;
  mask-position: center;
  ...
}
```

Funciona parecido a la propiedad background de css, podemos establecer una imagen mediante una url, si queremos que se repita o no la máscara, de esta manera tenemos mas control sobre los efectos de nuestra máscara.

***

**Ahora a ensuciarnos las manos ...** :sunglasses:

Para nuestro efecto vamos a duplicar nuestro elemento `.hero`.

![capas duplicadas](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fttqub0t4d7pnliqv00g.png)

```
<div class="container">
 <div class="hero">
  <div class="contain-name">
    <h1>Hi, I am Kim,</h1>
    <span>I am a</span>
    <span>web developer.</span>
  </div>
  ...
 </div>

 <div class="hero copy" aria-hidden="true">
  <div class="contain-name">
    <p>Hi, I am Kim,</p>
    <span>I am a</span>
    <span class="span web-developer">web developer.</span>
  </div>
  ...
 </div>
</container

```

Para mejorar la accesibilidad de nuestro contenido, hemos establecido el elemento duplicado en `aria-hidden="true"` para evitar que sea mencionado dos veces por lectores de pantalla.

### Enmascaramiento del elemento duplicado.

```
.hero.copy {
 --mask: radial-gradient(
    circle at 15% 50%,
    black 25%,
    transparent 0%
  );
  -webkit-mask: var(--mask);
  mask: var(--mask);
}
```

Estilos 

```

.container {
  background: #18191c;
}

.hero {
  opacity: 0.6;
}

.hero.copy {
  background: #7f8189af;
  filter: brightness(1.5);
  opacity: 1;
}

.span.web-developer {
  color: #ff03a0;
}
```

En el elemento `.container` utilizamos un fondo oscuro y en nuestro elemento base `.hero` establecemos una opacidad de 0.6 para dar una sensación de oscuridad.

Para la máscara utilizaremos un radial gradient, estableciendo el circulo que vemos a continuación, el fondo será de un color grisáceo para dar el efecto de un foco de luz blanca, aumentaremos un poco el brillo y resaltaremos el texto web developer con un color intenso.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/223cchv5b2n0kizgh6dp.png)

Como puedes ver, la máscara que es un circulo se está aplicando a nuestro elemento, vamos a difuminar un poco el circulo asignando un 4% al inicio del gradiente y un 25% al final.

```
.hero.copy {
 --mask: radial-gradient(
    circle at 15% 50%,
    black 4%,
    transparent 25%
  );
  -webkit-mask: var(--mask);
  mask: var(--mask);
}
```

El resultado ...

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/loissrtwa6x42677tguo.png)

###Rastrear la posición del cursor

Para lograr nuestro efecto de "movimiento de la luz", necesitamos rastrear el cursor de acuerdo al movimiento del usuario, JavaScript al rescate :muscle:

Primero definamos unas propiedades personalizadas "--x", "--y", y establezcamos una posición inicial para la máscara, 15% y 50% respectivamente.

```
--mask: radial-gradient(
  circle at var(--x, 15%) var(--y, 50%),
  black 4%,
  transparent 25%
  )
```
En nuestro archivo JS llamamos al evento "mousemove", obtenemos la posición del mouse y hacemos el cálculo para luego asignar ese valor porcentual a nuestras propiedades personalizadas --x y --y.

```
const hero = document.querySelector(".hero.copy");

window.addEventListener("mousemove", (e) => {
  const x = Math.round((e.clientX / window.innerWidth) * 100);
  const y = Math.round((e.clientY / window.innerHeight) * 100);
  hero.style.setProperty("--x", `${x}%` )
  hero.style.setProperty("--y", `${y}%`)
}); 
```

{% codesandbox https://codesandbox.io/embed/funny-night-vebz5t?fontsize=14&hidenavigation=1&theme=dark %}

Al movimiento de nuestro "foco de luz" le falta un poco de suavidad para que no se sienta tenso. Para lograr esto utilizaré una biblioteca js de animaciones llamada gsap https://greensock.com/docs/, esta biblioteca nos permite establecer una transición de manera sencilla a nuestra máscara ya que estamos utilizando propiedades personalizadas.

`npm install gsap`

```
import gsap from "gsap";

const hero = document.querySelector(".hero.copy");

window.addEventListener("mousemove", (e) => {
  const x = Math.round((e.clientX / window.innerWidth) * 100);
  const y = Math.round((e.clientY / window.innerHeight) * 100);
  gsap.to(hero, {
    "--x": `${x}%`,
    "--y": `${y}%`,
    duration: 0.4,
    ease: "sine.out",
  });
});
```

{% codesandbox https://codesandbox.io/embed/dry-tdd-3f7jiy?fontsize=14&hidenavigation=1&theme=dark %}

Ahora nuestro movimiento se siente mas natural :grin:

¡Espero este post haya sido de tu agrado!

Te invito a que juegues con las máscaras css y me enseñes ese próximo proyecto donde incluyas grandiosos efectos con esta propiedad.

Tu feedback es de mucha ayuda para mi :pray:

Conectemos :sunglasses:
https://twitter.com/JairDevep
https://www.linkedin.com/in/alfredo-moscoso-desarrollador-frontend/

¡Nos vemos pronto! :facepunch: