Créer des visuels interactifs avec JavaScript et HTML5 Canvas

, Author

Projet 1 : Lignes glacées

Pour de meilleurs résultats, ouvrez en plein écran

D’abord, nos lignes sont blanches, donc allons dans notre CSS et donnons au canevas un fond sombre :

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

Constructeur de ligne

Revenons maintenant à canvas.js . Créons une nouvelle classe Line:

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

A part la détermination de la position x et y de chaque ligne, nous avons quelques autres propriétés pour rendre nos visuels plus intéressants:

  • Nous pouvons utiliser la propriété offset pour rendre les lignes à des distances variables les unes des autres.
  • Nous allons également utiliser le mouvement circulaire dans notre exemple. Nous pouvons utiliser la propriété radians pour définir l’angle du mouvement et la propriété velocity pour déterminer la vitesse du mouvement.

Méthode de dessin de ligne

Puis, nous voudrons dessiner nos lignes. Il y a un petit cercle au bas de chaque ligne, que nous pouvons définir en utilisant la fonction arc, et ensuite la ligne s’élance vers le haut de l’écran:

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
}
}

Pour tester que cela fonctionne, vous pouvez créer une ligne échantillon:

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

Générer 100 lignes

Mais nous voulons que les lignes remplissent l’écran, donc nous aurons besoin d’un moyen de créer un tableau de 100 lignes. Voici une version simple :

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)
)
);
};

Pour visualiser ces lignes, nous devrons déclencher leurs méthodes draw. Comme nous allons bientôt les animer, le meilleur endroit pour le faire est dans la fonction animate:

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

Nous avons maintenant 100 lignes ! Mais nous pouvons rendre notre position de départ plus intéressante : dans le code ci-dessous, la variable random aide à fournir une variation subtile qui donne à l’effet global un aspect plus naturel. (J’utilise également Math.sin(i) pour ajouter un peu d’ondulation dans les positions de départ. Ce n’est pas nécessaire, mais c’est une touche agréable.)

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)
)
);
};

Joue avec les chiffres jusqu’à ce que tu aies un modèle de départ que tu aimes !

Animation

À partir d’ici, il est très simple d’ajouter l’animation que nous voulons. Retournez à notre classe Line, puis ajoutez ce qui suit dans la méthode update:

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

A chaque image d’animation, this.radians augmentera de this.velocity . Nous utiliserons ensuite this.radians pour créer un mouvement circulaire, via Math.cos .

Si vous n’avez jamais rencontré Math.sin ou Math.cos auparavant (ou si votre trigonométrie est un peu rouillée !), cela ne devrait pas vous empêcher de suivre. Sachez simplement que Math.cos nous permet de créer un mouvement de va-et-vient, selon un schéma identique à la ligne violette du graphique ci-dessous :

Vague cosinus

Enfin, en ajoutant this.offset , les lignes commenceront à se boucler à des angles différents.

Je pense que c’est un effet assez agréable. Mais pour une touche finale, ajoutons un peu d’interactivité. Lorsque l’utilisateur survole les lignes, faisons en sorte qu’elles changent de couleur.

Interactivité

La façon la plus simple de voir si la souris de l’utilisateur est sur l’une des lignes est d’utiliser la méthode isPointInPath intégrée à canvas.

Mais, sans autres ajustements, cela ne va pas être très utile. Les lignes ne font qu’un pixel de large, donc la chance de déclencher des changements sera trop faible pour être intéressante !

Une excellente solution à ce problème est de créer des lignes invisibles derrière chacune de nos lignes. Les lignes invisibles devraient être plus larges, et nous pouvons les utiliser pour déclencher isPointInPath.

isPointInPath

Dans notre méthode draw, créons une fonction appelée drawLinePath . Elle devrait prendre un width pour nos lignes invisibles, et un color (que nos lignes visibles deviendront, lorsque les lignes invisibles seront en contact):

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;
};
};

(Notez que l’utilisation des fonctions flèches ci-dessus lie implicitement le contexte correct pour this ).

Nous pouvons alors facilement ajouter différentes largeurs de lignes invisibles pour déclencher différents changements de couleur. Le code suivant devrait rendre clair ce qui se passe:

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

Mais, pour un effet plus subtil, essayez:

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

Et c’est un enveloppement!

Pour le code JavaScript complet, consultez ce gist.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.