笔划动画,如何将另一条路径附加到出现的笔划



我有以下动画:

@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
#currency-chart-path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 30s linear forwards;
}
<svg id="city-total-v2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<g id="Chartline">
<path id="currency-chart-path" stroke="#7C0A67" stroke-width="3px" fill="none" d="M443,439 L464,435 487,421 511,416 532,424 552,408 572,414 591,413 606,419" />
	<path id="chart-arrow" fill="#7C0A67" d="M604.4,423.5l6.88-2.26l-2.44-3.3c-0.1-0.22-0.25-0.41-0.43-0.58l0.01,0.02l-0.02-0.02
		c0,0,0,0.01,0.01,0.01l-2.48-3.36l-0.08,0.42l-0.27,1.66l-0.03-0.01l-0.68,3.8l0.09,0.04L604.4,423.5z"/>
</g>
</svg>

运行代码片段以查看动画。

我想将箭头附加到笔划上,使其看起来像沿着路径。

这怎么可能?

是的,这是可能的,但在这种情况下,您将需要JavaScript。请阅读我代码中的注释。

let chart = document.querySelector("#currency_chart_path");
// the length of the chart path
let length = currency_chart_path.getTotalLength();
// the request animation id
let rid = null;
// setting the stroke-dasharray and the stroke-dashoffset for the chart
chart.style.strokeDasharray = length;
chart.style.strokeDashoffset = length;
// the animation frames
let frames = length;
// two points on the path: the actual point and an other point very near used to calculate the angle of rotation for the arrow
let point1, point2;
// the animation:
function Frame() {
rid = requestAnimationFrame(Frame);
chart.style.strokeDashoffset = frames;
//two points on the path: the actual point and an other point very near
point1 = chart.getPointAtLength(length - frames);
point2 = chart.getPointAtLength((length - frames + 2) % length);
//the angle of rotation for the arrow
angle = Math.atan2(point2.y - point1.y, point2.x - point1.x);
// set the transformation for the arrow
arrow.setAttribute(
"transform",
"translate(" +
[point1.x, point1.y] +
")" +
"rotate(" +
angle * 180 / Math.PI +
")"
);
frames--;
// stop the animation
if (frames <= 2) {
cancelAnimationFrame(rid);
rid = null;
}
}
Frame();
svg{border:1px solid}
<svg id="city-total-v2" viewBox="400 370 250 100" >
<g id="Chartline">
<path id="currency_chart_path" stroke="#7C0A67" stroke-width="3px" fill="none" d="M443,439 L464,435 487,421 511,416 532,424 552,408 572,414 591,413 606,419" />
<path id="arrow" fill="#7C0A67" d="M0,0L0,-5L7,0L0,5"/>
</g>
</svg>

这是受"将SVG与CSS3和HTML5结合使用:用于Web设计的矢量图形"中的演示的启发

一个想法是在进行翻译时以相反的方向运行动画

@keyframes dash {
to {
stroke-dasharray: 190;
}
}
@keyframes move {
to {
transform: translateX(0);
}
}
#currency-chart-path {
stroke-dasharray: 279;
stroke-dashoffset: 381;
animation: dash 10s linear forwards;
}
#Chartline {
animation: move 10s linear forwards;
transform: translateX(-200px);
}
<svg id="city-total-v2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="300 300 400 400">
<g id="Chartline">
<path id="currency-chart-path" stroke="#7C0A67" stroke-width="3px" fill="none" d="M443,439 L464,435 487,421 511,416 532,424 552,408 572,414 591,413 606,419" />
	<path id="chart-arrow" fill="#7C0A67" d="M604.4,423.5l6.88-2.26l-2.44-3.3c-0.1-0.22-0.25-0.41-0.43-0.58l0.01,0.02l-0.02-0.02
		c0,0,0,0.01,0.01,0.01l-2.48-3.36l-0.08,0.42l-0.27,1.66l-0.03-0.01l-0.68,3.8l0.09,0.04L604.4,423.5z"/>
</g>
</svg>

纯SVG微笑解决方案

可以使用笔划dashoffset来设置线增长的动画。标记用作线末端的箭头,但不能使其随线移动,因为线实际上并没有增长。

这条线是提前画好的,它的增长只是通过将笔划dashoffset从177px减少到零来设置动画。

您可以使用另一种技术:将箭头沿该线移动的动画添加到该线增长的动画中。有必要为两个动画设置相同的时间,因此将创建所需的效果:

<svg id="city-total-v2" viewBox="400 370 250 100" style="border:1px solid;" >
<g id="Chartline">
<path id="currency_chart_path" stroke-dasharray="177" stroke="#7C0A67" stroke-width="3px" fill="none" d="M443,439 L464,435 487,421 511,416 532,424 552,408 572,414 591,413 606,419" >
<!-- Line growth animation -->
<animate
attributeName="stroke-dashoffset"
begin="0s"
dur="4s"
values="177;0"
repeatCount="indefinite" />
</path>
<path id="arrow" transform="rotate(180)" fill="#7C0A67" d="M0,0L0,-5L7,0L0,5">
<!-- Animate an arrow along a line   -->
<animateMotion
id="an"
dur="4s"
repeatCount="indefinite"
rotate="auto-reverse"
begin="0s"
restart="whenNotActive">
<mpath xlink:href="#currency_chart_path"/>
</animateMotion>
</path>
</g> 
</svg>

具有附加图表元素的选项

动画将在点击后开始

<svg id="city_total_v2" viewBox="400 370 250 100" style="border:1px solid;" >
<defs>
<marker id="mark" markerWidth="6.5" markerHeight="8" refX="5.5" refY="1"
orient="45">

<polygon points="0,3.25 3.25,6.5 6.5,0" fill="black" stroke-width="0.25" stroke="black" />
</marker> 
<marker id="mark2" markerWidth="7" markerHeight="7" refX="3.5" refY="3"
orient="-45">

<polygon points="0,3.25 3.25,6.5 6.5,0" fill="black" stroke-width="0.25" stroke="black" />
</marker>
</defs>   
<g transform="translate(440 465)">
<polyline  points="0,0 190,0" marker-end ="url(#mark)" fill="none" stroke="black" />
<polyline  points="0,0 0,-85" marker-end ="url(#mark2)" fill="none" stroke="black" /> 
<rect x="3" y="-24" width="19" height="23" fill="red" />
<rect x="28" y="-30" width="19" height="29" fill="crimson" />
<rect x="53" y="-43" width="19" height="42" fill="gold" /> 
<rect x="78" y="-38" width="19" height="37" fill="orange" />
<rect x="103" y="-52" width="19" height="51" fill="skyblue" /> 
<rect x="128" y="-48" width="19" height="47" fill="yellowgreen" /> 
<rect x="153" y="-41" width="19" height="40" fill="orange" />
</g>
<g id="Chartline">
<path id="currency_chart_path" stroke-dasharray="177" stroke-dashoffset="177" stroke="#7C0A67" stroke-width="3px" fill="none" d="M443,439 L464,435 487,421 511,416 532,424 552,408 572,414 591,413 606,419" >
<!--Line growth animation -->
<animate
attributeName="stroke-dashoffset"
begin="city_total_v2.click"
dur="7s"
values="177;0"
fill="freeze"
restart="whenNotActive" />
</path>
<path id="arrow" transform="rotate(180)" fill="#7C0A67" d="M0,0L0,-5L7,0L0,5">
<!--Arrow movement animation -->
<animateMotion 
id="an"
dur="7s"
repeatCount="1"
rotate="auto-reverse"
begin="city_total_v2.click"
fill="freeze"
restart="whenNotActive">
<mpath xlink:href="#currency_chart_path"/>
</animateMotion>
</path>
</g> 
</svg>

将矩形动画添加到箭头动画

<svg id="city_total_v2" viewBox="400 370 250 100" style="border:1px solid;" >
<defs>
<marker id="mark" markerWidth="6.5" markerHeight="8" refX="5.5" refY="1" orient="45">        
<polygon points="0,3.25 3.25,6.5 6.5,0" fill="black" stroke-width="0.25" stroke="black" />
</marker> 
<marker id="mark2" markerWidth="7" markerHeight="7" refX="3.5" refY="3"   orient="-45">        
<polygon points="0,3.25 3.25,6.5 6.5,0" fill="black" stroke-width="0.25" stroke="black" />
</marker>
</defs>   
<g transform="translate(440 465)">
<rect x="3" y="0" width="19" height="23" fill="red" >
<!-- Animating the first rectangle -->
<animate id="an1" attributeName="y" begin="city_total_v2.click" dur="1s" values="-1;-24" fill="freeze" restart="whenNotActive" />
</rect>

<rect x="28" y="0" width="19" height="29" fill="crimson" >
<!-- Animating the second rectangle -->
<animate id="an2" attributeName="y" begin="an1.end" dur="1s" values="-1;-30" fill="freeze" restart="whenNotActive" />
</rect>
<rect x="53" y="0" width="19" height="42" fill="gold" >
<animate id="an3" attributeName="y" begin="an2.end" dur="1s" values="-1;-43" fill="freeze" restart="whenNotActive" />
</rect>          
<rect x="78" y="0" width="19" height="37" fill="orange" >
<animate id="an4" attributeName="y" begin="an3.end" dur="1s" values="-1;-37" fill="freeze" restart="whenNotActive" />
</rect>        
<rect x="103" y="0" width="19" height="51" fill="skyblue" >
<animate id="an5" attributeName="y" begin="an4.end" dur="1s" values="-1;-52" fill="freeze" restart="whenNotActive" />
</rect>       
<rect x="128" y="0" width="19" height="47" fill="yellowgreen" >
<animate id="an6" attributeName="y" begin="an5.end" dur="1s" values="-1;-48" fill="freeze" restart="whenNotActive" />
</rect>    
<rect x="153" y="0" width="19" height="40" fill="orange" >
<animate id="an7" attributeName="y" begin="an6.end" dur="1s" values="-1;-41" fill="freeze" restart="whenNotActive" />
</rect>                
<!-- masking strip          -->
<rect x="1" y="0" width="100%" height="100%" fill="white" />
<polyline  marker-end ="url(#mark)" points="0,0 200,0" fill="none" stroke="black" />
<polyline  marker-end ="url(#mark2)" points="0,0 0,-85" fill="none" stroke="black" />   
</g>
<g id="Chartline">
<path id="currency_chart_path" stroke-dasharray="177" stroke-dashoffset="177" stroke="#7C0A67" stroke-width="3px" fill="none" d="M443,439 L464,435 487,421 511,416 532,424 552,408 572,414 591,413 606,419" >
<!-- Line animation -->
<animate attributeName="stroke-dashoffset" begin="city_total_v2.click" dur="7s" values="177;0" fill="freeze" restart="whenNotActive" />
</path>
<path id="arrow" transform="rotate(180)" fill="#7C0A67" d="M0,0L0,-5L7,0L0,5">
<!-- Arrow animation -->
<animateMotion
id="an"
dur="7s"
repeatCount="1"
rotate="auto-reverse"
begin="city_total_v2.click"
fill="freeze"
restart="whenNotActive">
<mpath xlink:href="#currency_chart_path"/>
</animateMotion>
</path>
</g> 
</svg>

图表动画循环

<svg id="city_total_v2" viewBox="400 370 250 100" style="border:1px solid;" >
<defs>
<marker id="mark" markerWidth="6.5" markerHeight="8" refX="5.5" refY="1" orient="45">        
<polygon points="0,3.25 3.25,6.5 6.5,0" fill="black" stroke-width="0.25" stroke="black" />
</marker> 
<marker id="mark2" markerWidth="7" markerHeight="7" refX="3.5" refY="3"  orient="-45">        
<polygon points="0,3.25 3.25,6.5 6.5,0" fill="black" stroke-width="0.25" stroke="black" />
</marker>
</defs>   
<g transform="translate(440 465)">
<rect x="3" y="0" width="19" height="23" fill="red" >
<animate id="an1" attributeName="y" begin="city_total_v2.click;an7.end" dur="1s" values="-1;-24" fill="freeze" restart="whenNotActive" />
</rect>

<rect x="28" y="0" width="19" height="29" fill="crimson" >
<animate id="an2" attributeName="y" begin="an1.end" dur="1s" values="-1;-30" fill="freeze" restart="whenNotActive" />
</rect>
<rect x="53" y="0" width="19" height="42" fill="gold" >
<animate id="an3" attributeName="y" begin="an2.end" dur="1s" values="-1;-43" fill="freeze" restart="whenNotActive" />
</rect>          
<rect x="78" y="0" width="19" height="37" fill="orange" >
<animate id="an4" attributeName="y" begin="an3.end" dur="1s" values="-1;-37" fill="freeze" restart="whenNotActive" />
</rect>        
<rect x="103" y="0" width="19" height="51" fill="skyblue" >
<animate id="an5" attributeName="y" begin="an4.end" dur="1s" values="-1;-52" fill="freeze" restart="whenNotActive" />
</rect>       
<rect x="128" y="0" width="19" height="47" fill="yellowgreen" >
<animate id="an6" attributeName="y" begin="an5.end" dur="1s" values="-1;-48" fill="freeze" restart="whenNotActive" />
</rect>    
<rect x="153" y="0" width="19" height="40" fill="orange" >
<animate id="an7" attributeName="y" begin="an6.end" dur="1s" values="-1;-41" fill="freeze" restart="whenNotActive" />
</rect>                
<!-- masking strip          -->
<rect x="1" y="0" width="100%" height="100%" fill="white" />
<polyline  marker-end ="url(#mark)" points="0,0 200,0" fill="none" stroke="black" />
<polyline  marker-end ="url(#mark2)" points="0,0 0,-85" fill="none" stroke="black" />   
</g>
<g id="Chartline">
<path id="currency_chart_path" stroke-dasharray="177" stroke-dashoffset="177" stroke="#7C0A67" stroke-width="3px" fill="none" d="M443,439 L464,435 487,421 511,416 532,424 552,408 572,414 591,413 606,419" >
<!-- Line animation -->
<animate attributeName="stroke-dashoffset" begin="city_total_v2.click;an7.end" dur="7s" values="177;0" fill="freeze" restart="whenNotActive" />
</path>
<path id="arrow" transform="rotate(180)" fill="#7C0A67" d="M0,0L0,-5L7,0L0,5">
<!-- Arrow animation -->
<animateMotion
id="an"
dur="7s"
repeatCount="1"
rotate="auto-reverse"
begin="city_total_v2.click;an7.end"
fill="freeze"
restart="whenNotActive">
<mpath xlink:href="#currency_chart_path"/>
</animateMotion>
</path>
</g> 
</svg>

最新更新