笔触动画,如何为显示的笔触附加其他路径?

时间:2018-12-12 07:52:02

标签: html html5 css3 animation svg

我有以下动画:

123
@keyframes dash {
 to {
    stroke-dashoffset: 0;
  }
}


#currency-chart-path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: dash 30s linear forwards;
}

运行代码段以查看动画。

我想将箭头附加到笔触上,使其看起来像遵循路径。

那怎么可能?

3 个答案:

答案 0 :(得分:3)

纯SVG Smil解决方案

您可以使用笔划划线偏移量来动画线条增长。 在行尾使用标记作为箭头,但是由于行实际上并没有增长,因此不能使其随行移动。

该线条是预先绘制的,并且可以通过将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-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>

答案 1 :(得分:2)

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

let chart = document.querySelector("#currency_chart_path");
// the length of the chart path
let length = currency_chart_path.getTotalLength();
// the request animatioon 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>

这是受Using SVG with CSS3 and HTML5: Vector Graphics for Web Design

中的演示的启发

答案 2 :(得分:1)

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

@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>