Crea visuales interactivos con JavaScript y HTML5 Canvas

, Author

Proyecto 1: Líneas heladas

Para obtener los mejores resultados, abre en pantalla completa

Primero, nuestras líneas son blancas, así que vayamos a nuestro CSS y demos al lienzo un fondo oscuro:

canvas {
background: linear-gradient(45deg, #0d1011 0% 20%, #163486);
}

Constructor de líneas

Ahora volvamos a canvas.js . Vamos a crear una nueva clase Line:

class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
}

Aparte de determinar la posición de cada línea x y y, tenemos algunas otras propiedades para hacer nuestros visuales más interesantes:

  • Podemos utilizar la propiedad offset para renderizar las líneas a diferentes distancias entre sí.
  • También vamos a utilizar el movimiento circular en nuestro ejemplo. Podemos utilizar la propiedad radians para definir el ángulo de movimiento y la propiedad velocity para determinar la velocidad del movimiento.

Método de dibujo de líneas

A continuación, querremos dibujar nuestras líneas. Hay un pequeño círculo en la parte inferior de cada línea, que podemos definir usando la función arc, y luego la línea sale disparada hacia la parte superior de la pantalla:

class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
} draw = () => {
c.strokeStyle = 'rgba(255, 255, 255, 0.5)';
c.fillStyle = 'rgba(255, 255, 255, 0.3)'; c.beginPath();
c.arc(this.x, this.y, 1, 0, Math.PI * 2, false);
c.fill();
c.moveTo(this.x, this.y);
c.lineTo(this.x + 300, this.y - 1000);
c.stroke();
c.closePath(); this.update();
} update = () => {
// this is where we control movement and interactivity
}
}

Para probar que funciona, puedes crear una línea de ejemplo:

const line = new Line(250, 800, 0);
line.draw();

Generación de 100 líneas

Pero queremos que las líneas llenen la pantalla, así que necesitaremos una forma de crear una matriz de 100 líneas. Aquí tenemos una versión sencilla:

const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const unit = 25; lineArray.push(
new Line(
start.x + unit * i,
start.y + i * -3,
0.1 + (1 * i)
)
);
};

Para ver estas líneas, necesitaremos activar sus métodos draw. Como pronto las animaremos, el mejor lugar para hacerlo es en la función animate:

function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
lineArray.forEach(line => {
line.draw();
});
};animate();

¡Ahora tenemos 100 líneas! Pero podemos hacer que nuestra posición inicial sea más interesante: en el código siguiente, la variable random ayuda a proporcionar una sutil variación que da al efecto general un aspecto más natural. (También estoy usando Math.sin(i) para añadir un poco de ondulación en las posiciones iniciales. Esto no es necesario, pero es un buen toque.)

const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const random = Math.random() - 0.5;
const unit = 25; lineArray.push(
new Line(
start.x + ((unit + random) * i),
start.y + (i + random) * -3 + Math.sin(i) * unit,
0.1 + (1 * i)
)
);
};

¡Juega con los números hasta que tengas un patrón de inicio que te guste!

Animación

A partir de aquí, es muy sencillo añadir la animación que queremos. Volvemos a nuestra clase Line y añadimos lo siguiente en el método update:

this.radians += this.velocity;
this.y = this.y + Math.cos(this.radians + this.offset);

Con cada fotograma de animación, this.radians aumentará en this.velocity . A continuación, utilizaremos this.radians para crear un movimiento circular, a través de Math.cos .

Si no has encontrado Math.sin o Math.cos antes (¡o tu trigonometría está un poco oxidada!), eso no debería impedirte seguir adelante. Sólo tienes que saber que Math.cos nos permite crear un movimiento de ida y vuelta, en un patrón idéntico a la línea púrpura en el gráfico de abajo:

Onda coseno

Por último, añadiendo this.offset , las líneas comenzarán a hacer un bucle en diferentes ángulos.

Creo que este es un efecto bastante bonito. Pero para darle un toque final, vamos a añadir algo de interactividad. Cuando el usuario pase por encima de las líneas, hagamos que cambien de color.

Interactividad

La forma más sencilla de ver si el ratón del usuario está sobre una de las líneas es utilizar el método isPointInPath incorporado en el lienzo.

Pero, sin más ajustes, esto no va a ser muy útil. Las líneas son de sólo 1 píxel de ancho, por lo que la posibilidad de desencadenar cualquier cambio será demasiado baja para ser interesante!

Una gran solución a este problema es crear líneas invisibles detrás de cada una de nuestras líneas. Las líneas invisibles deben ser más anchas, y podemos usarlas para disparar isPointInPath.

isPointInPath

Dentro de nuestro método draw , vamos a crear una función llamada drawLinePath . Debería tomar un width para nuestras líneas invisibles, y un color (en el que se convertirán nuestras líneas visibles, cuando las líneas invisibles estén en contacto):

const drawLinePath = (width = 0, color) => {
c.beginPath();
c.moveTo(this.x - (width / 2), this.y + (width / 2));
c.lineTo(this.x - (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2), this.y - (width / 2));
c.closePath();
if (c.isPointInPath(mouse.x, mouse.y) && color) {
c.strokeStyle = color;
};
};

(Ten en cuenta que el uso de las funciones de flecha anteriores vincula implícitamente el contexto correcto para this ).

Podemos entonces añadir fácilmente diferentes anchos de líneas invisibles para desencadenar diferentes cambios de color. El siguiente código debería dejar claro lo que está pasando:

drawLinePath(150, 'red');
drawLinePath(50, 'yellow');

Pero, para un efecto más sutil, prueba:

drawLinePath(150, '#baf2ef');
drawLinePath(50, '#dcf3ff');

¡Y eso es todo!

Para el código JavaScript completo, echa un vistazo a este gist.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.