vue2.x-echarts公共组件封装--简易篇(3d柱状图,炫酷仪表盘,折线,曲线图)
vue2.x-echarts公共组件封装--简易篇(3d柱状图,炫酷仪表盘,折线,曲线图)
·
更新一下之前写的echarts简单图表公共组件的封装,该组件可以实现自适应展示效果
废话不多说,上代码:
vue-echarts通用组件
<template>
<div class="companyList-ctn" :style="{ 'width':'100%','height': '100%' }">
<div :id="id" :style="{'width':'100%','height': '100%'}"></div>
</div>
</template>
<script>
let _c = { id: 1 };
import * as echarts from 'echarts';
import echartMixins from "@/utils/resizeMixins";
//引入echart
import 'echarts-gl'
export default {
mixins: [echartMixins],
created() {
_c.id++;
this.id = "charts_" + _c.id;
},
props: {
echartsData: {
type: Object,
},
},
data() {
return {
myPieChart:'',
width:'100%',
height:400+'px'
};
},
computed: {
heightFun(){
return this.echartsData.height+'px'
}
},
watch: {
echartsData:{
handler(newval, oldVal){
this.initChart();
},
deep:true //true 深度监听
}
},
mounted() {
// 初始化echarts
this.$nextTick(()=>{
this.initChart();
})
window.addEventListener('resize',this.initChart,false);
},
//vue组件实例销毁之前移除监听事件,避免当我们切换路由时导致vue出现警告:
//echarts.js?1be7:2160 Uncaught Error: Initialize failed: invalid dom.
beforeDestroy () {
window.removeEventListener('resize', this.initChart)
},
methods: {
initChart() {
var chartDom = document.getElementById(this.id);
if (this.myPieChart != null && this.myPieChart != "" && this.myPieChart != undefined) {
this.myPieChart.dispose();//销毁
}
this.myPieChart = echarts.init(chartDom);
this.myPieChart.resize()
var option=this.echartsData.option
this.myPieChart.setOption(option);
},
},
};
</script>
<style lang="scss" scoped>
.companyList-ctn {
width: 260px;
border-radius: 4px;
// background: white;
.companyList-oneItem {
display: flex;
justify-content: space-between;
align-items: center;
}
}
</style>
下面的一个混入文件是用来实现,窗口改变echarts自适应的js文件:
// 混入代码 resize-mixins.js
import { debounce } from '@/utils/index';
const resizeChartMethod = '$__resizeChartMethod';
export default {
data() {
// 在组件内部将图表init的引用映射到chart属性上
return {
chart: null,
};
},
created() {
window.addEventListener('resize', this[resizeChartMethod], false);
},
beforeDestroy() {
window.removeEventListener('reisze', this[resizeChartMethod]);
},
methods: {
// 通过lodash的防抖函数来控制resize的频率
[resizeChartMethod]: debounce(function() {
if (this.chart) {
this.chart.resize();
}
}, 100),
},
};
接下来是debounce.js
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result;
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp;
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
下面直接上代码:父组件调用+展示效果
<template>
<div class="user_protocal_box">
<!-- 折线图 -->
<DayLinkRatioCharts :echartsData="dayLinkRatio" />
</div>
</template>
<script>
import DayLinkRatioCharts from "@/components/charts";
export default {
components: {
DayLinkRatioCharts
},
data () {
return {
dayLinkRatio:{//日环比
option:{
tooltip: {
trigger: "axis",
},
legend: {
//标记属性
data: ['今日','昨日'],
orient: "horizontal", //标记排列显示
top:20, //标记位置
right:23, //标记位置
icon:'rect',
itemWidth: 16,
itemHeight:3,
itemGap:16,
formatter: [//用富文本组件实现图例与文字对齐的关键是富文本的格式转换
'{a|{name}}'
].join('\n'),
textStyle: {
color:'rgba(159,216,253,0.6)',
fontSize:13,
height:20,//图例字体高度
lineHeight:22, //图例字体行高
rich:{//用富文本组件实现图例与文字对齐
a:{
verticalAlign: 'middle'//图例与文字对齐方式
}
}
},
},
grid:{
//绘图区调整
left:23,
right:23,
bottom:20,
containLabel: true,
},
xAxis: {
type: "category",
boundaryGap: true,
data: ["0点","1点","2点","3点","4点","5点","6点","7点","8点","9点","10点","11点","12点","13点","14点","15点","16点","17点","18点","19点","20点","21点","22点","23点"],//x轴数据
axisLabel: {
//坐标轴文字显示样式
lineHeight: 15, //字体行高
fontSize:13,
fontNum: 15, //每行显示字数
rotate: 0, //文字旋转角度,0不旋转
color:'rgba(159,216,253,0.4)',
interval: 2//刻度间隔个数
},
axisLine: {//坐标轴线样式
lineStyle: {
color: 'rgba(159,216,253,0.4)',
type: 'solid'
},
},
axisTick:{//x轴刻度设置
alignWithLabel: true,//刻度线与点对齐
length:4,//刻度线的长度
interval: 2,//刻度间隔个数
show:true // 不显示坐标轴刻度线
},
},
yAxis:{
name:'',
type: "value",
axisLabel:{
color:'rgba(159,216,253,0.4)'
},
splitLine: {
show: true,//是否显示网格线
lineStyle: {
color: "rgba(159,216,253,0.15)",
textShadow: '0px 2px 4px 0px rgba(0,0,0,0.50)',
type: "solid"
}
},
axisLine:{show:false},//隐藏y轴
},
series: [
{
name: "今日",
data: [13.3, 11.34, 15.44, 13.53, 12.98, 12.36, 13.14, 14.46, 12.36, 12.45, 13.19, 10.64, 11.95, 12.2, 15.94, 15.73, 17.95, 14.94, 12.34, 17.55, 15.5, 15.82, 12.99, 15.98],
type: "line",
color:'#46A0FA',
showSymbol: false,//不显示圆点,hover时显示
smooth:true,//折线变为曲线
// yAxisIndex:1,
areaStyle: {//曲线阴影
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(70,160,250,0.4)", // 0% 处的颜色
},
{
offset: 1,
color: "rgba(70,160,250,0)", // 100% 处的颜色
}
])
},
},
{
name: "昨日",
data: [13.25, 12.96, 11.82, 14.66, 14.63, 12.75, 12.93, 15.29, 18.51, 17.03, 15.18, 15.81, 18.18, 19.14, 14.2, 7.71, 10, 15, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5,]
type: "line",
color:'#3FD4CF',
smooth:true,//折线变为曲线
showSymbol: false,//不显示圆点,hover时显示
// yAxisIndex:0,
areaStyle: {//曲线阴影
color: new echarts.graphic.LinearGradient(0, 0, 0, 1,[
{
offset: 0,
color: "rgba(63,212,207,0.4)", // 0% 处的颜色
},
{
offset: 1,
color: "rgba(63,212,207,0)", // 100% 处的颜色
}]),
},
}
],
},
},
}
},
mounted () {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>
截图:
下面是一个仪表盘的效果:请看代码:
<template>
<div class="user_protocal_box">
<!-- 仪表盘 -->
<HeightElectricCharts :echartsData="heightElectric" />
</div>
</template>
<script>
import HeightElectricCharts from "@/components/charts";
export default {
components: {
HeightElectricCharts
},
data () {
return {
heightElectric:{//电力高压负荷监控仪表盘
option:{
series: [
{//外圈的仪表盘
type: 'gauge',
startAngle: 180,
endAngle: 0,
min: 0,
max: 6000,
radius:'140%',
center:['50%','85%'],
splitNumber: 10,
progress: {
show: true,
roundCap: false,
width:30,
itemStyle: {
color:'rgba(255,255,255,0.25)',
shadowColor: 'rgba(255,255,255,0.5)',//rgba(0,255,255,0.8)
shadowBlur: 10,
shadowOffsetX: 2,
shadowOffsetY: 2,
},
},
pointer: {//指针
icon: 'path://M2090.36389,615.30999 L2090.36389,615.30999 C2091.48372,615.30999 2092.40383,616.194028 2092.44859,617.312956 L2096.90698,728.755929 C2097.05155,732.369577 2094.2393,735.416212 2090.62566,735.56078 C2090.53845,735.564269 2090.45117,735.566014 2090.36389,735.566014 L2090.36389,735.566014 C2086.74736,735.566014 2083.81557,732.63423 2083.81557,729.017692 C2083.81557,728.930412 2083.81732,728.84314 2083.82081,728.755929 L2088.2792,617.312956 C2088.32396,616.194028 2089.24407,615.30999 2090.36389,615.30999 Z',
length: '28%',
width: 3,
offsetCenter: [0, '-72%'],
itemStyle: {
color:'rgba(255,255,255,1)',
shadowColor: 'rgba(255,255,255,0.5)',//rgba(0,255,255,0.8)
shadowBlur: 10,
shadowOffsetX: 2,
shadowOffsetY: 2,
},
},
axisLine: {//槽内颜色
roundCap: false,
lineStyle: {
width: 30,
color: [
[1,new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: "#30C9C9"
},
{
offset: 0.15,
color: "#30C9C9"
},
{
offset: 0.2,
color: "#46A0FA"
},
{
offset: 0.4,
color: "#46A0FA"
},
{
offset: 0.55,
color: "#FCE26C"
},
{
offset: 0.75,
color: "#FCE26C"
},
{
offset: 1,
color: "#FB6C78"
}
])
]
]
}
},
axisTick: {//小刻度个数
splitNumber: 10,//小刻度个数
lineStyle: {
width:1,
color:'#5DD9FB'
}
},
splitLine: {//大刻度线
length: 10,
lineStyle: {
width:1.5,
color:'#5DD9FB'
}
},
axisLabel: {//刻度值
show:true,
distance: -55,
color: '#9FD8FD',
fontSize: 14,
offsetCenter: [-10, '0%'],
// formatter: function (value) {
// callback(value)
// },
},
title: {
show: true,
offsetCenter: [0, '0%'],
fontSize: 16,
color:'rgba(159,216,253,0.4)'
},
detail: {
width: '60%',
lineHeight: 40,
height: 40,
borderRadius: 8,
offsetCenter: [0, '-20%'],
valueAnimation: true,
formatter: function (value) {
return '{value|' + value.toFixed(0) + '}{unit|kw}';
},
rich: {
value: {
fontSize: 36,
fontWeight: 'bolder',
color: '#5DD9FB'
},
unit: {
fontSize: 35,
color: '#5DD9FB',
padding: [0, 0, 0, 0]
},
name: {
fontSize: 35,
color: '#5DD9FB',
padding: [0, 0, 0, 0]
},
}
},
data: [
{
value: 4900,
name: '当前负荷'
}
]
},
{//内圈的仪表盘刻度
type: 'gauge',
startAngle: 180,
endAngle: 0,
radius:'140%',
center:['50%','85%'],
min: 0,
max: 6000,
progress: {
show: false,
width: 30
},
axisLine: {
show: false,
lineStyle: {
width: 30
}
},
pointer:{
show:false
},
axisTick: {
show: false
},
splitLine: {
show: false,
length: 10,
lineStyle: {
width: 2,
color: '#999'
}
},
axisLabel: {
show: true,
distance:32,
color: '#5DD9FB',
fontSize: 12,
},
anchor: {
show: false,
showAbove: true,
size: 10,
itemStyle: {
borderWidth: 5
}
},
title: {
show: false
},
detail: {
show: false,
valueAnimation: true,
fontSize: 80,
offsetCenter: [0, '50%']
},
data: [
{
value: 4900
}
]
}
]
}
}
}
},
mounted () {
//仪表盘刻度值显示--该方法要放在接口返回去计算并渲染,因为刻度值转换为文字显示的是一个范围
this.heightElectric.option.series[0].axisLabel.formatter=function(value){
let oneItem=this.heightElectric.option.series[0].max/10
if (value == oneItem) {
return '轻载';
} else if (value == oneItem*3) {
return '正常';
} else if (value == oneItem*7) {
return '重载';
} else if (value == oneItem*9) {
return '过载';
}
return '';
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>
看图:
请注意:
简单说明一下,仪表盘本身就是一组数据,也就是series这个数组里面只有一项,但是如果如上图所示,要显示两个刻度盘,所以我们就要用了两组数据,第一组把刻度值修改成文字,第二组显示刻度值,第二组数据通过位置偏移来调节,图中的指针我是用的官方给的svg矢量图,这个是必须要用矢量图
下面是3d柱状图:
请看图:
补充一下:我没有显示底部切片,是因为如果数值为0时,底部切片和顶部切片会显示,效果不是很好,所以我选择了不显示底部切片,如果小伙伴有更好的解决办法,欢迎留言,共同进步o
<template>
<div class="user_protocal_box">
<!-- 3d柱状图 -->
<BuildEletricCharts :echartsData="buildEletric" />
</div>
</template>
<script>
import BuildEletricCharts from "@/components/charts";
let barWidth = 20;
var lastColor = {//3d柱状图柱子两个侧面的颜色
type: "linear",
x: 0,
x2: 1,
y: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: '#1FA6AA',
},
{
offset: 0.45,
color: '#1FA6AA',
},
{
offset: 0.5,
color: '#66DFD7',
},
{
offset: 1,
color: '#30C9C9',
},
],
};
var curColor = {//3d柱状图柱子两个侧面的颜色
type: "linear",
x: 0,
x2: 1,
y: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: '#2B78CF',
},
{
offset: 0.45,
color: '#2B78CF',
},
{
offset: 0.5,
color: '#58AFFB',
},
{
offset: 1,
color: '#46A0FA',
},
],
};
export default {
components: {
BuildEletricCharts
},
data () {
return {
buildEletric: {//建筑用电情况(kwh)
option: {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow", //鼠标悬停显示样式
shadowStyle: {
shadowColor: "rgba(0, 0, 0, 0.5)",
shadowBlur:2,
},
},
formatter: function(params) {
var str = params[0].name + ":";
params.filter(function(item) {
if (item.componentSubType == "bar") {
if(item.seriesName=='昨天'){
str += "<div id='id_flex3'>"+
"<p id='yesterday_circle1'></p>"+
"<p id='id_flex'>"+item.seriesName+ "\u00a0\u00a0" +"<span id='fb'>"+item.value+"</span>"+"</p>"+
"</div>"
}else{
str += "<div id='id_flex4'><p id='yesterday_circle2'></p><p id='id_flex2'>" + item.seriesName + "\u00a0\u00a0" + "<span id='fb'>"+item.value+"</span>"+"</p></div>"
}
}
});
return str;
},
},
grid: {
left:23,
right:23,
bottom:12,
containLabel: true,
},
legend: {
show: false,
data: ["昨天", "今天"],
top:20, //标记位置
right:23, //标记位置
icon:'rect',
textStyle: {
color: "rgba(159,216,253,0.4)",
fontSize: "13",
},
},
dataZoom:[{//展示不下时显示水平滚动条
show: true,
backgroundColor: "rgba(159,216,253,0.15)",
borderRadius: 5,
borderColor:"none",
height: 8,
startValue: 0, // 从头开始。
endValue: 3, // 一次性展示n个。
moveHandleIcon: "none",
moveHandleSize: 10,
zoomLock: true,
brushSelect: false,
showDataShadow: false,
fillerColor: "#58AFFB",
handleIcon: "path://M512,512m-448,0a448,448,0,1,0,896,0a448,448,0,1,0,-896,0Z",//滚动条圆角--官方推荐
handleSize: "70%",
handleColor:"#58AFFB",
textStyle: {
color: "transparent",
},
bottom: 2,
}
],
xAxis: {
data: ['高一教学楼', '高二教学楼', '高三教学楼', '女生宿舍楼', '男生宿舍楼', '行政楼', '食堂', '音乐厅', '国际交流中心', '实验楼', '图书馆', '体育馆'],
boundaryGap: true,
//坐标轴
axisLine: {
show: true,
lineStyle: {
width: 1,
color: "rgba(159,216,253,0.4)"
},
textStyle: {
color: "#000",
fontSize:20,
},
},
type: "category",
axisLabel: {
//坐标轴文字显示样式
lineHeight: 18, //字体行高
fontNum: 15, //每行显示字数
rotate: 0, //文字旋转角度,0不旋转
textStyle: {
color: "rgba(159,216,253,0.4)",
fontWeight: 'normal',
fontSize: "13",
},
},
axisTick: {
textStyle: {
color: "#fff",
fontSize: "16",
},
show: false,
},
splitLine: { show: false },
},
yAxis: {
type: "value",
//坐标轴
axisLine: {
show: false,
lineStyle: {
width: 1,
color: "#214776",
},
textStyle: {
color: "#fff",
fontSize: "10",
},
},
axisTick: {
show: false,
},
//坐标值标注
axisLabel: {
show: true,
textStyle: {
color: "rgba(159,216,253,0.4)",
},
},
//分格线
splitLine: {
lineStyle: {
color: "#13365f",
},
},
},
series: [
{
z: 1,
name: "昨天",
type: "bar",
barWidth: barWidth,
barGap: "0%",
data: [10.43, 23, 25.14, 27.32, 59.9, 35.82, 29.19, 19.32, 0, 2.22, 0.39, 4.1],
itemStyle: {
normal: {
color: lastColor,
},
},
},
{
z: 2,
name: "昨天",
type: "pictorialBar",
data: [10.43, 23, 25.14, 27.32, 59.9, 35.82, 29.19, 19.32, 0, 2.22, 0.39, 4.1],
symbol: "diamond",
symbolPosition: "start",
symbolOffset: ["-75%", "0%"],//底部切片位置,[x,y]
symbolSize: [0, 0],//底部切片尺寸,设置为0则不显示[宽,高]
itemStyle: {
normal: {
color: lastColor,
},
},
tooltip: {
show: false,
},
},
{
z: 3,
name: "昨天",
type: "pictorialBar",
symbolPosition: "end",
data: [10.43, 23, 25.14, 27.32, 59.9, 35.82, 29.19, 19.32, 0, 2.22, 0.39, 4.1],
symbol: "diamond",
symbolOffset: ["-75%", "-20%"],//底部切片位置,[x,y]
symbolSize: [barWidth , 5],//底部切片尺寸,设置为0则不显示[宽,高]
itemStyle: {
normal: {
borderWidth: -5,
color: '#BEF4ED',
},
},
tooltip: {
show: false,
},
},
{
z: 1,
name: "今天",
type: "bar",
barWidth: barWidth,
barGap: "50%",
data: [13.6, 35.43, 39.61, 35.58, 57.8, 56.58, 45.73, 39.77, 0, 2.89, 1.16, 5.93],
itemStyle: {
normal: {
color: curColor,
},
},
},
{
z: 2,
name: "今天",
type: "pictorialBar",
data: [13.6, 35.43, 39.61, 35.58, 57.8, 56.58, 45.73, 39.77, 0, 2.89, 1.16, 5.93],
symbol: "diamond",
symbolPosition: "start",
symbolOffset: ["75%", "0%"],
symbolSize: [0, 0],
itemStyle: {
normal: {
color: curColor,
},
},
tooltip: {
show: false,
},
},
{
z: 3,
name: "今天",
type: "pictorialBar",
symbolPosition: "end",
data: [13.6, 35.43, 39.61, 35.58, 57.8, 56.58, 45.73, 39.77, 0, 2.89, 1.16, 5.93],
symbol: "diamond",
symbolOffset: ["75%", "-20%"],
symbolSize: [barWidth , 5],
itemStyle: {
normal: {
borderWidth: -5,
color: '#C4E8FE',
},
},
},
],
},
},
}
},
mounted () {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>
说明:
为什么series里面每一类会有重复的数据,因为我们要实现的是3d柱状图,简单理解一下,就是:我们把3d柱状图一分为三份,第一份就是底部的切片,第二份就是中间的柱子,第三份就是顶部的切片,这样就是三份数据
今天的分享就到这里把,如果小伙伴有更好的解决办法,欢迎留言,共同进步o
更多推荐
已为社区贡献11条内容
所有评论(0)