Stroke animation, how to attach another path to the appearing stroke?

后端 未结 3 593
广开言路
广开言路 2020-12-19 08:01

I have the following animation:

相关标签:
3条回答
  • 2020-12-19 08:49

    An idea is to run the animation in the opposite direction while doing a translation

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

    0 讨论(0)
  • 2020-12-19 09:05

    Yes, it's possible, however in this case you will need JavaScript. Please reed the comments in my code.

    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>

    This is inspired by a demo in Using SVG with CSS3 and HTML5: Vector Graphics for Web Design

    0 讨论(0)
  • 2020-12-19 09:06

    Pure SVG Smil solution

    You can use stroke-dashoffset to animate line growth. A marker is used as an arrow at the end of the line, but it cannot be made to move with the line, since the line does not actually grow.

    The line is drawn in advance and its growth is simply animated by decreasing the stroke-dashoffset from 177px to zero.

    You can use another technique: add an animation of the movement of an arrow along this line to the animation of the growth of the line. It is necessary to set the same time for both animations and therefore the desired effect will be created:

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

    Option with additional chart elements

    The animation will start after clicking

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

    Added rectangle animations to arrow animation

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

    Chart animation loop

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

    0 讨论(0)
提交回复
热议问题