Wie kann ich das Zeichnen von Text auf einer Webseite animieren?


229

Ich möchte eine Webseite mit einem zentrierten Wort haben.

Ich möchte, dass dieses Wort mit einer Animation gezeichnet wird, so dass die Seite das Wort auf die gleiche Weise "schreibt", wie wir es tun würden, dh es beginnt an einem Punkt und zeichnet im Laufe der Zeit Linien und Kurven, so dass das Endergebnis eine Glyphe ist.

Es ist mir egal, ob dies mit <canvas>oder dem DOM gemacht wird, und es ist mir egal, ob es mit JavaScript oder CSS gemacht wird. Das Fehlen von jQuery wäre nett, aber nicht erforderlich.

Wie kann ich das machen? Ich habe gesucht erschöpfend ohne Glück.


2
Ich habe mir Gedanken darüber gemacht, wie man Charaktere tatsächlich "handschriftlich" schreibt,
markE

Es gibt etwas wirklich Ähnliches in einem Codrops-Artikel (mit einer Demo in Tympanos )
Francisco Presencia

1
Früher habe ich diese Animation in Flash mit animierten Sprite-Masken erstellt. Was Sie brauchen, ist eine Animation zu animieren, was bedeutet, dass sie nach und nach Text anzeigt. Die Animation würde aus Maskenrahmen bestehen.
Tiberiu-Ionuț Stan

Natürlich hätten Sie den Vorteil, dass Sie Text in Kurven zerlegen können. Sie müssten dies tun, bevor Sie SVGs und einen SVG-Editor (Illustrator oder was auch immer sonst kann eine SVG Ihres Textes erstellen) von Hand verwenden. Ich weiß nicht, ob SVGs Masken unterstützen, aber wenn doch, wäre dies viel einfacher zu animieren.
Tiberiu-Ionuț Stan

Verwenden Sie SVG und bearbeiten Sie den SVG-Code mit JavaScript, um die Animation zu erstellen.
Der Demz

Antworten:


264

Ich möchte, dass dieses Wort mit einer Animation gezeichnet wird, sodass die Seite das Wort auf die gleiche Weise "schreibt", wie wir es tun würden

Canvas-Version

Dadurch werden einzelne Zeichen eher so gezeichnet, als würde man von Hand schreiben. Es wird ein langes Strichmuster verwendet, bei dem die Ein / Aus-Reihenfolge im Laufe der Zeit pro Zeichen vertauscht wird. Es hat auch einen Geschwindigkeitsparameter.

Schnappschuss
Beispielanimation (siehe Demo unten)

Um den Realismus und das organische Gefühl zu erhöhen, habe ich zufällige Buchstabenabstände, einen y-Delta-Versatz, Transparenz, eine sehr subtile Drehung und schließlich eine bereits "handgeschriebene" Schriftart hinzugefügt. Diese können als dynamische Parameter zusammengefasst werden, um eine breite Palette von "Schreibstilen" bereitzustellen.

Für ein noch realistischeres Aussehen wären die Pfaddaten erforderlich, die nicht standardmäßig vorhanden sind. Dies ist jedoch ein kurzer und effizienter Code, der sich dem handgeschriebenen Verhalten annähert und einfach zu implementieren ist.

Wie es funktioniert

Durch Definieren eines Strichmusters können wir marschierende Ameisen, gepunktete Linien usw. erstellen. Wenn Sie dies ausnutzen, indem Sie einen sehr langen Punkt für den "Aus" -Punkt definieren und den "Ein" -Punkt schrittweise erhöhen, entsteht die Illusion, die Linie beim Streichen zu zeichnen, während Sie die Punktlänge animieren.

Da der Off-Punkt so lang ist, ist das sich wiederholende Muster nicht sichtbar (die Länge hängt von der Größe und den Eigenschaften der verwendeten Schrift ab). Der Pfad des Buchstabens hat eine Länge, daher müssen wir sicherstellen, dass jeder Punkt mindestens diese Länge abdeckt.

Bei Buchstaben, die aus mehr als einem Pfad bestehen (z. B. O, R, P usw.), wie einer für den Umriss, einer für den hohlen Teil, scheinen die Linien gleichzeitig gezeichnet zu sein. Wir können mit dieser Technik nicht viel dagegen tun, da der Zugriff auf jedes Pfadsegment separat ausgeführt werden müsste.

Kompatibilität

Für Browser, die das Canvas-Element nicht unterstützen, kann eine alternative Möglichkeit zum Anzeigen des Texts zwischen den Tags platziert werden, z. B. ein gestalteter Text:

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

Demo

Dies erzeugt das animierte Live-Stroke-On ( keine Abhängigkeiten ) -

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>


21
Bin ich der einzige, der verrückt danach wird? Sieht zumindest so real aus, viel besser als die erste Antwort und der Frage des Fragestellers am nächsten.
KhoPhi

5
Am Ende habe ich die andere Antwort verwendet, weil ich sie sofort als schnellen und schmutzigen Hack brauchte, den ich am nächsten Tag benutzte und dann nie wieder berührte, aber ich akzeptiere diese, weil sie viel näher an dem liegt, was ich suchte zum.
strugee

Wie können wir es für mehrere Zeilen und einen langen Textblock machen?
Saad Farooq

1
@ K3N Ja, es war eigentlich eine nette Geste: p Großartige Arbeit.
Keyser

1
@ AliAl-arnous Sie könnten x auf das andere Ende setzen, die Zeichenbreite subtrahieren anstatt zu addieren, mit negiertem negativen Leerzeichen transformieren und clearRect ändern, um auf der anderen Seite des Zeichens zu löschen.

216

Bearbeiten Sie 2019


Ich habe eine Javascript-Bibliothek erstellt, mit der realistische Animationen erstellt werden können. Es ist einfach zu bedienen und erfordert eine spezielle JSON-Datei, die als Schriftart fungiert.

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>

Auf der Github-Seite finden Sie Dokumentation und Beispiele. Und Codepen


Vorherige Antwort

Im folgenden Beispiel werden snap.js verwendet, um tspanElemente dynamisch zu erstellen und dann jedes ihrer Elemente zu animieren stroke-dashoffset.

Vorherige Antwort


Sie können so etwas mit svg's machen stroke-dasharray

Ohne keyframesAnimation können Sie so etwas tun

Und für die IE-Unterstützung können Sie jquery / javascript verwenden


4
Wow, das ist wirklich interessant. Ich habe Ihr ursprüngliches Code-Snippet genommen und es etwas verbessert, indem ich doppelte CSS-Eigenschaften entfernt, prozentuale Offsets und Dasharray-Werte verwendet und die Strichbreite geändert habe, um die Funktionsweise des Codes deutlicher zu machen: jsfiddle.net/Ajedi32/gdc4azLn / 1 Sie können jede dieser Verbesserungen in Ihrer Antwort bearbeiten, wenn Sie möchten.
Ajedi32

2
Dies ist eine epische Lösung für diese Frage. SVG ist besser als Canvas (+1), sofern der Browser dies nicht unterstützt, wird stattdessen der Text angezeigt.
Jeffery ThaGintoki

3
@JefferyThaGintoki Sie können dies auch mit Canvas tun. Platzieren Sie den Text einfach zwischen den Canvas-Tags. Wenn Canvas nicht unterstützt wird, wird stattdessen der Text (oder das animierte GIF wie in der anderen Antwort im Text angezeigt) angezeigt. Wenn der Browser kein Canvas unterstützt, wird er wahrscheinlich auch kein SVG unterstützen.
Torox

1
Ich denke, die Verwendung von SVG-Text ist großartig, aber ich frage mich, ob es möglich ist, die Füllung irgendwann hinzuzufügen? Nur die Umrisse der Buchstaben sehen nicht in allen Projekten gut aus, Prost! und natürlich +1 auf diese Antwort
randomguy04

1
@ randomguy04 Überprüfen Sie das erste Snippet, ich habe es bearbeitet, um einen Fülleffekt hinzuzufügen. Dies geschieht durch Hinzufügen $(this).css('fill', 'red')als Rückruf zur Animation
Akshay

2

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


0

Nach vielen Tests finden Sie hier einige Hinweise. Ziel ist es, schnelle Textdaten auf DOM-Seiten, die Benutzerinteraktionen erfordern , auf die am wenigsten blockierende Weise anzuzeigen .

Es gibt natürlich viele Möglichkeiten, dasselbe zu erreichen. In diesem Beispiel sind die Unterschiede möglicherweise nicht offensichtlich, sondern gelten wirklich für komplexe Schnittstellen.

Am langsamsten : innerHTMLund Inline-Styling. Das DOM wird bei jeder Iteration neu berechnet. Der Browser arbeitet hart daran, den Zug zu halten. Es wird schnell ausfallen und Speicherlecks verursachen und einfrieren:

setInterval(function(){
  out.innerHTML = `<span style="position:fixed;top:${~~(Math.random() * 220)}px">${Math.random() * 1000}<span>`
},1)
<h1 id="out"></h1>

Viel besser : Die Verwendung textContent, requestAnimationFrameund die Web - Animation api. Dies läuft viel reibungsloser, es ist auf DOM-schweren Seiten offensichtlich. Die Benutzerinteraktionen blockieren die Neulackierungen nicht. Einige Neulackierungen werden möglicherweise übersprungen, damit die Benutzeroberfläche gut reagiert.

let job
const paint = () => {
  job = requestAnimationFrame(paint)
  out.textContent = Math.random() * 1000
  out.animate([{top: ~~(Math.random() * 220)+"px"},{top:0}],{duration: 1,iterations: 1})
}

/* Start looping -----------------------------------------*/
requestAnimationFrame(paint)
#out{
position: fixed}
<h1 id="out"></h1>

Im obigen Beispiel wird das DOM immer noch für den Textüberlauf neu berechnet. Wir können sehen, dass der Debugger stark blinkt. Dies ist wirklich wichtig bei kaskadierenden Elementen! Dies kann das Scrollen von Javascript und Benutzern immer noch verlangsamen.

Geben Sie hier die Bildbeschreibung ein

Volle Leistung : Es ist möglich, CSS allein zu verwenden, um die Daten mit der CSS- contentRegel und den CSS-Variablen zu aktualisieren. Der Text kann dann nicht ausgewählt werden.

let job
const paint = () => {
  job = requestAnimationFrame(paint)
  out.setAttribute('data-before', Math.random() * 1000)
  out.animate([{top: ~~(Math.random() * 220)+"px"},{top:0}],{duration: 1,iterations: 1})
}

/* Start looping -----------------------------------------*/
requestAnimationFrame(paint)
#out{
  position: fixed
  
  }
#out:before {
   content: attr(data-before)
 }
<h1 id="out"></h1>

Geben Sie hier die Bildbeschreibung ein

Meine Tests haben große Verbesserungen gezeigt, die Javascript-Engine überspringt schnell andere Aufgaben. Manchmal beginnt es etwas langsamer als im obigen Beispiel. Abgesehen davon blockiert dies nicht die Schriftrollen der Benutzer, und der Debugger mag auch keine Sprünge mehr.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.