醉美水芙蓉 发表于 2026-7-19 21:41:22

马黑黑《textPath startOffset动画 》

<style>
    @import 'https://638183.freep.cn/638183/web/css/hl.css';
    .artBox { margin: 20px auto; font: normal 18px/26px sans-serif; }
    .artBox mark { padding: 2px 6px; background: #ccc; }
    .artBox pre { white-space: pre-wrap; }
    .artBox p { margin: 10px 0; }
    .tMid { text-align: center; }
</style>

<div class="artBox">
    <p>属性 <mark>startOffset</mark> 用于定义 <mark>&lt;textPath&gt;</mark> 中的文本在指定路径上的起始位置,可以利用此属性令文本在路径上移动。但此属性不支持 CSS 设置,所以 @keyframe 动画不能使用,只能在 XML 代码中插入 <mark>&lt;animate&gt;</mark> 标签。看代码和效果:</p>
   
    <pre id="codePre" class="hlCode">&lt;style&gt;
    #msvg { border: 1px solid gray; }
    #msvg text { font: bold 30px Sans-serif; text-anchor: middle; fill: darkred; }
&lt;/style&gt;

&lt;svg id="msvg" widt="600" height="300" viewBox="-200 -100 400 200" xmlns="http://www.w3.org/2000/svg"&gt;
    &lt;path id="tp" d="M -180 100 Q 0 -160,180 100" fill="none" stroke="none" /&gt;
    &lt;text&gt;
      &lt;textPath href="#tp" &gt;
            于无声处听惊雷
            &lt;animate id="ani" attributeName="startOffset" from="120%" to="50%" dur="8s" repeatCount="1" fill="freeze" /&gt;
      &lt;/textPath&gt;
    &lt;/text&gt;
&lt;/svg&gt;</pre>
   
    <div id="showRes" class="tMid"></div>
    <p class="tMid"><button onclick="resetAnimate()">重置 animate 动画</button></p>
    <p>核心在 animate 代码行。里面的主要属性:</p>
    <ol>
      <li>attributeName :指明上层父元素参与动画的属性名称;</li>
      <li>from :动画开始值。这里设为 120%,令文字基本隐藏在路径右侧;</li>
      <li>to :动画终止值。这里设为 50%,令文本居中(需要配合 text-anchor,可以在 CSS 中设置);</li>
      <li>dur :动画运行周期时长(带单位);</li>
      <li>repeatCount :动画重复次数(indefinite 为永远重复);</li>
      <li>fill :动画结束后的保持状态(freeze、remove)</li>
    </ol>
    <p>animate 动画还有其它相关属性,这里未用上就不赘述了。</p>
    <p>示例中可以重置动画,一并给出核心 JS 代码:</p>
   
    <pre class="hlCode">function resetAnimate() {
    const ani = document.getElementById('ani');
    setTimeout(() => ani.beginElement(), 0);
}</pre>
   
    <p>其中的 <mark>animateElement.beginElement()</mark> 方法是重新开始动画指令,终止动画可使用 <mark>endElement() 方法。</p>
</div>

<script>
    showRes.innerHTML = codePre.textContent;
   
    function resetAnimate() {
      const ani = document.getElementById('ani');
      setTimeout(() => ani.beginElement(), 0);
    }
</script>

klxf 发表于 7 天前

谢谢分享~有趣的文字路径动画
页: [1]
查看完整版本: 马黑黑《textPath startOffset动画 》