web-dev-qa-db-fra.com

Comment puis-je animer le dessin de texte sur une page Web?

Je veux avoir une page Web qui a un mot centré.

Je veux que ce mot soit dessiné avec une animation, telle que la page "écrit" le mot de la même façon que nous le ferions, c'est-à-dire qu'elle commence à un point et trace des lignes et des courbes dans le temps, de sorte que le résultat final est un glyphe.

Peu m'importe que cela soit fait avec <canvas> ou le DOM, et peu importe que ce soit avec JavaScript ou CSS. L'absence de jQuery serait bien, mais pas obligatoire.

Comment puis-je faire ceci? J'ai cherché de manière exhaustive sans chance.

223
strugee

Je veux que cette Parole soit dessinée avec une animation, telle que la page "écrit" la Parole de la même manière que nous le ferions.

Version toile

Cela va dessiner des caractères uniques plus comme on l'écrirait à la main. Il utilise un long motif en tirets dans lequel l'ordre d'activation/désactivation est permuté dans le temps par caractère. Il a également un paramètre de vitesse.

Snapshot
Exemple d'animation (voir la démo ci-dessous)

Pour augmenter le réalisme et la sensation organique, j'ai ajouté un espacement aléatoire des lettres, un décalage y delta, une transparence, une rotation très subtile et enfin l'utilisation d'une police déjà "manuscrite". Ceux-ci peuvent être regroupés sous forme de paramètres dynamiques pour fournir une large gamme de "styles d'écriture".

Pour une apparence encore plus réaliste, les données de chemin seraient requises, ce qui n’est pas le cas par défaut. Mais il s’agit d’un code court et efficace, proche du comportement écrit à la main, et facile à mettre en œuvre.

Comment ça fonctionne

En définissant un motif en pointillé, nous pouvons créer des fourmis en marche, des lignes en pointillés, etc. Profitant de cela en définissant un très long point pour le point "off" et en augmentant progressivement le point "on", cela donnera l’illusion de tracer la ligne lorsque l’on trace le trait tout en animant la longueur du point.

Comme le point mort est trop long, le motif répété ne sera pas visible (la longueur variera en fonction de la taille et des caractéristiques de la police utilisée). Le chemin de la lettre aura une longueur, nous devons donc nous assurer que chaque point couvre au moins cette longueur.

Pour les lettres composées de plusieurs chemins (par exemple, O, R, P, etc.), comme pour le contour, pour la partie creuse, les lignes apparaîtront dessinées simultanément. Nous ne pouvons pas faire grand chose à ce sujet avec cette technique, car elle nécessiterait un accès à chaque segment de chemin pour être tracé séparément.

Compatibilité

Pour les navigateurs qui ne prennent pas en charge l’élément canvas, une autre manière d’afficher le texte peut être placée entre les balises, par exemple un texte stylé:

<canvas ...>
    <div class="txtStyle">STROKE-ON CANVAS</div>
</canvas>

Démo

Cela produit le coup animé en direct (pas de dépendances) -

var ctx = document.querySelector("canvas").getContext("2d"),
    dashLen = 220, dashOffset = dashLen, speed = 5,
    txt = "STROKE-ON CANVAS", x = 30, i = 0;

ctx.font = "50px Comic Sans MS, cursive, TSCu_Comic, sans-serif"; 
ctx.lineWidth = 5; ctx.lineJoin = "round"; ctx.globalAlpha = 2/3;
ctx.strokeStyle = ctx.fillStyle = "#1f2f90";

(function loop() {
  ctx.clearRect(x, 0, 60, 150);
  ctx.setLineDash([dashLen - dashOffset, dashOffset - speed]); // create a long dash mask
  dashOffset -= speed;                                         // reduce dash length
  ctx.strokeText(txt[i], x, 90);                               // stroke letter

  if (dashOffset > 0) requestAnimationFrame(loop);             // animate
  else {
    ctx.fillText(txt[i], x, 90);                               // fill final letter
    dashOffset = dashLen;                                      // prep next char
    x += ctx.measureText(txt[i++]).width + ctx.lineWidth * Math.random();
    ctx.setTransform(1, 0, 0, 1, 0, 3 * Math.random());        // random y-delta
    ctx.rotate(Math.random() * 0.005);                         // random rotation
    if (i < txt.length) requestAnimationFrame(loop);
  }
})();
canvas {background:url(http://i.imgur.com/5RIXWIE.png)}
<canvas width=630></canvas>
254
user1693593

Éditer 2019


J'ai créé une bibliothèque javascript permettant de créer des animations réalistes. Il est facile à utiliser et nécessite un fichier JSON spécial qui fait office de police.

var vara = new Vara("#container", "https://rawcdn.githack.com/akzhy/Vara/ed6ab92fdf196596266ae76867c415fa659eb348/fonts/Satisfy/SatisfySL.json", [{
  text: "Hello World!!",
  fontSize: 48,
  y:10
}, {
  text: "Realistic Animations",
  fontSize: 34,
  color:"#f44336"
}], {
  strokeWidth: 2,
  textAlign:"center"
});
#container {
  padding: 30px;
}
<script src="https://rawcdn.githack.com/akzhy/Vara/16e30acca2872212e28735cfdbaba696a355c780/src/vara.min.js"></script>
<div id="container"></div>

Consultez la page Github pour obtenir de la documentation et des exemples. Et Codepen


Réponse précédente

L'exemple ci-dessous utilise snap.js pour créer dynamiquement des éléments tspan, puis animer chacun de leurs stroke-dashoffset.

var s = Snap('svg');
var text = 'Some Long Text'
var len = text.length;
var array = [];
for (var x = 0; x < len; x++) {
  var t = text[x]
  array.Push(t);
}
var txt = s.text(50, 50, array)
$('tspan').css({
  'font-size': 50,
  fill: 'none',
  stroke: 'red',
  "stroke-width":2,
  'stroke-dasharray': 300,
  'stroke-dashoffset': 300
})

$('tspan').each(function(index) {
  $(this).stop(true, true).delay(300 * index).animate({
    'stroke-dashoffset': 0,
  }, 300, function() {
    $(this).css('fill', 'red')
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="500" height="500">
</svg>

Réponse précédente


Vous pouvez faire quelque chose comme ceci en utilisant stroke-dasharray de svg

text {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  -webkit-animation: draw 8s forwards;
}
@-webkit-keyframes draw {
  100% {
    stroke-dashoffset: 0;
  }
}
text {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  -webkit-animation: draw 8s forwards;
  -moz-animation: draw 8s forwards;
  -o-animation: draw 8s forwards;
  -ms-animation: draw 8s forwards;
  animation: draw 8s forwards;
}
@-webkit-keyframes draw {
  100% {
    stroke-dashoffset: 0;
  }
}
@-moz-keyframes draw {
  100% {
    stroke-dashoffset: 0;
  }
}
@-o-keyframes draw {
  100% {
    stroke-dashoffset: 0;
  }
}
@-ms-keyframes draw {
  100% {
    stroke-dashoffset: 0;
  }
}
@keyframes draw {
  100% {
    stroke-dashoffset: 0;
  }
}
<svg width="500" height="500">
  <text x="100" y="80" fill="none" stroke="black" stroke-width="1" font-size="50">Some text</text>
</svg>

Sans keyframes animation, vous pouvez faire quelque chose comme ceci

<svg width="500" height="500">
  <text x="100" y="80" fill="none" stroke="black" stroke-width="5" font-size="50"  stroke-dasharray="1000"
  stroke-dashoffset="1000">Some text
  <animate attributeName="stroke-dashoffset"
    from="1000"
    to="0" 
    dur="8s"
      fill="freeze">
          
      </animate> </text>
</svg>

Et pour le support IE, vous pouvez utiliser jquery/javascript

$('text').animate({
    'stroke-dashoffset':'0'
},8000)
text {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="500" height="500">
  <text x="100" y="80" fill="none" stroke="black" stroke-width="1" font-size="50" 
 >Some text
  </text>
</svg>
211
Akshay

Seulement CSS:

@keyframes fadein_left {
  from {
    left: 0;
  }
  to {
    left: 100%;
  }
}

#start:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0%;
  opacity: 0.7;
  height: 25px;
  background: #fff;
  animation: fadein_left 3s;
}
<div id="start">
  some text some text some text some text some text
</div>
2
zloctb