Vue中使用Echarts实现立体柱状图(长方体)
预览:
代码:
页面部分:
<template>
<div class="roadnum-all" ref="roadnumall">
<div id="roadnum" ref="dom"></div>
</div>
</template>
CSS部分:
.roadnum-all {
width: 100%;
height: 100%; /*填满父级容器*/
}
JS部分:
import echarts from 'echarts' // 引入Echarts
export default {
name: "ltzzt",
data() {
return {
data: [],
dom: null
}
},
mounted() {
this.$nextTick(() => { // 给图标宽高 使图标填满容器
document.getElementById('roadnum').style.width = this.$refs.roadnumall.offsetWidth + 'px';
document.getElementById('roadnum').style.height = this.$refs.roadnumall.offsetHeight + 'px';
this.draw();
})
},
methods: {
// 画图
draw() {
// 网络请求 假装从后端拿回来的数据
this.data = [
{ name: '京哈高速', value: 10 },
{ name: '京哈高速1', value: 20 },
{ name: '京哈高速2', value: 30 },
{ name: '京哈高速3', value: 40 },
{ name: '京哈高速4', value: 50 },
{ name: '京哈高速5', value: 60 },
{ name: '京哈高速6', value: 70 },
{ name: '京哈高速7', value: 80 },
{ name: '京哈高速8', value: 90 },
{ name: '京哈高速9', value: 100 },
{ name: '京哈高速10', value: 110 },
{ name: '京哈高速11', value: 120 }
];
// 拼轴显示和数据的数组
let xAxisText = [];
let dataList = [];
this.data.forEach(item => {
xAxisText.push(item.name);
dataList.push(item.value)
})
// 从这里开始 创建自定义图形 —— 长方体的正面
var MyCubeRect = echarts.graphic.extendShape({
shape: {
x: 0,
y: 0,
width: 180, // 长方体宽度
zWidth: 8, // 阴影折角宽
zHeight: 4 // 阴影折角高
},
buildPath: function (ctx, shape) {
console.log(ctx, shape);
const api = shape.api;
const xAxisPoint = api.coord([shape.xValue, 0]);
const p0 = [shape.x, shape.y];
const p1 = [shape.x - shape.width / xAxisText.length, shape.y];
const p4 = [shape.x + shape.width / xAxisText.length, shape.y];
const p2 = [xAxisPoint[0] - shape.width / xAxisText.length, xAxisPoint[1]];
const p3 = [xAxisPoint[0] + shape.width / xAxisText.length, xAxisPoint[1]];
ctx.moveTo(p0[0], p0[1]); //0
ctx.lineTo(p1[0], p1[1]); //1
ctx.lineTo(p2[0], p2[1]); //2
ctx.lineTo(p3[0], p3[1]); //3
ctx.lineTo(p4[0], p4[1]); //4
ctx.lineTo(p0[0], p0[1]); //0
ctx.closePath();
}
})
// 创建第二个自定义图形 —— 长方体的上面和侧面
var MyCubeShadow = echarts.graphic.extendShape({
shape: {
x: 0,
y: 0,
width: 180,
zWidth: 8,
zHeight: 4
},
buildPath: function (ctx, shape) {
const api = shape.api;
const xAxisPoint = api.coord([shape.xValue, 0]);
const p0 = [shape.x, shape.y];
const p1 = [shape.x - shape.width / xAxisText.length, shape.y];
const p4 = [shape.x + shape.width / xAxisText.length, shape.y];
const p6 = [shape.x + shape.width / xAxisText.length + shape.zWidth, shape.y - shape.zHeight];
const p7 = [shape.x - shape.width / xAxisText.length + shape.zWidth, shape.y - shape.zHeight];
const p3 = [xAxisPoint[0] + shape.width / xAxisText.length, xAxisPoint[1]];
const p5 = [xAxisPoint[0] + shape.width / xAxisText.length + shape.zWidth, xAxisPoint[1] - shape.zHeight];
ctx.moveTo(p4[0], p4[1]); //4
ctx.lineTo(p3[0], p3[1]); //3
ctx.lineTo(p5[0], p5[1]); //5
ctx.lineTo(p6[0], p6[1]); //6
ctx.lineTo(p4[0], p4[1]); //4
ctx.moveTo(p4[0], p4[1]); //4
ctx.lineTo(p6[0], p6[1]); //6
ctx.lineTo(p7[0], p7[1]); //7
ctx.lineTo(p1[0], p1[1]); //1
ctx.lineTo(p4[0], p4[1]); //4
ctx.closePath();
}
});
echarts.graphic.registerShape('MyCubeRect', MyCubeRect);
echarts.graphic.registerShape('MyCubeShadow', MyCubeShadow);
const option = {
color: ['#33b56a', '#fdcf5c', '#4c90ff', '#fe7b7a', '#69ccf6', '#a38bf8', '#ff9561', '#8cb0ea', '#fe81b4', '#ffb258'],
title: {
text: '验算路线排行榜',
left: 20,
top: 20
},
legend: {
show: true,
top: 25
},
grid: {
left: '3%',
right: '4%',
top: '15%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: xAxisText,
boundaryGap: true,
interval: 0,
axisLabel: {
color: '#333',
// 让x轴文字方向为竖向
interval: 0,
formatter: function (value) {
return value.split('').join('\n')
}
}
},
yAxis: {
type: 'value'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
},
series: [{
name: '次数',
type: 'custom',
renderItem: (params, api) => {
let location = api.coord([api.value(0), api.value(1)]);
return {
type: 'group',
children: [{
type: 'MyCubeRect',
shape: {
api,
xValue: api.value(0),
yValue: api.value(1),
x: location[0],
y: location[1]
},
style: api.style(), // api.style()——继承原本的样式
}, {
type: 'MyCubeShadow',
shape: {
api,
xValue: api.value(0),
yValue: api.value(1),
x: location[0],
y: location[1]
},
style: {
fill: api.style(),
text: '' // 继承原本样式的基础上将label清空 如果不清空生成的图上会显示两个重叠的label
}
}]
}
},
stack: '总量',
label: {
show: true,
position: 'top',
color: '#333',
formatter: `{c}次`,
fontSize: 16,
distance: 15
},
itemStyle: {
normal: {
color: (params) => {
// 使每根柱子颜色都不一样
let colorList = ['#33b56a', '#fdcf5c', '#4c90ff', '#fe7b7a', '#69ccf6', '#a38bf8', '#ff9561', '#8cb0ea', '#fe81b4', '#ffb258'];
if (params.dataIndex + 1 <= colorList.length) {
return colorList[params.dataIndex]
} else {
// 如果柱子的数量超过颜色数组 就从头再来一遍
return colorList[params.dataIndex - colorList.length]
}
}
}
},
data: dataList
}]
};
this.dom = echarts.init(this.$refs.dom);
this.dom.setOption(option, true)
window.addEventListener("resize", () => {
if (document.getElementById('roadnum') && this.$refs.roadnumall) {
document.getElementById('roadnum').removeAttribute('_echarts_instance_');
document.getElementById('roadnum').style.width = this.$refs.roadnumall.offsetWidth + 'px';
document.getElementById('roadnum').style.height = this.$refs.roadnumall.offsetHeight + 'px';
this.dom.resize();
}
});
}
}
}