JSFiddle - React, Tailwind, and code Playground

HTML

Overshoot: <input id="overshoot" type="number" size="4" value="1.5" step="0.1">
Elasticity: <input id="elasticity" type="number" size="3" value="3" step="0.5"><br>
<svg width="500" height="500">
  <g transform="translate(30 20)" id="plot-area"></g>
</svg>

CSS

.axis, .overshootLine, .oneLine {
  fill: none;
  stroke-width: 1;
}
.axis {
  stroke: black;
}
.overshootLine {
  stroke: grey;
  stroke-dasharray: 2 4;
}
.oneLine {
  stroke: maroon;
}
.resultLine {
  stroke-width: 2;
  stroke: blue;
  fill: none;
  stroke-linejoin: round;
}
.xAxisLabel {
  fill: grey;
  font-size: 10px;
  text-anchor: middle;
}
.yAxisLabel {
  font-size: 12px;
  text-anchor: end;
}
}
.tick {
  fill: none;
  stroke: grey;
  stroke-width: 0.5;
}

JavaScript

var overshootField = document.getElementById('overshoot'),
    elasticityField = document.getElementById('elasticity'),
    plot = document.getElementById("plot-area"),
    SVGNS = "http://www.w3.org/2000/svg";

function getY(x, overshoot, elasticity) {
  // --------------- HELP NEEDED ------------------
  // This function here needs your help!!!
  // See http://brian.sol1.net/svg/ for details
  //
  // You can ignore the rest of the fiddle.
  // However, one extension which might be helpful
  // is to add a bouncing ball animation at the
  // bottom and simulate the effect timing function
  // (e.g. using SVG's keyTimes and keyPoints).
  // ----------------------------------------------
  
  // Sine wave
  var compression = 2;
  var numCycles = (Math.floor(overshoot * elasticity) + 0.5) * 2;
  var cos = Math.cos(numCycles/2*Math.pow(x,compression)*Math.PI);
  
  // Work out where the first peak lies
  var firstPeak = Math.pow(numCycles/2,-1/compression);
  
  // Adjust the amount of damping so there's none around the first peak
  var dampingFactor = x > firstPeak ? (1 - x) / (1 - firstPeak)
                                    : x / firstPeak;
  var scaleFactor = Math.log(overshoot-1) / (-firstPeak*Math.E)-1;
  return 1 - Math.exp(-x*(dampingFactor*scaleFactor+1)*Math.E)*cos;
}

function update() {
  var points = [],
      overshoot = overshootField.value,
      elasticity = elasticityField.value;
  for (var i = 0; i <= 100; i++) {
    points.push({ x: i/100, y: getY(i/100, overshoot, elasticity) });
  }
  updateChart(points);
}

function updateChart(points) {
  var yBounds = points.reduce(function(prev, curr) {
    return { min: Math.floor(Math.min(prev.min, curr.y)),
             max: Math.ceil(Math.max(prev.max, curr.y)) };
  }, { min: -1, max: 2 });
  var yScale = 400 / (yBounds.max - yBounds.min);
  
  var toPlotSpace = function(y) {
    return (yBounds.max - y) * yScale;
  };
  
  // Shift lines
  moveObject("xAxisGroup", [ 0, toPlotSpace(0) ]);
 ...