vue水波球实现
Vue 水波球实现方法
水波球(也称为波浪球或液体填充效果)通常用于数据可视化或进度展示。以下是基于 Vue 的实现方法,结合 Canvas 或 SVG 技术。
使用 Canvas 实现
通过 Canvas 动态绘制波浪路径,结合动画实现波浪效果。
模板部分
<template>
<div class="wave-ball">
<canvas ref="canvas" :width="size" :height="size"></canvas>
<div class="progress-text">{{ progress }}%</div>
</div>
</template>
脚本部分
export default {
props: {
size: { type: Number, default: 200 },
progress: { type: Number, default: 50 },
color: { type: String, default: '#3eaf7c' }
},
mounted() {
this.drawWave();
},
methods: {
drawWave() {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext('2d');
const radius = this.size / 2;
let time = 0;
const animate = () => {
ctx.clearRect(0, 0, this.size, this.size);
// 绘制圆形背景
ctx.beginPath();
ctx.arc(radius, radius, radius, 0, Math.PI * 2);
ctx.fillStyle = '#f5f5f5';
ctx.fill();
// 绘制波浪路径
ctx.beginPath();
for (let x = 0; x < this.size; x++) {
const y = Math.sin(x * 0.05 + time) * 10 +
(this.size - (this.progress / 100 * this.size));
ctx.lineTo(x, y);
}
ctx.lineTo(this.size, this.size);
ctx.lineTo(0, this.size);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
time += 0.1;
requestAnimationFrame(animate);
};
animate();
}
},
watch: {
progress() {
this.drawWave();
}
}
};
样式部分
.wave-ball {
position: relative;
}
.progress-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24px;
font-weight: bold;
}
使用 SVG 实现
通过 SVG 路径动态生成波浪效果,适合需要矢量缩放场景。
模板部分
<template>
<div class="wave-ball">
<svg :width="size" :height="size" viewBox="0 0 200 200">
<circle cx="100" cy="100" r="90" fill="#f5f5f5" />
<path :d="wavePath" :fill="color" />
<text x="100" y="110" text-anchor="middle" font-size="24">{{ progress }}%</text>
</svg>
</div>
</template>
脚本部分
export default {
props: {
size: { type: Number, default: 200 },
progress: { type: Number, default: 50 },
color: { type: String, default: '#3eaf7c' }
},
data() {
return {
time: 0
};
},
computed: {
wavePath() {
const height = 200 - (this.progress / 100 * 200);
let path = `M 0 ${height + 10}`;
for (let x = 0; x <= 200; x += 10) {
const y = Math.sin(x * 0.05 + this.time) * 10 + height;
path += ` L ${x} ${y}`;
}
path += ` L 200 200 L 0 200 Z`;
return path;
}
},
mounted() {
setInterval(() => {
this.time += 0.1;
}, 100);
}
};
使用第三方库
对于复杂需求,可考虑以下库:
- vue-wavesurfer:专为音频波形设计的库,支持自定义样式。
- progressbar.js:轻量级库,支持圆形和波浪进度条。
安装示例
npm install progressbar.js
集成代码
import ProgressBar from 'progressbar.js';
export default {
mounted() {
const bar = new ProgressBar.Circle(this.$refs.container, {
strokeWidth: 6,
trailColor: '#f5f5f5',
trailWidth: 1,
easing: 'easeInOut',
duration: 1400,
text: {
autoStyleContainer: false
},
from: { color: '#3eaf7c', width: 1 },
to: { color: '#3eaf7c', width: 6 },
step: (state, circle) => {
circle.path.setAttribute('stroke', state.color);
circle.path.setAttribute('stroke-width', state.width);
circle.setText(this.progress + '%');
}
});
bar.animate(this.progress / 100);
}
};
关键优化点
- 性能优化:使用
requestAnimationFrame替代setInterval实现平滑动画。 - 响应式设计:通过
watch监听进度变化,实时更新视图。 - 可配置性:通过
props暴露颜色、尺寸等参数,增强组件复用性。
以上方法可根据项目需求选择,Canvas 适合高性能动态效果,SVG 更适合矢量场景,第三方库能快速实现复杂功能。







