给echarts图表添加弧形动画效果

         这里在option中一定要设置animation: false,因为echarts的5.0版本以后执行动画效果会卡顿,不清楚为什么。开启定时器时,定时器的间隔应当设置小一点,不然也会出现卡顿效果,希望echarts5.50版本之后能修复ecahrts执行加载效果卡顿的问题吧......

<template>
	<div class="h-120px" ref="pieChart"></div>
</template>

<script lang="ts" setup>
import { watch, ref, onMounted, onBeforeUnmount } from "vue";
import * as echarts from "echarts";
import { useEcharts } from "@/hooks/useEcharts";
const pieChart = ref();
const props = defineProps({
	data: {
		type: Object,
		default: () => {}
	}
});
watch(
	() => props.data,
	() => {
		initPieChart();
	},
	{
		deep: true
	}
);

/**
 * 制作弧形的动画效果
 */
let angle = 0; //角度,用来做简单的动画效果的
let timer: NodeJS.Timer; // 定时器
// 更新旋转的弧形的开始角度和结束角度
//获取圆上面某点的坐标(s:起始角度,e:结束角度,angle角度)
const getCirclePoint = (s: number, e: number) => {
	return {
		startAngle: ((s + angle) * Math.PI) / 180,
		endAngle: ((e + angle) * Math.PI) / 180
	};
};
const draw = (myChart: echarts.ECharts, option: echarts.EChartsCoreOption) => {
	angle = angle + 3;
	myChart.setOption(option, true);
};
// 鼠标移入echarts图表暂停动画
const stopAnimation = () => {
	clearInterval(timer);
};
// 鼠标移出echarts图表开始动画
const startAnimation = (myChart: echarts.ECharts, option: echarts.EChartsCoreOption) => {
	timer = setInterval(() => {
		draw(myChart, option);
	}, 50);
};
// 初始化图表
const initPieChart = () => {
	// 判断当前echarts是否存在
	let myChart = echarts.getInstanceByDom(pieChart.value);
	if (myChart == null) {
		myChart = echarts.init(pieChart.value);
	}
	const productList = ["产品1", "产品2", "产品3", "产品4", "产品5", "产品6", "产品7"];
	let totalData = [1.5, 1.3, 1.1, 2.3, 2.4, 2.6, 2.4];
	let totalNumber = 0;
	totalData.forEach(item => {
		totalNumber += item;
	});
	let finalData = [];
	for (let i = 0; i < productList.length; i++) {
		finalData.push({ name: productList[i], value: totalData[i] });
	}

	const option = {
		animation: false,
		tooltip: {
			trigger: "item",
			formatter: "{b} <br/>产能: {c}t"
		},
		legend: {
			type: "plain",
			orient: "vertical",
			height: "88%",
			right: "20",
			top: "center",
			itemWidth: 8,
			itemHeight: 8,
			data: productList,
			//格式化每一项内容
			formatter(name: string) {
				//只接收一个参数,就是类目名称
				let value = 0;
				//使用name去放内容的数组中拿到对应的值
				finalData.forEach(item => {
					if (item.name == name) {
						value = item.value;
					}
				});
				//name, value可以理解为样式标记符,用于在富文本中设置对应的样式
				return name + " " + ((value / totalNumber) * 100).toFixed(2) + "%";
			},
			textStyle: {
				fontSize: 14,
				fontWeight: 400,
				color: "#D1D6DF"
			}
		},
		series: [
			{
				type: "pie",
				radius: ["58%", "88%"],
				center: ["16%", "50%"],
				color: ["#4E7BFE", "#6796FD", "#3CB4FF", "#26D080", "#6B72D4", "#FEC704", "#FF4756"],
				label: {
					normal: {
						show: false
					}
				},
				labelLine: {
					normal: {
						show: false
					}
				},
				data: finalData
			},
			// 内圈阴影
			{
				itemStyle: {
					normal: {
						color: "rgba(8, 58, 84, 1)"
					}
				},
				type: "pie",
				hoverAnimation: false,
				radius: ["50%", "65%"],
				center: ["16%", "50%"],
				label: {
					normal: {
						show: false
					}
				},
				data: [
					{
						value: 1
					}
				],
				z: -1
			},
			// 外圈圆弧
			{
				name: "ring1",
				type: "custom",
				coordinateSystem: "none",
				renderItem: function (params: any, api: any) {
					let point = getCirclePoint(60, 120);
					return {
						type: "arc",
						shape: {
							cx: api.getWidth() * 0.16,
							cy: api.getHeight() / 2,
							r: Math.min(api.getWidth(), api.getHeight()) * 0.48,
							startAngle: point.startAngle,
							endAngle: point.endAngle
						},
						style: {
							stroke: "#FF0351",
							fill: "transparent",
							lineWidth: 1.5
						},
						silent: true
					};
				},
				data: [0]
			},
			{
				name: "ring2",
				type: "custom",
				coordinateSystem: "none",
				renderItem: function (params: any, api: any) {
					let point = getCirclePoint(180, 240);
					return {
						type: "arc",
						shape: {
							cx: api.getWidth() * 0.16,
							cy: api.getHeight() / 2,
							r: Math.min(api.getWidth(), api.getHeight()) * 0.48,
							startAngle: point.startAngle,
							endAngle: point.endAngle
						},
						style: {
							stroke: "#FF0351",
							fill: "transparent",
							lineWidth: 1.5
						},
						silent: true
					};
				},
				data: [0]
			},
			{
				name: "ring3",
				type: "custom",
				coordinateSystem: "none",
				renderItem: function (params: any, api: any) {
					let point = getCirclePoint(300, 360);
					return {
						type: "arc",
						shape: {
							cx: api.getWidth() * 0.16,
							cy: api.getHeight() / 2,
							r: Math.min(api.getWidth(), api.getHeight()) * 0.48,
							startAngle: point.startAngle,
							endAngle: point.endAngle
						},
						style: {
							stroke: "#FF0351",
							fill: "transparent",
							lineWidth: 1.5
						},
						silent: true
					};
				},
				data: [0]
			}
		]
	};

	useEcharts(myChart, option);
	// 开始定时器执行动画效果
	startAnimation(myChart, option);
	// 给echarts图表绑定鼠标移入移除事件
	myChart.on("mouseover", function () {
		stopAnimation();
	});
	myChart.on("mouseout", function () {
		startAnimation(myChart, option);
	});
};
onMounted(() => {
	initPieChart();
});
onBeforeUnmount(() => {
	stopAnimation();
});
</script>

<style lang="scss" scoped></style>

附上自己封装的useEcharts函数:给ecahrts添加响应式

import { onBeforeUnmount, onActivated, onDeactivated } from "vue";
import { useDebounceFn } from "@vueuse/core";
import * as echarts from "echarts";

/**
 * @description 使用Echarts(只是为了添加图表响应式)
 * @param {Element} myChart Echarts实例(必传)
 * @param {Object} options 绘制Echarts的参数(必传)
 * @return void
 * */
export const useEcharts = (myChart: echarts.ECharts, options: echarts.EChartsCoreOption) => {
	if (options && typeof options === "object") {
		myChart.setOption(options);
	}
	const echartsResize = useDebounceFn(() => {
		myChart && myChart.resize();
	}, 100);

	window.addEventListener("resize", echartsResize);

	onBeforeUnmount(() => {
		window.removeEventListener("resize", echartsResize);
	});

	onActivated(() => {
		window.addEventListener("resize", echartsResize);
	});

	onDeactivated(() => {
		window.removeEventListener("resize", echartsResize);
	});
};

相关推荐

  1. echarts图表添加弧形动画效果

    2024-06-12 15:32:05       30 阅读
  2. 图片添加

    2024-06-12 15:32:05       48 阅读
  3. WPF添加动画过渡效果

    2024-06-12 15:32:05       23 阅读
  4. wordpress网站添加瀑布流效果

    2024-06-12 15:32:05       37 阅读
  5. 如何在vue添加echarts图表

    2024-06-12 15:32:05       43 阅读
  6. 使用css制作心形图案并且添加动画心动效果

    2024-06-12 15:32:05       24 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-12 15:32:05       91 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-12 15:32:05       97 阅读
  3. 在Django里面运行非项目文件

    2024-06-12 15:32:05       78 阅读
  4. Python语言-面向对象

    2024-06-12 15:32:05       88 阅读

热门阅读

  1. PTA:7-184 通过嵌套循环输出二维矩阵

    2024-06-12 15:32:05       31 阅读
  2. Web前端模板引擎:深度解析与应用探索

    2024-06-12 15:32:05       30 阅读
  3. 一台 Linux 服务器最多能支撑多少个 TCP 连接

    2024-06-12 15:32:05       31 阅读
  4. wildcard邀请码

    2024-06-12 15:32:05       33 阅读
  5. 每天一个数据分析题(三百六十)- 整数规划

    2024-06-12 15:32:05       30 阅读
  6. 【Python基础】文件处理

    2024-06-12 15:32:05       29 阅读
  7. 1358 - 素数环

    2024-06-12 15:32:05       27 阅读
  8. rk3576作为2024行业新秀,那么rk3588和rk3399

    2024-06-12 15:32:05       24 阅读
  9. Hadoop之HDFS分布式文件系统

    2024-06-12 15:32:05       28 阅读
  10. DevOps的原理及应用详解(三)

    2024-06-12 15:32:05       39 阅读
  11. 【日常记录】Jackson如何支持org.joda.time.DateTime

    2024-06-12 15:32:05       20 阅读
  12. 力扣-2225

    2024-06-12 15:32:05       22 阅读
  13. Lua 基础 05 时间

    2024-06-12 15:32:05       29 阅读
  14. leetcode刷题记录38-16. 最接近的三数之和

    2024-06-12 15:32:05       25 阅读