echarts使用自定义图形实现3D柱状图

news2024/9/22 3:57:09

先看下效果吧

custom3dBar

实现思路

  1. 使用graphic创建并注册自定义图形。根据每组的数据值,得到一个对应的点,从点出发用canvas绘制一组图形,分别为
    顶部的菱形
    top
    const CubeTop = echarts.graphic.extendShape({
      buildPath: function (ctx, shape) {
         const c1 = [shape.x, shape.y]; // 下
         const c2 = [shape.x + 9, shape.y - 7]; // 右
         const c3 = [shape.x, shape.y - 12]; // 上
         const c4 = [shape.x - 9, shape.y - 7]; // 左
         ctx
            .moveTo(c1[0], c1[1])
            .lineTo(c2[0], c2[1])
            .lineTo(c3[0], c3[1])
            .lineTo(c4[0], c4[1])
            .closePath();
      }
    });
    
    左侧的四边形 left
    const CubeLeft = echarts.graphic.extendShape({
       buildPath: function (ctx, shape) {
          const xAxisPoint = shape.xAxisPoint;
          const c0 = [shape.x, shape.y]; // 右上
          const c1 = [shape.x - 9, shape.y - 7]; //左上
          const c2 = [xAxisPoint[0] - 9, xAxisPoint[1] - 6]; // 左下
          const c3 = [xAxisPoint[0], xAxisPoint[1]]; // 右下
          ctx
              .moveTo(c0[0], c0[1])
              .lineTo(c1[0], c1[1])
              .lineTo(c2[0], c2[1])
              .lineTo(c3[0], c3[1])
              .closePath();
       }
    });
    
    右侧的四边形
    right
    const CubeRight = echarts.graphic.extendShape({
       buildPath: function (ctx, shape) {
          const xAxisPoint = shape.xAxisPoint;
          const c1 = [shape.x, shape.y]; // 左上
          const c2 = [xAxisPoint[0], xAxisPoint[1]]; // 左下
          const c3 = [xAxisPoint[0] + 9, xAxisPoint[1] - 7]; //右下
          const c4 = [shape.x + 9, shape.y - 7]; // 右上
          ctx
              .moveTo(c1[0], c1[1])
              .lineTo(c2[0], c2[1])
              .lineTo(c3[0], c3[1])
              .lineTo(c4[0], c4[1])
              .closePath();
      }
    });
    
  2. 用series自定义系列(custom)的renderItem将这一组图形元素返回,组合形成3D柱状图

代码实现

<template>
    <div id="graphicBar"></div>
</template>

<script setup>
    import {reactive, onMounted} from 'vue'
    import * as echarts from "echarts";
    const barData = reactive({
        xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
        data: [200, 180, 120, 220, 80, 160, 150]
    })
    const customShape = () => {
        // 创建自定义的shape类型
        const CubeLeft = echarts.graphic.extendShape({
            buildPath: function (ctx, shape) {
                const xAxisPoint = shape.xAxisPoint;
                const c0 = [shape.x, shape.y]; // 右上
                const c1 = [shape.x - 9, shape.y - 7]; //左上
                const c2 = [xAxisPoint[0] - 9, xAxisPoint[1] - 6]; // 左下
                const c3 = [xAxisPoint[0], xAxisPoint[1]]; // 右下
                ctx
                    .moveTo(c0[0], c0[1])
                    .lineTo(c1[0], c1[1])
                    .lineTo(c2[0], c2[1])
                    .lineTo(c3[0], c3[1])
                    .closePath();
            }
        });
        const CubeRight = echarts.graphic.extendShape({
            buildPath: function (ctx, shape) {
                const xAxisPoint = shape.xAxisPoint;
                const c1 = [shape.x, shape.y]; // 左上
                const c2 = [xAxisPoint[0], xAxisPoint[1]]; // 左下
                const c3 = [xAxisPoint[0] + 9, xAxisPoint[1] - 7]; //右下
                const c4 = [shape.x + 9, shape.y - 7]; // 右上
                ctx
                    .moveTo(c1[0], c1[1])
                    .lineTo(c2[0], c2[1])
                    .lineTo(c3[0], c3[1])
                    .lineTo(c4[0], c4[1])
                    .closePath();
            }
        });
        const CubeTop = echarts.graphic.extendShape({
            buildPath: function (ctx, shape) {
                const c1 = [shape.x, shape.y]; // 下
                const c2 = [shape.x + 9, shape.y - 7]; // 右
                const c3 = [shape.x, shape.y - 12]; // 上
                const c4 = [shape.x - 9, shape.y - 7]; // 左
                ctx
                    .moveTo(c1[0], c1[1])
                    .lineTo(c2[0], c2[1])
                    .lineTo(c3[0], c3[1])
                    .lineTo(c4[0], c4[1])
                    .closePath();
            }
        });
        // 注册创建的自定义的shape类型
        echarts.graphic.registerShape('CubeLeft', CubeLeft);
        echarts.graphic.registerShape('CubeRight', CubeRight);
        echarts.graphic.registerShape('CubeTop', CubeTop);
    }
    const draw_bar = () => {
        customShape()
        const option = {
            xAxis: {
                data: barData.xAxis,
                axisLabel: {
                    fontSize: 12,
                    color: '#FFFFFF'
                },
                axisLine: {
                    lineStyle: {
                        color: '#3A4547',
                    }
                },
                axisTick: {
                    show: false
                }
            },
            yAxis: {
                type: 'value',
                axisLabel: {
                    fontSize: 12,
                    color: '#A8B5C1'
                },
                splitLine: {
                    lineStyle: {
                        color: ['#303638'],
                        type: 'dashed'
                    }
                }
            },
            grid: {
                containLabel: true,
                top: 10,
                bottom: 0,
                right: 0,
                left: 0
            },
            series: [        
                {
                    type: 'custom',
                    renderItem: (params, api) => {
                        // coord 将数据值映射到坐标系上
                        // api.value 给定维度的数据值
                        const location = api.coord([api.value(0), api.value(1)]);
                        return {
                            type: 'group',
                            children: [
                                {
                                    type: 'CubeLeft',
                                    shape: {
                                        api,
                                        x: location[0], // 图形元素的右上角在父节点坐标系中的横坐标值
                                        y: location[1], // 图形元素的右上角在父节点坐标系中的纵坐标值
                                        xAxisPoint: api.coord([api.value(0), 0]) // 图形元素的右下角在父节点坐标系中的坐标值
                                    },
                                    style: {
                                        // 渐变色填充
                                        fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                            {
                                                offset: 0,
                                                color: 'rgba(35, 153, 254, 1)'
                                            },
                                            {
                                                offset: 1,
                                                color: 'rgba(70, 207, 255, 1)'
                                            },
                                        ])
                                    }
                                },
                                {
                                    type: 'CubeRight',
                                    shape: {
                                        api,
                                        x: location[0], // 中间上的x
                                        y: location[1], // 中间上的y
                                        xAxisPoint: api.coord([api.value(0), 0]) // 中间下
                                    },
                                    style: {
                                        fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                            {
                                                offset: 0,
                                                color: 'rgba(32, 147, 255, 1)'
                                            },
                                            {
                                                offset: 1,
                                                color: 'rgba(71, 237, 255, 1)'
                                            },
                                        ])
                                    }
                                },
                                {
                                    type: 'CubeTop',
                                    shape: {
                                        api,
                                        x: location[0],
                                        y: location[1],
                                    },
                                    style: {
                                        fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                            {
                                                offset: 0,
                                                color: 'rgba(107, 230, 254, 1)'
                                            },
                                            {
                                                offset: 1,
                                                color: 'rgba(48, 211, 255, 1)'
                                            }
                                        ])
                                    }
                                }
                            ]
                        };
                    },
                    data: barData.data
                }
            ]
        };
        return option
    }
    const chart_init = () => {
        let curChart = echarts.init(document.getElementById('graphicBar'))
        const exampleOption = draw_bar()
        curChart.setOption(exampleOption);
    }
    onMounted(() => {
        chart_init()
    })
</script>

<style scoped>
    #graphicBar{
        width: 460px;
        height: 300px;
    }
</style>

补充说明

  1. 以上内容是vite构建的vue3项目
  2. echarts版本5.5.1

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

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

相关文章

【ComfyUI的API接口调用示例】

ComfyUI的API接口调用示例 本文目的 本文调用接口示例主要指导需要调用ComfyUI的开发者如何调用ComfyUI官方的API接口提交任务、查询历史、获取绘画视频结果等。 阅读本文的前提是你本地已经安装了ComfyUI&#xff0c;并且对工作流绘画和生成视频已经有所了解。注意如图右边栏…

印刷企业如何判断数字工厂管理系统的实施周期

在数字化转型的浪潮中&#xff0c;印刷企业正积极拥抱新技术以提升生产效率、优化成本结构并增强市场竞争力。数字工厂管理系统的引入&#xff0c;作为这一转型的关键步骤&#xff0c;不仅能够实现生产流程的自动化、智能化监控&#xff0c;还能显著提升数据分析能力和决策效率…

VScode 格式化插件Prettier设置无效

VScode在配置格式化代码的插件的时候&#xff0c;可以选择Prettier或者ESlint等插件 比如选择Prettier格式化代码 在某文件修改代码之后&#xff0c;ctrls 保存代码&#xff0c;保存之后会自动格式化代码&#xff0c;但是我们发现控制台有报错 为什么已经设置了格式化插件为Pr…

软考《信息系统运行管理员》-3.2信息系统设施运维的环境管理

3.2信息系统设施运维的环境管理 1 计算机机房的选址要求 电子计算机机房地理位置 选择水源充足&#xff0c;电子比较稳定可靠&#xff0c;交通通信方便&#xff0c;自然环境清洁的地点要远离产生粉尘、油烟、有害气体以及生产或存储具有腐蚀性、易燃、易爆物品的工厂、仓库、…

Vue+SpringBoot实现仿网盘项目

目录 一、效果展示 二、前端代码 三、后端代码及核心解释 四、进阶开发与思路 一、效果展示 1.1读取文件夹内的文件 1.2删除功能 1.3 上传文件 1.4 文件下载 对应的网盘实际地址与对应下载内容&#xff1a; 二、前端代码 2.1 创建vue项目&#xff08;需要有vuex与router&…

【C++】类和对象--类,实例化,this指针

文章目录 前言一、类1.1 类的定义1.2 类的书写和使用1.3 访问限定符1.4 类域 二、实例化2.1 实例化概念2.2 对象大小 三.this指针总结 前言 前面的几篇文章我们介绍了命名空间&#xff0c;inline&#xff0c;nullptr等C 中常见的的基础概念。今天的文章我们来介绍一些C中类与对…

一款24小时实时检测的六氟化硫气体泄漏报警系统

尽管当前工业生产模式越来越趋于自动化、智能化&#xff0c;但安全生产仍然是时下屡被提及的话题。在配电室等使用六氟化硫气体的众多领域中&#xff0c;由于气体泄漏而引发的中毒、火灾、爆炸、窒息事故仍高发频发。因此&#xff0c;安装六氟化硫气体泄漏报警监测系统仍是企业…

使用PEFT库进行ChatGLM3-6B模型的QLORA高效微调

PEFT库进行ChatGLM3-6B模型QLORA高效微调 QLORA微调ChatGLM3-6B模型安装相关库使用ChatGLM3-6B模型GPU显存占用准备数据集加载数据集数据处理数据集处理加载量化模型-4bit预处理量化模型配置LoRA适配器训练超参数配置开始训练保存LoRA模型模型推理合并模型使用微调后的模型 QLO…

UE5 本地化多语言方案

导入插件&#xff1a; https://www.unrealengine.com/marketplace/zh-CN/product/07e1d9bd9ced444c9b2a7e232161f74d​www.unrealengine.com/marketplace/zh-CN/product/07e1d9bd9ced444c9b2a7e232161f74d 打开测试关卡 打开插件下图目录&#xff0c;csv文件可以添加多个&…

MD5加密和注册页面的编写

MD5加密 1.导入包 npm install --save ts-md5 2.使用方式 import { Md5 } from ts-md5; //md5加密后的密码 const md5PwdMd5.hashStr("123456").toUpperCase(); 遇见的问题及用到的技术 注册页面 register.vue代码 <template><div class"wappe…

模型评估、交叉验证

目录 一、模型评估&#xff1a;二、交叉验证&#xff1a; 一、模型评估&#xff1a; 模型评估用来检验模型的预测精度。 首先数据集分为训练集和测试集两部分&#xff0c;使用训练集进行模型的训练&#xff0c;使用测试集进行模型的评估。 注意&#xff0c;模型评估阶段应该…

A股强反之后继续下单,难道是主力再使障眼法?

今天的A股太不对劲了&#xff0c;主力再使障眼法&#xff0c;很多散户都被成功迷惑&#xff0c;市场有望出现芙蓉出水&#xff0c;不废话&#xff0c;直奔主题&#xff1a; 1、今天两市低开再次探底&#xff0c;太不对劲了&#xff0c;昨天主力大幅流入&#xff0c;今天又跑了…

IT入门知识第十部分《IT职业发展》(10/10)

IT职业发展的深度解析&#xff1a;技能、路径与规划 在当今这个快速发展的数字化时代&#xff0c;IT行业不仅是技术革新的前沿阵地&#xff0c;也是职业发展和个人成长的沃土。本文将深入探讨IT行业的职业发展&#xff0c;包括职业路径的选择、技能提升的策略、以及职业规划的…

FastAPI 学习之路(三十七)元数据和文档 URL

实现前的效果 那么如何实现呢&#xff0c;第一种方式如下&#xff1a; from routers.items import item_router from routers.users import user_router""" 自定义FastApi应用中的元数据配置Title&#xff1a;在 OpenAPI 和自动 API 文档用户界面中作为 API 的…

迅为3A5000LoongArch架构核心主板支持国产麒麟、统信、以及实时系统翼辉SylixOS

性能强 采用全国产龙芯3A5000处理器&#xff0c;基于龙芯自主指令系统 (LoongArch)的LA464微结构&#xff0c;并进一步提升频率&#xff0c;降低功耗&#xff0c;优化性能。 桥片 采用龙芯 7A2000&#xff0c;支持PCIE 3.0、USB 3.0和 SATA 3.0.显示接口2 路、HDMI 和1路 VGA&a…

昆法尔The Quinfall在Steam上怎么搜索 Steam上叫什么名字

昆法尔The Quinfall是一款全新的MMORPG&#xff0c;在中世纪的深处&#xff0c;参与独特的战斗和沉浸式的故事&#xff0c;有几十个不同的职业。而游戏中的战斗系统更是丰富多彩&#xff0c;无论是陆地激战、海上鏖战还是城堡围攻&#xff0c;都能让玩家感受到前所未有的刺激和…

pytorch实现水果2分类(蓝莓,苹果)

1.数据集的路径&#xff0c;结构 dataset.py 目的&#xff1a; 输入&#xff1a;没有输入&#xff0c;路径是写死了的。 输出&#xff1a;返回的是一个对象&#xff0c;里面有self.data。self.data是一个列表&#xff0c;里面是&#xff08;图片路径.jpg&#xff0c;标签&…

如何分辨AI生成的内容?AI生成内容检测工具对比实验

检测人工智能生成的文本对各个领域的组织都提出了挑战&#xff0c;包括学术界和新闻界等。生成式AI与大语言模型根据短描述来进行内容生成的能力&#xff0c;产生了一个问题&#xff1a;这篇文章/内容/作业/图像到底是由人类创作的&#xff0c;还是AI创作的&#xff1f;虽然 LL…

【数据库】Redis主从复制、哨兵模式、集群

目录 一、Redis的主从复制 1.1 主从复制的架构 1.2 主从复制的作用 1.3 注意事项 1.4 主从复制用到的命令 1.5 主从复制流程 1.6 主从复制实现 1.7 结束主从复制 1.8 主从复制优化配置 二、哨兵模式 2.1 哨兵模式原理 2.2 哨兵的三个定时任务 2.3 哨兵的结构 2.4 哨…

MT3047 区间最大值

思路&#xff1a; 使用哈希表map和set&#xff08;去重&#xff09;维护序列 代码&#xff1a; #include <bits/stdc.h> using namespace std; const int N 1e5 10; int n, k, A[N]; map<int, int> mp; // 元素出现的次数 set<int> s; // 维护出现…