<h1>Wavy Numbers Gauge</h1>
<p>go ahead... drag or throw that slider</p>
<svg id="demo" xmlns="http://www.w3.org/2000/svg" width="1000" height="280" viewBox="0 0 1000 280"> 
  <path id="slider" d="M15.63,1.49.4,27.87A3,3,0,0,0,3,32.35H33.45A3,3,0,0,0,36,27.87L20.81,1.49A3,3,0,0,0,15.63,1.49Z" fill="#5cceee"/></svg>

<div class="branding">
  <p>see the tutorial on</p>
  <h2><span>motion</span>tricks.com</h2>
  <a href="https://www.motiontricks.com/wavy-gauge-numbers/" target="_blank">Tutorial</a>
</div>
body {
  font-family: "proxima-nova", sans-serif;
  display: flex;
  height: 100vh;
  background: #000;
  overflow: hidden;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: white;
  font-size: 20px;
  background-image: linear-gradient(
    0deg,
    rgb(10, 10, 10),
    rgb(20, 20, 20),
    rgb(43, 59, 105)
  );
}

svg {
  width: 80vw;
  height: auto;
  max-width: 1200px;
  margin-top: 1rem;
}


svg text {
  fill: white;
  font-size: 20px;
  user-select: none;
}

svg line {
  stroke-width: 1.5;
  stroke: white;
}

h2 {
  font-weight: 400;
}
h2 span {
  font-weight: 700;
  color: #5cceee;
}

.branding {
  display: flex;
  flex-direction: column;
  align-items: center;

}

h1, h2,
p {
  margin: 0;
}

a {
  background: #5cceee;
  color: white;
  padding: 10px;
  text-decoration: none;
  border-radius: 3px;
  margin-top: 10px;
}

a:hover {
  background: white;
    color: #5cceee;
}
gsap.registerPlugin(InertiaPlugin);

console.clear();
const svgns = "http://www.w3.org/2000/svg";
const demo = document.querySelector("svg");

let positions = 20; // how many numbers
let count = 0; // simple counter for the numbers
let startX = 30; // first line position and fist number position
let dragMin = startX;
let y2Pos = 200; // bottom of each tick line
let y1Pos;
let spacing = 9.4; // space between lines
let jump = 120; // height of number jump during animation
let dur = 1.1; // master duration
let masterStagger = 3; // higher numbers tighten the curve

// move the draggable element into position
gsap.set("#slider", { x: startX, xPercent: -50, y: y2Pos + 20 });

// make a 5 pack of lines for each number
for (let j = 0; j < positions; j++) {
  makeNumber();
  for (let i = 0; i < 5; i++) {
    y1Pos = i === 0 ? y2Pos - 25 : y2Pos - 15; // first line in each pack is slightly taller
    makeLine(y1Pos);
    startX += spacing;
  }
  count++;
}

makeNumber(); // need one final number 
makeLine(y2Pos - 25); //  need 1 extra line for the last number

// creates the line elements
function makeLine(yp) {
  let newLine = document.createElementNS(svgns, "line");
  demo.appendChild(newLine);
  gsap.set(newLine, {
    attr: { x1: startX, x2: startX, y1: yp, y2: y2Pos }
  });
}

// creates the numbers
function makeNumber() {
  let txt = document.createElementNS(svgns, "text");
  demo.appendChild(txt);
  txt.textContent = count;
  gsap.set(txt, {
    attr: { x: startX, y: y2Pos - 40, "text-anchor": "middle" }
  });
}

// final position of last line is new draggable max
let dragMax = startX;

// main timeline for the number jump
let animNumbers = gsap.timeline({ paused: true });
animNumbers
  .to("text", {
    duration: dur,
    y: -jump,
    scale: 1.5,
    fill: "#5cceee",
    stagger: {
      amount: masterStagger,
      yoyo: true,
      repeat: 1
    },
    ease: "sine.inOut"
  })
  .time(dur); // set the time to the end of the first number jump



// Map the drag range to the timeline duration
let mapper = gsap.utils.mapRange(
  dragMin,
  dragMax,
  dur,
  animNumbers.duration() - dur
);

// Create the draggable element and set the range 
Draggable.create("#slider", {
  type: "x",
  bounds: {
    minX: dragMin,
    maxX: dragMax
  },
  inertia: true,
  edgeResistance: 1,
  onDrag: updateMeter,
  onThrowUpdate: updateMeter
});

// using the mapper, update the current time of the timeline
function updateMeter() {
  gsap.set(animNumbers, { time: mapper(this.x) });
}

External CSS

  1. https://use.typekit.net/xlj8lcy.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.4/gsap.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.4/Draggable.min.js
  3. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/InertiaPlugin.min.js