vue3 3D饼图

const getPie3D = (pieData, internalDiameterRatio) => {
	let that = this;
	let series = [];
	let sumValue = 0;
	let startValue = 0;
	let endValue = 0;
	let seriesValue = '';
	let legendData = [];
	let legendBfb = [];
	let k = 1 - internalDiameterRatio;
	pieData.sort((a, b) => {
		return (b.value - a.value);
	});
	// 为每一个饼图数据,生成一个 series-surface(参数曲面) 配置
	for (let i = 0; i < pieData.length; i++) {
		sumValue += pieData[i].value;
		let seriesItem = {
			//系统名称
			name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
			type: 'surface',
			//是否为参数曲面(是)
			parametric: true,
			//曲面图网格线(否)上面一根一根的
			wireframe: {
				show: false
			},
			pieData: pieData[i],
			pieStatus: {
				selected: false,
				hovered: false,
				k: k
			},
			label: {
				show: true,
			},
		};

		//曲面的颜色、不透明度等样式。
		if (typeof pieData[i].itemStyle != 'undefined') {
			let itemStyle = {};
			typeof pieData[i].itemStyle.color != 'undefined' ? itemStyle.color = pieData[i].itemStyle.color : null;
			typeof pieData[i].itemStyle.opacity != 'undefined' ? itemStyle.opacity = pieData[i].itemStyle.opacity : null;
			seriesItem.itemStyle = itemStyle;
		}
		series.push(seriesItem);
	}
	// 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,
	// 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
	legendData = [];
	legendBfb = [];
	for (let i = 0; i < series.length; i++) {
		endValue = startValue + series[i].pieData.value;
		seriesValue = series[i].pieData.value;
		series[i].pieData.startRatio = startValue / sumValue;
		series[i].pieData.endRatio = endValue / sumValue;
		series[i].parametricEquation = getParametricEquation(series[i].pieData.startRatio, series[i].pieData.endRatio,
			false, false, k, series[i].pieData.value);
		startValue = endValue;
		console.log(series, 'seriesseries')
		let bfb = fomatFloat(series[i].pieData.value / sumValue, 4);

		legendData.push({
			name: series[i].name,
			value: bfb,
			seriesValue: seriesValue
		});
		legendBfb.push({
			name: series[i].name,
			value: bfb,
			seriesValue: seriesValue

		});
	}
	let boxHeight = getHeight3D(series, 13);//通过传参设定3d饼/环的高度
	// 准备待返回的配置项,把准备好的 legendData、series 传入。
	series.push({
		name: 'pie2d',
		type: 'pie',
		label: {
			opacity: 1,
			fontSize: 10,
			lineHeight: 10,
			textStyle: {
				color: '#41aaff',
				fontSize: 14,
			},
		},
		labelLine: {
			length: 10,
			length2: 10,
		},
		startAngle: -30, //起始角度,支持范围[0, 360]。
		clockwise: false, //饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
		radius: ['20%', '50%'],
		center: ['50%', '50%'],
		data: pieData,
		itemStyle: {
			opacity: 0,
		},
	});
	let option = {
		//图例组件
		title: {
			top: "0%",
			left: "center",
			text: [
				`{a|${textZong.value}}`,
				'{c|:}',
				`{b|${textshu.value}}`
			],
			textStyle: {
				rich: {
					a: {
						fontSize: 20,
						fontWeight: 'bold',
						fontFamily: 'MyFont',
						color: '#ffffff',
					},
					b: {
						fontSize: 40,
						color: '#ff9a04',
						fontFamily: 'MyFont',
					},
					c: {
						fontSize: 20,
						color: '#ffffff',
					}
				}
			}
		},
		legend: {
			data: legendData,
			//图例列表的布局朝向。
			pageIcons: {
				horizontal: ['circle', 'circle', 'circle'],
			},
			pageIconSize: [8, 8],
			width: '90%',
			icon: 'circle',
			show: true,
			data: ["无星级", "一星级", "二星级", "三星级", '四星级', '五星级'],
			x: 'center', // 水平位置,可设置为'left', 'center', 'right'
			y: 'bottom', // 垂直位置,可设置为'top', 'middle', 'bottom'
			padding: [10, 20, 0, 0], // 上、右、下、左的内边距
			itemGap: 10,
			itemHeight: 20,
			itemWidth: 10,
			right: "2%",
			textStyle: {
				color: "#fff",
				fontSize: 12,
				rich: {
					name: {
						fontSize: 14,
						color: "#fff",
					},
					value: {
						fontSize: 18,
						color: "#1bff6b",
						fontFamily: 'MyFont',
					},
				},
			},
			formatter: function (param) {
				let item = legendBfb.filter(item => item.name == param)[0];
				return "{name|" + item.name + "}" + "  " + "{value|" + item.seriesValue + "}";
			}
		},
		tooltip: {
			formatter: params => {
				if (params.seriesName !== 'mouseoutSeries' && params.seriesName !== 'pie2d') {
					let bfb = ((option.series[params.seriesIndex].pieData.endRatio - option.series[params.seriesIndex].pieData.startRatio) *
						100).toFixed(2);
					return `${params.seriesName}<br/>` +
						`<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${params.color};"></span>` +
						`占比${bfb}%`;
				}
			}
		},
		labelLine: {
			show: true,
			lineStyle: {
				color: '#41aaff'
			},
			normal: {
				show: true,
				length: 10,
				length2: 10,
			},
		},
		label: {
			show: true,
			position: "outside",
			formatter: "占比{d}%",
		},
		//这个可以变形
		xAxis3D: {
			min: -1,
			max: 1
		},
		yAxis3D: {
			min: -1,
			max: 1
		},
		zAxis3D: {
			min: -1,
			max: 1
		},
		//此处是修改样式的重点
		grid3D: {
			show: false,
			boxHeight: boxHeight, //圆环的高度
			bottom: "50%",
			//这是饼图的位置
			top: '32',
			left: '0%',
			height:230,
			viewControl: {
				// distance: 200,
				beta: 21,
				alpha: 22,
				rotateSensitivity: 1,
				zoomSensitivity: 0,
				panSensitivity: 0,
				autoRotate: true,
				autoRotateSpeed: 30
			},
			postEffect: {
				enable: true,
				bloom: {
					enable: true,
					bloomIntensity: 0.1
				},
				SSAO: {
					enable: true,
					quality: 'medium',
					radius: 2
				},
				temporalSuperSampling: {
					enable: true // 开启时域超采样
				},
				antiAliasing: {
					enable: true, // 开启抗锯齿
					SMAA: {
						enable: true // 使用SMAA算法进行抗锯齿
					}
				}
			},
		},
		series: series
	};
	return option;
}
const getHeight3D = (series, height) => {
	series.sort((a, b) => {
		return (b.pieData.value - a.pieData.value);
	})
	return height * 25 / series[0].pieData.value;
}
// 生成扇形的曲面参数方程,用于 series-surface.parametricEquation
const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, h) => {
	// 计算
	let midRatio = (startRatio + endRatio) / 2;
	let startRadian = startRatio * Math.PI * 2;
	let endRadian = endRatio * Math.PI * 2;
	let midRadian = midRatio * Math.PI * 2;
	// 如果只有一个扇形,则不实现选中效果。
	if (startRatio === 0 && endRatio === 1) {
		isSelected = false;
	}
	// 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
	k = typeof k !== 'undefined' ? k : 1 / 3;
	// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
	let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
	let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
	// 计算高亮效果的放大比例(未高亮,则比例为 1)
	let hoverRate = isHovered ? 1.05 : 1;
	// 返回曲面参数方程
	return {
		u: {
			min: -Math.PI,
			max: Math.PI * 3,
			step: Math.PI / 32
		},
		v: {
			min: 0,
			max: Math.PI * 2,
			step: Math.PI / 20
		},
		x: function (u, v) {
			if (u < startRadian) {
				return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
			}
			if (u > endRadian) {
				return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
			}
			return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
		},
		y: function (u, v) {
			if (u < startRadian) {
				return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
			}
			if (u > endRadian) {
				return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
			}
			return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
		},
		z: function (u, v) {
			if (u < -Math.PI * 0.5) {
				return Math.sin(u);
			}
			if (u > Math.PI * 2.5) {
				return Math.sin(u) * h * .1;
			}
			return Math.sin(v) > 0 ? 1 * h * .1 : -1;
		}
	};
}
const fomatFloat = (num, n) => {
	var f = parseFloat(num);
	if (isNaN(f)) {
		return false;
	}
	f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n); // n 幂   
	var s = f.toString();
	var rs = s.indexOf('.');
	//判定如果是整数,增加小数点再补0
	if (rs < 0) {
		rs = s.length;
		s += '.';
	}
	while (s.length <= rs + n) {
		s += '0';
	}
	return s;
}
const inittwo = (hotelStarList) => {
	let option = getPie3D(
		hotelStarList, 0.59
	);
	// let option = getPie3D(
	// 	[
	// 		{
	// 			name: "一星级",
	// 			value: 1000,
	// 			itemStyle: {
	// 				//   opacity: 0.5,
	// 				color: "#17977d",
	// 			},
	// 		},

	// 		{
	// 			name: "三星级",
	// 			value: 2600,
	// 			itemStyle: {
	// 				//   opacity: 0.5,
	// 				color: "#1b49a7",
	// 			},
	// 		},

	// 		{
	// 			name: "二星级",
	// 			value: 1658,
	// 			itemStyle: {
	// 				//   opacity: 0.5,
	// 				color: "#c6ca30",
	// 			},
	// 		},
	// 		{
	// 			name: "四星级",
	// 			value: 1000,
	// 			itemStyle: {
	// 				//   opacity: 0.5,
	// 				color: "#c37965",
	// 			},
	// 		},

	// 		{
	// 			name: "五星级",
	// 			value: 958,
	// 			itemStyle: {
	// 				//   opacity: 0.5,
	// 				color: "#e1298e",
	// 			},
	// 		},
	// 		{
	// 			name: "无星级",
	// 			value: 958,
	// 			itemStyle: {
	// 				//   opacity: 0.5,
	// 				color: "#ab54c0",
	// 			},
	// 		}
	// 	],
	// 	0.59
	// );
	console.log(option, 'option')
	var myChart = echarts.init(document.getElementById('chartsContent'));
	//将配置项设置进去
	myChart.setOption(option);

}

需注意点数据源的传入,value值必须是number,否则,饼图的高度会有问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值