Echarts 3d饼状图
记录使用Echarts 实现3D饼状图的过程。
效果图:
1.首先安装echarts 3d插件
"echarts": "^4.7.0",
"echarts-gl": "^1.1.2",
npm install echarts --save
npm install echarts-gl
2.封装组件
<template><divref="chartPanel"id="chart-panel":style="{width: '950PX', height: height}"></div>
</template><script>
import {getPie3D} from '@/utils/largeScreen/sector'
import 'echarts-gl'
import {colorMixin} from '@/store/mixins/color'const colors = ['#13c5a1', '#3de9d4', '#1256dd', '#39a0fe', '#fff942', '#126109', '#9ce3cc', '#a5c9ef', '#cbe5de', '#bfb6db']
export default {name: 'PieChartSolid',mixins: [colorMixin],props: {// options: {// type: Object,// default: () => null// },height: {type: String,default: '388PX'}},data() {return {backgroundDots: {'材料成本': '#13c5a1','劳务分包成本': '#3de9d4','人工成本': '#1256dd','设备成本': '#39a0fe','其他费用成本': '#fff942'},notUseColors: [],optionData: [{name: '材料成本',value: 0,itemStyle: {opacity: 0.7,color: '#D6476C'}},{name: '劳务分包成本',value: 0,itemStyle: {opacity: 0.7,color: '#c79caa'}},{name: '人工成本',value: 0,itemStyle: {opacity: 0.7,color: '#804BC6'}},{name: '设备成本',value: 1,itemStyle: {opacity: 0.7,color: '#cbe5de'}},{name: '其他成本',value: 2,itemStyle: {opacity: 0.7,color: '#bfb6db'}}]}},mounted() {this.draw3d()},watch: {},methods: {draw3d(options) {this.optionData = this.getOptionData(options)console.log(this.optionData, '初始化')if (!this.optionData.length) {return}const echarts = this.$echarts// 基于准备好的dom,初始化echarts实例let chartPanel = echarts.init(document.getElementById('chart-panel'))// 传入数据生成 optionlet series = getPie3D(this.optionData, 1.35)let option = {tooltip: {formatter: (params) => {// console.log(params)if (params.seriesName !== 'mouseoutSeries' &¶ms.seriesName !== 'pie2d') {return `<div style="padding:0 10px;">${params.seriesName}:${(option.series[params.seriesIndex].pieData.proportion * 100).toFixed(2)}%</div>`}}},// left: 100,legend: {// data: legendData,// width: '90%',itemGap: 25,// bottom: 'bottom',icon: 'circle',top: 'center',right: 'right',textStyle: {color: this.colorText,fontSize: 14}},xAxis3D: {min: -1,max: 1},yAxis3D: {min: -1,max: 1},zAxis3D: {min: -1,max: 1},grid3D: {show: false, // 是否显示三维笛卡尔坐标系。boxHeight: 10, // 三维笛卡尔坐标系在三维场景中的高度boxDepth: 100,top: '-8.5%',left: 0,// bottom: '80%',// environment: "#021041", //背景viewControl: {// 用于鼠标的旋转,缩放等视角控制alpha: 50, // 角度distance: 200, // 调整视角到主体的距离,类似调整zoom 重要rotateSensitivity: 0, // 设置为0无法旋转zoomSensitivity: 0, // 设置为0无法缩放panSensitivity: 0, // 设置为0无法平移autoRotate: false // 自动旋转}},series: series}chartPanel.setOption(option)for (let i = 0; i < this.optionData.length; i++) {console.log(this.optionData[i].itemStyle.opacity, 'this.optionData[i].itemStyle.opacity')delete this.optionData[i].itemStyle.opacity}// 是否需要label指引线,如果要就添加一个透明的2d饼状图并调整角度使得labelLine和3d的饼状图对齐,并再次setOptionoption.series.push({name: 'pie2d',type: 'pie',label: {// color: '#333333',fontSize: 12,// position: 'inner',// formatter: "{b}\n\n",// padding: [0, -40],formatter: (item) => {// console.log(item)return item.data.name + '\n\n' + item.percent + '%'}},labelLine: {length: 20,length2: 20,lineStyle: {// color: '#6ddb61',// width: 1.5// top: '0PX',// left: '50PX'}},startAngle: 330, // 起始角度,支持范围[0, 360]。 //重要clockwise: false, // 饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式radius: ['40%', '65%'],center: ['50%', '50%'],data: this.optionData,itemStyle: {opacity: 0},left: '0%',top: '0%',avoidLabelOverlap: true // 防止标签重叠})chartPanel.setOption(option)this.initEchart()},getOptionData(options) {const optionData = []this.notUseColors = []console.log(options, 'dd')for (const key in options) {let color = this.backgroundDots[key]if (!color) {color = colors.find(s => !this.notUseColors.includes(s))}if (color) {this.notUseColors.push(color)}const data = {name: key,value: options[key],itemStyle: {opacity: 0.8,color: color}}optionData.push(data)}return optionData},initEchart() {this.$nextTick(() => {let parent = document.getElementById('chart-panel') // 获取父元素let canvas = parent.getElementsByTagName('canvas') // 获取父元素下面的所有canvas元素canvas[1].style.transform = 'rotateX(20deg)'// canvas[1].style.transform = 'rotateY(-20deg)'/* 为了对齐线 */canvas[1].style.top = '-15PX'canvas[1].style.left = '-10PX'})}}
}
</script><style scoped></style>
封装方法
// 生成模拟 3D 饼图的配置项
// pieData(object):饼图数据
// internalDiameterRatio(0~1之间的浮点数):内径/外径的值(默认值 1/2),当该值等于 0 时,
// heigth配置每个数据生成的高度
export function getPie3D(pieData, internalDiameterRatio, height) {let series = []let sumValue = 0let startValue = 0let endValue = 0let legendData = []let k =typeof internalDiameterRatio !== 'undefined'? (1 - internalDiameterRatio) / (1 + internalDiameterRatio): 1 / 3// 计算比例let total = 0for (let i = 0; i < pieData.length; i++) {pieData[i].value = Number(pieData[i].value)// console.log(Number(pieData[i].value))total += Number(pieData[i].value)}// console.log(total)for (let i = 0; i < pieData.length; i++) {pieData[i].proportion = parseFloat(pieData[i].value / total).toFixed(4)// console.log(pieData[i].proportion)}// 为每一个饼图数据,生成一个 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: pieData[i].selected ? pieData[i].selected : false,hovered: pieData[i].hovered ? pieData[i].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.value// console.log(series[i]);series[i].pieData.startRatio = startValue / sumValueseries[i].pieData.endRatio = endValue / sumValueseries[i].parametricEquation = getParametricEquation(series[i].pieData.startRatio,series[i].pieData.endRatio,series[i].pieStatus.selected,series[i].pieStatus.hovered,k,height ? series[i].pieData.proportion * height : 1 //自己自定义传入高度,每个类型按比例生成高度// series[i].pieData.value ==>这个是饼图默认自己生成高度// 1 设置为1所有的扇形高度都一样高)startValue = endValuelegendData.push(series[i].name)}// console.log(series);return series
}// startRatio(浮点数): 当前扇形起始比例,取值区间[0, endRatio)
// endRatio(浮点数): 当前扇形结束比例,取值区间(startRatio, 1]
// isSelected(布尔值): 是否选中,效果参照二维饼图选中效果(单选)
// isHovered(布尔值): 是否放大,效果接近二维饼图高亮(放大)效果(未能实现阴影)
// k(0~1之间的浮点数):用于参数方程的一个参数,取值 0~1 之间,通过「内径 / 外径」的值换算而来。
//height配置3d扇形高度
export 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.2 : 0let offsetY = isSelected ? Math.sin(midRadian) * 0.2 : 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}}
}
Echarts 3d饼状图相关推荐
- 【echarts记录 -- 3d 饼状图实现】
echarts记录 -- 3d 饼状图实现 实现效果 效果1 效果2 代码 实现效果 效果1 效果2 代码 /************************* pie3D 尝试更新时间: 2020. ...
- highcharts实现立体3D饼状图
最近做一个h5活动页,设计师给我设计出了一个3D饼状图,我当时觉得没啥,觉得强大的echarts应该能做出来的,因为公司的项目涉及到图表的都用的echarts,但是后来去echarts官网一查,没这个 ...
- Jpgraph php怎么变异,php使用Jpgraph绘制3D饼状图的方法
此文实例介绍了php使用Jpgraph绘制3D饼状图的方法.分享给大伙供大家参考.具体实现方法如下: include ("src/jpgraph.php"); include (& ...
- JFreeChart在Struts2中实现3D饼状图统计
在Struts2中,用JFreeChart实现3D饼状图统计 前段时间学习了一下JFreeChart,现在来整理一下自己所作的实例. 下面分别用两种方式来实现: 一种是以java应用程序的方式,一种是 ...
- echarts制作饼状图如何设置不同类别之间有一定间隔?
解决echarts饼状图不同类之间有一定间隔 用echarts制作饼状图时,为了有利于区分不同类别,一般通过设置不同的颜色代表不同的类别即可,但为了进一步体现不同类别之间的区分,可通过设置不同类别之间 ...
- Ehcarts绘制3D饼状图
需要用到echarts.min.js和echarts-gl.min.js 网上找了半天没找到靠谱的自己查资料弄一个了方便自己以后看 直接复制到html文件中即可运行 <!DOCTYPE html ...
- highcharts实现3D饼状图
刚接触前端的时候作图大多数时候都用echarts,但今天项目中一个需求是要实现3D的饼状图,所以转向highcharts来实现,具体实现过程如下. 首先要引入所需的js文件,在官网详细说明该引入那些j ...
- python饼状图颜色一样_使用echarts画饼状图,设置饼状图颜色
前言: 前面已经跟大家分享了使用echarts画柱状图.折线图,一些之前自己遇到的坑也跟大家说了,这次就不再赘述.官方有配置文档,很详细,大家不懂的地方也可以交流. 今日分享重点:画饼状图. 1.引入 ...
- 使用echarts画饼状图,设置饼状图颜色
前言: 使用echarts遇到过的坑: 一定要给图表容器添加宽度与高度. 图表在容器中可以调整位置,让图表显示的更完整. 今日分享重点:画饼状图. 1.引入相关js <script type=& ...
最新文章
- 模拟一下goldengate中断后,重新同步操作
- 几款xshell绝佳配色方案
- MySQL 磁盘空间不够用 方案_Mysql数据磁盘不足,不停机扩容方案
- mysql存储过程打不开了_请问mysql存储过程的问题,我找了几个例子一个都运行不起来,...
- HashMap、TreeMap、Hashtable、HashSet和ConcurrentHashMap区别
- 孙宇晨终于和巴菲特共进晚餐 还赠送数字币作为见面礼
- ps练习实例_拥有一份史上最全面的50集ps抠图学习教程是什么一种体验?
- python和循环语句_Python 小白零基础入门 -- 条件语句和循环语句
- windows C++删除非空文件夹
- Procexp.exe —— 强大的进程管理器
- 康佳电视系统升级服务器地址,康佳电视各平台升级方法及强制刷机汇总
- python个人所得税怎么写_Python计算个人所得税!
- 增长黑客读书笔记(一)搭建增长团队
- transact sql mysql_Sql Server数据库常用Transact-SQL脚本(推荐)
- (React入门)ref
- 博科光纤交换机常用命令
- matlab中将数据导出到Excel表格、.txt、.xml等文件中
- 彻底解决Torch[mat1 dim 1 must match mat2 dim 0]
- 从通达信中获取得到股票、期货等金融标的的分时数据。
- Brightcove推出业务连续性套件,以帮助安全地管理业务沟通