使用场景
用于加载页面,环形进度条,中间放一个圆形图片,动态加载一周
效果图
代码示例
<template>
<view class="container">
<!-- Canvas 画布 -->
<canvas id="progressCanvas" class="progress-canvas" canvas-id="progressCanvas"></canvas>
<!-- 中心的图片 -->
<image class="center-image" src="../../static/logo.png" mode="aspectFill" />
</view>
</template>
<script>
export default {
data() {
return {
currentProgress: 0, // 当前进度值
targetProgress: 100, // 目标进度值
};
},
mounted() {
this.startAnimation(this.targetProgress); // 页面加载时自动开始动画
},
methods: {
// 绘制环形进度条
drawProgressCircle() {
const ctx = uni.createCanvasContext('progressCanvas', this);
const width = 200; // canvas宽度
const height = 200; // canvas高度
const radius = 80; // 圆的半径
const lineWidth = 10; // 进度条宽度
// 进度条的颜色和背景色
const progressColor = '#4caf50';
const bgColor = '#ddd';
// 画布中心坐标
const centerX = width / 2;
const centerY = height / 2;
// 清除画布,重新绘制
ctx.clearRect(0, 0, width, height);
// 绘制背景圆环(只占据进度条的背景)
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); // 绘制一个完整的圆环
ctx.setLineWidth(lineWidth); // 设置线宽,确保它是环形的
ctx.setStrokeStyle(bgColor); // 背景色
ctx.setLineCap('round'); // 设置圆角
ctx.stroke();
// 绘制进度圆弧
ctx.beginPath();
const startAngle = -Math.PI / 2; // 从上面开始画
const endAngle = startAngle + (2 * Math.PI) * (this.currentProgress / 100);
ctx.arc(centerX, centerY, radius, startAngle, endAngle);
ctx.setLineWidth(lineWidth); // 设置进度条线宽
ctx.setStrokeStyle(progressColor);
ctx.setLineCap('round'); // 设置圆角
ctx.stroke();
// 绘制完毕,渲染画布
ctx.draw();
},
// 启动进度条动画
startAnimation(targetProgress) {
this.targetProgress = targetProgress;
this.animateProgress(0); // 从 0 开始动画
},
// 动画递归函数
animateProgress(progress) {
if (progress >= this.targetProgress) {
this.currentProgress = this.targetProgress; // 确保最终到达目标进度
this.drawProgressCircle(); // 最后一次绘制
return;
}
this.currentProgress = progress; // 更新当前进度
this.drawProgressCircle(); // 更新进度条显示
// 增加进度,控制动画速度
const increment = 1; // 每次更新 1%
const delay = 10; // 更新频率,10 毫秒
// 使用 setTimeout 递归调用
setTimeout(() => {
this.animateProgress(progress + increment); // 递归更新
}, delay);
}
},
beforeDestroy() {
// 清除动画,防止内存泄漏
if (this.animationFrameId) {
clearTimeout(this.animationFrameId);
}
}
};
</script>
<style scoped>
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
flex-direction: column;
position: relative
}
.progress-canvas {
width: 200px;
height: 200px;
}
.center-image {
position: absolute;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
transform: translate(-50%, -50%);
/* 图片居中 */
border-radius: 50%;
/* 圆形图片 */
}
</style>