JSFiddle - React, Tailwind, and code Playground

HTML

<div></div>

CSS

div {
  height: 100px;
  background: red;
}

JavaScript

var c4 = (2 * Math.PI) / 3
function easeOutElastic (x) {
  return x === 0 ? 0 : x === 1 ? 1 :
    Math.pow(2, -10 * x) * Math.sin((x * 10 - 0.75) * c4) + 1
}

var div = document.getElementsByTagName('div')[0] // 要变化高度的 div
var startValue = 100 // div 的初始高度
var endValue = 400 // div 的最终高度
var changeValue = endValue - startValue // div 变化了这么多高度
var during = 2000 // 动画持续 2 秒钟

// 为了让动画足够流畅,我们需要达到 60 帧/每秒的动画速率,
// 即大约 17 毫秒更新一次动画的状态
var updateTime = 1000 / 60
// 计算出两秒内我们需要更新动画多少次
var updateCount = during / updateTime
// 我们需要一个在下一帧执行动画的函数
var rAF = window.requestAnimationFrame || function(cb) { setTimeout(cb, updateTime) }

var startPosition = 0 // 动画的开始时间点是 0%
var endPosition = 1 // 动画的结束时间点是 100%
// 因为我们要在动画从 0% 运动到 100% 时更新 `updateCount` 次动画,
// 所以要计算出每次更新动画时动画经过的时间
var perUpdateDistance = endPosition / updateCount

var position = startPosition // 记录动画的当前时间点

function step () {
  // 计算 div 在当前时间点的高度
  var height = startValue + changeValue * easeOutElastic(position)
  div.style.height = height + 'px' // 更新 div 的高度
  position += perUpdateDistance
  // 如果动画还没结束,则准备在下一帧更新动画
  if (position < endPosition) {
    rAF(step)
  } else {
    console.log('动画结束')
  }
}

step() // 开始运行动画