echarts实现3d饼图


html

typescript 复制代码
<script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script>
<style>
	#echarts {
	width: 500px;
	height: 500px
	}
</style>
<div id="echarts"></div>

js

typescript 复制代码
 let option3;
    var newArr = [{
        name: '线下常规培训',
        value: 55,
        itemStyle: {
            color: '#438ddf'
        }
    }, {
        name: '线上指导培训',
        value: 30,
        itemStyle: {
            color: '#6be397',
        }
    }, {
        name: '专业院校系统培训',
        value: 20,
        itemStyle: {
            color: '#e6e6e6'
        }
    }, {
        name: '托育员现场实践培训',
        value: 16,
        itemStyle: {
            color: '#f6ca6c'
        }
    },
    {
        name: '托育监管人员培训',
        value: 30,
        itemStyle: {
            color: '#8BE3FF'
        }
    }
    ];

    function 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;
            }
        };
    }
    // 生成模拟 3D 饼图的配置项
    function getPie3D(pieData, internalDiameterRatio) {

        let series = [];
        let sumValue = 0;
        let startValue = 0;
        let endValue = 0;
        let legendData = [];
        let k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3;

        // 为每一个饼图数据,生成一个 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
                }
            };

            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,也就是实现每一个扇形。
        for (let i = 0; i < series.length; i++) {
            endValue = startValue + 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;

            legendData.push(series[i].name);
        }
        // 准备待返回的配置项,把准备好的 legendData、series 传入。
        let option = {
            // animation: true,
            legend: [{
                orient: 'vertical',
                itemHeight: 5,
                // data: newArr.slice(2, 4),
                bottom: '17%',
                left: '10%',
                align: 'left',
                textStyle: {
                    color: "#2CD9FE",
                    fontSize: 12,
                },
                itemGap: 20
            },
            ],
            tooltip: {
                backgroundColor: 'RGBA(0, 49, 85, 1)',
                borderColor: 'rgba(0, 151, 251, 1)',
                borderWidth: 1,
                borderRadius: 0,
                textStyle: {
                    color: '#BCE9FC',
                    fontSize: 12,
                    align: 'left',
                },
                formatter: params => {
                    if (params.seriesName !== 'mouseoutSeries') {
                        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}`;
                    }
                }
            },
            xAxis3D: {
                min: -1,
                max: 1
            },
            yAxis3D: {
                min: -1,
                max: 1
            },
            zAxis3D: {
                min: -1,
                max: 1
            },
            grid3D: {
                show: false,
                boxHeight: 15,
                top: '5%',
                left: '18%',
                viewControl: {//3d效果可以放大、旋转等,请自己去查看官方配置
                    alpha: 40,
                    // beta: 40,
                    rotateSensitivity: 0,
                    zoomSensitivity: 0,
                    panSensitivity: 0,
                    autoRotate: false,
                    projection: 'perspective', // 先设置为这个perspective
                    distance: 200
                },
                //后处理特效可以为画面添加高光、景深、环境光遮蔽(SSAO)、调色等效果。可以让整个画面更富有质感。
                postEffect: {//配置这项会出现锯齿,请自己去查看官方配置有办法解决 
                    enable: true,
                    bloom: {
                        enable: true,
                        bloomIntensity: 0.1
                    },
                    SSAO: {
                        enable: true,
                        quality: 'medium',
                        radius: 2
                    }
                }
            },
            series: series,
        };
        return option;
    }

    function handleRender3DPie() {
        const echart3 = echarts.init(document.getElementById('echarts'));
        option3 = getPie3D(newArr, 0.59);
        echart3.clear()
        echart3.setOption(option3)
    }
    //调用
    handleRender3DPie()
相关推荐
m0_743106461 小时前
【论文笔记】MV-DUSt3R+:两秒重建一个3D场景
论文阅读·深度学习·计算机视觉·3d·几何学
m0_743106461 小时前
【论文笔记】TranSplat:深度refine的camera-required可泛化稀疏方法
论文阅读·深度学习·计算机视觉·3d·几何学
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me7 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架