<!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>