如何为网页上的文字绘制动画?

JavaScript CSS

伽罗理查德

2020-03-30

我想要一个包含一个居中单词的网页。

我希望用动画来绘制该单词,以便页面以与我们相同的方式“写”出该单词,即,它从一个点开始并随时间绘制线条和曲线,从而最终结果是一个字形。

我不在乎这是使用<canvas>DOM还是DOM 完成,也不关心它是使用JavaScript还是CSS完成的。缺少jQuery会很好,但不是必需的。

我怎样才能做到这一点?我进行了详尽的搜索,没有运气。

第3869篇《如何为网页上的文字绘制动画?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

2个回答
凯理查德 2020.03.30

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

Mandy 2020.03.30

我希望通过动画来绘制该单词,以便页面以与我们将要使用的相同方式“写”出该单词

画布版本

这将绘制单个字符,就像用手写的字符一样。它使用长破折号模式,其中每个字符的开/关顺序会随着时间交换。它还具有速度参数。

快照
动画示例(请参见下面的演示)

为了增加真实感和自然感,我添加了随机字母间距,y增量偏移,透明度,非常细微的旋转,最后使用了已经“手写”的字体。这些可以包装为动态参数以提供广泛的“书写样式”。

为了更真实的外观,将需要路径数据,默认情况下不需要。但这是一段简短高效的代码,近似于手写行为,并且易于实现。

怎么运行的

通过定义破折号模式,我们可以创建行进蚂蚁,虚线等。通过为“ off”点定义一个很长的点并逐渐增加“ on”点来利用这一点,这会给人一种在绘制点的动画时画线的动画效果,同时赋予点长以动画效果。

由于关闭点太长,因此无法看到重复图案(长度将随所使用字体的大小和特性而变化)。字母的路径将有一个长度,因此我们需要确保每个点至少覆盖该长度。

对于包含多个路径(例如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>

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android