本文实例为大家分享了canvas实现水球加载动画的具体代码,供大家参考,具体内容如下
效果展示:
源码展示:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>canvas实现水球加载动画</title>
<style>
body {
display:flex;
flex-flow:column wrap;
justify-content:center;
align-items:center;
}
#c {
margin-top:20px;
}
input[type=range]::before {
content:attr(min);
color:#000;
padding-right:5px;
}
input[type=range]::after {
content:attr(max);
color:#000;
padding-left:5px;
}
</style>
</head>
<body>
<canvas id="c">当前浏览器不支持canvas 请升级!</canvas>
<input type="range" name="range" min="0" max="100" step="1">
<script>
canvas = document.getElementById("c");
ctx = canvas.getContext("2d");
oRange = document.getElementsByName("range")[0];
M = Math;
Sin = M.sin;
Cos = M.cos;
Sqrt = M.sqrt;
Pow = M.pow;
PI = M.PI;
Round = M.round;
oW = canvas.width = 300;
oH = canvas.height = 300;
// 线宽
lineWidth = 2
// 大半径
r = (oW / 2);
cR = r - 8 * lineWidth;
ctx.beginPath();
ctx.lineWidth = lineWidth;
// 水波动画初始参数
axisLength = 2 * r - 16 * lineWidth; // Sin 图形长度
unit = axisLength / 8; // 波浪宽
range = .2 // 浪幅
nowrange = range;
xoffset = 8 * lineWidth; // x 轴偏移量
data = ~~(oRange.value) / 100; // 数据量
sp = 0; // 周期偏移量
nowdata = 0;
waveupsp = 0.002; // 水波上涨速度
// 圆动画初始参数
arcStack = []; // 圆栈
bR = r - 8 * lineWidth;
soffset = -(PI / 2); // 圆动画起始位置
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 = "#1c86d1";
ctx.fill()
ctx.restore();
}
function drawText() {
ctx.globalCompositeOperation = 'source-over';
var size = 0.4 * cR;
ctx.font = 'bold ' + size + 'px Microsoft Yahei';
txt = (nowdata.toFixed(2) * 100).toFixed(0) + '%';
var fonty = r + size / 2;
var fontx = r - size * 0.8;
ctx.fillStyle = "rgba(06, 85, 128, 0.8)";
ctx.fillText(txt, fontx, fonty)
}
function render() {
ctx.clearRect(0, 0, oW, oH);
if (circleLock) {
if (arcStack.length) {
var temp = arcStack.shift();
ctx.lineTo(temp[0], temp[1])
ctx.stroke();
} else {
circleLock = false;
ctx.lineTo(cStartPoint[0], cStartPoint[1])
ctx.stroke();
arcStack = null;
ctx.globalCompositeOperation = 'destination-over';
ctx.beginPath();
ctx.lineWidth = lineWidth;
ctx.arc(r, r, bR, 0, 2 * PI, 1);
ctx.beginPath();
ctx.save();
ctx.arc(r, r, r - 16 * lineWidth, 0, 2 * PI, 1);
ctx.restore()
ctx.clip();
ctx.fillStyle = "#1c86d1";
// 初始拖拽控件
oRange.addEventListener("change", function() {
data = ~~(oRange.value) / 100;
console.log("data=" + data)
}, 0);
}
} else {
// 开始水波动画
// 控制波幅
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)
}
</script>
<hr>
<pre style="color:red">
感: 最近贡献一下我在教学中的小案例 希望能给你一些帮助 ,希望大家继续关注我的博客
--王
</pre>
</body>
</html>