JSFiddle - React, Tailwind, and code Playground

HTML

<body>
	<div id="ball"></div>
</body>

CSS

body {
	padding: 0;
	margin: 0;
	background: white;
}
#ball {
	position: absolute;
	top: 0%;
	left: calc(50% - 50px);
	width: 100px;
	height: 100px;
	border-radius: 100%;
	background-color: rgba(0,0,0,.8);
}

JavaScript

/* Example animation function 
 * 
 * Interpolate between a start and end position.
 *
 * obj.x represents a position parameter (e.g. 12.2)
 * end_pos is the value obj.x will have at the end of the animation
 * msec is the number of milliseconds we want to run the animation for
 * easing is a timing function that accepts a number between 0 to 1 
 *    and returns the proportion of the interpolation between start and end to move the object to. 
 * 
 * Returns: void (performs animation as a side effect)
 */
function animation (args) {
	args = args || {};

  	var easing = args.easing || function (t) { return t }; // default to linear easing
  	var obj = args.obj;

  	var style = window.getComputedStyle(obj);

	var start_pos = parseInt(style.top.replace("%", ""), 10),
		end_pos = args.end !== undefined ? args.end : start_pos,
  		msec = args.msec || 1000;

	// performance.now is guaranteed to increase and gives sub-millisecond resolution
	// Date.now is susceptible to system clock changes and gives some number of milliseconds resolution
	var start = window.performance.now(), 
	  delta = end_pos - start_pos;

	function frame () {
		var now = window.performance.now();
		var t = (now - start) / msec; // normalize to 0..1

		if (t >= 1) { // if animation complete or running over
		  obj.style.top = end_pos + "%"; // ensure the animation terminates in the specified state
		  return;
		}

		var proportion = easing(t);
		obj.style.top = (start_pos + proportion * delta) + "%";

		requestAnimationFrame(frame); // next frame!
	}

	requestAnimationFrame(frame); // you can use setInterval, but this will give a smoother animation
}

function clamp (x, min, max) {
    return Math.min(Math.max(x, min), max);
}

function bounceFactory (bounces, threshold) {
	threshold = threshold || 0.001;

	function energy_to_height (energy) {
		return energy; // h = E/mg
	}

	function height_to_energy (height) {
		return height; // E = mgh
	}

	function bounce_time (height) {
		return 2 *...