vue3+ts项目中封装3d单柱柱状图

news2024/11/16 11:43:55

vue3+ts项目中封装单柱的柱状图

成品图

 下载echarts npm i echarts

封装组件为Barchart.vue文件 

<template>
</template>

<script setup lang="ts">
import { nextTick, watch } from 'vue'
import echarts from '@/assets/ts/echarts';
import useResizeChart from '@/hooks/useResizeChart';
import { CustomChart } from 'echarts/charts';
// import { LegendComponent } from 'echarts/components';
// import { LegendComponent } from 'echarts/types/dist/components';
echarts.use([ CustomChart]);
//合并配置项
function mergeConfig(defaultConfig: object, config: object) {
    return Object.assign(defaultConfig, config);
}
  //向外接收
  const props = defineProps({
    pid: {
        type: String,
        required: true,
    },
    title: {
        type: Object,
        default: {},
    },
    xAxisData: {
        type: Array,
        required: true,
    },
    legend: {
        type: Object,
        default: {},
    },
    grid: {
        type: Object,
        default: {},
    },
    XAxisLine: {
        type: Object,
        default: {},
    },
    YAxisLine: {
        type: Object,
        default: {},
    },
    yUnit: {
        type: String,
        default: '',
    },
    XSplitLine: {
        type: Object,
        default: {},
    },
    YSplitLine: {
        type: Object,
        default: {},
    },
    XAxisTick: {
        type: Object,
        default: {},
    },
    YAxisTick: {
        type: Object,
        default: {},
    },
    config: {
        type: Object as () => echarts.EChartsCoreOption,
        default: {},
    },
    value: {
        type: Array,
        required: true,
    },
    // 柱子的颜色
    color: {
        type: Array,
        default: ['rgba(29, 230, 235,1)', 'rgba(7, 235, 251,1)'],
    },
});
function initOption(): echarts.EChartsCoreOption {
   
    // 绘制左侧面
    const CubeLeft = echarts.graphic.extendShape({
        shape: {
            x: 0,
            y: 0,
        },
        buildPath: function (ctx, shape) {
            // 会canvas的应该都能看得懂,shape是从custom传入的
            const xAxisPoint = shape.xAxisPoint;
            const c0 = [shape.x + 3.5, shape.y];
            const c1 = [shape.x - 11.5, shape.y - 3];
            const c2 = [xAxisPoint[0] - 11.5, xAxisPoint[1] - 6.5];
            const c3 = [xAxisPoint[0] + 3.5, xAxisPoint[1]];
            ctx.moveTo(c0[0], c0[1])
                // @ts-ignore

                .lineTo(c1[0], c1[1])
                .lineTo(c2[0], c2[1])
                .lineTo(c3[0], c3[1])
                .closePath();
        },
    });
    // 绘制右侧面
    const CubeRight = echarts.graphic.extendShape({
        shape: {
            x: 0,
            y: 0,
        },
        buildPath: function (ctx, shape) {
            const xAxisPoint = shape.xAxisPoint;
            const c1 = [shape.x + 3, shape.y];
            const c2 = [xAxisPoint[0] + 3, xAxisPoint[1]];
            const c3 = [xAxisPoint[0] + 12, xAxisPoint[1] - 7];
            const c4 = [shape.x + 12, shape.y - 7];

            ctx.moveTo(c1[0], c1[1])
                // @ts-ignore

                .lineTo(c2[0], c2[1])
                .lineTo(c3[0], c3[1])
                .lineTo(c4[0], c4[1])
                .closePath();
        },
    });
    // 绘制顶面
    const CubeTop = echarts.graphic.extendShape({
        shape: {
            x: 0,
            y: 0,
        },
        buildPath: function (ctx, shape) {
            const c1 = [shape.x + 3.5, shape.y];
            const c2 = [shape.x + 12.5, shape.y - 7.5]; //右点
            const c3 = [shape.x - 2.5, shape.y - 10];
            const c4 = [shape.x - 11.5, shape.y - 3];

            ctx.moveTo(c1[0], c1[1])
                // @ts-ignore

                .lineTo(c2[0], c2[1])
                .lineTo(c3[0], c3[1])
                .lineTo(c4[0], c4[1])
                .closePath();
        },
    });
    // 注册三个面图形
    echarts.graphic.registerShape('CubeLeft', CubeLeft);
    echarts.graphic.registerShape('CubeRight', CubeRight);
    echarts.graphic.registerShape('CubeTop', CubeTop);
  
//接收x轴值
    const VALUE = props.value;
     const series =[
        //自带顶部数值样式
        {
            type: 'bar',
            label: {
                show: true,
                position: 'top',
                fontSize: 14,
                color: props.color[0],
                offset: [2, -10],
            },
            itemStyle: {
                color: 'transparent',
            },
            tooltip: {},
            data: VALUE,
        },
        {
            type: 'custom',
            renderItem: (params:any, api:any) => {
                const location = api.coord([api.value(0), api.value(1)]);
                //定义三个面,每个面颜色
                let cubeLeftStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                        offset: 0,
                        // @ts-ignore
                        color: props.color[0],
                    },
                    {
                        offset: 1,
                        color: 'rgba(7, 20, 52,0.7)',
                    },
                ]);
                let cubeRightStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                        offset: 0,
                        color: 'rgba(7, 20, 52,1)',
                    },
                    {
                        offset: 1,
                        // @ts-ignore

                        color: props.color[0],
                    },
                ]);
                let cubeTopStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                        offset: 0,
                        // @ts-ignore
                        color: props.color[1] || props.color[0],
                    },
                ]);

                return {
                    type: 'group',
                    /*(2)根据数据转换成坐标系中的坐标点
			api.coord([x,y])
             */
                    children: [
                        {
                            //左平面样式
                            type: 'CubeLeft',
                            shape: {
                                api,
                                xValue: api.value(0),
                                yValue: api.value(1),
                                x: location[0],
                                y: location[1],
                                //此处表示左侧面的面的长度
                                xAxisPoint: api.coord([api.value(0), 0]),
                            },
                            style: {
                                fill:cubeLeftStyle
                            },
                        },
                        {
                            // 右平面
                            type: 'CubeRight',
                            shape: {
                                api,
                                xValue: api.value(0),
                                yValue: api.value(1),
                                x: location[0],
                                y: location[1],
                                xAxisPoint: api.coord([api.value(0), 0]),
                            },
                            style: {
                                fill:cubeRightStyle
                            },
                        },
                        {
                            // 上平面
                            type: 'CubeTop',
                            shape: {
                                api,
                                xValue: api.value(0),
                                yValue: api.value(1),
                                x: location[0],
                                y: location[1],
                                xAxisPoint: api.coord([api.value(0), api.value(1)]),
                            },
                            style: {
                                fill: cubeTopStyle
                            },
                        },
                    ],
                };
            },
            // color: 'blue',
            data: VALUE,
        },
     ]
    //标题样式
    const title = mergeConfig({
        show: true,
        text: '',
        left: 'center',
        textStyle: {
            color: "#333",
            fontSize: 20
        },
    }, props.title);

 //x轴字体样式
    const XAxisLine = mergeConfig({
        show: true,
        lineStyle: {
            color: "#333",
            type: 'solid',
            width: 1
        },
    }, props.XAxisLine);

    const YAxisLine = mergeConfig({
        show: false,
        lineStyle: {
            show: true,
            lineStyle: {
                color: "#fff",
                type: 'solid',
                width: 1
            },
        },
    }, props.YAxisLine);

    //x轴刻度线
    const XSplitLine = mergeConfig({
        show: false,
        lineStyle: {
            color: "#333",
            type: 'dotted',
            width: 1
        },
    }, props.XSplitLine);
  //y轴刻度线
    const YSplitLine = mergeConfig({
        show: true,
        lineStyle: {
            color: "#ECECEC",
            type: 'dashed',
            width: 1
        },
    }, props.YSplitLine);

    const XAxisTick = mergeConfig({
        show: false,
        length: 5,
        inside: true,
        alignWithLabel: true,
        lineStyle: {
            color: "#333",
            type: 'solid',
            width: 1
        },
    }, props.XAxisTick);

    const YAxisTick = mergeConfig({
        show: false,
        length: 5,
        inside: true,
        alignWithLabel: true,
        lineStyle: {
            color: "#333",
            type: 'solid',
            width: 1
        },
    }, props.YAxisTick);


    const legend = mergeConfig({
        show: true,
        left: "center",
        top: "90%",
        icon: 'rect'
    }, props.legend)
  
    const grid = mergeConfig(
        {
            left: '5%',
            right: '5%',
            top: '12%',
            bottom: '0%',
            containLabel: true,
        },
        props.grid,
    );

    let option: echarts.EChartsCoreOption = {
        title,
        // grid: {
        //     top: '10%',
        //     left: '5%',
        //     bottom: '15%',
        //     right: '0%',
        // },
        tooltip: {
            trigger: "axis",
            //阴影提示器
            axisPointer: {
                type: 'shadow',
               shadowStyle:{
                shadowColor:'#2e3e51' //阴影颜色
               }
            },
            //显示提示器内数据
            formatter:function(params){
             const item=params[1]
             return item.name + ' : ' + item.value;
            },
            // 提示框背景颜色
            backgroundColor: '#122843',
            // 提示框边框颜色
            borderColor: '#42D1F1',
            // 提示框文本样式
            textStyle: {
                color: '#fff',
            },
        },
        legend:legend,
        grid:grid,
        xAxis: {
            type: 'category',
            // boundaryGap: false,
            data: props.xAxisData,
            axisLine: XAxisLine,
            splitLine: XSplitLine,
            axisTick: XAxisTick,
            axisLabel: {
                //x轴文字的配置
                show: true,
                color: '#fff',
                fontSize: 12,
                rotate: 30,
            },
        },
        yAxis: {
            type: 'value',
            name: props.yUnit,
            nameTextStyle: {
                color: '#fff',
                fontSize: 16,
            },
            axisLine: YAxisLine,
            splitLine: YSplitLine,
            axisTick: YAxisTick,
            axisLabel: {
                //y轴文字的配置
                color: '#fff',
                fontSize: 12,
            },
        },
        
        series
    };
    option = Object.assign(option, props.config);
    return option;
}


//通用 初始化 option
let option = initOption();

let container: HTMLElement | null = null;
let myChart: echarts.ECharts | null = null;

const renderChart = (notMerge: boolean = false) => {
    if (!myChart) myChart = echarts.init(container as HTMLElement);
    myChart.setOption(option, {
        notMerge,
    });
};
//更新视图
nextTick(() => {
    container = document.querySelector('#' + props.pid) as HTMLElement;
    renderChart();
    useResizeChart(container, myChart as echarts.ECharts);
});

//开启监听,监听变化
watch(
    //监听props变化进行动态更新数据
    ()=>props,
    (newVal,oldVal)=>{
        // 开启
        let notMerge = true;
        option = initOption();
        renderChart(notMerge);
    }
)
//导出图片功能
// function exportImg() {
//     const src = (myChart as echarts.ECharts).getDataURL({
//         pixelRatio: 2,
//         backgroundColor: '#08172A'
//     });
//     const a = document.createElement('a');
//     a.href = src;
//     a.download = (option.title as { text: string }).text || "chart-img";
//     a.click();
// }

// defineExpose({
//     exportImg
// });
</script>

<style lang="scss" scoped>
</style>

使用组件

<template>
 <div id="CO-info" >
    <BarThreeCharts pid="CO-info" :value="COValue" :xAxisData="tunnelList"></BarThreeCharts>
  </div>
</template>


<script setup lang="ts">
const COValue = [12, 23, 13, 46, 53, 26, 17, 8, 19, 23, 14, 33, 42];
const tunnelList = ['苍龙峡', '云雾山', '白鹿塬', '铜钱峡', '堡子村', '北辰公园', '双沟桥', '新桥村1#', '新桥村2#', '农光村', '元岭村', '石磨村', '白家崖'];

</script>
<style lang="scss" scoped>
 #CO-info {
            width: 100%;
            height: vh(265);
            }
</style >

3d柱状图要注意创建左切面,右切面和上切面 三种颜色形成3d柱状效果 

切换 

 推荐vue3封装echarts博客地址 https://www.jb51.net/article/267642.htm

 import useResizeChart from '@/hooks/useResizeChart';

useResizeChart.ts文件

// 用于自适应 echarts 图表大小
import echarts from "@/assets/ts/echarts";
export default function useResizeChart(container: HTMLElement, chart: echarts.ECharts) {

    // 监听容器大小变化
    const resizeObserver = new ResizeObserver(entries => {
        // 重新设置大小
        chart.resize({
            animation: {
                duration: 500
            }
        });
    });

    resizeObserver.observe(container);

    // onBeforeUnmount(() => {
    // 	// 销毁前解除监听
    // 	resizeObserver.unobserve(container);
    // })

}

知识点补充  

api.coord

api.coord(...),意思是进行坐标转换计算。例如 var point = api.coord([api.value(0), api.value(1)]) 表示 dataItem 中的数值转换成坐标系上的点.

Object.assign(target,..sources)

参数;taget ==>目标对象    source==>源对象

返回值:target,即目标对象

例:

var target={name:'guxin',age:18}
var source={state:'signle',age:22}
var result=Object.assign(target,source)
console.log(target)

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

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

相关文章

[附源码]计算机毕业设计在线项目管理Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

十三、Vue CLI(2)

本章概要 项目结构编写一个 Hello 组件package.json 13.4 项目结构 通过 Vue CLI 生成的项目的目录结构及各文件夹和文件的用途说明如下&#xff1a; |--node_modules //项目依赖的模块 |--public //该目录下的文件不会被 Webpack 编译压缩处理&…

Springboot社区疫情防控系统毕业设计,社区疫情防控管理系统设计与实现,毕设作品参考

功能清单 【后台管理员功能】 关于我们设置&#xff1a;设置学校简介、联系我们、加入我们、法律声明、学校详情 广告管理&#xff1a;设置小程序首页轮播图广告和链接 留言列表&#xff1a;所有用户留言信息列表&#xff0c;支持删除 会员列表&#xff1a;查看所有注册会员信…

【树莓派开发日记2 】树莓派安装Ubuntu22系统及启动黑屏等问题的踩坑记录

树莓派安装Ubuntu22系统及启动黑屏等问题的踩坑记录 在成功进行了组装后&#xff0c;就到了最为关键的部分了&#xff0c;进行树莓派的系统烧录。虽然树莓派有自己对应的系统&#xff0c;raspbian&#xff0c;但是绝大部分的开发者还是会选择Ubuntu系统作为主要的开发系统 Ub…

软件架构模式

如果有兴趣了解更多相关内容&#xff0c;欢迎来我的个人网站看看&#xff1a;瞳孔空间 创建软件系统基本结构的原则称为软件体系结构。软件结构由软件元素及其相互关系组成&#xff0c;这些元素起着蓝图的作用&#xff0c;规划了要执行的任务的模式。软件设计团队极大地依赖于…

【java】2-串行与并发分别将计数器从1累加到10亿

串行、并行、并发 串行是100个人的队伍从一条通道里顺序通行 并行是100个人从n(n>1)条通道分别通行 并发是只有一条通道&#xff0c;100个人排成n个队伍&#xff0c;每队依次派一个人从通道通行&#xff1b;或是有m条通道&#xff0c;100个人排成n个队伍&#xff0c;各个队…

[附源码]计算机毕业设计SpringBoot心理健康系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Spark3 AQE (Adaptive Query Execution) 一文搞懂 新特性

Spark 3 AQE (Adaptive Query Execution) 序 在搭建平台的过程中&#xff0c;我们使用 CDH 6.3.2 进行搭建&#xff0c;但 CDH 中阉割掉了 spark-sql 功能&#xff0c;所以我们外挂了 Spark 3&#xff0c;补充 spark-sql 功能&#xff0c;版本为 3.3。在使用的过程中&#xff…

【抓包工具】win 10 / win 11:WireShark 下载、安装、使用

目录 一、WireShark 下载 二、WireShark 安装 &#xff08;1&#xff09;双击运行安装程序 &#xff08;2&#xff09;Choose Components&#xff1a;选择组件 &#xff08;3&#xff09;Additional Tasks&#xff1a;附加任务 &#xff08;4&#xff09;Choose lnstall …

精品基于Java的社区团购系统SSM

《基于Java的社区团购系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 使用技术&#xff1a; 开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xf…

【JUC】并发编程学习笔记(二)

JUC并发编程五、多线程锁5.1、synchronized实现同步的基础5.2、公平锁与非公平锁5.3、可重入锁5.4、死锁5.4.1、概念5.4.2、案例5.4.3、查看死锁六、Callable接口6.1、概述6.2、FutureTask概述和原理6.3、案例七、辅助类7.1、减少计数CountDownLatch7.2、循环棚栏CyclicBarrier…

[HITCON CTF 2022] Superprime,rev Meow_way,BabySSS格基约减法,Secret共模攻击模未知

目录 Superprime Reverse Meow_way BabySSS Secret Superprime 这个题5层RSA加密&#xff0c;很简单就是要带条件爆破5组p,q&#xff0c;一开始看错了&#xff0c;对为5组是一一对应的&#xff0c;回头发现后边两对不是对应的。 from Crypto.Util.number import getPrime,…

[附源码]Python计算机毕业设计Django旅游度假村管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

计算程序运行时间:计算或者不计算sleep()的两种情况perf_counter()和process_time()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 计算程序运行时间&#xff1a; 计算或者不计算sleep()的两种情况 perf_counter()和process_time() [太阳]选择题 对下面描述错误的选项为&#xff1f; import time print(使用perf_counter…

[附源码]计算机毕业设计作业管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Matplotlib绘制图像大全】(二十四):Matplotlib为图像添加网格信息

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

Mybatis练习(多条件查询)

Mybatis练习(多条件查询) 概述 功能实现的步骤&#xff1a; 编写接口方法 参数&#xff1a;所有查询条件结果&#xff1a;List 在映射配置文件中编写SQL语句 编写测试方法并执行 编写接口方法 在 BrandMapper 接口中定义多条件查询的方法。 而该功能有三个参数&#xf…

排序算法两万字总结(C语言实现)

文章目录前言一、排序的概念二、常见的排序算法排序实现的接口(1)插入排序基本思想1.直接插入排序1.1代码实现1.2直接插入排序特性总结2.希尔排序(缩小增量排序)2.1代码实现2.2希尔排序的特性总结(2)选择排序基本思想1.直接选择排序1.1代码实现1.2直接选择排序的特性总结2.堆排…

Sentinel服务保护

一&#xff0e;微服务雪崩问题&#xff1f; 微服务模块之间相互调用&#xff0c;因为调用(同步调用)链中的一个服务故障&#xff0c;引起整个链路都无法访问的情况 解决方案: 避免服务宕机&#xff1a;流量控制服务已经宕机&#xff1a;熔断降级Hystrix -----springcloud …

python中numpy创建数组

1. numpy数组的创建 1.1 使用array方法进行创建 数组是numpy中一种常见的格式&#xff0c;和列表类似&#xff0c;可以理解为矩阵&#xff0c;可以使用array方法进行获取 import numpy as np import random#使用numpy生成数组,得到ndarray的类型 t1 np.array([1,2,3,]) pri…