SVG线端点独立设置动画 [英] SVG line endpoints animate independently
问题描述
我正在尝试为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"/><圆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解决方案,但是库不是一个选择.
您能给我指出正确的方向吗?
对于您的特定示例,我们可以使用<; animate/>
标记.您的路径是一个非常简单的示例,因此创建此 values ="..."
列表非常简单.
如果您想针对任何路径更一般地执行此操作,则可能需要构建d路径的JavaScript解析器,并将其转换为x和y值的列表(对于弯曲路径,则为非常困难,但并非没有:
HTML:
< svg viewBox ="0 0 500 500">< path stroke ="grey" fill ="none" id ="route" d ="M50,25 l25,30 l-40,20 z"/><圆圈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/>
标记的动画的圆的位置:
演示:
I'm trying to animate one of SVG-line endpoints to move along certain path, while the other endpoint stands still, so the line is stretching and shrinking, while staying straight.
What I achieved so far is to make my entire line move along the path with one of endpoints bound to it:
<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>
What I want to get is point A moving along the path and point B standing still.
I'd gladly consider CSS/JavaScript solution, but libraries are not an option.
Would you, please, point me to the right direction?
For your specific example, we can do it by using the values="..."
attribute of the <animate/>
tag. Your path is quite a simple example so creating this values="..."
list is quite trivial.
If you want to to do this more generally, for any path, then you likely need to build a JavaScript parser of the d path and turn that into a list of x and y values (and for curved paths, this would be very difficult, but not impossible: https://stackoverflow.com/a/17096947/9792594)
Here's the demo: 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>
Alternatively, we could think about JavaScript to animate it.
UPDATE - using JavaScript to track the circle's location as it is animated with the <animateMotion/>
tag:
Demo: 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();
})
This is much more flexible, and we can change our amimate path to: <path stroke="grey" fill="none" id="route" d="M50,25 75,55 Q75,75 35,75 z" />
and we can also follow this non-linear path:
这篇关于SVG线端点独立设置动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!