Vue3 Echarts 3D圆柱体柱状图实现教程以及封装一个可复用的组件_echarts3d柱状图
文章目录
- 前言
- 一、实现原理
- 二、series ——type: \"pictorialBar\" 简介
-
- 2.1 常用属性
- 三、代码实战
-
- 3.1 封装一个echarts通用组件 echarts.vue
- 3.2 首先实现一个基础柱状图
- 3.3 添加上下2个椭圆面
- 3.4 进阶封装一个可复用的3D圆形柱状图组件
- 总结
前言
在前端开发的数据可视化场景中,ECharts 是一个强大且灵活的工具,它能创建各种复杂而美观的图表。本文将详细阐述如何利用 ECharts实现3D圆柱体柱状图,并封装一个可复用的组件。
一、实现原理
3D圆柱体柱状图实现原理很简单,可以看成普通的柱状图+上下两个圆面组合合成。模拟人眼斜俯视视角,上下两个面呈现椭圆形,再把普通柱状图调成一定透明度使得底部圆面也能被看到,从而把简单2D平面呈现出一定3D效果。
如上图所示上下2个独立圆面往普通柱状图靠,调到合适位置变成如下效果:
上下两个椭圆形可通过 echarts ——series—— type: “pictorialBar” 自定义图形实现
二、series ——type: “pictorialBar” 简介
type: “pictorialBar” 是 ECharts 中的一种特殊柱状图类型,它允许使用自定义图形(如图片、形状)来代替传统的柱状条,为数据可视化增添更多创意和灵活性。
type: \"pictorialBar\"也被叫作象形柱图。它首先是个柱状图,但是柱状图的柱子并不显示。这些柱子我们称为『基准柱(reference bar)』,根据基准柱来定位和显示各种象形图形(包括图片)。
每个象形图形根据基准柱的定位,是通过 symbolPosition、symbolOffset 来调整其于基准柱的相对位置。
2.1 常用属性
-
symbol 图形类型,默认圆形
可选值 ‘circle’(圆形), ‘rect’(直角长方形), ‘roundRect’(圆角长方形), ‘triangle’(三角形), ‘diamond’(菱形), ‘pin’(漏斗), ‘arrow’(箭头), ‘none’(无)
-
symbolSize 图形的大小,默认值 [‘100%’, ‘100%’]
可以用数组分开表示宽和高,例如 [20, 10] 表示标记宽为20,高为10,也可以设置成诸如 10 这样单一的数字,表示 [10, 10]。
可以设置成绝对值(如 10),也可以设置成百分比(如 ‘120%’、[‘55%’, 23])。
- symbolPosition 图形的定位位置
可选择 start’:图形边缘与柱子开始的地方内切,‘end’:图形边缘与柱子结束的地方内切。‘center’:图形在柱子里居中。
-
symbolOffset 图形相对于原本位置的偏移,默认[0, 0]
-
data 系列中的数据内容数组。数组项通常为具体的数据项。
更多属性可以查阅官方文档
本例需求通过上面几个属性我们就能构建一个椭圆形面
例如:
{ type: \"pictorialBar\", symbolSize: [50, 22],//50x22尺寸 symbolOffset: [0, -8],//向上偏移8px symbolPosition:\'end\',//位于顶部 }
三、代码实战
以vue3为代码为示例
3.1 封装一个echarts通用组件 echarts.vue
echarts.vue
<template><div class=\"echarts-box\"><div ref=\"echartRef\" class=\"charts\" ></div></div></template><script setup>import { ref, onMounted, onBeforeUnmount, watch, nextTick, markRaw } from \'vue\';import * as echarts from \'echarts\';const props = defineProps({// 图表配置data: {type: Object,default: () => {},},});const echartRef = ref();let dom = null;//设置图表配置const setOptions = (options) => {//清除画布dom && dom.clear();//重新渲染dom && dom.setOption(options);};watch(() => props.data,(val) => {nextTick(() => {//默认关闭动画setOptions({animation: false,...val});});},{ deep: true, immediate: true });const emits= defineEmits([\'click\'])onMounted(() => {//初始化dom = markRaw(echarts.init(echartRef.value));//点击事件 dom.on(\'click\', (param)=> {emits(\'click\',param) } )});onBeforeUnmount(() => {//离开销毁echarts.dispose(dom);dom = null;});defineExpose({setOptions,});</script><style lang=\"scss\" scoped>.echarts-box {width: 100%;height: 100%;box-sizing: border-box;}.charts {width: 100%;height: 100%;}</style>
上述代码封装了一个echarts通用组件,只需传入data图表配置数据就会重新渲染,需要注意的是组件默认继承父元素的宽高(100%),所以父元素需要设置尺寸。
3.2 首先实现一个基础柱状图
demo.vue
<template> <div class=\"container\"> <div class=\"echarts-view\"> <Echarts :data=\"data\" /> </div> </div></template><script setup>import Echarts from \"./echarts.vue\";import { ref } from \"vue\";const data = ref({ //位置 grid: { left: \"5%\", right: \"5%\", bottom: \"10%\", top: \"15%\", }, //提示框 tooltip: {}, //图例 legend: { show: true, right: \"5%\", textStyle: { color: \"#fff\", fontSize: 14, }, }, //x轴 xAxis: { type: \"category\", //坐标轴轴线 axisLine: { show: true, lineStyle: { color: \"rgba(0, 176, 255,0.3)\", }, }, //刻度 axisTick: { show: false, }, //分割线 splitLine: { show: false, }, // x轴文字 axisLabel: { color: \"#D8E6FF\", fontSize: 14, margin: 15, }, data: [ \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\", \"星期日\", ], }, //y轴 yAxis: { name: \"单位:元\", //单位文字 nameTextStyle: { //单位样式 color: \"#BCD0F4\", nameLocation: \"start\", fontSize: 14, }, nameGap: 40, //单位与y轴距离 type: \"value\", //分割线 splitLine: { show: true, lineStyle: { color: \"rgba(0, 176, 255, 0.2)\", type: \"dashed\", }, }, //坐标轴轴线 axisLine: { show: false, }, //刻度数值文字样式 axisLabel: { color: \"#BCD0F4\", fontSize: 14, }, }, //数据 series: [ //中间柱状图 { type: \"bar\", barWidth: 50, //柱子宽度 itemStyle: { //柱子样式 color: { //渐变颜色 type: \"linear\", x: 0, y: 0, x2: 0, y2: 1, colorStops: [ { offset: 0, color: \"#00B7FF\" }, { offset: 1, color: \"rgba(34,68,172,0.3)\" }, ], }, }, name: \"收入\", data: [200, 500, 300, 250, 360, 700, 556], }, ],});</script><style scoped>.container { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; background-color: #0a2270; align-items: center;}.echarts-view { height: 700px; width: 1200px;}</style>
运行效果:
上述代码渲染一个最基础的柱状图
3.3 添加上下2个椭圆面
新增如下代码
//数据 series:[ //中间柱状图 .... .... .... //顶部圆面 { type: \"pictorialBar\", symbolSize: [50, 22], symbolOffset: [0, -8], symbolPosition: \"end\", z: 12,//层级 itemStyle: { color:\'#21F3FF\', }, name: \"收入\", data: [200, 500, 300, 250, 360, 700, 556], }, //底部圆面 { type: \"pictorialBar\", symbolSize: [50, 22], symbolOffset: [0, 8], z: 12,//层级 itemStyle: { color: \'rgba(31,97,234,0.4)\', }, name: \"收入\", data: [200, 500, 300, 250, 360, 700, 556], } ]
运行效果:
上述代码通过象形柱状图自定义2个椭圆面,其中一个椭圆面通过symbolPosition: \"end\"设置为顶部显示另一个默认显示在底部,并通过symbolOffset调整椭圆面位置偏移量使得与基础柱状图融合为一体。
3.4 进阶封装一个可复用的3D圆形柱状图组件
bar-3d.vue
<!-- 3D柱状图 --><template> <div class=\"bar-wrap\"> <Echarts :data=\"data\" /> </div></template><script setup>import Echarts from \"../components/echarts.vue\";import { computed } from \"vue\";const props = defineProps({//位置 grid: { type: Object, default: () => ({ left: \"5%\", right: \"5%\", bottom: \"10%\", top: \"15%\", }), }, //图例 legend:{ type: Object, default: () => {}, }, //数据 series: { type: Object, default: () => {}, }, //x轴配置 xAxis: { type: Array, default: () => {}, }, //y轴配置 yAxis: { type: Object, default: () => {}, }, //单位 unit: { type: String, default: \"\", }, //上下圆面颜色 pictorialBarColor: { type: Array, default: () => [\"#21F3FF\", \"rgba(31,97,234,0.4)\"], },});//echarts配置const data = computed(() => { let { name, data } = props.series; //series配置处理 let seriesData = [ //中间柱状图 { type: \"bar\", barWidth: 50, //柱子宽度 itemStyle: { //柱子样式 color: { //渐变颜色 type: \"linear\", x: 0, y: 0, x2: 0, y2: 1, colorStops: [ { offset: 0, color: \"#00B7FF\" }, { offset: 1, color: \"rgba(34,68,172,0.3)\" }, ], }, }, ...props.series, }, //顶部圆面 { type: \"pictorialBar\", symbolSize: [50, 22], symbolOffset: [0, -8], symbolPosition:\'end\', z: 12, itemStyle: { color: props.pictorialBarColor[0], }, name, data: data.map((item) => { return { value: item, itemStyle: { opacity: item > 0 ? 1 : 0, //值为0时隐藏 }, }; }), }, //底部圆面 { type: \"pictorialBar\", symbolSize: [50, 22], symbolOffset: [0, 8], z: 12, itemStyle: { color: props.pictorialBarColor[1], }, name, data: data.map((item) => { return { value: item, itemStyle: { opacity: item > 0 ? 1 : 0, }, }; }), }, ]; return { grid: props.grid, tooltip: {}, legend: { show: true, right: \"5%\", textStyle: { color: \"#fff\", fontSize: 14, }, ...props.legend }, //x轴 xAxis: { type: \"category\", axisLine: { show: true, lineStyle: { color: \"rgba(0, 176, 255,0.3)\", }, }, axisTick: { show: false, }, splitLine: { show: false, }, // x轴文字 axisLabel: { color: \"#D8E6FF\", fontSize: 14, margin: 15, }, data: props.xAxis, }, //y轴 yAxis: { name: props.unit ? `单位:${props.unit}` : \"\", //单位文字 nameTextStyle: { //单位样式 color: \"#BCD0F4\", nameLocation: \"start\", fontSize: 14, }, nameGap: 40, //单位与y轴距离 type: \"value\", splitLine: { show: true, lineStyle: { color: \"rgba(0, 176, 255, 0.2)\", type: \"dashed\", }, }, axisLine: { show: false, }, //刻度数值样式 axisLabel: { color: \"#BCD0F4\", fontSize: 14, }, ...props.yAxis, }, series: seriesData, };});</script><style scoped lang=\"scss\">.bar-wrap { width: 100%; height: 100%;}</style>
上述代码封装了一个3D圆形柱状图组件,预设了默认样式,同时也暴露了x轴、y轴、图例、圆形柱状图颜色等配置属性可根据需求自定义进行样式覆盖。
页面调用:
demo.vue
<template> <div class=\"container\"> <div class=\"echarts-view\"> <Bar3D unit=\"元\" :xAxis=\"xAxisData\" :series=\"seriesData\" /> </div> </div></template><script setup>import Bar3D from \"./components/bar-3d.vue\";import { ref } from \"vue\";//x轴标签const xAxisData = ref([ \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\", \"星期日\",]);//数据const seriesData = ref({ name: \"收入\", data: [200, 500, 300, 250, 360, 700, 556],});</script><style scoped>.container { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; background-color: #0a2270; align-items: center;}.echarts-view { height: 700px; width: 1200px;}</style>
运行效果:
默认渐变色样式
修改圆柱配色
<template> <div class=\"container\"> <div class=\"echarts-view\"> <Bar3D unit=\"元\" :xAxis=\"xAxisData\" :series=\"seriesData\" :pictorialBarColor=\"pictorialBarColor\"/> </div> </div></template><script setup>import Bar3D from \"./bar-3d.vue\";import { ref } from \"vue\";//x轴标签const xAxisData = ref([ \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\", \"星期日\",]);//数据const seriesData = ref({ name: \"收入\", data: [200, 500, 300, 250, 360, 700, 556], //柱状图颜色 itemStyle: { color: \"#14b1eb\", opacity: 0.7, },});//上下圆面颜色const pictorialBarColor=ref([\'#14b1eb\',\'#14b1eb\'])</script><style scoped>.container { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; background-color: #0a2270; align-items: center;}.echarts-view { height: 700px; width: 1200px;}</style>
运行效果:
总结
通过组合使用 type: bar 和 type: “pictorialBar”,我们成功实现了 3D 圆柱体柱状图。同时,了解了 type: “pictorialBar” 的简单使用,它为我们在数据可视化方面提供了更多的创意和可能性。你可以根据实际需求,进一步调整图表的样式和配置,创造出更加美观和实用的可视化效果。
实际开发中可根据使用场景进阶封装,例如在echarts中加入对屏幕尺寸变化监听改变图表尺寸以达到不同分辨率响应式效果以及空数据的显示优化,使得组件更加健壮。