分享几款ECharts图表,话不多说直接上
官方文档请看:ECharts官方配置项文档
目录
进度条图表
ECharts 没有提供进度条类型的图表,但是可以根据仪表盘类型修改得到,上图
进度条配置:
<template>
<!-- 进度条类型组件 -->
<div class="progressChart">
<div class="chart" id="progressChart" ref="chartRef"></div>
<label class="bottom le-0-font">{{ bottomTitle }}</label>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
data() {
return {
series: [
{
type: 'gauge', // 仪表盘类型
name: '系列名称', // 用于tooltip的显示
startAngle: 90, // 仪表盘开始角度(设置背景圆的角度)
endAngle: -270, // 仪表盘结束角度
center: ['50%', '50%'], // 中心点(圆心坐标)
radius: '100%', // 圆大小(仪表盘半径)
clockwise: true, // 仪表盘刻度是否是顺时针增长
// 仪表盘轴线相关配置
axisLine: {
show: true,
roundCap: false, // 两端显示成圆形(背景环)
clip: false, // 是否裁剪超出部分
// 设置背景圆环样式
lineStyle: {
width: 10, // 圆环宽度
color: [[1, '#002865']] // 圆环背景色
}
},
// 仪表盘指针
pointer: {
show: false
},
// 进度设置
progress: {
show: true,
overlap: false, // 多组数据时进度条是否重叠
roundCap: true, // 是否在两端显示成圆形
clip: false, // 是否裁掉超出部分
// 进度条样式
itemStyle: {
borderWidth: 0,
shadowColor: '',
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: this.startColor // 0% 处的颜色 '#02C77E'
},
{
offset: 1,
color: this.endColor // 100% 处的颜色 '#017770'
}
],
global: false // 缺省为 false
}
}
},
// 仪表盘分割线
splitLine: {
show: false
},
// 刻度样式
axisTick: {
show: false
},
// 刻度标签
axisLabel: {
show: false
},
title: {
show: false,
fontSize: 24
},
detail: {
// width: 50,
// height: 14,
fontSize: 14,
color: 'auto'
},
data: [
{
value: this.centerValue,
name: '345',
title: {},
detail: {
// 中心title设置
offsetCenter: ['0%', '0%'],
color: '#01F8FF',
formatter: '{value}%'
// borderColor: '#01F8FF',
// borderRadius: 20,
// borderWidth: 1,
}
}
],
}
]
}
},
setup() {},
props: {
startColor: {
type: String,
default: ''
},
endColor: {
type: String,
default: ''
},
centerValue: {
type: [Number, String],
default: 0
},
bottomTitle: {
type: String,
default: ''
}
},
methods: {},
created() {},
mounted() {
const currentWindow: isWindow = Window
const Echarts = currentWindow.$Echarts
// let myChart = Echarts.init(document.getElementById('progressChart'));
let myChart = Echarts.init(this.$refs['chartRef']) // 使用Id无法实现
myChart.setOption({
series: this.series
})
}
})
</script>
<style lang="scss" scoped>
.progressChart {
width: 99%;
height: 100%;
.chart {
width: 100%;
height: 75%;
}
.bottom {
display: inline-block;
width: 100%;
color: #01f8ff;
text-align: center;
height: 1rem;
font-size: 12px;
}
}
</style>
环状饼图
环状饼图配置:
<template>
<div class="box-container">
<BoxHeader info="货物类型" utils="万吨" type="dis" tips="3" />
<div class="content">
<div class="charts-content" id="rightPieChart" ref="rightPieChart"></div>
</div>
</div>
</template>
<script lang="ts">
import BoxHeader from '../BoxHeader/index.vue'
import { defineComponent } from 'vue'
export default defineComponent({
components: { BoxHeader },
data() {
return {
chartOption: {
// 标题组件,包含主标题和副标题
title: {
// 调整中心圆饼尺寸
show: true,
text: '异常', // 主标题文本
left: 'center', // 组件距离容器左侧距离
top: 'center',
// 主标题文本样式
textStyle: {
color: '#01F8FF',
lineHeight: 22
},
backgroundColor: '#004396', // 中心圆饼背景
borderWidth: 1,
borderColor: '#101129',
borderRadius: 45,
padding: [23, 15, 23, 15],
},
legend: {
//图例组件
show: false,
right: 100 //图例组件离右边的距离
},
color: ['#B53E36', '#CA9419', '#004396', '#27B57D', '#7B60EC'], //手动设置每个图例的颜色
series: [
//系列列表
{
name: '设备状态', //系列名称
type: 'pie', //类型 pie表示饼图
center: ['50%', '50%'], //设置饼的原心坐标 不设置就会默认在中心的位置
radius: ['35%', '55%'], //饼图的半径,第一项是内半径,第二项是外半径,内半径为0就是真的饼,不是环形
itemStyle: {
//图形样式
// normal 是图形在默认状态下的样式
normal: {
label: {
//饼图图形上的文本标签
show: true, //平常不显示
color: '#01F8FF',
formatter: '{b}\n{d}%', // {b}\n{c}起,{d}%
rotate: 0, // 标签旋转角度
fontSize: 5,
align: 'left',
lineHeight: 15, // 文字行高
alignTo: 'labelLine',
padding: [0, -10, 0, -10]
},
labelLine: {
//标签的视觉引导线样式
show: true, //平常不显示
smooth: false, //
// length2: 40,
lineStyle: {
color: '#067FFC'
}
}
},
// emphasis 是图形在高亮状态下的样式,比如在鼠标悬浮或者图例联动高亮时。
emphasis: {
label: {
//饼图图形上的文本标签
show: true,
// position : 'center',
textStyle: {
fontSize: '12'
}
}
}
},
data: [
{ value: 328, name: '违规区域' },
{ value: 156, name: '入围区域' },
{ value: 88, name: '线路偏移' },
{ value: 64, name: '停车超时' },
{ value: 60, name: '离线' }
]
}
]
}
}
},
setup() {
return {}
},
created() {},
mounted() {
const currentWindow: isWindow = Window
const Echarts = currentWindow.$Echarts
let myChart = Echarts.init(document.getElementById('rightPieChart'))
myChart.setOption(this.chartOption)
}
})
</script>
<style lang="scss" scoped>
.box-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.content {
height: 100%;
width: 100%;
.charts-content {
width: 100%;
height: 100%;
}
}
}
</style>
折线图
折线图配置:
<template>
<div class="box-container">
<BoxHeader info="运价环比折线图" utils="吨/公里" type="dis" />
<div class="content">
<div class="charts-content" id="lineChart" ref="lineChart"></div>
</div>
</div>
</template>
<script lang="ts">
import BoxHeader from './BoxHeader/index.vue'
import { defineComponent } from 'vue'
export default defineComponent({
components: { BoxHeader },
data() {
return {
chartsOption: {
tooltip: {
trigger: 'axis' // 触发方式:坐标轴触发
},
legend: {
type: 'plain',
data: ['长途', '中途', '短途']
},
// 网格
grid: {
show: false,
top: '17%',
left: '3%',
right: '4%',
bottom: '0%',
containLabel: true,
borderColor: '#f00'
},
// 工具栏
toolbox: {
show: false,
feature: {
saveAsImage: {
// show: false
}
}
},
xAxis: {
type: 'category',
boundaryGap: true,
axisLine: {
// 坐标轴轴线相关设置
lineStyle: {
color: '#007FFF',
width: 2
}
},
splitLine: {
// 坐标轴在 grid 区域中的分隔线
show: true,
lineStyle: {
color: '#0851B5',
opacity: 0.5 // 图线透明度
}
},
axisTick: {
// 坐标轴刻度设置
show: false
},
axisLabel: {
// 坐标轴文字设置
color: '#01F8FF'
// fontSize: 12 ,
},
data: ['7月', '6月', '5月', '4月', '3月', '2月', '1月', '12月', '11月', '10月', '9月', '8月', '7月']
},
yAxis: {
show: true,
type: 'value',
max: 0.6,
// data: ['0.000', '0.100', '0.200', '0.300', '0.400', '0.500', '0.600'],
axisLine: {
//坐标轴轴线相关设置
show: true,
lineStyle: {
color: '#007FFF',
width: 2
}
},
axisLabel: {
// 坐标轴文字设置
color: '#01F8FF',
// fontSize: 12 ,
formatter: function(value) {
const texts: any = []
if (Number(value) < 0.1) {
texts.push('0.000')
} else if (Number(value) < 0.2) {
texts.push('0.100')
} else if (Number(value) < 0.3) {
texts.push('0.200')
} else if (Number(value) < 0.4) {
texts.push('0.300')
} else if (Number(value) < 0.5) {
texts.push('0.400')
} else if (Number(value) < 0.6) {
texts.push('0.500')
} else if (Number(value) < 0.7) {
texts.push('0.600')
}
return texts
}
},
splitLine: {
// 坐标轴在 grid 区域中的分隔线
show: false,
lineStyle: {
color: '#0851B5',
width: 1
}
},
minorSplitLine: {
// 坐标轴的次分割线
show: true,
lineStyle: {
color: '#0851B5',
opacity: 0.5 // 图线透明度
// join: 'bevel',
}
},
minorTick: {
// 坐标轴线上的刻度设置
show: false
},
data: [0, 20, 40, 80, 100]
},
series: [
{
name: '长途',
type: 'line',
symbol: 'none',
smooth: 0, // 折线弧度
// stack: '长途',
data: ['0.230', '0.231', '0.234', '0.240', '0.250', '0.275', '0.280', '0.285', '0.280', '0.270', '0.260', '0.250', '0.240']
},
{
name: '中途',
type: 'line',
symbol: 'none',
smooth: 0, // 折线弧度
// stack: '中途',
data: ['0.290', '0.280', '0.275', '0.279', '0.298', '0.310', '0.323', '0.319', '0.320', '0.310', '0.297', '0.295', '0.300']
},
{
name: '短途',
type: 'line',
// stack: '总量',
smooth: 0, // 折线弧度
symbol: 'none',
data: ['0.460', '0.456', '0.445', '0.450', '0.460', '0.470', '0.485', '0.496', '0.500', '0.495', '0.489', '0.470', '0.460']
}
]
}
}
},
setup() {
return {}
},
created() {},
mounted() {
const currentWindow: isWindow = Window
const Echarts = currentWindow.$Echarts
let myChart = Echarts.init(document.getElementById('lineChart'))
// let myChart = Echarts.init(this.$refs["rightPieChart"]);
myChart.setOption(this.chartsOption)
}
})
</script>
<style lang="scss" scoped>
.box-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.content {
height: 100%;
width: 100%;
.charts-content {
width: 100%;
height: 100%;
}
}
}
</style>
特殊折线图
<template>
<CommonBox class="inner" :isLoaded="isLoaded">
<div class="header">
<p class="header-left">总量变化趋势</p>
<FormItem size="mini">
<el-select
:options="selectEnum"
v-model="currentSelect"
:popper-append-to-body="false"
@change="selectChangeFn"
>
<el-option
v-for="item in selectEnum"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</FormItem>
</div>
<e-charts v-show="!isLoaded" :option="option" autoresize />
</CommonBox>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, watch } from 'vue';
import * as echarts from 'echarts';
import CommonBox from './commonBox.vue';
import { ECharts } from '/@/components/ECharts';
import { EChartsOption } from 'echarts';
import { FormItem } from '/@/components/Form';
import { getDataList } from '/@/api/dataLayout/index';
import dayjs from 'dayjs';
export default defineComponent({
components: {
CommonBox,
ECharts,
FormItem,
},
props: {
refreshNum: {
type: Number,
default: 0,
},
},
setup(props) {
const selectEnum = ref([
{
value: 1,
label: '最近7天',
},
{
value: 2,
label: '最近半年',
},
]);
const currentSelect = ref(1);
const queryTab = ref('purchaseShipmentTrendDay');
const option = ref<EChartsOption>({});
const isLoaded = ref(1);
const xAxisBig = ref(false);
watch(
() => props?.refreshNum,
(newVal) => {
if (newVal) {
getList();
}
}
);
onMounted(async () => {
setTimeout(() => {
getList();
}, 1600);
});
// select change
function selectChangeFn(val) {
if (val === 1) {
queryTab.value = 'purchaseShipmentTrendDay'; // 按日统计
} else {
queryTab.value = 'purchaseShipmentTrendMonth'; // 按月统计
}
getList();
}
async function getList() {
const dayCount = currentSelect.value === 1 ? 6 : 179;
const st = new Date().setDate(new Date().getDate() - dayCount);
const start = dayjs(st).format('YYYY-MM-DD');
const end = dayjs().format('YYYY-MM-DD');
const params = {
category: 'tssShipmentHo',
tab: queryTab.value,
fetchMode: 'body',
groupId: 'all',
query: {
logic: 'and',
items: [
{
leftValue: 'shipmentOpInfoIn.finishTime',
predicate: 'between',
rightValue: [`${start} 00:00:00`, `${end} 23:59:59`],
},
],
},
};
const { errno, res } = await getDataList(params);
isLoaded.value = res?.data?.length ? 0 : 2;
if (errno !== '0') return;
setEChartsData(res.data);
}
function setEChartsData(data) {
xAxisBig.value = false;
let XAxisData: any = [];
const seriesData: any = [];
XAxisData = getXAxisTimeList(currentSelect.value);
XAxisData.forEach((t) => {
const obj = data.find((item) => t === item['shipmentOpInfoIn.finishTime']);
if (obj) {
seriesData.push(obj.unloadNetWeight);
} else {
seriesData.push(0);
}
});
xAxisBig.value = data.some((s) => s.unloadNetWeight > 8000);
option.value = {
backgroundColor: 'transparent',
tooltip: {
trigger: 'item',
},
//图表的位置
grid: {
left: xAxisBig.value ? '16%' : '10%',
top: '12%',
right: '1%',
},
xAxis: {
data: XAxisData,
axisLine: {
show: true, //隐藏X轴轴线
lineStyle: {
color: '#4F566D', // 设置透明度会显示下方虚线
},
},
axisTick: {
show: false, //隐藏X轴刻度
},
axisLabel: {
show: true,
fontSize: 12,
color: 'rgba(255,255,255,0.75)',
interval: 0,
},
// 内部虚线框
splitLine: {
show: true,
lineStyle: {
color: '#ffffff',
width: 1,
type: 'dashed',
opacity: 0.2,
},
},
},
yAxis: [
{
type: 'value',
name: '单位:t',
nameGap: 15, // 坐标名称与轴线距离
nameLocation: 'end',
nameTextStyle: {
color: 'rgba(255,255,255,0.75)',
fontSize: 12,
padding: [0, 30, 0, 0],
},
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
lineStyle: {
color: '#c0c3cd',
},
},
axisLabel: {
show: true,
fontSize: 12,
color: 'rgba(255,255,255,0.75)',
},
splitLine: {
show: true,
lineStyle: {
color: '#ffffff',
width: 1,
type: 'dashed',
opacity: 0.2,
},
},
},
{
type: 'value',
name: '',
position: 'right',
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
},
{
type: 'value',
splitLine: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
splitArea: {
show: false,
},
},
],
series: [
{
name: '',
type: 'line',
smooth: false, //平滑曲线显示
symbol: 'circle', //标记的图形为实心圆
symbolSize: 16, //标记的大小
itemStyle: {
//折线拐点标志的样式
color: 'transparent',
borderWidth: 1, // 圆的border
shadowColor: 'rgba(72,216,191, 0.3)',
shadowBlur: 10,
borderColor: '#FEBE36',
},
lineStyle: {
color: '#FFB236',
},
areaStyle: {
color: 'transparent',
},
data: seriesData,
},
// 内部白色圆点
{
name: '',
type: 'line',
smooth: false, //平滑曲线显示
symbol: 'circle', //标记的图形为实心圆
symbolSize: 3, //标记的大小
itemStyle: {
//折线拐点标志的样式
color: '#ffffff',
borderWidth: 3, // 圆的border
shadowColor: 'rgba(72,216,191, 0.3)',
shadowBlur: 10,
borderColor: '#ffffff',
},
lineStyle: {
color: '#FFB236',
},
areaStyle: {
color: 'transparent',
},
data: seriesData,
},
// 下方柱线
{
name: '',
type: 'bar',
barWidth: 2,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#FFB236' },
{ offset: 1, color: '#675236' },
]),
},
data: seriesData,
},
],
};
}
// 获取x轴时间列表
function getXAxisTimeList(type, region = 7) {
// region 区间数
const timeList: string[] = [];
for (let i = 0; i < region; i++) {
const date = new Date();
if (type === 1) {
date.setDate(date.getDate() - i);
} else {
date.setMonth(date.getMonth() - i);
}
const dateStr = dateFormater(date, type === 1 ? 'day' : 'month');
timeList.unshift(dateStr);
}
return timeList;
}
// x轴时间格式化
function dateFormater(time, type) {
const date = new Date(time);
let y = date.getFullYear();
let M = date.getMonth() + 1; //获取当前月份的日期
let d = date.getDate();
if (type === 'day') {
return `${M < 10 ? '0' + M : M}.${d < 10 ? '0' + d : d}`;
} else {
return `${y.toString().slice(2)}.${M < 10 ? '0' + M : M}`;
}
}
return {
selectEnum,
currentSelect,
option,
queryTab,
selectChangeFn,
isLoaded,
};
},
});
</script>
<style lang="less" scoped>
.inner {
height: 100%;
}
</style>
图表大小自适应
import { debounce } from '@/utils'
export default {
mounted() {
this.__resizeHanlder = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHanlder)
},
beforeDestroy() {
window.removeEventListener('resize', this.__resizeHanlder)
}
}