当前位置: 首页 > news >正文

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

效果

安装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',},}])

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 828华为云征文 | 华为云FlexusX实例下的Kafka集群部署实践与性能优化
  • Unity 粒子系统参数说明
  • Qt与MQTT交互通信
  • Python之NumPy超详细学习指南:从入门到精通(上篇)
  • 『功能项目』战士的伤害型技能【45】
  • Spring Boot 自动配置
  • 深度学习-03 Pytorch
  • 基于Python的自然语言处理系列(8):使用TorchText进行新闻分类
  • 迎接AI时代的机遇与挑战:个人成长指南
  • C语言 | Leetcode C语言题解之第404题左叶子之和
  • c++类和对象(3):默认成员函数(下)
  • 电巢科技携Ecosmos元宇宙产品亮相第25届中国光博会
  • Java | Leetcode Java题解之第404题左叶子之和
  • 光伏选址和设计离不开气象分析!
  • Android 蓝牙三方和动态权限三方
  • 2017 前端面试准备 - 收藏集 - 掘金
  • 2019.2.20 c++ 知识梳理
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • echarts的各种常用效果展示
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Linux gpio口使用方法
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Median of Two Sorted Arrays
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 小程序01:wepy框架整合iview webapp UI
  • 一些css基础学习笔记
  • 自制字幕遮挡器
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • ionic异常记录
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • # Redis 入门到精通(一)数据类型(4)
  • # 职场生活之道:善于团结
  • #include
  • #pragma multi_compile #pragma shader_feature
  • #在 README.md 中生成项目目录结构
  • (安卓)跳转应用市场APP详情页的方式
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (二)正点原子I.MX6ULL u-boot移植
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)nsfocus-绿盟科技笔试题目
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET 中让 Task 支持带超时的异步等待
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • /bin/bash^M: bad interpreter: No such file or directory
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • @entity 不限字节长度的类型_一文读懂Redis常见对象类型的底层数据结构
  • [] 与 [[]], -gt 与 > 的比较
  • [AI StoryDiffusion] 创造神奇故事,AI漫画大乱斗!
  • [android学习笔记]学习jni编程
  • [AutoSar]工程中的cpuload陷阱(三)测试