Introduction
Décortication.
Trois ingrédients
Pour faire votre propre typotap, il vous faut :
- Environ 26 SVG ;
- 26 MP3 ;
- 200 gr de JavaScript.
Les SVG
Pour les SVG, il est nécessaire de comprendre, le dessin en SVG via un logiciel de votre choix (Illustrator, Figma, InkScape, Affinity Designer), la balise <g>
et les options de la balise <svg>
pour certains cas (preserveAspectRatio).
Les MP3
Par défaut, les animations vont être créées avec une base temporelle en seconde, pour certains sons rythmiques, j’ai réglé les BPM à 120 ou 60 (astuce offerte).
Le JavaScript
On décompose les connaissances :
- Détecter les événements du clavier — les touches pressées (niveau débutant) ;
- Charger un SVG en JavaScript (pas débutant, mais facile à écrire avec un exemple) ;
- Animer le SVG, on utilisera la librairie GSAP (niveau moyen) ;
- Lire le MP3, on utilisera ToneJS (niveau débutant avec un exemple) ;
- Retirer le SVG (une ligne :))
Récipient
L’ensemble des ingrédients sera mélangé dans votre navigateur, de préférence à jour et on monte le tout dans une page HTML, avec un peu de CSS.
En pratique
On commence par le clavier et le JavaScript.
See the Pen clavier by Benoît Wimart (@benoitwimart) on CodePen.
Puis pour le SVG, on va chercher le fichier (fetch) et si on le trouve (internet ok, le site ok, le fichier existe…), dès qu’il est totalement chargé, on l’insère dans l’élément « #play ».
See the Pen fetch svg by Benoît Wimart (@benoitwimart) on CodePen.
Les deux ensemble (en supposant que le svg est dans le même dossier) :
const play = document.querySlector('#play'); function load(letter){ fetch(letter+'.svg') // concatenation, je charge a.svg ou b.svg … z.svg .then(function(response){ if(response.ok){ response.text().then(function(svg){ play.insertAdjacentHTML("beforeend", svg); }); } }); } document.addEventListener('keyup',function(e){ load(e.key); // une fonction qui charge });
J’anime
Voici l’avant dernière étape, l’animation, il faut connaitre les fonctions, GSAP et l’overlap (la superposition) en CSS avec Grid.
L’ensemble est ici sur Repl.it.
const play = document.querySelector('#play'); function load(letter){ fetch(letter+'.svg') // concatenation, je charge a.svg ou b.svg … z.svg .then(function(response){ if(response.ok){ response.text().then(function(svg){ // insertion professionnelle play.insertAdjacentHTML("beforeend", svg); // on ajoute un id avec la lettre et la date en ms // depuis 1970 pour le rendre unique // ex : r1586771234272 // https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Date/now play.lastElementChild.id = letter + Date.now(); // la fonction qui animera // je lui donne la lettre, l'élément et l'id anim(letter,play.lastElementChild,play.lastElementChild.id); }); } }); } document.addEventListener('keyup',function(e){ load(e.key); // une fonction qui charge }); function anim(letter,el,id){ // je récupère la letter, l'élément et l'id pour gsap et le switch // voir la doc mdn sur le switch/case switch(letter) { case 'r': // j'attache une timeline à l'élément el.tl_= gsap.timeline(); // gsap to el.tl_.to('body',{backgroundColor:'#F90'}); // '#'+id+' .r' sera '#r1586771234272 .r' el.tl_.to('#'+id+' .r',{duration:.2,rotation:-15,transformOrigin:'left bottom',repeat:1,yoyo:true,ease:'power1.out'},0); el.tl_.to('#'+id,{scale:1.1,transformOrigin:'.5 .5',opacity:0,duration:2,ease:'power1'},0); // on enchaine et efface l'élément quand l'animation est finie :) el.tl_.call(function(){el.remove()}); break; // avec les autres lettres /* case 's': el.tl_= gsap.timeline(); el.tl_.to('body',{backgroundColor:'#000'}); el.tl_.to('#'+id+' .s',{duration:.2,rotation:-15,transformOrigin:'left bottom',repeat:1,yoyo:true,ease:'power1.out'},0); el.tl_.to('#'+id,{scale:1.1,transformOrigin:'.5 .5',opacity:0,duration:2,ease:'power1'},0); el.tl_.call(function(){el.remove()}); break; */ } }
Let’s the musique play
J’ajoute la librairie dans la page d’HTML.
Je connnais peu ToneJS, mais le sampler permet de charger nos sons et avoir une polyphonie.
Pour TypoTap, après chargement, j’ajoute l’écouteur d’événement du clavier.
Voici la demo sur repl.it
Le code JavaScript :
const play = document.querySelector('#play'); /* TONE JS */ const alphabet = new Tone.Sampler({ "F3":"r.mp3", // , <- virgule "G3":"s.mp3" // on liste les sons ici }, // <- virgule function(){ // quand les mp3 sont chargés, on ajoute l'écouteur de clavier // ce bout de code était plus bas document.addEventListener('keyup',function(e){ load(e.key); // une fonction qui charge }); } ).toMaster(); // <- un truc de toneJS pour envoyer le son function load(letter){ fetch(letter+'.svg') // concatenation, je charge a.svg ou b.svg … z.svg .then(function(response){ if(response.ok){ response.text().then(function(svg){ // insertion professionnelle play.insertAdjacentHTML("beforeend", svg); // on ajoute un id avec la lettre et la date en ms // depuis 1970 pour le rendre unique // ex : r1586771234272 // https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Date/now play.lastElementChild.id = letter + Date.now(); // la fonction qui animera // je lui donne la lettre, l'élément et l'id anim(letter,play.lastElementChild,play.lastElementChild.id); }); } }); } function anim(letter,el,id){ // je récupère la letter, l'élément et l'id pour gsap et le switch // voir la doc mdn sur le switch/case switch(letter) { case 'r': /* Tone JS en action */ alphabet.triggerAttack("F3"); // j'attache une timeline à l'élément el.tl_= gsap.timeline(); // gsap to el.tl_.to('body',{backgroundColor:'#F90'}); // '#'+id+' .r' sera '#r1586771234272 .r' el.tl_.to('#'+id+' .r',{duration:.2,rotation:-15,transformOrigin:'left bottom',repeat:1,yoyo:true,ease:'power1.out'},0); el.tl_.to('#'+id,{scale:1.1,transformOrigin:'.5 .5',opacity:0,duration:2,ease:'power1'},0); // on enchaine et efface l'élément quand l'animation est finie :) el.tl_.call(function(){el.remove()}); break; // avec les autres lettres /* case 's': el.tl_= gsap.timeline(); el.tl_.to('body',{backgroundColor:'#000'}); el.tl_.to('#'+id+' .s',{duration:.2,rotation:-15,transformOrigin:'left bottom',repeat:1,yoyo:true,ease:'power1.out'},0); el.tl_.to('#'+id,{scale:1.1,transformOrigin:'.5 .5',opacity:0,duration:2,ease:'power1'},0); el.tl_.call(function(){el.remove()}); break; */ } }