Search code examples
javascriptjquerycsssvgsvg-animate

Animate a circle with the growth of <path> on scroll


Question updated

This what I have done so far.

It works fine but I want to do an animation which is little much complicated for me.

// Get the id of the <path> element and the length of <path>
var myline = document.getElementById("myline");
var length = myline.getTotalLength();

// The start position of the drawing
myline.style.strokeDasharray = length;

// Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
myline.style.strokeDashoffset = length;

// Find scroll percentage on scroll (using cross-browser properties), and offset dash same amount as percentage scrolled
window.addEventListener("scroll", myFunction);

function myFunction() {
  // What % down is it?
  var scrollpercent = (document.body.scrollTop + document.documentElement.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
  // Length to offset the dashes
  var draw = length * scrollpercent;

  // Reverse the drawing (when scrolling upwards)
  myline.style.strokeDashoffset = length - draw;
}
body {
  height: 2000px;
  background: #f1f1f1;
}

#mySVG {
  position: fixed;
  top: 15%;
  width: 100vw;
  height: 100vh;
  margin-left: -50px;
}

.st0 {
  fill: none;
  stroke-dashoffset: 3px;
  stroke: red;
  stroke-width: 5;
  stroke-miterlimit: 10;
  stroke-dasharray: 20;
}
<h2>Scroll down this window to draw my path.</h2>
<p>Scroll back up to reverse the drawing.</p>

<svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
  <path id="myline" class="st0" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
</svg>

what I want is to animate a <circle> with the growth of the <path> like this

I know the path is growing using the strokeDasharray. But still, is there a way to attain what am looking for.? if no then please do suggest another way. thank you..!


Solution

  • Use getPointAtLength()

    Looks like another answer already suggested this :)

    // Get the id of the <path> element and the length of <path>
    var myline = document.getElementById("myline");
    var length = myline.getTotalLength();
    circle = document.getElementById("circle");
    // The start position of the drawing
    myline.style.strokeDasharray = length;
    
    // Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
    myline.style.strokeDashoffset = length;
    
    // Find scroll percentage on scroll (using cross-browser properties), and offset dash same amount as percentage scrolled
    window.addEventListener("scroll", myFunction);
    
    function myFunction() {
      // What % down is it?
      var scrollpercent = (document.body.scrollTop + document.documentElement.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
      // Length to offset the dashes
      var draw = length * scrollpercent;
    
      // Reverse the drawing (when scrolling upwards)
      myline.style.strokeDashoffset = length - draw;
      
      //get point at length
      endPoint = myline.getPointAtLength(draw);
      circle.setAttribute("cx", endPoint.x);
      circle.setAttribute("cy", endPoint.y);
      
    }
    body {
      height: 2000px;
      background: #f1f1f1;
    }
    
    #circle{
    fill:red;
    }
    
    #mySVG {
      position: fixed;
      top: 15%;
      width: 100vw;
      height: 100vh;
      margin-left: -50px;
    }
    
    .st0 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: red;
      stroke-width: 5;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
    }
    <h2>Scroll down this window to draw my path.</h2>
    <p>Scroll back up to reverse the drawing.</p>
    
    <svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
      <circle id="circle" cx="10" cy="10" r="10"/>
      <path id="myline" class="st0" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
    </svg>