vue3 echarts 波浪球进度条例子
一效果演示
0.35
二、安装 echarts echarts-liquidfill
bash
npm install echarts echarts-liquidfill -S
三、Vue3 组件代码
WaveProgress.vue
查看 WaveProgress.vue 源码
vue
<template>
<div class="chart-wrap">
<div ref="chartRef" class="chart-container"></div>
</div>
</template>
<script setup>
// 引入 Vue 的 ref、onMounted、onBeforeUnmount、watch 函数,用于响应式数据、组件挂载、卸载生命周期及侦听属性变化
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
// 定义从父组件传入的属性 value,默认为 0,取值范围0-1
const props = defineProps({
value: { type: Number, default: 0 },
});
// 按需引入 ECharts 的核心模块以及所需的渲染器和组件
import * as echarts from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { TooltipComponent } from "echarts/components";
// 注册 ECharts 组件
echarts.use([CanvasRenderer, TooltipComponent]);
// 引入水球图插件(liquidfill)
import "echarts-liquidfill";
// 使用 ref 引用 DOM 元素,用于渲染图表
const chartRef = ref(null);
// 存储 ECharts 实例和 ResizeObserver 实例
let myChart = null;
let resizeObserver = null;
/**
* 封装获取 ECharts 配置项的函数
* @param {Number} value 图表要展示的值(0-1之间)
* @returns {Object} ECharts 配置对象
*/
function getOption(value) {
return {
backgroundColor: "#fff", // 图表背景色
series: [
{
type: "liquidFill", // 使用水球图
radius: "100%", // 水球图的半径
center: ["50%", "50%"], // 图表中心位置
data: [value], // 显示的数值(即水位)
color: ["#3399FF"], // 水球的颜色
outline: {
show: false, // 不显示轮廓外线
},
itemStyle: {
opacity: 1, // 水球不透明度为1
shadowBlur: 0, // 无阴影模糊
shadowColor: "transparent", // 无阴影颜色
},
backgroundStyle: {
color: "#ffffff", // 水球底色为白色
shadowBlur: 0,
shadowColor: "transparent",
},
label: {
// 使用富文本显示标题和数值
formatter: `{title|磁盘空间剩余}\n{value|${
(value * 100).toFixed(0) + "%"
}}`,
rich: {
title: {
fontSize: 14,
color: "#7b7b7b",
},
value: {
fontSize: 24,
color: "#000",
padding: [14, 0, 0, 0],
},
},
},
amplitude: 10, // 波浪振幅
waveLength: "80%", // 波长
phase: 0, // 波的初相位
period: 2000, // 波的动画周期(毫秒)
},
],
};
}
// 组件挂载后初始化图表和监听器
onMounted(() => {
// 初始化 ECharts 实例
myChart = echarts.init(chartRef.value);
// 设置初始图表数据
myChart.setOption(getOption(props.value));
// 创建 ResizeObserver,当容器大小变化时自动调整图表
resizeObserver = new ResizeObserver(() => {
myChart && myChart.resize();
});
// 开始观察引用的 DOM 元素大小变化
resizeObserver.observe(chartRef.value);
});
// 组件卸载前清理资源
onBeforeUnmount(() => {
// 停止观察
if (resizeObserver) {
resizeObserver.disconnect();
}
// 销毁图表实例,释放资源
if (myChart) {
myChart.dispose();
myChart = null;
}
});
// 监听传入的 value 值的变化,一旦变化即更新图表数据
watch(
() => props.value,
(newVal) => {
if (myChart) {
// 当 value 改变时,重新设置图表选项
myChart.setOption(getOption(newVal));
}
}
);
</script>
<style scoped lang="scss">
.chart-wrap {
display: inline-flex;
border: 2px solid #3399ff;
border-radius: 50%;
padding: 2px;
box-sizing: border-box;
}
.chart-container {
width: var(--chart-size, 200px);
height: var(--chart-size, 200px);
border-radius: 50%;
overflow: hidden;
cursor: default;
}
</style>
服务端渲染,ssr 或者 ssg 可能会出现下面错误
✓ building client + server bundles...
⠸ rendering pages...ReferenceError: self is not defined
at Object.<anonymous> (D:\project\vite-docs\node_modules\echarts-liquidfill\dist\echarts-liquidfill.js:10:4)
at Module._compile (node:internal/modules/cjs/loader:1254:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
at Module.load (node:internal/modules/cjs/loader:1117:32)
at Module._load (node:internal/modules/cjs/loader:958:12)
at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:169:29)
at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
✖ rendering pages...
build error:
self is not defined
ReferenceError: self is not defined
at Object.<anonymous> (D:\project\vite-docs\node_modules\echarts-liquidfill\dist\echarts-liquidfill.js:10:4)
at Module._compile (node:internal/modules/cjs/loader:1254:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
at Module.load (node:internal/modules/cjs/loader:1117:32)
at Module._load (node:internal/modules/cjs/loader:958:12)
at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:169:29)
at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
PS D:\project\vite-docs>
解决办法,改为动态引入 import('echarts-liquidfill')
查看修改后的 WaveProgress.vue 源码
vue
<template>
<div class="chart-wrap">
<div ref="chartRef" class="chart-container"></div>
</div>
</template>
<script setup>
// 引入 Vue 的 ref、onMounted、onBeforeUnmount、watch 函数,用于响应式数据、组件挂载、卸载生命周期及侦听属性变化
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
// 定义从父组件传入的属性 value,默认为 0,取值范围0-1
const props = defineProps({
value: { type: Number, default: 0 },
});
// 按需引入 ECharts 的核心模块以及所需的渲染器和组件
import * as echarts from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { TooltipComponent } from "echarts/components";
// 注册 ECharts 组件
echarts.use([CanvasRenderer, TooltipComponent]);
// 引入水球图插件(liquidfill)
// import "echarts-liquidfill";
// https://github.com/ecomfe/echarts-liquidfill/issues/147#issuecomment-984211663
function isClient() {
return typeof window !== "undefined";
}
// 使用 ref 引用 DOM 元素,用于渲染图表
const chartRef = ref(null);
// 存储 ECharts 实例和 ResizeObserver 实例
let myChart = null;
let resizeObserver = null;
/**
* 封装获取 ECharts 配置项的函数
* @param {Number} value 图表要展示的值(0-1之间)
* @returns {Object} ECharts 配置对象
*/
function getOption(value) {
return {
backgroundColor: "#fff", // 图表背景色
series: [
{
type: "liquidFill", // 使用水球图
radius: "100%", // 水球图的半径
center: ["50%", "50%"], // 图表中心位置
data: [value], // 显示的数值(即水位)
color: ["#3399FF"], // 水球的颜色
outline: {
show: false, // 不显示轮廓外线
},
itemStyle: {
opacity: 1, // 水球不透明度为1
shadowBlur: 0, // 无阴影模糊
shadowColor: "transparent", // 无阴影颜色
},
backgroundStyle: {
color: "#ffffff", // 水球底色为白色
shadowBlur: 0,
shadowColor: "transparent",
},
label: {
// 使用富文本显示标题和数值
formatter: `{title|磁盘空间剩余}\n{value|${
(value * 100).toFixed(0) + "%"
}}`,
rich: {
title: {
fontSize: 14,
color: "#7b7b7b",
},
value: {
fontSize: 24,
color: "#000",
padding: [14, 0, 0, 0],
},
},
},
amplitude: 10, // 波浪振幅
waveLength: "80%", // 波长
phase: 0, // 波的初相位
period: 2000, // 波的动画周期(毫秒)
},
],
};
}
// 组件挂载后初始化图表和监听器
onMounted(async () => {
if (isClient()) {
// require("echarts-liquidfill");
await import("echarts-liquidfill");
// 初始化 ECharts 实例
myChart = echarts.init(chartRef.value);
// 设置初始图表数据
myChart.setOption(getOption(props.value));
// 创建 ResizeObserver,当容器大小变化时自动调整图表
resizeObserver = new ResizeObserver(() => {
myChart && myChart.resize();
});
// 开始观察引用的 DOM 元素大小变化
resizeObserver.observe(chartRef.value);
}
});
// 组件卸载前清理资源
onBeforeUnmount(() => {
// 停止观察
if (resizeObserver) {
resizeObserver.disconnect();
}
// 销毁图表实例,释放资源
if (myChart) {
myChart.dispose();
myChart = null;
}
});
// 监听传入的 value 值的变化,一旦变化即更新图表数据
watch(
() => props.value,
(newVal) => {
if (myChart) {
// 当 value 改变时,重新设置图表选项
myChart.setOption(getOption(newVal));
}
}
);
</script>
<style scoped lang="scss">
.chart-wrap {
display: inline-flex;
border: 2px solid #3399ff;
border-radius: 50%;
padding: 2px;
box-sizing: border-box;
}
.chart-container {
width: var(--chart-size, 200px);
height: var(--chart-size, 200px);
border-radius: 50%;
overflow: hidden;
cursor: default;
}
</style>
四、Vue3 使用代码
查看源码
vue
<template>
<div style="--chart-size: 500px;">
<WaveProgress :value="diskUsageValue" />
</div>
</template>
<script setup>
import { ref } from "vue";
import WaveProgress from "./WaveProgress.vue";
const diskUsageValue = ref(0.7);
// 模拟异步修改值
setTimeout(() => {
diskUsageValue.value = 0.5;
}, 2000);
</script>
五、html 代码
查看源码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>波浪球进度条示例</title>
<script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts-liquidfill/dist/echarts-liquidfill.min.js"></script>
</head>
<body>
<div id="main" style="width: 400px; height: 400px"></div>
<script>
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById("main"));
// 假设进度值为0.6即60%
var value = 0.9;
var option = {
backgroundColor: "#fff", // 背景色可根据需求调整
series: [
{
type: "liquidFill",
radius: "100%", // 控制球体的大小
center: ["50%", "50%"],
data: [value], // 数据数组中第一个值就是显示的进度值(0~1)
color: ["#3399FF"], // 波浪颜色
outline: {
show: false,
},
label: {
formatter: `{title|磁盘空间剩余}\n{value|${
(value * 100).toFixed(0) + "%"
}}`,
rich: {
title: {
fontSize: 20,
color: "#000",
},
value: {
fontSize: 40,
color: "#000",
padding: [14, 0, 0, 0], // 上、右、下、左四方向padding
},
},
},
backgroundStyle: {
color: "#f2f2f2", // 球体背景色
},
// 下方选项可根据美观需求自行调整
amplitude: 10, // 波浪振幅
waveLength: "80%", // 波长
phase: 0, // 波的初相
period: 2000, // 波的动画周期(ms)
},
],
};
// 使用指定的配置项和数据显示图表
myChart.setOption(option);
</script>
</body>
</html>