代码注释顶部标注
// 多系列无法定位:该方案只支持单组数据,如果多系列多根柱子并排,pictorialBar 菱形底座 / 顶盖无法精准对齐每一根柱子,会错位。
核心实现原理前置说明
ECharts 没有原生 3D 柱状图 bar3D (echarts-gl 是独立 3D 组件,此代码未引入 gl),本方案是2D 图层叠加模拟立体柱子:
-
底层:普通
bar矩形柱体(柱子主体) -
下层装饰:
pictorialBar菱形(柱子底部切面,模拟立体底座) -
上层装饰:
pictorialBar菱形(柱子顶部切面,模拟立体封顶) 通过三层 series 设置不同z层级上下叠加,搭配渐变填充、菱形斜面,视觉欺骗出 3D 立体效果。 -
如果需要支持多系列、真 3D 旋转视角,需要引入
echarts-gl插件,使用bar3D系列,不需要多层 pictorialBar 叠加。 -
单系列正常逻辑 只有一组 bar 数据时,pictorialBar 的 data 长度、类目位置和 bar 完全匹配,菱形底座 / 顶盖能精准落在每根柱子上下。
-
多系列失效原因 当存在两组及以上 bar(多组并列柱子):
- pictorialBar 是全局类目渲染,无法区分第 1 组柱、第 2 组柱;
- 菱形图形会居中在类目格子中间,和多根并列柱子错位;
- 没有配置参数可以控制 pictorialBar 偏移到对应系列柱子位置,因此多系列场景该伪 3D 方案不可用。
javascript// 全局通用文字线条灰色 var normalColor = "#94a1a9"; /** * 渐变颜色数组,两套线性渐变用于柱子填充 * 渐变类型:水平线性渐变(x从0到1,y不变=横向渐变) */ var colors = [{ type: 'linear', // 渐变类型:线性渐变 x: 0, x2: 1, // 渐变起点x=0,终点x=1 → 水平左右渐变 y: 0, y2: 0, // y全程不变,无上下渐变 colorStops: [{ // 渐变分段色标 offset: 0, color: '#0a4368' }, { offset: 0.5, color: '#0a4368' }, { offset: 0.5, color: '#0a4368' }, { offset: 1, color: '#0a4368' }] }, { type: 'linear', x: 0, x2: 1, y: 0, y2: 0, colorStops: [{ offset: 0, color: 'rgba(10, 67, 104,0.6)' }, { offset: 0, color: '#fff' }, { offset: 0.05, color: 'rgba(10, 67, 104,0.6)' }, { offset: 0.5, color: 'rgba(10, 67, 104,0.6)' }, { offset: 0.5, color: '#fff' }, { offset: 0.55, color: 'rgba(10, 67, 104,0.6)' }, { offset: 0.95, color: 'rgba(10, 67, 104,0.9)' }, { offset: 1, color: '#fff' }] }]; // 柱子宽度统一变量,三层图表共用宽度保证对齐 var barWidth = 80; // ECharts 配置项 option = { animation: false, // 关闭图表初始化加载动画,避免立体分层动画错位 backgroundColor: "#ccc", // 画布背景浅灰色 title: { text: '' // 无图表标题 }, // X轴:类目轴,年份分类 xAxis: { type: 'category', boundaryGap: true, // 坐标轴两端留白,柱子不会贴紧画布左右边缘 axisLabel: { // X轴文字样式 color: normalColor, fontSize: 16, }, axisTick: { // 隐藏X轴刻度小短线 show: false }, axisLine: { // X轴线样式 show: true, lineStyle: { type: "dashed", // 虚线坐标轴 color: normalColor } }, splitLine: { // X轴纵向分割线 show: true, lineStyle: { type: "dashed", color: normalColor } }, data: ['2016', '2017', '2018', '2019'] // X轴类目数据 }, // Y轴:数值轴,单根数组表示单Y轴 yAxis: [{ name: "", type: 'value', axisLine: { // Y轴线 show: true, lineStyle: { color: normalColor, } }, axisTick: { // 隐藏Y轴刻度短线 show: false, }, axisLabel: { // Y轴数值文字 color: normalColor, fontSize: 16, margin: 25, // 文字距离Y轴线间距 formatter: '{value}' // 数值原样展示 }, splitLine: { // Y轴横向网格分割线 show: true, lineStyle: { type: "dashed", color: normalColor } }, }, ], /** * series三层图层叠加实现伪3D柱子,z值越大层级越靠上 * z=1:底层主体矩形柱子 * z=2:底层菱形底座(柱子底部斜面) * z=3:顶层菱形顶盖(柱子顶部斜面) */ series: [ // 第一层:柱状图主体(矩形柱身,核心载体) { z: 1, // 层级最低,在最下方 type: 'bar', // 基础柱状图 barWidth: barWidth, // 柱宽统一80px label: { // 柱子顶部数值标签 show: true, position: "top", // 文字在柱子上方 padding: 10, textStyle: { color:normalColor, fontSize: 30 // 数值放大突出 } }, data: [220, 182, 191, 234], // 柱子高度数值 itemStyle: { normal: { color: colors[1] // 柱子填充为第二套渐变 } }, }, // 第二层:pictorialBar 菱形底座,模拟柱子底部立体切面 { z: 2, // 层级高于柱身,叠在柱子底部上方 name: '底部', type: 'pictorialBar', // 象形柱状图,自定义图形标记 data: [1, 1, 1, 1, 1, 1, 1], // 数值固定1,只渲染图形不控制高度 symbol: 'diamond', // 自定义图形:菱形 symbolOffset: [0, '50%'], // 图形垂直向下偏移50%,贴在柱子底端 symbolSize: [barWidth, 10], // 菱形宽=柱宽,高度10px(底座厚度) itemStyle: { normal: { color: colors[1], borderColor: '#fff', // 白色描边增强立体分割感 borderWidth: 2, } }, }, // 第三层:pictorialBar 菱形顶盖,模拟柱子顶部立体切面 { z: 3, // 层级最高,覆盖在柱子最顶端 name: '上部1', type: 'pictorialBar', symbolPosition: 'end', // 图形吸附在数值终点(柱子顶端) data: [220, 182, 191, 234], // 和柱身高度数值完全一致,精准对齐顶端 symbol: 'diamond', // 顶部菱形切面 symbolOffset: [0, '-50%'], // 垂直向上偏移50%,贴合柱子顶端上沿 symbolSize: [barWidth - 4, 15 * (barWidth - 4) / barWidth], // 菱形略窄于柱身,比例缩小高度 itemStyle: { normal: { borderColor: '#fff', // 白色边框区分顶盖和柱身 borderWidth: 2, color: '#0a4368' // 顶盖纯色加深,强化立体明暗对比 } } } ] };