網站搜尋

javascript - 我如何在網頁上動畫化文字的繪製?


我想要有一個網頁,上面有一個置中的單詞。

我希望這個單詞能用動畫的方式被描繪出來,使頁面像我們一樣“書寫”這個單詞,也就是說,它從一個點開始,隨著時間畫出線條和曲線,使最終結果成為一個字形。

我不在乎這是用 <canvas> 還是 DOM 完成的,也不在乎是用 JavaScript 還是 CSS 完成的。沒有 jQuery 會比較好,但不是必需的。

我該如何做這件事?我已經徹底搜尋過,但沒有任何結果。

答案#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>

答案#2

編輯 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 進行動畫處理。

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>

先前的回答


你可以使用 SVG 的 stroke-dasharray 做類似這樣的事情

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>

沒有 keyframes 動畫,你可以做類似這樣的事情

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

而對於 IE 支援,你可以使用 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>