我想有一个网页有一个中心字。

我想用动画来绘制这个单词,这样页面就会像我们一样“写出”这个单词,即它从一个点开始,随着时间的推移绘制直线和曲线,最终结果是一个字形。

我不关心这是用<canvas>或DOM完成的,我也不关心它是用JavaScript还是CSS完成的。没有jQuery会很好,但不是必需的。

我该怎么做呢?我竭尽全力地找,但一无所获。


当前回答

我想用动画来绘制这个单词,这样页面 “写出”这个词的方式和我们写的一样

帆布版本

这将画出单个字符,更像手写。它使用长虚线模式,其中每个字符的开/关顺序随时间交换。它还有一个速度参数。

动画示例(见下面的演示)

为了增加真实感和有机感,我添加了随机的字母间距,一个y delta偏移量,透明度,一个非常微妙的旋转,最后使用一个已经“手写”的字体。这些可以被包装成动态参数,以提供广泛的“写作风格”。

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

它是如何工作的

通过定义破折号模式,我们可以创建行进的蚂蚁,虚线等等。利用这一点,为“关闭”点定义一个非常长的点,并逐渐增加“打开”点,它会给人一种在描边时绘制直线的错觉,同时给点长度动画。

由于关闭点太长,重复的图案将不可见(长度将随着所使用字体的大小和特征而变化)。字母的路径将有一个长度,所以我们需要确保每个点至少覆盖这个长度。

对于包含多个路径的字母(f.ex。O, R, P等),因为一个是轮廓,一个是中空部分,线条会同时出现。对于这种技术,我们不能做太多,因为它需要对每个路径段分别进行描边。

兼容性

对于不支持canvas元素的浏览器,另一种显示文本的方法可以放在标签之间,例如样式文本:

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

Demo

这将生成实时动画笔画(无依赖项)-

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>

其他回答

编辑2019


我创建了一个javascript库,可以创建现实的动画。它很容易使用,需要一个特殊的JSON文件作为字体。

var vara = new vara(“#容器”,“https://rawcdn.githack.com/akzhy/Vara/ed6ab92fdf196596266ae76867c415fa659eb348/fonts/Satisfy/SatisfySL.json”,[{ 文本:“Hello World!!”, 字形大小:48岁 y: 10 },{ 文本:“现实动画”, 字形大小:34岁 颜色:“# f44336” }, { strokeWidth: 2 textAlign:“中心” }); #{容器 填充:30 px; } < script src = " https://rawcdn.githack.com/akzhy/Vara/16e30acca2872212e28735cfdbaba696a355c780/src/vara.min.js " > < /脚本> < div id = "容器" > < / 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>

如果没有关键帧动画,你可以这样做

<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 " >一些文本 <动画attributeName = " stroke-dashoffset " 从= " 1000 " = " 0 " 大调的= " 8 s” 填补= "冻结" > < /动画> < /文本> < / svg >

对于IE的支持,你可以使用jquery/javascript

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

我想用动画来绘制这个单词,这样页面 “写出”这个词的方式和我们写的一样

帆布版本

这将画出单个字符,更像手写。它使用长虚线模式,其中每个字符的开/关顺序随时间交换。它还有一个速度参数。

动画示例(见下面的演示)

为了增加真实感和有机感,我添加了随机的字母间距,一个y delta偏移量,透明度,一个非常微妙的旋转,最后使用一个已经“手写”的字体。这些可以被包装成动态参数,以提供广泛的“写作风格”。

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

它是如何工作的

通过定义破折号模式,我们可以创建行进的蚂蚁,虚线等等。利用这一点,为“关闭”点定义一个非常长的点,并逐渐增加“打开”点,它会给人一种在描边时绘制直线的错觉,同时给点长度动画。

由于关闭点太长,重复的图案将不可见(长度将随着所使用字体的大小和特征而变化)。字母的路径将有一个长度,所以我们需要确保每个点至少覆盖这个长度。

对于包含多个路径的字母(f.ex。O, R, P等),因为一个是轮廓,一个是中空部分,线条会同时出现。对于这种技术,我们不能做太多,因为它需要对每个路径段分别进行描边。

兼容性

对于不支持canvas元素的浏览器,另一种显示文本的方法可以放在标签之间,例如样式文本:

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

Demo

这将生成实时动画笔画(无依赖项)-

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>

只有CSS:

@keyframes fadein_left { 从{ 左:0; } , { 左:100%; } } #开始:{之前 内容:”; 位置:绝对的; 上图:0; 左:0; 右:0%; 透明度:0.7; 高度:25 px; 背景:# fff; 动画:fadein_left 3s; } < div id = "开始" > 一些文字,一些文字,一些文字,一些文字 < / div >

经过多次测试,这里有一些注意事项。目标是以最少的阻塞方式在需要用户交互的DOM重页面上显示快速文本数据。

当然,有很多方法可以达到同样的目的。在这个例子中,差异可能不明显,但它确实适用于复杂的接口。

最慢:innerHTML和内联样式。在每次迭代中重新计算DOM。浏览器正在努力保持列车。它会很快失败,导致内存泄漏和冻结:

setInterval(函数(){ 出去了。innerHTML = ' <span style="position:fixed;top:${~~(Math.random() * 220)}px">${Math.random() * 1000}<span> ' }, 1) < h1 id = "出" > < / h1 >

更好的方法:使用textContent, requestAnimationFrame和web动画api。这将更加流畅,这在DOM较多的页面上很明显。用户交互不会阻碍重绘。一些重绘可能会被跳过,以保持界面良好的响应。

让工作 Const paint = () => { job = requestAnimationFrame(paint) 出去了。textContent = Math.random() * 1000 出去了。动画([{:~ ~ (math . random() * 220) +“px”},{:0}),{持续时间:1、迭代:1}) } / *开始循环 -----------------------------------------*/ requestAnimationFrame(油漆) #出{ 位置:固定} < h1 id = "出" > < / h1 >

在上面的例子中,DOM仍然在为文本溢出重新计算。我们可以看到调试器在闪烁。这对级联元素非常重要!这仍然会降低javascript和用户滚动的速度。

全功能:可以单独使用css使用css内容规则和css变量来刷新数据。文本将不可选。

让工作 Const paint = () => { job = requestAnimationFrame(paint) 出去了。setAttribute('data-before', Math.random() * 1000) 出去了。动画([{:~ ~ (math . random() * 220) +“px”},{:0}),{持续时间:1、迭代:1}) } / *开始循环 -----------------------------------------*/ requestAnimationFrame(油漆) #出{ 位置:固定 } #:{之前 内容:attr(数据) } < h1 id = "出" > < / h1 >

我的测试显示了很大的改进,javascript引擎在其他任务上快速跳过。有时它的启动速度比上面的例子要慢一些。但除此之外,这不会阻止用户滚动,调试器也喜欢,没有更多的跳跃。