温馨提示:本文翻译自stackoverflow.com,查看原文请点击:javascript - SVG line endpoints animate independently
css javascript svg

javascript - SVG线端点独立设置动画

发布于 2020-03-31 23:40:59

我正在尝试为SVG线端点中的一个设置动画,使其沿特定路径移动,而另一个端点保持静止,因此该线在延伸和缩小的同时保持笔直。

到目前为止,我所要做的就是使我的整条线沿着路径移动并绑定到其中一个端点:

<svg viewBox="0 0 500 500">
  <path stroke="grey" fill="none" id="route" d="M50,25 l25,30 l-40,20 z" />
  <g>
  <line x1="0" y1="0" x2="150" y2="50" stroke="blue" />
  <circle r=5 fill="blue" />
  <text x="-5" y="-10">A</text>
  <circle cx="150" cy="50" r="5" fill="blue" />
  <text x="145" y="40">B</text>
    <animateMotion dur="5s" repeatCount="indefinite" >
      <mpath xlink:href="#route" />
    </animateMotion>
  </g>
</svg>

我想要得到的是A点沿着路径移动,B点保持静止。

我很乐意考虑CSS / JavaScript解决方案,但是库不是一个选择

您能给我指出正确的方向吗?

查看更多

提问者
user12800422
被浏览
66
Alex L 2020-02-02 19:34

对于您的特定示例,我们可以使用标签values="..."属性来实现<animate/>您的路径是一个简单的示例,因此创建此values="..."列表非常简单。

如果您想针对任何路径更普遍地执行此操作,则可能需要构建d路径的JavaScript解析器,并将其转换为x和y值的列表(对于弯曲路径,这将非常困难,但并非不可能:https : //stackoverflow.com/a/17096947/9792594

这是演示:https : //codepen.io/Alexander9111/pen/Jjogbbe

在此处输入图片说明

HTML:

<svg viewBox="0 0 500 500">
    <path stroke="grey" fill="none" id="route" d="M50,25 l25,30 l-40,20 z" />
    <circle cx="50" cy="25" r=5 fill="blue">
        <animate attributeName="cx" values="50;75;35;50" dur="5s" repeatCount="indefinite" />
        <animate attributeName="cy" values="25;55;75;25" dur="5s" repeatCount="indefinite" />
    </circle>
    <text x="50" y="25" text-anchor="middle" transform="translate(0,-7)">A
        <animate attributeName="x" values="50;75;35;50" dur="5s" repeatCount="indefinite" />
        <animate attributeName="y" values="25;55;75;25" dur="5s" repeatCount="indefinite" />
    </text>
    <circle cx="150" cy="50" r="5" fill="blue"> </circle>
    <text x="145" y="40">B</text>
    <line x1="50" y1="25" x2="150" y2="50" stroke="blue">
        <animate attributeName="x1" values="50;75;35;50" dur="5s" repeatCount="indefinite" />
        <animate attributeName="y1" values="25;55;75;25" dur="5s" repeatCount="indefinite" />
    </line>
</svg>

另外,我们可以考虑使用JavaScript对其进行动画处理。

更新-使用JavaScript跟踪带有<animateMotion/>标记的动画圆的位置

演示:https : //codepen.io/Alexander9111/pen/NWPQbma

HTML:

<svg viewBox="0 0 500 500">
    <path stroke="grey" fill="none" id="route" d="M50,25 l25,30 l-40,20 z" />
    <circle id="circle_motion" r=5 fill="blue">
        <animateMotion dur="5s" fill="freeze">
            <mpath xlink:href="#route" />
        </animateMotion>
    </circle>
    <rect id="BBox" x="" y="" width="" height=""></rect>
    <text id="text_motion" x="50" y="25" text-anchor="middle" transform="translate(0,-7)">A
    </text>
    <circle cx="150" cy="50" r="5" fill="blue"> </circle>
    <text x="150" y="50" text-anchor="middle" transform="translate(0,-7)">B</text>
    <line id="line_motion" x1="50" y1="25" x2="150" y2="50" stroke="blue">
    </line>
</svg>

JS:

const svg = document.querySelector('svg');
const animateElem = document.querySelector('animateMotion');
const circle_motion = document.querySelector('#circle_motion');
const text_motion = document.querySelector('#text_motion');
const line_motion = document.querySelector('#line_motion');
const BBox = document.querySelector('#BBox');
var myInterval;

function startFunction() {
  const box = circle_motion.getBoundingClientRect();
  var pt = svg.createSVGPoint();
  pt.x = (box.left + box.right) / 2;
  pt.y = (box.top + box.bottom) / 2;
  var svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
  //console.log(svgP.x,svgP.y)
  text_motion.setAttribute('x', (svgP.x) );
  text_motion.setAttribute('y', (svgP.y) );
  line_motion.setAttribute('x1', (svgP.x) );
  line_motion.setAttribute('y1', (svgP.y) );
}

function endFunction() {
  clearInterval(myInterval)
}

animateElem.addEventListener('beginEvent', () => {
  console.log('beginEvent fired');
  myInterval = setInterval(startFunction, 10);
})

animateElem.addEventListener('endEvent', () => {
  console.log('endEvent fired');
  endFunction();
})

这更加灵活,我们可以将有生命的路径更改为:<path stroke="grey" fill="none" id="route" d="M50,25 75,55 Q75,75 35,75 z" />并且也可以遵循以下非线性路径:

在此处输入图片说明

最新帖子

最新文章