vue3之echarts3D环柱图-间隔版

news2024/9/24 13:25:07
vue3之echarts3D环柱图-间隔版

效果:
在这里插入图片描述

版本
"echarts": "^5.4.1", "echarts-gl": "^2.0.9"

核心代码:

<template>
    <div class="content">
        <div ref="eCharts" class="chart"></div>
        <div ref="eCharts2" class="chart"></div>
    </div>
</template>

<script setup>
import { onMounted, ref } from "vue";
import * as echarts from "echarts";
import "echarts-gl";

const eCharts = ref(null);
let myChart = null;
const eCharts2 = ref(null);
let myChart2 = null;

let boxHeight;
let optionData = ref([
    {
        name: "已核销",
        value: 10000,
        itemStyle: {
            color: "rgba(91, 149, 255, 1)",
        },
        isShow: true
    },
    {
        name: "未核销",
        value: 12116,
        itemStyle: {
            color: "transportant",
        },
        isShow: false
    },
]);
let optionData2 = ref([
    {
        name: "已核销",
        value: 10000,
        itemStyle: {
            color: "transportant",
        },
        isShow: false
    },
    {
        name: "未核销",
        value: 12116,
        itemStyle: {
            color: "rgba(66, 250, 251, 1)",
        },
        isShow: true
    },
]);

onMounted(() => {
    initCharts(myChart, eCharts.value, optionData.value, 0);
    initCharts(myChart2, eCharts2.value, optionData2.value, '-4%');
});

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 * 0.1;
            }
            return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
        },
    };
};

const getPie3D = (pieData, internalDiameterRatio) => {
    // internalDiameterRatio:透明的空心占比
    let series = [];
    let sumValue = 0;
    let startValue = 0;
    let endValue = 0;

    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,
            },
            center: ["10%", "50%"],
        };

        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 // 控制各模块高度一致100   控制各模块高度根据value改变
        );
        startValue = endValue;
    }
    boxHeight = getHeight3D(series, 15); //通过传参设定3d饼/环的高度,26代表26PX
    return series;
};

const getHeight3D = (series, height) => {
    series.sort((a, b) => {
        return b.pieData.value - a.pieData.value;
    });
    return (height * 8) / series[0].pieData.value;
};

const initCharts = (chart, chartContainer, optionData, top) => {
    chart = echarts.init(chartContainer);
    const series = getPie3D(optionData, 0.8);
    series.push({
        name: "pie2d",
        type: "pie",
        label: {
            opacity: 1,
            fontSize: 12,
            lineHeight: 12,
        },
        labelLine: {
            length: 10,
            length2: 40,
        },
        startAngle: -40, // 起始角度,支持范围[0, 360]。
        clockwise: false, // 饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
        radius: ["10%", "52%"],
        center: ["50%", "50%"],
        data: optionData,
        itemStyle: {
            opacity: 0,
        },
    });
    optionData.forEach((item, index) => {
        item.label = {
            color: item.itemStyle.color,
            show: item.isShow,
            formatter: (item) => {
                return `{b|${item.name} }`;
            },
            rich: {
                b: {
                    fontSize: 12,
                    lineHeight: 20,
                },
                c: {
                    color: "#fff",
                    fontSize: 12,
                },
            },
        };
    });

    let option = {
        xAxis3D: {
            min: -1,
            max: 1,
        },
        yAxis3D: {
            min: -1,
            max: 1,
        },
        zAxis3D: {
            min: -1,
            max: 1,
        },
        grid3D: {
            show: false,
            top, //距离上边的间距
            boxHeight, //圆环的高度
            viewControl: {
                //3d效果可以放大、旋转等,请自己去查看官方配置
                alpha: 32, //角度
                distance: 220, //调整视角到主体的距离,类似调整zoom
                rotateSensitivity: 0, //设置为0无法旋转
                zoomSensitivity: 0, //设置为0无法缩放
                panSensitivity: 0, //设置为0无法平移
                autoRotate: false, //自动旋转
            },
        },
        series,
    };
    chart?.setOption(option);
};

</script>
<style lang="scss" scoped>
.content {
    position: relative;

    .chart {
        position: absolute;
        top: -28px;
        left: -15px;
        width: 434px;
        height: 300px;
    }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享4款不能错过的修改照片尺寸的软件!

在当今这个数字化时代&#xff0c;照片已经成为我们分享生活、表达观点的重要方式。但是&#xff0c;你是否曾遇到过这样的问题&#xff1a;一张精美的照片因为尺寸不合适而无法在朋友圈中展现出最佳效果&#xff1f;不用担心&#xff0c;今天我们就来聊聊那些可以帮助你轻松修…

Day02-课后练习2-参考答案(数据类型和运算符)

文章目录 巩固题1、案例&#xff1a;今天是周2&#xff0c;100天以后是周几&#xff1f;2、案例&#xff1a;求三个整数x,y,z中的最大值3、案例&#xff1a;判断今年是否是闰年4、分析如下代码的计算结果5、分析如下代码的计算结果6、分析如下代码的计算结果7、分析如下代码的计…

Real power also called true or active power

Real power also called true or active power flyfish 三相电路的总功率都等于各相功率之和&#xff0c;任意相的有功功率等于该相的相电压乘以相电流&#xff0c;再乘以该相负载的功率因数。 P P A P B P C PP_AP_BP_C PPA​PB​PC​ P有功功率&#xff0c;瓦特(W) U电压…

Springboot 实现基于用户和物品的协同过滤算法

目录 简介 协同过滤算法(简称CF) 算法详解 算法使用 基于用户 基于物品 总结 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡&#xff0c;忘记了停…

简单线性Dp

文章目录 线性Dp的定义AcWing 898. 数字三角形思路CODE正序倒序 AcWing 895. 最长上升子序列Dp 分析CODE AcWing 897. 最长公共子序列Dp 分析CODE 线性Dp的定义 处理起来是线性的&#xff08;&#xff1f;&#xff1f;&#xff1f;&#xff09;&#xff0c;这部分交给ai老先生…

Gurobi输出日志文件的解读【Gurobi】

本章来解读一下Gurobi的刷屏式输出&#xff0c;根本不需要cout&#xff0c;直接通过model.optimize();进行输出。 例如&#xff1a; 现在我们来逐行解读一下&#xff1a; 第一部分&#xff1a;版本型号 可以直接跳过 CPU model: 12th Gen Intel(R) Core(TM) i5-12500H, instr…

【EI会议征稿通知】第五届计算机信息和大数据应用国际学术会议(CIBDA 2024)

第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09; 2024 5th International Conference on Computer Information and Big Data Applications 第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09;将于2024年3月22-24日在…

Google Chrome 中出现 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误

证书的方式发生了变化&#xff0c;出现了这个新错误&#xff0c;导致我无法浏览该网站。 可以右键属性获取位置 关闭导航器chrome并转到文件夹&#xff0c;找到Local State文件并删除 执行指令结束进程&#xff0c;重新打开浏览器即可 taskkill /im "chrome.exe"…

基于C#制作一个俄罗斯方块小游戏

目录 引言游戏背景介绍游戏规则游戏设计与实现开发环境与工具游戏界面设计游戏逻辑实现游戏优化和测试性能优化测试工具和流程说明引言 俄罗斯方块是一款经典的益智游戏,深受玩家喜爱。本文将介绍如何使用C#编程语言制作一个简单的俄罗斯方块小游戏,并探讨其设计与实现过程。…

TOFU: A Two-Step Floorplan Refinement Framework for Whitespace Reduction

TOFU: A Two-Step Floorplan Refinement Framework for Whitespace Reduction 目录 摘要一、简介二、准备工作2.1 布局规划2.2 基于约束图的合法化 3 提出的算法A 概况B 平面图合法化1&#xff09;约束图构造&#xff1a; C 两步空白删除框架1.基于位置的模块2. 基于区域重新分…

利用二分法及不动点迭代求解非线性方程(MatLab)

一、问题描述 利用二分法及不动点迭代求解非线性方程。 二、实验目的 掌握二分法及不动点迭代的算法原理&#xff1b;能分析两种方法的收敛性&#xff1b;能熟练编写代码实现利用二分法及不动点迭代来求解非线性方程。 三、实验内容及要求 二分法 (1) 编写代码计算下列数字…

华为配置小型网络WLAN 的基本业务示例

配置小型网络WLAN基本业务示例 组网图形 图1 配置小型网络WLAN基本业务组网图 小型WLAN网络简介配置注意事项组网需求数据规划配置思路操作步骤配置文件 小型WLAN网络简介 本文介绍的WLAN网络是指利用频率为2.4GHz或5GHz的射频信号作为传输介质的无线局域网&#xff0c;相对于有…

Vue-43、Vue中组件自定义事件

1、给学生绑定atguigu事件 2、在组件内触发事件 第二种写法 传多个参数。 解绑 解绑一个事件 解绑多个自定义事件 this.$off([xxx1,xxx2]);解绑所有事件 this.$off();总结

一文速学-selenium高阶操作连接已存在浏览器

前言 不得不说selenium不仅在自动化测试作为不可或缺的工具&#xff0c;在数据获取方面也是十分好用&#xff0c;能够十分快速的见到效果&#xff0c;这都取决于selenium框架的足够的灵活性&#xff0c;甚至在一些基于web端的自动化办公都十分有效。 通过selenium连接已经存在…

【活动回顾】CMeet 成都:转鸿蒙 对应用开发来说是否是职业发展新机会 - 圆满结束!

文章目录 前言一、活动介绍二、精彩分享内容及活动议程2.1、《COC 成都社区情况和活动介绍》2.2、“匿”问我答&#xff0c;现场互动2.3、《话题一&#xff1a;升职加薪》2.4、《话题二&#xff1a;说说鸿蒙》2.5、2023 CSDN 1024 程序员节成都站贡献人物表彰2.6、《话题三&…

谁说后端不能画出美丽的动图?让我来给大家拜个年!

今天我们要介绍的是Python的内置库——小海龟&#xff08;turtle&#xff09;&#xff0c;它是一个非常实用的绘画工具&#xff0c;不仅可以帮助我们绘制图形&#xff0c;还能让我们查看整个绘画过程。即使对绘画一窍不通的人也能够使用它来创作出生动、形象的gif动图。现在正是…

AIGC项目——Meta:根据对话音频生成带动作和手势的3d逼真数字人

From Audio to Photoreal Embodiment: Synthesizing Humans in Conversations From Audio to Photoreal Embodiment:Synthesizing Humans in Conversations 从二元对话的音频中&#xff0c;我们生成相应的逼真的面部、身体和手势。 概括性:角色是由作者的声音驱动的(而不是模…

【获奖必看2.0】美赛小技巧之一秒输入一个公式

大家好呀&#xff0c;美赛开赛还有四天的时间&#xff0c;今天给大家带来的是美赛论文写作时非常实用的一个小技巧——快速输入任何复杂公式。 相信很多小伙伴在论文写作的时候都有一个小烦恼&#xff0c;那就是在面对比较复杂的公式的时候&#xff0c;应该怎么进行快速输入呢…

12.2 关键点提取——SIFT

一、理论 文章看了以下博文&#xff1a;Sift中尺度空间、高斯金字塔、差分金字塔&#xff08;DOG金字塔&#xff09;、图像金字塔-CSDN博客 该文章对SIFT写的很详细&#xff0c;所以在这里我直接抄过来作为笔记。如果以后作者变为付费文章可以提醒我删除。 1.图像金字塔 图像…

酒店|酒店管理小程序|基于微信小程序的酒店管理系统设计与实现(源码+数据库+文档)

酒店管理小程序目录 目录 基于微信小程序的酒店管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 (1) 用户信息管理 (2) 酒店管理员管理 (3) 房间信息管理 2、小程序序会员模块的实现 &#xff08;1&#xff09;系统首页 &#xff0…