Webページのテキストの描画をアニメーション化するにはどうすればよいですか?


229

中心的な単語が1つあるWebページが欲しい。

この単語をアニメーションで描画して、ページが同じように単語を「書き出す」ようにします。つまり、ある時点から始まり、最終的な結果がグリフになるように時間とともに線と曲線を描画します。

これが<canvas>DOMで行われるかどうかは気にせず、JavaScriptとCSSのどちらで行われるかは気にしません。jQueryがないことは良いことですが、必須ではありません。

これどうやってするの?私は運が悪くて徹底的に検索しました。


2
私はどのように実際には「手書き」の文字にいくつかの考えを入れて、ここに私の考えを投稿:stackoverflow.com/questions/12700731/...
Markeの

codropsの記事tympanusでのデモを含む)には本当に似たようなものがあります
Francisco Presencia

1
昔は、アニメーションスプライトマスクを使用してFlashでこのアニメーションを行っていました。必要なのは、マスクをアニメーション化することです。つまり、マスクにテキストを徐々に表示させます。アニメーションはマスクフレームで構成されます。
Tiberiu-Ionuț Stan

もちろん、テキストを曲線に分解できる利点があります。これは、SVGと一部のSVGエディタ(Illustrator、またはその他のテキストのSVGを作成できるもの)を事前に使用して行う必要があります。SVGがマスクをサポートしているかどうかはわかりませんが、サポートしていると、アニメーション化がはるかに簡単になります。
Tiberiu-Ionuțスタン

SVGを使用し、JavaScriptでSVGコードを操作してアニメーションを作成します。
Demz

回答:


264

この単語がアニメーションで描かれるようにして、ページが単語を「書く」のと同じように書き出す

キャンバスバージョン

これは、手書きで書くように単一の文字を描画します。時間ごとにオン/オフの順序が文字ごとに入れ替わる長いダッシュパターンを使用します。また、速度パラメータもあります。

スナップショット
アニメーションの例(下のデモを参照)

リアリズムと有機的な感触を高めるために、ランダムな文字間隔、yデルタオフセット、透明度、非常に微妙な回転を追加し、最後にすでに「手書き」のフォントを使用しました。これらを動的パラメーターとしてラップして、幅広い「ライティングスタイル」を提供できます。

さらにリアルな外観を得るには、デフォルトではないパスデータが必要になります。しかし、これは手書きの動作に似た短く効率的なコードであり、実装は簡単です。

使い方

ダッシュパターンを定義することで、マーチングアリや点線などを作成できます。これを利用して、「オフ」のドットに非常に長いドットを定義し、「オン」のドットを徐々に増やしていくと、ドットの長さをアニメートしながらストロークしたときに線が引かれているように見えます。

オフドットは非常に長いため、繰り返しパターンは表示されません(長さは、使用する書体のサイズと特性によって異なります)。文字のパスには長さがあるため、各ドットが少なくともこの長さをカバーしていることを確認する必要があります。

1つはアウトライン用、もう1つは中空部分用など、複数のパス(例:O、R、Pなど)で構成される文字の場合、線が同時に描かれているように見えます。この手法では、各パスセグメントに個別にストロークする必要があるため、これについて多くのことを行うことはできません。

互換性

canvas要素をサポートしていないブラウザの場合、テキストを表示する別の方法をタグの間に配置できます。たとえば、スタイル付きテキスト:

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

デモ

これにより、ライブアニメーションのストロークオンが生成されます(依存関係なし)-

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
これに夢中になるのは私だけですか?少なくとも、最初の回答よりもかなりリアルで、質問者の質問に最も近いように見えます。
KhoPhi

5
翌日使用したクイックアンドダーティーハックとしてすぐに必要になり、その後は二度と触れないため、他の回答を使用することになりました。ために。
2015年

複数の行と長いテキストブロックを作成するにはどうすればよいですか?
Saad Farooq、

1
@ K3Nはい、それは実際にいい感じでした:pすばらしい仕事。
キーヤー

1
@ AliAl-arnous xを反対側の端に設定し、追加する代わりにcharの幅を減算し、負の負のスペースで変換し、charの反対側でclearRectをclearに変更できます。

216

2019を編集


リアルなアニメーションを作成できるJavaScriptライブラリを作成しました。使い方は簡単で、フォントとして機能する特別なJSONファイルが必要です。

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>

ドキュメントと例については、Githubページご覧ください。そしてCodepen


前の回答

次の例では、snap.jsを使用して動的にtspan要素を作成し、各要素をアニメーション化していstroke-dashoffsetます。

前の回答


あなたはsvgを使ってこのようなことをすることができます stroke-dasharray

keyframesアニメーションがなければ、このようなことができます

IEのサポートには、jquery / javascriptを使用できます


4
うわー、それは本当に面白いです。元のコードスニペットを取得し、重複したCSSプロパティを削除し、パーセンテージベースのオフセットとダッシュ配列値を使用し、ストローク幅を変更してコードがどのように機能するかをより明確にすることにより、コードを少し改善しました:jsfiddle.net/Ajedi32/gdc4azLn / 1必要に応じて、これらの改善点を回答に自由に編集してください。
Ajedi32

2
これはこの質問に対する1つの壮大なソリューションです。ブラウザがサポートしていない場合は、代わりにテキストを表示する限り、SVGはキャンバス(+1)より優れています。
Jeffery ThaGintoki

3
@JefferyThaGintoki canvasでもこれを行うことができます。canvasタグの間にテキストを置くだけで、canvasがサポートされていない場合は、代わりにテキスト(または他の回答のようにアニメーションgifが表示される)が表示されます。ブラウザがキャンバスをサポートしていない場合、おそらくsvgもサポートしていません。
torox

1
SVGテキストの使用は素晴らしいと思いますが、ある時点で塗りつぶしを追加することは可能ですか?文字の輪郭だけがすべてのプロジェクトで美しく見えるわけではありません、乾杯!そしてもちろんこの答えに+1
randomguy04

1
@ randomguy04最初のスニペットをチェックして、塗りつぶし効果を追加するように編集しました。それは$(this).css('fill', 'red')アニメーションへのコールバックとして追加することによって行われます
Akshay

2

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

多くのテストに続いて、ここにいくつかの注意事項があります。目標は、ユーザーの操作を必要とするDOMの重いページで、ブロックの少ない方法で高速テキストデータを表示することです。

もちろん、同じことを達成する方法はたくさんあります。この例では、違いは明らかではないかもしれませんが、実際には複雑なインターフェースに適用されます。

最も遅いinnerHTMLインラインスタイル。DOMは反復ごとに再計算されます。ブラウザは列車を維持するために一生懸命働いています。それはすぐに失敗し、メモリリークとフリーズを引き起こします:

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

より良い方法textContentrequestAnimationFrameおよびWebアニメーションAPIを使用する。これはよりスムーズに進み、DOMの重いページでは明白です。ユーザー操作は再描画をブロックしません。インターフェイスの応答性を維持するために、一部の再描画はスキップされる場合があります。

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>

上記の例では、テキストオーバーフローのためにDOMがまだ再計算されています。デバッガが激しく点滅しているのがわかります。これはカスケード要素で本当に重要です!これにより、JavaScriptとユーザーのスクロールが遅くなる可能性があります。

ここに画像の説明を入力してください

フルパワー:cssを単独で使用して、css contentルールとcss変数でデータを更新できます。その後、テキストは選択できなくなります。

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>

ここに画像の説明を入力してください

私のテストでは、大幅な改善が見られました。JavaScriptエンジンは、他のタスクをすばやくスキップしています。場合によっては、上記の例よりも少し遅く起動することがあります。しかし、それに加えて、これはユーザーのスクロールをブロックせず、デバッガーも好みで、ジャンプする必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.