vue3.0 使用echarts与echarts-gl 实现3D饼图

server/2024/9/24 9:19:48/

效果

安装echarts

npm install echarts
npm install echarts-gl

3d饼图组件:

<template><div style="width: 100%; height: 100%" ref="echart"></div>
</template><script setup>
import { reactive, ref, onMounted, watch } from 'vue'
import * as echarts from 'echarts'
import 'echarts-gl'const boxHeight = ref([])
const legendData = ref([])
const echart = ref()const props = defineProps({optionsData: []
})const echartInit = () => {var myChart = echarts.init(echart.value)const series = getPie3D(props.optionsData, 0.7)series.push({center: ['10%', '90%'],name: 'pie2d',type: 'pie',label: {show: false,opacity: 1,fontSize: 12,lineHeight: 10,textStyle: {fontSize: 12,color: '#fff',},},labelLine: {length: 30,length2: 30,},startAngle: -30, //起始角度,支持范围[0, 360]。clockwise: false, //饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式radius: ['40%', '60%'],//data: props.optionsData,data: props.optionsData.map(item => {item.itemStyle.opacity = 0return item}),itemStyle: {opacity: 0,}})// 准备待返回的配置项,把准备好的 legendData、series 传入。let option = {legend: {show: true,tooltip: {show: true,},orient: 'vertical',//data: ['待办', '已办', '未处理'],data: legendData.value,top: 'center',// 设置图例为矩形itemWidth: 14,   // 图例标记的宽度,默认为14itemHeight: 14,  // 图例标记的高度,默认为12itemStyle: {// 设置边框圆角,可以设置为 0 实现正方形borderRadius: 5},itemGap: 12,right: '2%',textStyle: {color: '#fff',fontSize: 12,},formatter: (param)=> {let item = legendData.value.filter(item => item.name == param)[0];let bfs = fomatFloat(item.value * 100, 2) + "%";let v = item.value2;//return `${item.name}  ${bfs}`;return `${item.name}  ${v}`;}},animation: true,tooltip: {formatter: (params) => {if (params.seriesName !== 'mouseoutSeries' &&params.seriesName !== 'pie2d') {return `${params.seriesName}<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${params.color};"></span>${option.series[params.seriesIndex].pieData.value + '台'}`}},textStyle: {fontSize: 12,},},title: {x: 'center',top: '20',textStyle: {color: '#fff',fontSize: 12,},},// backgroundColor: '#FFF',labelLine: {show: false,lineStyle: {color: '#7BC0CB',},normal: {show: false,length: 10,length2: 10,},},label: {show: false,position: 'outside',formatter: '{b} \n{d}%',textStyle: {color: '#fff',fontSize: '14px',},},xAxis3D: {min: -1,max: 1,},yAxis3D: {min: -1,max: 1,},zAxis3D: {min: -1,max: 1,},grid3D: {show: false,//boxHeight: 0.01,boxHeight: boxHeight.value,//top: '30%',bottom: '50%',left: '-18%',// environment: "rgba(255,255,255,0)",viewControl: {distance: 180,//这个数值越大图就越小alpha: 25,//倾斜角度beta: 60,//起始渲染角度autoRotate: false, // 自动旋转rotateSensitivity: 1,//旋转灵敏度,鼠标按住不放可进行角度偏移zoomSensitivity: 1,//缩放灵敏度,鼠标滚轮可修改大小panSensitivity: 0,// 平移操作的灵敏度,值越大越灵敏。默认为1,设置为0后无法平移。支持使用数组分别设置横向和纵向的平移灵敏度},},series: series,}// 使用刚指定的配置项和数据显示图表。myChart.setOption(option)}function 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('.');//判定如果是整数,增加小数点再补0if (rs < 0) {rs = s.length;s += '.';}while (s.length <= rs + n) {s += '0';}return s;
}// 获取3d饼图的最高扇区的高度
function getHeight3D(series, height) {series.sort((a, b) => {return (b.pieData.value - a.pieData.value);})return height * 25 / series[0].pieData.value;
}
function getParametricEquation(startRatio,endRatio,isSelected,isHovered,k,height,
) {// 计算let midRatio = (startRatio + endRatio) / 2let startRadian = startRatio * Math.PI * 2let endRadian = endRatio * Math.PI * 2let 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 : 0let 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)}return Math.sin(v) > 0 ? 1 * height : -1},}}// 生成模拟 3D 饼图的配置项function getPie3D(pieData, internalDiameterRatio) {let series = []let sumValue = 0let startValue = 0let endValue = 0//let legendData = []let k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3pieData.sort((a, b) => {return (b.value - a.value);});// 为每一个饼图数据,生成一个 series-surface 配置for (let i = 0; i < pieData.length; i++) {sumValue += pieData[i].valuelet 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,},}if (typeof pieData[i].itemStyle != 'undefined') {let itemStyle = {}typeof pieData[i].itemStyle.color != 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : nulltypeof pieData[i].itemStyle.opacity != 'undefined' ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : nullseriesItem.itemStyle = itemStyle}series.push(seriesItem)}// 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,// 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。for (let i = 0; i < series.length; i++) {endValue = startValue + series[i].pieData.valueseries[i].pieData.startRatio = startValue / sumValueseries[i].pieData.endRatio = endValue / sumValueseries[i].parametricEquation = getParametricEquation(series[i].pieData.startRatio,series[i].pieData.endRatio,false,false,k,series[i].pieData.value,)boxHeight.value = getHeight3D(series, 2);//通过传参设定3d饼/环的高度,26代表26pxstartValue = endValue//legendData.value.push(series[i].name)let bfb = fomatFloat(series[i].pieData.value / sumValue, 4);legendData.value.push({name: series[i].name,value: bfb,value2: series[i].pieData.value});}return series}watch(() => [props.optionsData],() => {echartInit()}
)onMounted(() => {echartInit()
})</script>

vue中的使用:

<My3DPie :optionsData="optionsData" />

vue的js引入组件

// 传入数据生成 optionconst optionsData = ref([{name: '饮料',value: 36,itemStyle: {opacity: 0.8,color: '#14EC92',},},{name: '小食品',value: 29,itemStyle: {opacity: 0.8,color: '#42A2D8',},}])


http://www.ppmy.cn/server/115563.html

相关文章

【机器学习】python补充知识点

在Python中&#xff0c;range() 和 arange() 都是用于生成数字序列的函数&#xff0c;但它们属于不同的库&#xff0c;并且有不同的用途和特性。 range()&#xff1a; range() 是Python内置的函数&#xff0c;用于生成一个整数序列。它返回一个range对象&#xff0c;这是一个可…

模板语法

模板语法 {{.}} 模板语法都包含在 {{ 和 }} 中间&#xff0c;其中{{ . }}中的点表示当前对象。 当传入一个结构体对象时&#xff0c;可以根据 . 来访问结构体的对应字段。 当传入的变量是map时&#xff0c;也可以在模板文件中通过 . 根据key来取值。 main.go package maini…

point transformer v3复现及核心代码详解

point transformer v3复现及核心代码详解 1. 复现1.1 复现1.2 数据预处理1.3 跑通 2. 核心代码详解2.1 读取数据2.2 dataloder2.3 模型读取数据的逻辑2.4 forward2.4.1 Point2.4.2 backbone2.4.2.1 point.serialization2.4.2.2 稀疏化2.4.2.3 embedding2.4.2.4 encoder 1. 复现…

Linux——网络基础

一.协议 协议是一种约定。 为了让不同的计算机厂商生产出来的计算机能够相互顺畅的通讯&#xff0c;提出一个需要大家共同遵守的约定&#xff0c;即网络协议。 1.协议分层 网络通信协议的设计非常复杂&#xff0c;因此需要进行协议分层&#xff0c;使其具有模块化。 协议分…

《实现 HTML 图片轮播效果》

目录 &#xff08;一&#xff09;HTML 结构 &#xff08;二&#xff09;CSS 样式 &#xff08;三&#xff09;JavaScript 实现轮播逻辑 一、轮播效果的重要性与应用场景 在网页设计中&#xff0c;轮播效果是非常常见且重要的元素。它可以在有限的空间内展示多张图片或者广告…

Pytorch2.4.0自动安装cudnn9.1??? pip安装cudnn方法

Pytorch2.4.0使用官方安装方式安装的时候&#xff0c;会自动给我安装cudnn9.1&#xff0c;不论是conda安装还是pip安装&#xff0c;害得我出了一大堆问题&#xff0c;气死我了 我倒退到安装pytorch2.3.0才没出现自动安装cudnn的问题 以及&#xff0c;记录一个pip安装cudnn的方…

DisplayManagerService启动及主屏添加-Android13

// 以下代码是模拟DisplayManagerService在Android 13中启动并添加主屏的过程。 // 注意&#xff1a;这只是一个简化的代码示例&#xff0c;实际的系统服务可能包含复杂的逻辑和错误处理。 import android.hardware.display.DisplayManagerGlobal; import android.view.Displ…

bpftrace使用

bpftrace是一种基于eBPF&#xff08;Extended Berkeley Packet Filter&#xff09;的跟踪工具&#xff0c;用于在Linux系统中进行动态跟踪和系统性能分析。理解bpftrace的概念、原理和使用方法有助于更好地使用和应用它。 介绍 eBPF&#xff08;Extended Berkeley Packet Filt…