通用组件(利用组件可快速实现常用图表)
ComLineChart.vue 组件
<template>
<div ref="boxRef" style="position: relative; z-index: 1; width: 100%; height: 100%">
<!--图表容器 -->
<div ref="chartRef" style="width: 100%; height: 100%"></div>
</div>
</template>
<script setup>
import * as echarts from "echarts";
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";
const boxRef = ref(null);
const chartRef = ref(null);
let chartInstance = null;
let chartResizeObserver = null;
// 默认参数
const defaultParam = ref({
title: {}, // 标题组件
label: {}, // 标签
labelLine: {}, // 标签引导线配置
tooltip: {}, // 提示框组件
legend: {}, // 图例组件
grid: {}, // 坐标系容器
showLegend: true, // 图例是否显示
xAxis: {}, // X轴
xData: [], // X轴展示的数据, 例如: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
xFormatter: `{value}`, // 内容格式器
xAxisLineColor: "#DBDEE3", // 坐标轴线的颜色
xShowAxisLine: true, // 是否显示X轴的坐标线
xBoundaryGap: true, // 坐标轴两边留白策略, 柱状图要设置 true, 对于折线图要想起始点在 Y轴上要设置为false.
xInterval: 0, // 用于刻度标签的间隔多少个再显示标签
xRotate: 0, // 用于刻度标签的旋转角度 -90 度到 90
xAxisLabel: true, // xAxisLabel
yAxis: {}, // Y轴
yName: "", // Y轴的名称 例如: Y轴表示 "(辆) "
yShowAxisLine: true, // 是否显示Y轴的坐标线
yAxisLineColor: "#DBDEE3", // Y轴线颜色
yShowSplitLine: true, //是否分隔线
ySplitLineStyle: {
type: "solid", // 指定线条样式: 'solid', 'dashed', 'dotted' 虚线可以设置虚线的长短和偏移量: type: [5, 10], dashOffset: 5
color: ["#B2C2D3"], // 分割线颜色
opacity: 1, // 图形透明度 0-1
},
series: [
// 系列
{
name: "系列名称", // 图例名称
legendIcon: "", // 自定义图例图标样式 ( 折线图默认是圆圈加横线, 柱状图默认是矩形) 'emptyCircle', 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: "line",
},
],
});
const props = defineProps({
data: {
type: Object,
default() {
return {};
},
},
});
// 渲染图表数据
const setOptions = (ops) => {
const params = { ...defaultParam.value, ...ops };
console.log("======📈📈= 打印图表参数 📈📈:", params);
// 动态设置图表配置参数
let option = {
title: {
// 标题组件
show: false,
...(params.title || {}),
},
label: {
// 文本标签
show: false,
...(params.label || {}),
},
labelLine: {
// 引导线配置
show: false,
...(params.labelLine || {}),
},
tooltip: {
// 提示框组件
show: true,
trigger: "axis",
axisPointer: {
type: "shadow",
},
textStyle: {
fontWeight: "bold",
fontSize: 16,
},
confine: true, //
...(params.tooltip || {}),
},
legend: {
// 图例组件
show: params.series.length > 0 && params.showLegend !== false,
selectedMode: true, // 控制是否可以通过点击图例改变系列的显示状态
top: "10",
right: "1.5%",
itemGap: 14,
itemWidth: 16,
itemHeight: 8,
// icon: "rect", // 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
textStyle: {
color: "#333",
fontSize: 14,
},
// 支持自定义图例图标和样式
data: params.series
.filter((item) => item && item.type !== "pictorialBar")
.map((item) => ({
name: item.name,
icon: item.legendIcon,
itemStyle: {
color: item.itemStyle?.color || item.color || "#5470c6",
},
})),
...(params.legend || {}),
},
grid: {
// 坐标系容器
top: "50",
left: "3%",
right: "5%",
bottom: "4%",
containLabel: true, // 防止标签溢出
...(params.grid || {}),
},
xAxis: {
// x 轴
type: "category", // 类目轴
data: params.xData, // 类目数据: data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
boundaryGap: params.xBoundaryGap, // 坐标轴两边留白策略, 柱状图要设置 true, 对于折线图要想起始点在 Y轴上要设置为false.
splitLine: {
// 显示分隔线
show: false,
},
axisLabel: {
// 刻度标签
show: params.xAxisLabel, // 是否展示刻度标签
fontSize: 15,
color: "#7591B2",
interval: params.xInterval, // 用于刻度标签的间隔多少个再显示标签
rotate: params.xRotate, // 用于刻度标签的旋转角度 -90 度到 90
margin: 10, // 刻度标签与轴线之间的距离。
formatter: params.xFormatter, // 刻度标签的内容格式器 例如: '{value} kg'
/*
formatter: function (value, index) {
return value + 'kg';
}
*/
},
axisTick: {
// 是否显示坐标轴刻度。
show: false,
},
axisLine: {
// 坐标轴轴线
show: params.xShowAxisLine,
lineStyle: {
color: params.xAxisLineColor,
},
},
...(params.xAxis || {}),
},
yAxis: Array.isArray(params.yAxis)
? params.yAxis
: {
// Y轴
type: "value",
name: params.yName, // y坐标轴单位名称。
nameGap: 20,
nameTextStyle: {
// y 坐标轴名称的文字样式
color: "#B5C5D4",
fontSize: 15,
},
splitLine: {
// 分隔线
show: params.yShowSplitLine,
lineStyle: {
type: "solid", // 指定线条样式: 'solid', 'dashed', 'dotted' 虚线可以设置虚线的长短和偏移量: type: [5, 10], dashOffset: 5
color: ["#B2C2D3"], // 分割线颜色
opacity: 1, // 图形透明度 0-1
...params.ySplitLineStyle,
},
},
axisLabel: {
// 坐标轴刻度标签
show: true,
fontSize: 15,
color: "#B5C5D4",
margin: 10,
},
axisTick: {
// 坐标轴刻度
show: false,
},
axisLine: {
// 坐标轴轴线
show: params.yShowAxisLine,
lineStyle: {
color: params.yAxisLineColor,
},
},
...(params.yAxis || {}),
},
series: params.series.map((item) => {
// 系列用来设置样式
return { ...item };
}),
};
// 清除画布
chartInstance && chartInstance.clear();
// 重新渲染
chartInstance && chartInstance.setOption(option);
};
watch(
() => props.data,
(val) => {
nextTick(() => {
setOptions(val);
});
},
{ deep: true, immediate: true }
);
// 异步观察元素尺寸变化的
onMounted(() => {
chartInstance = echarts.init(chartRef.value);
chartResizeObserver = new ResizeObserver(() => {
requestAnimationFrame(() => {
chartInstance?.resize();
});
});
chartResizeObserver.observe(boxRef.value);
});
onBeforeUnmount(() => {
chartResizeObserver?.disconnect();
chartInstance?.dispose();
chartResizeObserver = null;
chartInstance = null;
});
</script>
<style lang="scss" scoped></style>
页面使引用:
<template>
<div style="width: 500px; height: 500px">
<ComChart :data="lineChart"></ComChart>
</div>
</template>
// 引用组件
import ComChart from "./components/ComLineChart.vue";
1. 折线图
5fbfb540-07f3-4915-bf92-29070d8625b7.png
// 折线图
const lineChart = ref({
xBoundaryGap: true,
xAxisLineColor: "#304871",
yName: "(辆)",
ySplitLine: true,
ySplitLineStyle: {
// 设置 Y轴隔离线为虚线
type: [1, 4],
dashOffset: 3,
color: ["#516179"],
opacity: 1,
},
yShowAxisLine: false,
smooth: false, // 是否平滑曲线显示
showSymbol: true, // 是否显示 symbol,
symbol: "emptyCircle", // 标记的图形。'emptyCircle', 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
tooltip: { // 使用坐标轴提示框
axisPointer: {}
},
xData: ["企业1", "企业2", "企业3", "企业4", "企业5", "企业6"],
series: [
{
name: "折线图",
type: "line",
data: [20, 10, 36, 10, 10, 20],
},
],
});
2. 带背景的柱状图
9209f8b4-b350-4e85-a3d6-d8e45f823103.png
// 柱状图
const barChart = ref({
xBoundaryGap: true,
xAxisLineColor: "#304871",
yName: "(辆)",
ySplitLine: true,
ySplitLineStyle: {
// 设置 Y轴隔离线为虚线
type: [1, 4],
dashOffset: 3,
color: ["#516179"],
opacity: 1,
},
yShowAxisLine: false,
xData: ["企业1", "企业2", "企业3", "企业4", "企业5", "企业6"], // 修复:xdata -> xData
series: [
{
name: "图例名称",
type: "bar",
data: [40, 20, 66, 80, 30, 20],
barWidth: 20, // 柱体宽
showBackground: true, // 是否显示柱条的背景色
backgroundStyle: {
// 设置柱条的背景色
color: "rgb(1,1,1,0.1)",
},
itemStyle: {
// 设置柱体渐变色
color: {
type: "linear",
x: 1,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: "red", // 0% 处的颜色
},
{
offset: 1,
color: "blue", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
],
});
3. 堆叠柱状图 + 折线图的示例
bf4ff2da-b53f-46d4-8c2e-6e6c85b30b18.png
// 这是一个柱状图 + 折线图的示例, 不要删除!!!
// legendIcon: "rect", // 自定义图例图标为长方形
const fzBarChart = ref({
xBoundaryGap: true,
xAxisLineColor: "#349ADF",
yName: "(票)",
yShowAxisLine: false,
ySplitLine: true,
ySplitLineStyle: {
// 设置 Y轴隔离线为虚线
type: [1, 4],
dashOffset: 3,
color: ["#5DC0FF"],
opacity: 1,
},
xData: ["企业1", "企业2", "企业3", "企业4", "企业5", "企业6"],
series: [
{
name: "快件",
type: "bar",
stack: "货量", // 数据堆叠,同个类目轴上系列配置相同的 stack 值可以堆叠放置
barWidth: 20, // 柱体宽
data: [40, 20, 66, 80, 30, 20],
legendIcon: "rect", // 自定义图例图标为长方形
itemStyle: {
// 设置柱体渐变色
color: {
type: "linear",
x: 1,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: "#1B2C44", // 0% 处的颜色
},
{
offset: 1,
color: "#3EE087", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
{
name: "跨境",
type: "bar",
stack: "货量", // 数据堆叠,同个类目轴上系列配置相同的 stack 值可以堆叠放置
barWidth: 20, // 柱体宽
data: [10, 20, 36, 40, 50, 60],
legendIcon: "rect", // 自定义图例图标为长方形
itemStyle: {
// 设置柱体渐变色
color: {
type: "linear",
x: 1,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: "#122D4B", // 0% 处的颜色
},
{
offset: 1,
color: "#0470ED", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
{
name: "总量",
type: "line",
data: [50, 40, 92, 80, 80, 90],
smooth: false, // 是否平滑曲线显示
showSymbol: true, // 是否显示 symbol,
symbol: "emptyCircle", // 标记的图形。'emptyCircle', 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
symbolSize: 8, // 标记的大小,稍微增大一点
z: 10, // 设置层级,确保折线图在最上层
legendIcon: "", // 使用 line 图标类型,实现标准的折线图图例
lineStyle: {
// 线条样式
color: "#1DBFDA", // 修复颜色值,添加 # 号
width: 3, // 增加线条宽度
},
itemStyle: {
// 折线拐点标志的样式
color: "#1DBFDA", // 使用与线条相同的颜色
},
// 添加数值标签显示
label: {
show: true, // 显示标签
position: "top", // 标签位置:top(上方), bottom(下方), left(左侧), right(右侧)
distance: 8, // 标签与拐点的距离
fontSize: 12, // 标签字体大小
color: "#1DBFDA", // 标签颜色,与线条颜色保持一致
fontWeight: "bold", // 字体粗细
formatter: "{c}", // 标签内容格式,{c} 表示数据值
backgroundColor: "rgba(255,255,255,0.8)", // 标签背景色
borderRadius: 4, // 背景圆角
padding: [4, 6], // 标签内边距 [上下, 左右]
borderColor: "#1DBFDA", // 边框颜色
borderWidth: 1, // 边框宽度
},
},
],
});
4. 区域图
7ec3d990-0f04-4905-aefc-2aa7141d88d4.png
// 区域图图标示例, 不要删除!!!
const areaLineChart = ref({
xBoundaryGap: false,
xAxisLineColor: "#349ADF",
yName: "(票)",
yShowAxisLine: false,
ySplitLine: true,
ySplitLineStyle: {
// 设置 Y轴隔离线为虚线
type: [1, 4],
dashOffset: 3,
color: ["#5DC0FF"],
opacity: 1,
},
tooltip: {
trigger: "axis",
textStyle: {
fontWeight: "bold",
fontSize: 16,
},
// 去掉阴影,只保留坐标系
axisPointer: {},
},
/** 配置双 Y轴
* 创建双 Y轴后, 需要在 series 中的 图形中使用 yAxisIndex 指定图形对应的 Y轴数据
* yAxisIndex: 当一个 ECharts 实例中存在多个 y轴时,用其指定所使用的 y 轴。
*/
yAxis: [
{
// 左边的 Y轴
type: "value",
position: "left",
name: "(票)",
nameTextStyle: {
color: "#333",
fontSize: 15,
},
splitLine: {
show: true,
lineStyle: {
type: [1, 4],
color: ["#5DC0FF"],
opacity: 1,
},
},
axisLabel: {
fontSize: 15,
color: "#333",
margin: 10,
formatter: "{value}",
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
},
{
// 右边 Y轴
type: "value",
position: "right",
// name: "(%)",
// nameGap: 20,
// nameTextStyle: {
// color: "#333",
// fontSize: 15,
// },
splitLine: {
show: false, // 右边轴不显示分割线,避免重叠
},
axisLabel: {
fontSize: 15,
color: "#333",
margin: 10,
formatter: "{value}%",
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
},
],
xData: ["企业1", "企业2", "企业3", "企业4", "企业5", "企业6"],
series: [
{
name: "进口",
type: "line",
yAxisIndex: 0, // 使用左边的Y轴(数值轴), 当一个 ECharts 实例中存在多个 y轴时,用其指定所使用的 y 轴。
// stack: "货量", // 数据堆叠,同个类目轴上系列配置相同的 stack 值可以堆叠放置
smooth: true, // 是否平滑曲线显示
data: [80, 20, 86, 30, 60, 20],
// symbol: 'none', //标记的图形。
showSymbol: false, // 是否显示 symbol,
areaStyle: {
// 线性渐变,前四个参数分别是 x0, y0, x2, y2, 范围从 0 - 1,相当于在图形包围盒中的百分比,如果 globalCoord 为 `true`,则该四个值是绝对的像素位置
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(49, 175, 255, 1)", // 0% 处的颜色
},
{
offset: 1,
color: "rgba(49, 175, 255, 0.37)", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
{
name: "出口",
type: "line",
// stack: "货量", // 数据堆叠,同个类目轴上系列配置相同的 stack 值可以堆叠放置
yAxisIndex: 1, // 使用右边的Y轴(百分比轴)
smooth: true, // 是否平滑曲线显示
data: [20, 80, 26, 80, 20, 50],
// symbol: 'none', //标记的图形。
showSymbol: false, // 是否显示 symbol,
areaStyle: {
// 径向渐变,前三个参数分别是圆心 x, y 和半径,取值同线性渐变
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(192, 210, 242, 1)", // 0% 处的颜色
},
{
offset: 1,
color: "rgba(192, 210, 242, 0.37)", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
],
});
5. 纹理柱状图
7ff0dd81-6d52-422b-b8ad-5f565e8d4da1.png
/** 纹理图柱状图
*
* pictorialBar是如何定位的?
*
* 首先设置:
* barGap: '-100%', // 想要两个系列的柱子重叠,可以设置 barGap 为 '-100%'
* z: 2, // 控制图像将图像显示到最上,防止被其他图像遮盖
*
* 要理解一点: 即使创建多个 pictorialBar, 它的初始位置都会重叠在一起且创建单个柱图的上方.
* 后面可通过 symbolOffset 来定位 不同的pictorialBar的位置偏移进行调整.
*
* 主要通过 symbolPosition、symbolOffset
* -- symbolPosition 在柱体内图形的定位位置, start, end, center
* -- symbolOffset 图形相对于原本位置的偏移. 注意: 这个偏移是相对于每个单个柱体的位置来定位的.
*
*
*/
const pictorialBarChart = ref({
xBoundaryGap: true,
xAxisLineColor: "#349ADF",
yName: "(票)",
yShowAxisLine: false,
ySplitLine: true,
ySplitLineStyle: {
// 设置 Y轴隔离线为虚线
type: [1, 4],
dashOffset: 3,
color: ["#5DC0FF"],
opacity: 1,
},
xData: ["企业1", "企业2", "企业3", "企业4", "企业5", "企业6"],
series: [
{
name: "快件",
type: "bar",
barWidth: 20, // 柱体宽
data: [40, 20, 66, 80, 30, 20],
legendIcon: "rect", // 自定义图例图标为长方形
itemStyle: {
// 设置柱体渐变色
color: {
type: "linear",
x: 1,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: "#1B2C44", // 0% 处的颜色
},
{
offset: 1,
color: "#3EE087", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
z: 1,
},
{
// 象形柱体,是个柱状图,但是柱状图的柱子并不显示.
type: "pictorialBar",
barWidth: 20, // 柱体宽
barGap: "-100%", // 不同系列的柱间距离, 两个系列的柱子重叠,可以设置 barGap 为 '-100%'
data: [40, 20, 66, 80, 30, 20], // 通过数据定位
symbol: "rect", // 图形类型
symbolMargin: 2.5, // 图形的两边间隔
symbolSize: [25, 3], // 图形的大小 [宽,高] ,
symbolRepeat: true, // 元素是否重复
symbolClip: true, // 是否剪裁图形
symbolRotate: "45", // 图形的旋转角度
symbolOffset: [ // 定位偏移,确保显示的位置准确
"-47%",
"0"
],
itemStyle: {
// 设置柱体渐变色
color: "orange",
opacity: 1,
},
z: 2, // 显示优先级
},
{
name: "跨境",
type: "bar",
barWidth: 20, // 柱体宽
data: [10, 20, 36, 40, 50, 60],
legendIcon: "rect", // 自定义图例图标为长方形
itemStyle: {
// 设置柱体渐变色
color: {
type: "linear",
x: 1,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: "#122D4B", // 0% 处的颜色
},
{
offset: 1,
color: "#0470ED", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
"z": 1,
},
{
// 象形柱体
type: "pictorialBar",
data: [10, 20, 36, 40, 50, 60], // 通过数据定位
barWidth: 20,
barGap: "-100%",
symbol: "rect",
symbolMargin: 2.5,
symbolSize: [25, 2],
symbolRepeat: true,
symbolClip: true,
symbolRotate: "45",
symbolOffset: [
"50%",
"0"
],
itemStyle: {
color: "red",
opacity: 1,
},
z: 2,
},
],
});
6. 饼图
32ddb15e-cd20-47c7-8abb-5068cd9fb130.png
/**
* 圆环
*/
const pieChart = ref({
xAxis: {
show: false
},
yAxis: {
show: false
},
title: {
show: true,
x: "center",
y: "center",
text: "{name|总数}\n{val|10256个}",
textStyle: {
rich: {
name: {
fontSize: 14,
fontWeight: "normal",
color: "#666666",
padding: [10, 0],
},
val: {
fontSize: 32,
fontWeight: "bold",
color: "#333333",
},
}
},
},
series: [{
type: 'pie',
radius: ['45%', '60%'],
center: ['50%', '50%'],
data: [
{
name: "A类",
value: "3720",
},
{
name: "B类",
value: "2920",
},
{
name: "C类",
value: "2200",
},
{
name: "D类",
value: "1420",
},
],
itemStyle: { // 每份数据, 通过设置borderWidth可以将间距显示出来
borderColor: "#fff",
borderWidth: 10,
},
labelLine: {
// 标签的视觉引导线配置
show: true,
length: 20, // 视觉引导线第一段的长度
length2: 100, // 视觉引导项第二段的长度。
lineStyle: {
color: "red"
}
},
label: {
padding: [0, -100, 25, -100],
formatter: (params) => {
return (
"{icon|●}{name|" +
params.name +
"}{value|1000}"
);
},
rich: {
icon: {
fontSize: 16,
},
name: {
fontSize: 14,
padding: [0, 10, 0, 4],
color: "#666666",
},
value: {
fontSize: 18,
fontWeight: "bold",
color: "#333333",
},
},
}
}]
})
7. 使用极坐标系实现圆环进度条
c6360233-3e62-4dac-82f6-8e3dd6e2a49d.png
/** 使用极坐标系实现圆环进度条
*
*/
const jzbRingChart = ref({
title: [
{
text: "已完成",
x: "center",
top: "55%",
textStyle: {
color: "#FFFFFF",
fontSize: 16,
fontWeight: "100",
},
},
{
text: "75%",
x: "center",
y: "center",
textStyle: {
fontSize: "60",
color: "#FFFFFF",
fontFamily: "DINAlternate-Bold, DINAlternate",
foontWeight: "600",
},
},
],
backgroundColor: "#111",
polar: { // 极坐标系
radius: ["42%", "52%"], // 极坐标系的半径
center: ["50%", "50%"], // 极坐标系的中心(圆心)坐标
},
angleAxis: { // 极坐标系的角度轴。
max: 100,
show: false,
},
radiusAxis: { // 极坐标系的径向轴
type: "category", // 指定类目轴类目数据可自动从 series.data获取
show: true,
axisLabel: { //坐标轴刻度标签的相关设置
show: false,
},
axisLine: { // 坐标轴轴线相关设置
show: false,
},
axisTick: { // 坐标轴刻度相关设置
show: false,
},
},
series: [
{
name: "",
type: "bar",
roundCap: true, // 是否在环形柱条两侧使用圆弧效果。
barWidth: 30,
showBackground: true,
backgroundStyle: {
color: "rgba(66, 66, 66, .3)",
},
data: [60],
coordinateSystem: "polar", // 布局在一个 极坐标系中
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: "#16CEB9",
},
{
offset: 1,
color: "#6648FF",
},
]),
},
},
},
{
name: "",
type: "pie",
startAngle: 80,
radius: ["56%"],
center: ["50%", "50%"],
itemStyle: {
color: "rgba(66, 66, 66, .1)",
borderWidth: 1,
borderColor: "red",
},
data: [100],
},
{
name: "",
type: "pie",
startAngle: 80,
radius: ["38%"],
hoverAnimation: false,
center: ["50%", "50%"],
itemStyle: {
color: "rgba(66, 66, 66, .1)",
borderWidth: 1,
borderColor: "orange",
},
data: [100],
},
],
})