JSFiddle - React, Tailwind, and code Playground

by garmashnikolay

HTML

<canvas id="canvas" width="500" height="300"></canvas>

CSS

#canvas {
  width: 500px;
  height: 300px;
}

JavaScript

const canvas = document.getElementById('canvas')

const context = canvas.getContext('2d')

context.imageSmoothingEnabled = true

function normalDistr (x, mean, variance) {
	return (1 / Math.sqrt(2 * Math.PI * variance)) * Math.pow(2.718, -1 * (Math.pow(x - mean, 2) / 2 * variance))
}

let phase = 0

function draw () {
  context.fillStyle = 'white'
  context.fillRect(0, 0, 500, 300)

	context.fillStyle = 'black'
  context.lineWidth = 5
  const period = Math.PI * 2
  const periods = 5
  
  const normalDistrRange = 7
  const ampNormalDistrRange = 15
  const maxPhase = 100
  
  context.beginPath()
  context.moveTo(0, 150)
  
  for (let i = 0; i < period * periods; i += 0.2) {
  	const x = i * 500 / (period * periods)
    const normalDistrKoef = normalDistr(x / (500 / normalDistrRange) - (normalDistrRange / 2), 0, 4)
    
    const amplitudeKoef = normalDistr(phase / (maxPhase / ampNormalDistrRange) - (ampNormalDistrRange / 2), -0.5, 0.2)

    const y = amplitudeKoef * ((Math.sin(i - phase) * normalDistrKoef * 300)) + 150
    
		context.lineTo(x, y)
  }
  
  context.stroke()
  
  phase += 0.6
  
  if (phase >= maxPhase) {
  	phase = 0
  }
  
  if (phase < maxPhase) {
  	// window.requestAnimationFrame(draw)
  }
}

window.requestAnimationFrame(draw)