笔画动画,如何为出现的笔画附加另一条路径?
Posted
技术标签:
【中文标题】笔画动画,如何为出现的笔画附加另一条路径?【英文标题】:Stroke animation, how to attach another path to the appearing stroke? 【发布时间】:2019-05-13 06:46:38 【问题描述】:我有以下动画:
@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- 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>
运行代码sn-p查看动画。
我想将箭头附加到笔划上,使其看起来像跟随路径。
这怎么可能?
【问题讨论】:
【参考方案1】:是的,这是可能的,但是在这种情况下,您将需要 javascript。请重新输入我的代码中的 cmets。
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();
svgborder:1px solid
<svg id="city-total-v2" viewBox="400 370 250 100" >
<g id="Chartline">
<path id="currency_chart_path" stroke="#7C0A67" stroke- 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>
这是受Using SVG with CSS3 and html5: Vector Graphics for Web Design中的演示启发
【讨论】:
arrow
是chart
路径后面的箭头。我无法在您的代码中使用它,因为它不合适。当你做这种事情时,你需要在 svg 画布的原点绘制箭头(在这种情况下)。
嗨,谢谢,这正是我所需要的。有没有办法可以玩动画持续时间?
我尝试增加frame
,但效果不佳
Insetad 将frames
每一步减少一个 (frames--
),尝试将其减少小于 1。例如,减去 0.5 (frames -= 0.5;
) 将使动画长度加倍.【参考方案2】:
一个想法是在进行翻译时以相反的方向运行动画
@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- 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>
【讨论】:
谢谢,这很有趣,我会选择@enxaneta 解决方案,因为它更接近我想要的。【参考方案3】:纯 SVG Smil 解决方案
您可以使用 stroke-dashoffset 动画线的增长。 标记用作线条末端的箭头,但它不能随线条移动,因为线条实际上并没有增长。
这条线是预先画好的,它的增长只是通过将 stroke-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- 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- 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- 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" fill="red" />
<rect x="28" y="-30" fill="crimson" />
<rect x="53" y="-43" fill="gold" />
<rect x="78" y="-38" fill="orange" />
<rect x="103" y="-52" fill="skyblue" />
<rect x="128" y="-48" fill="yellowgreen" />
<rect x="153" y="-41" fill="orange" />
</g>
<g id="Chartline">
<path id="currency_chart_path" stroke-dasharray="177" stroke-dashoffset="177" stroke="#7C0A67" stroke- 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- 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- stroke="black" />
</marker>
</defs>
<g transform="translate(440 465)">
<rect x="3" y="0" 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" 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" 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" 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" 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" 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" 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" 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- 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- 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- stroke="black" />
</marker>
</defs>
<g transform="translate(440 465)">
<rect x="3" y="0" 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" 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" 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" 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" 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" 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" 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" 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- 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>
【讨论】:
以上是关于笔画动画,如何为出现的笔画附加另一条路径?的主要内容,如果未能解决你的问题,请参考以下文章