canvas水波上涨进度动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>水波上涨进度动画</title>
<style>
body {
display: flex;
flex-flow: column wrap;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<canvas id="c">当前浏览器不支持canvas 请升级!</canvas>
</body>
<script>
function draw(data, color) {
let canvas = document.getElementById("c");
let ctx = canvas.getContext("2d");
let oRange = document.getElementsByName("range")[0];
let M = Math;
let Sin = M.sin;
let Cos = M.cos;
let Sqrt = M.sqrt;
let Pow = M.pow;
let PI = M.PI;
let Round = M.round;
let oW = (canvas.width = 250);
let oH = (canvas.height = 250);
// 线宽
let lineWidth = 2;
// 大半径
let r = oW / 2;
let cR = r - 10 * lineWidth;
ctx.beginPath();
ctx.lineWidth = lineWidth;
// 水波动画初始参数
let axisLength = 2 * r - 16 * lineWidth; // Sin 图形长度
let unit = axisLength / 9; // 波浪宽
let range = 0.4; // 浪幅
let nowrange = range;
let xoffset = 8 * lineWidth; // x 轴偏移量
data = ~~data / 100; // 数据量
let sp = 0; // 周期偏移量
let nowdata = 0;
let waveupsp = 0.006; // 水波上涨速度
// 圆动画初始参数
let arcStack = []; // 圆栈
let bR = r - 8 * lineWidth;
let soffset = -(PI / 2); // 圆动画起始位置
let circleLock = true; // 起始动画锁
// 获取圆动画轨迹点集
for (var i = soffset; i < soffset + 2 * PI; i += 1 / (8 * PI)) {
arcStack.push([r + bR * Cos(i), r + bR * Sin(i)]);
}
// 圆起始点
cStartPoint = arcStack.shift();
ctx.strokeStyle = "#1c86d1";
ctx.moveTo(cStartPoint[0], cStartPoint[1]);
// 开始渲染
render();
function drawSine() {
ctx.beginPath();
ctx.save();
var Stack = []; // 记录起始点和终点坐标
for (var i = xoffset; i <= xoffset + axisLength; i += 20 / axisLength) {
var x = sp + (xoffset + i) / unit;
var y = Sin(x) * nowrange;
var dx = i;
var dy = 2 * cR * (1 - nowdata) + (r - cR) - unit * y;
ctx.lineTo(dx, dy);
Stack.push([dx, dy]);
}
// 获取初始点和结束点
var startP = Stack[0];
var endP = Stack[Stack.length - 1];
ctx.lineTo(xoffset + axisLength, oW);
ctx.lineTo(xoffset, oW);
ctx.lineTo(startP[0], startP[1]);
ctx.fillStyle = color;
ctx.fill();
ctx.restore();
}
function drawText() {
ctx.globalCompositeOperation = "source-over";
var size = 0.4 * cR;
txt = (nowdata.toFixed(2) * 100).toFixed(0) + "%";
var fonty = r + size / 2;
var fontx = r - size * 0.8;
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText(txt, r + 5, r - 50);
}
//最外面淡黄色圈
function drawCircle() {
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = color;
ctx.arc(r, r, cR + 1, 0, 2 * Math.PI);
ctx.stroke();
ctx.restore();
}
//裁剪中间水圈
function clipCircle() {
ctx.beginPath();
ctx.arc(r, r, cR, 0, 2 * Math.PI, false);
ctx.clip();
}
//渲染canvas
function render() {
ctx.clearRect(0, 0, oW, oH);
//最外面淡黄色圈
drawCircle();
//裁剪中间水圈
clipCircle();
if (data >= 0.85) {
if (nowrange > range / 4) {
var t = range * 0.01;
nowrange -= t;
}
} else if (data <= 0.1) {
if (nowrange < range * 1.5) {
var t = range * 0.01;
nowrange += t;
}
} else {
if (nowrange <= range) {
var t = range * 0.01;
nowrange += t;
}
if (nowrange >= range) {
var t = range * 0.01;
nowrange -= t;
}
}
if (data - nowdata > 0) {
nowdata += waveupsp;
}
if (data - nowdata < 0) {
nowdata -= waveupsp;
}
sp += 0.07;
// 开始水波动画
drawSine();
// 写字
drawText();
requestAnimationFrame(render);
}
}
draw(50, "skyblue");
</script>
</html>