【问题标题】:Is it possible create animation where Html tag will follow svg path animation?是否可以创建 Html 标签将遵循 svg 路径动画的动画?
【发布时间】:2021-11-24 15:41:30
【问题描述】:

我正在使用 svg 路径在 javascript 中创建自定义进度动画。我从后端获取有关应该移动多少路径的数据。它工作正常,但在动画完成的那个地方我需要一些带有百分比的文本。我知道可以使用 svg 文本来做到这一点,但这在样式上是有限的。 (我只能将其设置为 svg)所以我的问题是:是否可以创建动画,其中 Html 标记例如 p 将遵循 svg 路径动画?或者我可以如何解决它的任何其他想法? Svg 路径没有规则的形状。

【问题讨论】:

  • 将 p 放入 foreignObject 并使用 animateMotion 为 foreignObject 设置动画。无需 javascript。
  • 另外请阅读(CSS 运动路径)[developer.mozilla.org/en-US/docs/Web/CSS/CSS_Motion_Path].然而,这是一项实验性技术。至于“任何其他想法”,请将一个简单的代码示例放在一起,以便 SO 的人可以帮助您。您还可以添加具有所需结果的图像
  • @RobertLongson 当我将它放入 foreignObject 时,是否可以将其设置为具有所有属性(如变换、边框、背景、字体-...)的 html 标记?

标签: svg svg-animate


【解决方案1】:

我举了两个例子。第一个是“仅”使用 SVG 元素,下一个是 <foreignObject> 和 HTML <span>

在此示例中,<text> 遵循动画运动路径。必须更新属性keyPointsend 以使文本遵循stroke-dasharray

var path = document.getElementById('path');
var text = document.getElementById('text');
var motion = document.getElementById('motion');

document.forms.rangeform.range.addEventListener('change', e => {
  path.style.strokeDasharray = `${e.target.value} 100`;
  text.textContent = `${e.target.value}%`;
  motion.attributes['keyPoints'].value = `${e.target.value/100};${e.target.value/100}`;
  motion.attributes['end'].value = `${e.target.value}ms`;
});
<form name="rangeform">
  <input type="range" name="range" min="0" max="100" value="75">
</form>
<svg viewBox="0 0 120 80" width="400" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <path id="path2" d="M 10 50 C 20,50 25,30 50,30 S 80,50 80,50"
      pathLength="100" stroke-linecap="round" fill="none" />
  </defs>
  <use href="#path2" stroke-dasharray="none" stroke="lightblue" stroke-width="2" />
  <use href="#path2" id="path" stroke-dasharray="75 100" stroke-dashoffset="0"
    stroke="navy" stroke-width="4" />
  <text style="font-family:sans-serif;font-size:8px;font-weight:bold;"
    transform="translate(0 -5)">
    <tspan id="text">75%</tspan>
    <animateMotion id="motion" rotate="0" begin="0s" dur="100ms"
      end="75ms" keyPoints=".75;.75" keyTimes="0;1" fill="freeze">
      <mpath href="#path2"/>
    </animateMotion>
  </text>
</svg>

这里我用&lt;foreignObject&gt;做了一个例子。为了让它移动,我必须创建一个父元素 (&lt;g&gt;),因为我无法在 &lt;foreignObject&gt; 本身上制作动画。

var path = document.getElementById('path');
var text = document.getElementById('text');
var motion = document.getElementById('motion');

document.forms.rangeform.range.addEventListener('change', e => {
  path.style.strokeDasharray = `${e.target.value} 100`;
  text.textContent = `${e.target.value}%`;
  motion.attributes['keyPoints'].value = `${e.target.value/100};${e.target.value/100}`;
  motion.attributes['end'].value = `${e.target.value}ms`;
});
span {
  font-size: 8px;
  font-family: sans-serif;
  font-weight: bold;
}
<form name="rangeform">
  <input type="range" name="range" min="0" max="100" value="75">
</form>
<svg viewBox="0 0 120 80" width="400" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <path id="path2" d="M 10 50 C 20,50 25,30 50,30 S 80,50 80,50"
      pathLength="100" stroke-linecap="round" fill="none" />
  </defs>
  <use href="#path2" stroke-dasharray="none" stroke="lightblue" stroke-width="2" />
  <use href="#path2" id="path" stroke-dasharray="75 100" stroke-dashoffset="0"
    stroke="navy" stroke-width="4" />
  <g>
    <foreignObject width="30" height="20" transform="translate(0 -20)">
      <span id="text" xmlns="http://www.w3.org/1999/xhtml">75%</span>
    </foreignObject>  
    <animateMotion id="motion" rotate="0" begin="0s" dur="100ms"
      end="75ms" keyPoints=".75;.75" keyTimes="0;1" fill="freeze">
      <mpath href="#path2"/>
    </animateMotion>
  </g>
</svg>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 2016-01-06
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    相关资源
    最近更新 更多