Canvas is used to create the effect of music rhythm, and the fluctuation can be adjusted automatically according to the volume
The focus is on the calculation of displacement points, the size of the y axis of each point, the need to use trigonometric function conversion, with relevant parameters, the specific realization of direct code.
HTML part:
<body>
<div class="canvasBox">
<canvas id="my-canvas"> </canvas>
</div>
<div id="start">start</div>
<div id="stop">stop</div>
</body>
Copy the code
The CSS part:
* { padding: 0; margin: 0; } body { width: 100%; min-height: 100vh; Background-color: rgba(100, 100, 100, 0.2); display: flex; flex-direction: column; justify-content: center; align-items: center; } .canvasBox { overflow: hidden; border: 1px solid red; box-sizing: border-box; } #my-canvas { transform-origin: 0 0; The transform: scale (0.5); } #start, #stop { width: 100px; height: 50px; border-radius: 6px; margin: 10px 0; line-height: 50px; text-align: center; Background: rgba(96, 96, 96, 0.2); } #start:hover, #stop:hover { cursor: pointer; }Copy the code
Javascript part:
<script> const configInfo = {width: 600,// width of the canvas height: 200,// width of the canvas lineWidth: 4,// line size linear1: [0, "rgba (181, 21, 135, 1)", 0.5, "rgba (115, 174, 73, 1)", 1, "rgba (242, 128, 6, 1)"], / / the first wave line gradient linear2: [0, "rgba (22, 108, 220, 0.6)", 1, "rgba (255, 42, 42, 0.6)"], / / the second wave line gradient linearBg: [0, "Rgba (222,222,0.3)", 1," Rgba (80,165,222,0.2)"],// Gradient of wave background scale: 2,// Canvas scaling ratio is set to 2 for clearer display on mobile terminal 8,// Movement rate _phase: 0, dataLength: 1200,// Molecular parameter of conversion rate sampleRate: 16000// denominator parameter of conversion rate}; const canvas = document.querySelector("#my-canvas"); const ctx = canvas.getContext("2d"); const scale = configInfo.scale; const width = configInfo.width * scale; const height = configInfo.height * scale; canvas.width = width; canvas.height = height; const Box = document.querySelector(".canvasBox") Box.style.width = width / 2 + 'px'; Box.style.height = height / 2 + 'px'; /** * TODO: Handle line color to gradient * @params: * CTX --> brush context * size--> Width and height * colors--> line gradient color group */ const GenLinear = (CTX, size, colors, top) => { const gradient = ctx.createLinearGradient( 0, 0, top ? 0 : size, top ? size : 0 ); for (let i = 0; i < colors.length;) { gradient.addColorStop(colors[i++], colors[i++]); } return gradient; }; const CanvasGradient1 = GenLinear(ctx, configInfo.width, configInfo.linear1); const CanvasGradient2 = GenLinear(ctx, configInfo.width, configInfo.linear2); const LinearBg = GenLinear(ctx, configInfo.height, configInfo.linearBg, true); */ const GenPath = (frequency, amplitude, phase) => {const RTV = []; const maxAmplitude = (configInfo.height * scale) / 2; for (let x = 0; x < width; */ const scaling = (1 + math.pi (math.pi + (x/width) * 2 * math.pi)) / 2; const y = scaling * maxAmplitude * amplitude * Math.sin(2 * Math.PI * (x / width) * frequency + phase) + maxAmplitude; rtv.push(y); } return rtv; }; const HandleInput = (powerLevel) => { const speedx = (configInfo.speed * configInfo.dataLength) / configInfo.sampleRate; const phase = (configInfo._phase -= speedx); // const amplitude = powerLevel / 100; const path1 = GenPath(2, amplitude, phase); Const path2 = GenPath(1.8, amplitude, phase + speedx * 5); // Clear the rectangle canvas ctx.clearRect(0, 0, width, height); // Draw the enclosing background ctx.beginPath(); for (var i = 0, x = 0; x < width; i++, x += scale) { if (x == 0) { ctx.moveTo(x, path1[i]); } else { ctx.lineTo(x, path1[i]); } } i--; for (let x = width - 1; x >= 0; i--, x -= scale) { ctx.lineTo(x, path2[i]); } ctx.closePath(); ctx.fillStyle = LinearBg; ctx.fill(); // Draw two wavy lines DrawPath(path2, CanvasGradient2); DrawPath(path1, CanvasGradient1); }; /* const DrawPath = (path, linear) => {ctx.beginPath(); for (let i = 0, x = 0; x < width; i++, x += scale) { if (x == 0) { ctx.moveTo(x, path[i]); } else { ctx.lineTo(x, path[i]); } } ctx.lineWidth = configInfo.lineWidth * scale; ctx.strokeStyle = linear; ctx.stroke(); }; /* let PL = 0; /* let PL = 0; let flag = false; let animationId = null; HandleInput (PL)/API to perform * * web animation/const RequestAnimFrame = () = > {animationId = window. RequestAnimationFrame ((t) = > {the if (PL === 100) flag = false; if (PL === 0) flag = true; if (PL % 6 === 0) HandleInput(PL) RequestAnimFrame() if (flag) PL++ if (! flag) PL-- }) } const ClearAnimation = () => { cancelAnimationFrame(animationId) animationId = null } const domStart = document.getElementById("start") const domStop = document.getElementById("stop") domStart.addEventListener("click", function () { RequestAnimFrame() }, false) domStop.addEventListener("click", function () { ClearAnimation() }, false) </script>Copy the code
Effect:
Codepen link