在做可视化大屏时,时常会遇到一些共用的图表,一个一个这样实现起来不仅代码很复杂,也会看上去很乱。基于这个问题,简单封装了一个仪表盘组件,进行复用修改来完成不同需求。同时,大家也可以按照不同需求来封装更多类似这种的。
实现效果展示:
1.首先安装插件
- 安装echarts
npm install echarts --save
- 安装
npm install element-resize-detector --save
2.在views文件夹下新建gaugeChart.vue
<template>
<div :style="{ height: height, width: width }"></div>
</template>
<script>
import * as echarts from "echarts";
import resize from "./mixins/resize";
export default {
mixins: [resize],
props: {
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "280px",
},
chartData: {
type: Object,
required: true,
},
},
data() {
return {
chart: null,
};
},
watch: {
// 监听表数据变化,重新初始化图表
chartData: {
deep: true,
handler(val) {
if (this.chart) {
this.$nextTick(() => {
this.initChart();
});
}
},
},
},
mounted() {
// 初始化图表
this.initChart();
},
beforeDestroy() {
// 页面销毁时 销毁图表
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
this.chart = echarts.init(this.$el);
this.setOptions(this.chartData);
},
// 图表配置项
setOptions(chartData) {
// 图表数据
const data = chartData.data;
// 使用核数
const userData = chartData.userData;
const name = chartData.name;
var colorTemplate1 = [
[0.2, "rgba(255,0,0,0.8)"],
[0.8, "rgba(0,255,255,0.8)"],
[1, "rgba(0,255,0,0.8)"],
];
// var colors = ["#00c05a", "#e6a900", "#e00005"];
var options = {
backgroundColor: "#09153d",
tooltip: {
// 本系列特定的 tooltip 设定。
show: true,
formatter: "{b}:{c}%",
backgroundColor: "rgba(50,50,50,0.7)", // 提示框浮层的背景颜色。注意:series.tooltip 仅在 tooltip.trigger 为 'item' 时有效。
borderColor: "#333", // 提示框浮层的边框颜色。...
borderWidth: 0, // 提示框浮层的边框宽。...
padding: 5, // 提示框浮层内边距,单位px,默认各方向内边距为5,接受数组分别设定上右下左边距。...
textStyle: {
// 提示框浮层的文本样式。...
// color ,fontStyle ,fontWeight ,fontFamily ,fontSize ,lineHeight ,.......
},
},
graphic: {
type: "text",
left: "33%",
top: "22%",
style: {
text: userData,
textAlign: "center",
fill: name == "cpu" ? "green" : name == "内存" ? "yellow" : "red",
fontSize: 24,
fontWeight: "bold",
fontFamily: "impact",
},
},
series: [
{
name: "单仪表盘示例", // 系列名称,用于tooltip的显示,legend 的图例筛选,在 setOption 更新数据和配置项时用于指定对应的系列。
type: "gauge", // 系列类型
radius: "100%", // 参数:number, string。 仪表盘半径,默认 75% ,可以是相对于容器高宽中较小的一项的一半的百分比,也可以是绝对的数值。
center: ["50%", "50%"], // 仪表盘位置(圆心坐标)
startAngle: 225, // 仪表盘起始角度,默认 225。圆心 正右手侧为0度,正上方为90度,正左手侧为180度。
endAngle: -45, // 仪表盘结束角度,默认 -45
clockwise: true, // 仪表盘刻度是否是顺时针增长,默认 true。
min: 0, // 最小的数据值,默认 0 。映射到 minAngle。
max: 100, // 最大的数据值,默认 100 。映射到 maxAngle。
splitNumber: 10, // 仪表盘刻度的分割段数,默认 10。
axisLine: {
// 仪表盘轴线(轮廓线)相关配置。
show: true, // 是否显示仪表盘轴线(轮廓线),默认 true。
lineStyle: {
// 仪表盘轴线样式。
color: [
[
1,
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0.1,
color: "green",
},
{
offset: 0.8,
color: "yellow",
},
{
offset: 1,
color: "red",
},
]),
],
], //仪表盘的轴线可以被分成不同颜色的多段。每段的 结束位置(范围是[0,1]) 和 颜色 可以通过一个数组来表示。默认取值:[[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']]
opacity: 0.9, //图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。
width: 7, //轴线宽度,默认 30。
// shadowBlur: 20, //(发光效果)图形阴影的模糊大小。该属性配合 shadowColor,shadowOffsetX, shadowOffsetY 一起设置图形的阴影效果。
// shadowColor: "#fff", //阴影颜色。支持的格式同color。
},
},
splitLine: {
// 分隔线样式。
show: false, // 是否显示分隔线,默认 true。
length: 30, // 分隔线线长。支持相对半径的百分比,默认 30。
lineStyle: {
// 分隔线样式。
color: "#eee", //线的颜色,默认 #eee。
opacity: 1, //图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。
width: 2, //线度,默认 2。
type: "solid", //线的类型,默认 solid。 此外还有 dashed,dotted
shadowBlur: 10, //(发光效果)图形阴影的模糊大小。该属性配合 shadowColor,shadowOffsetX, shadowOffsetY 一起设置图形的阴影效果。
shadowColor: "#fff", //阴影颜色。支持的格式同color。
},
},
axisTick: {
// 刻度(线)样式。
show: false, // 是否显示刻度(线),默认 true。
splitNumber: 5, // 分隔线之间分割的刻度数,默认 5。
length: 8, // 刻度线长。支持相对半径的百分比,默认 8。
lineStyle: {
// 刻度线样式。
color: colorTemplate1, //线的颜色,默认 #eee。
opacity: 1, //图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。
width: 1, //线度,默认 1。
type: "solid", //线的类型,默认 solid。 此外还有 dashed,dotted
shadowBlur: 10, //(发光效果)图形阴影的模糊大小。该属性配合 shadowColor,shadowOffsetX, shadowOffsetY 一起设置图形的阴影效果。
shadowColor: "#fff", //阴影颜色。支持的格式同color。
},
},
axisLabel: {
// 刻度标签。
show: false, // 是否显示标签,默认 true。
distance: 20, // 标签与刻度线的距离,默认 5。
color: "#fff", // 文字的颜色,默认 #fff。
fontSize: 12, // 文字的字体大小,默认 5。
formatter: "{value}", // 刻度标签的内容格式器,支持字符串模板和回调函数两种形式。 示例:// 使用字符串模板,模板变量为刻度默认标签 {value},如:formatter: '{value} kg'; // 使用函数模板,函数参数分别为刻度数值,如formatter: function (value) {return value + 'km/h';}
},
pointer: {
// 仪表盘指针。
show: true, // 是否显示指针,默认 true。
length: "85%", // 指针长度,可以是绝对数值,也可以是相对于半径的百分比,默认 80%。
width: 2, // 指针宽度,默认 8。
},
itemStyle: {
// 仪表盘指针样式。
color: "auto", // 指针颜色,默认(auto)取数值所在的区间的颜色
opacity: 1, // 图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。
borderWidth: 0, // 描边线宽,默认 0。为 0 时无描边。
borderType: "solid", // 柱条的描边类型,默认为实线,支持 'solid', 'dashed', 'dotted'。
borderColor: "#000", // 图形的描边颜色,默认 "#000"。支持的颜色格式同 color,不支持回调函数。
shadowBlur: 10, // (发光效果)图形阴影的模糊大小。该属性配合 shadowColor,shadowOffsetX, shadowOffsetY 一起设置图形的阴影效果。
shadowColor: "#fff", // 阴影颜色。支持的格式同color。
},
emphasis: {
// 高亮的 仪表盘指针样式
itemStyle: {
//高亮 和正常 两者具有同样的配置项,只是在不同状态下配置项的值不同。
},
},
title: {
// 仪表盘标题。
show: true, // 是否显示标题,默认 true。
offsetCenter: [0, "40%"], //相对于仪表盘中心的偏移位置,数组第一项是水平方向的偏移,第二项是垂直方向的偏移。可以是绝对的数值,也可以是相对于仪表盘半径的百分比。
color: "#fff", // 文字的颜色,默认 #333。
fontSize: 14, // 文字的字体大小,默认 15。
fontWeight: 500,
fontFamily: "impact",
},
detail: {
// 仪表盘详情,用于显示数据。
show: true, // 是否显示详情,默认 true。
offsetCenter: ["10%", "80%"], // 相对于仪表盘中心的偏移位置,数组第一项是水平方向的偏移,第二项是垂直方向的偏移。可以是绝对的数值,也可以是相对于仪表盘半径的百分比。
color:
name == "cpu" ? "green" : name == "内存" ? "yellow" : "red", // 文字的颜色,默认 auto。
fontSize: 22, // 文字的字体大小,默认 15。
formatter: "{value}%", // 格式化函数或者字符串
fontWeight: 500,
fontFamily: "impact",
},
data: data,
},
{
// 第二个刻度盘
type: "gauge",
radius: "90%",
center: ["50%", "50%"],
startAngle: 225, // 仪表盘起始角度,默认 225。圆心 正右手侧为0度,正上方为90度,正左手侧为180度。
endAngle: -45,
min: 0,
max: 100,
progress: {
show: false,
width: 8,
},
pointer: {
show: false,
},
axisLine: {
lineStyle: {
width: 1,
color: [[1, "#19549d"]],
},
},
axisTick: {
// 刻度线
distance: -8,
splitNumber: 4,
lineStyle: {
width: 1,
color: "#19549d",
},
},
splitLine: {
distance: -12,
length: 5,
lineStyle: {
width: 1,
color: "#19549d",
},
},
axisLabel: {
show: false,
},
detail: {
show: false,
},
},
],
};
this.chart.setOption(options);
},
},
};
</script>
3.在组件中使用
<div style="display: flex; justify-content: space-between">
<gaugeChart
:chartData="chartDataAr1"
width="200px"
height="120px"
></gaugeChart>
<gaugeChart
:chartData="chartDataAr2"
width="200px"
height="120px"
></gaugeChart>
<gaugeChart
:chartData="chartDataAr3"
width="200px"
height="120px"
></gaugeChart>
</div>
4.使用数据的展示格式(按不同需求来定义)
chartDataAr1: {
name: "cpu",
userData: 0,
data: [
{
value: 0,
name: "cpu",
},
],
},
chartDataAr2: {
name: "内存",
userData: 0,
data: [
{
value: 0,
name: "内存",
},
],
},
chartDataAr3: {
name: "磁盘",
userData: 0,
data: [
{
value: 0,
name: "磁盘",
},
],
},
5.配置 element-resize-detector 公共方法(图表自适应,也适用于其它图表)
在views文件夹下面新建 mixins 文件夹 然后 新建 resize.js
// resize.js
import elementResizeDetectorMaker from "element-resize-detector";
import { debounce } from '@/utils/debounce'
export default {
data() {
return {
$_sidebarElm: null,
$_resizeHandler: null
};
},
mounted() {
var erd = elementResizeDetectorMaker();
setTimeout(() => {
if (this.chart) {
erd.listenTo(this.chart._dom, ele => {
debounce(() => {
if (typeof this.getDomSizeFn === "function") {
this.getDomSizeFn(ele);
}
if (this.chart && this.chart.resize) {
this.chart.resize();
}
}, 100)();
});
}
});
this.$_resizeHandler = debounce(() => {
if (this.chart && this.chart.resize) {
this.chart.resize();
}
}, 100);
this.$_initResizeEvent();
this.$_initSidebarResizeEvent();
},
beforeDestroy() {
this.$_destroyResizeEvent();
this.$_destroySidebarResizeEvent();
},
// to fixed bug when cached by keep-alive
// https://github.com/PanJiaChen/vue-element-admin/issues/2116
activated() {
this.$_initResizeEvent();
this.$_initSidebarResizeEvent();
},
deactivated() {
this.$_destroyResizeEvent();
this.$_destroySidebarResizeEvent();
},
methods: {
// use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_initResizeEvent() {
window.addEventListener("resize", this.$_resizeHandler);
},
$_destroyResizeEvent() {
window.removeEventListener("resize", this.$_resizeHandler);
},
$_sidebarResizeHandler(e) {
if (e.propertyName === "width") {
this.$_resizeHandler();
}
},
$_initSidebarResizeEvent() {
this.$_sidebarElm = document.getElementsByClassName(
"sidebar-container"
)[0];
this.$_sidebarElm &&
this.$_sidebarElm.addEventListener(
"transitionend",
this.$_sidebarResizeHandler
);
},
$_destroySidebarResizeEvent() {
this.$_sidebarElm &&
this.$_sidebarElm.removeEventListener(
"transitionend",
this.$_sidebarResizeHandler
);
}
}
};
6.在 utils 新建 debounce.js
// index.js
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
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
}
}
}
return function (...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
根据不同需求去修改及使用!!!