javascript - SVG 线端点独立动画
问题描述
我正在尝试为 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 解决方案,但库不是一个选项。
请您指出正确的方向吗?
解决方案
对于您的具体示例,我们可以通过使用标签的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();
})
这更加灵活,我们可以将我们的 amimate 路径更改为:<path stroke="grey" fill="none" id="route" d="M50,25 75,55 Q75,75 35,75 z" />
并且我们也可以遵循这条非线性路径:
推荐阅读
- c++ - 同步和异步 gRPC 之间的区别
- python - 如何从spark sql中的不同路径读取多个csv文件
- sql - DELETE 查询是否与 SELECT 花费相同的时间
- css - 从列的一半开始网格列
- python - Pandas Merge - 如何同时合并不同的索引列
- react-router - React NavLink:捕获动态路由但 onClick 重定向到特定路由
- sql - 更新表与其他表的比较
- javascript - 清除excel记录和单元格
- spring-boot - axis2客户端记录请求响应spring boot
- python - Python 对字符串进行切片并添加到列表中