<!DOCTYPE html> <head> <title>Canvas 水波纹</title> <meta charset="utf-8" /> <style> *{margin: 0;padding: 0;} html,body{ height: 100% } .waveBox{ 100%;height: 100%;position: relative;overflow: hidden;background-color: #051128} .waveBox canvas{100%;height:280px;position: absolute;bottom: 0;left: 0;} #myCanvas1{z-index: 1;} #myCanvas2{z-index: 2;} </style> </head> <body> <div class="waveBox"> <canvas id="myCanvas1">not support</canvas> <canvas id="myCanvas2">not support</canvas> <canvas id="myCanvas3">not support</canvas> </div> <script> // 获取dom var _c1 = document.getElementById("myCanvas1"), _c2 = document.getElementById("myCanvas2"), _c3 = document.getElementById("myCanvas3"); // 参数设置 var params = [ { canvas : _c1 , //canvas ctx : _c1.getContext("2d"), //2d画布 waveHeight:360, //波浪高度 waveCount:6, //波浪个数 progress:100, //波浪位置的高度 offset : 0, //初始偏移位置 fillStyle:'rgba(0, 123, 197, 0.7)', //填充颜色 globalAlpha:0.6 }, { canvas : _c2, ctx : _c2.getContext("2d"), waveHeight:330, waveCount:5, progress:90, offset : 0, fillStyle:'rgba(0, 188, 232, 0.6)', globalAlpha:0.5 }, { canvas : _c3, ctx : _c3.getContext("2d"), waveHeight:360, waveCount:4, progress:100, offset : 0, fillStyle:'rgba(0, 227, 232, 0.5)', globalAlpha:0.4 } ] // 波浪总宽度,起始X轴坐标和Y轴坐标 var waveWidth = 3300, startX = -1000, startY = 280; function init(params){ for(var i in params){ //初始化canvas var width = document.body.clientWidth > 1920 ? 1920 : document.body.clientWidth; var height = document.body.clientHeight > 1920 ? 1920 : document.body.clientHeight; params[i].canvas.width = width; params[i].canvas.height = height; params[i].box = [width,height]; var d2 = waveWidth / params[i].waveCount, // 每个波浪宽度 d = d2 / 2, //半个波浪宽度 hd = d / 2, //四分之一宽度 offsetY = startY - params[i].progress; //波浪顶点Y轴坐标 params[i].d2 = d2; params[i].d = d; params[i].hd = hd; params[i].offsetY = offsetY; animate(params[i]); } } function animate(params){ // 清除画布 params.ctx.clearRect(0, 0, params.box[0], params.box[1]); // 移动位置 params.offset -= 5; if (-1 * params.offset === params.d2) params.offset = 0; // 颜色填充 params.ctx.fillStyle = params.fillStyle; //透明度填充 params.ctx.globalAlpha = params.globalAlpha; // 路径绘制 params.ctx.beginPath(); // 起始点,x轴向右偏移,Y轴保持不变 params.ctx.moveTo(startX - params.offset, params.offsetY); // 循环为一个波浪,绘制弧线 for (var j = 0; j < params.waveCount; j++) { // 每个波浪的x加上起始位置减去偏移量 var dx = j * params.d2; var offsetX = dx + startX - params.offset; // 绘制曲线,绘制两条的原因是曲线的过渡地方不是平滑的,需要覆盖 params.ctx.quadraticCurveTo(offsetX + params.hd, params.offsetY + params.waveHeight, offsetX + params.d, params.offsetY); params.ctx.quadraticCurveTo(offsetX + params.hd + params.d, params.offsetY - params.waveHeight, offsetX + params.d2, params.offsetY); } // 闭合线条填充 params.ctx.lineTo(startX + waveWidth, document.body.clientHeight ); params.ctx.lineTo(startX, document.body.clientHeight ); params.ctx.closePath(); params.ctx.fill(); // 动画 requestAnimationFrame(function(){ animate(params); }); } init(params); </script> </body> </html>