最终页面效果
问题现象背景
之前一篇文档是将一条曲线的数据根据类型拆分开两个series的两个数组实现虚实结合,但是存在一个问题,曲线类型为smooth为true的时候,对于虚线与实线的转折点会存在曲线趋势不圆滑的问题,这是因为将一条线的数据拆开两个数组存进series里面,一条曲线相当于被拆成两条曲线拼接在一起,势必会存在虚实之间曲线趋势不圆滑的问题。
之前曲线打点的时候,用的是 visualMap ,想了一下是否可以用 visualMap 来实现一条曲线上实现圆滑的虚实曲线图,实践后是可行的 。
对比:
1、visualMap piecewise是根据数据的维度做分段映射,本质上是一组数据的不同分段的映射。
2、而之前的的方式,是一组数据拆成了两组数据,实质是两组数据的拼接,拼接的位置就一定会存在趋势不圆滑的问题。
【2024-04-11】Echarts 折线上实线虚实曲线结合_echarts 折线图 实现虚线实线-优快云博客
visualMap 具体功能参考API Documentation - Apache ECharts
代码部分:
<template>
<div class="out-scc main">
<div class="chart-css" id="main"></div>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
import * as echarts from 'echarts';
import Https from '@/axios/http.js';
onMounted(() => {
showCurve();
});
function curveData() {
return Https.curveXuShi();
}
async function showCurve() {
const chartDom = document.getElementById('main');
let myChart = echarts.init(chartDom);
const responseData = await curveData();
const res = responseData.data.data;
let nameList = [];
for (let item in res) {
nameList.push(item);
}
let xData = []; // 横坐标数据
for (let item in res) {
res[item].map((val) => {
if (xData.indexOf(val.time) === -1) {
xData.push(val.time);
}
});
}
xData.sort((a, b) => a - b);
let xObjData = {}; // 线的纵坐标数据
for (let item in res) {
xObjData[item] = res[item].map((v) => v.data || '-');
}
let colors = [
'#8681FF',
'#FA053B',
'#00FFC9',
'#1515FF',
'#798300',
'#BF89FF',
];
/**
* 配合后面的 rich 使用
* let setRichColorObj = {};
colors.forEach((v, i) => {
setRichColorObj['name' + i] = {
color: v,
fontSize: 14,
};
setRichColorObj['num' + i] = {
color: v,
fontSize: 14,
};
});
*/
let option = {
backgroundColor: 'rgba(11, 51, 126, 0.8)',
tooltip: {
trigger: 'axis',
formatter: (params) => {
let filterList = params.filter((v, i) => i % 2 === 0);
let name = filterList[0].name;
let tipBox = '';
filterList.forEach((v, i) => {
tipBox +=
`<span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:${colors[i]};"></span>` +
v.seriesName +
': ' +
v.value +
'<br/>';
});
return name + '<br/>' + tipBox;
},
backgroundColor: '#133d7e',
axisPointer: {
lineStyle: {
color: '#7ec7ff',
},
},
borderWidth: 0,
textStyle: {
color: '#fff',
},
confine: true,
},
legend: {
// right: '5%',
left: 'center',
top: '6%',
textStyle: {
color: '#ffffff',
fontSize: 16,
},
icon: 'rect',
itemGap: 25,
itemWidth: 16,
itemHeight: 12,
},
grid: {
top: '17%',
left: '5%',
right: '15%',
bottom: '4%',
containLabel: true,
},
xAxis: {
type: 'category',
boundaryGap: false,
axisLine: {
show: false,
lineStyle: {
color: '#4d538d',
width: 4,
},
},
axisLabel: {
interval: 0,
margin: 20,
textStyle: {
color: '#C5E4FE',
fontSize: 16,
},
},
splitLine: {
show: false,
lineStyle: {
color: 'rgba(27, 179, 245, 0.4)',
},
},
axisTick: {
show: false,
},
data: xData,
},
yAxis: {
splitLine: {
show: true,
lineStyle: {
color: 'rgba(27, 179, 245, 0.4)',
},
},
axisLine: {
show: false,
lineStyle: {
color: '#4d538d',
width: 4,
},
},
axisLabel: {
margin: 20,
textStyle: {
color: '#C5E4FE',
fontSize: 16,
},
},
axisTick: {
show: false,
},
},
visualMap: [],
series: [],
dataZoom: [
{
type: 'inside',
show: false,
start: 0,
end: 100,
yAxisIndex: [0],
},
], // 缩放功能
};
nameList.forEach((v, i) => {
const resClone = JSON.parse(JSON.stringify(res));
const dataList = resClone[v];
let xuList = dataList.filter((item) => {
return item.type === 'forecast';
});
const solidLength = dataList.length - 1 - xuList.length;
option.visualMap.push(
{
type: 'piecewise', // continuous 连续型 piecewise 分段型
show: false, // 是否显示 visualMap-piecewise 组件。如果设置为 false,不会显示,但是数据映射的功能还存在。
dimension: 0,
seriesIndex: 2 * i, // 指定取哪个系列的数据,即哪个系列的 series.data。 默认取所有系列。
pieces: [
// 分段型属性,自定义『分段式视觉映射组件(visualMapPiecewise)』的每一段的范围,以及每一段的文字,以及每一段的特别的样式
{
gte: 0, // lt(小于),lte(小于等于)来表达边界
lte: solidLength, // gt(大于),gte(大于等于)来表达边界
color: colors[i],
},
{
gt: solidLength,
lte: 100,
color: '#0000', // 透明色
},
],
},
{
type: 'piecewise',
show: false,
dimension: 0,
seriesIndex: 2 * i + 1,
pieces: [
{
gte: 0,
lte: solidLength,
color: '#0000',
},
{
gt: solidLength,
color: colors[i],
},
],
}
);
option.series.push(
{
name: v,
type: 'line',
smooth: true,
showAllSymbol: false,
symbolSize: 0,
data: xObjData[v],
},
{
name: v,
type: 'line',
smooth: true,
showAllSymbol: false,
symbolSize: 0,
itemStyle: {
normal: {
lineStyle: {
width: 2,
type: 'dotted',
},
},
},
data: xObjData[v],
// 右侧是否显示曲线名称及值
/**
* label: {
show: true,
position: 'right',
color: '#fff',
fontSize: 14,
formatter: (params) => {
if (params.dataIndex === xData.length - 1) {
let name = params.seriesName;
let index = nameList.findIndex((v) => v === name);
return `{name${index}|${name}} {num${index}|${params.value}}`;
} else {
return '';
}
},
rich: setRichColorObj,
},
*/
}
);
});
option && myChart.setOption(option);
}
</script>
<style lang="scss" scoped>
.out-scc {
background: #ffffff;
box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
width: 100%;
.chart-css {
height: 500px;
width: 1366px;
}
}
</style>
数据部分:
{
"data":{
"2024年05日":[
{
"data":520,
"time":"01",
"type":"actual"
},
{
"data":444,
"time":"02",
"type":"actual"
},
{
"data":567,
"time":"03",
"type":"actual"
},
{
"data":89,
"time":"04",
"type":"actual"
},
{
"data":11,
"time":"05",
"type":"actual"
},
{
"data":432,
"time":"06",
"type":"actual"
},
{
"data":664,
"time":"07",
"type":"actual"
},
{
"data":222,
"time":"08",
"type":"actual"
},
{
"data":445,
"time":"09",
"type":"actual"
},
{
"data":520,
"time":"10",
"type":"actual"
},
{
"data":1234,
"time":"11",
"type":"actual"
},
{
"data":3432,
"time":"12",
"type":"actual"
},
{
"data":1299,
"time":"13",
"type":"actual"
},
{
"data":234,
"time":"14",
"type":"actual"
},
{
"data":543,
"time":"15",
"type":"actual"
},
{
"data":652,
"time":"16",
"type":"actual"
},
{
"data":2369,
"time":"17",
"type":"actual"
},
{
"data":856,
"time":"18",
"type":"actual"
},
{
"data":223,
"time":"19",
"type":"actual"
},
{
"data":445,
"time":"20",
"type":"forecast"
},
{
"data":765,
"time":"21",
"type":"forecast"
},
{
"data":223,
"time":"22",
"type":"forecast"
},
{
"data":2323,
"time":"23",
"type":"forecast"
},
{
"data":523,
"time":"24",
"type":"forecast"
},
{
"data":1223,
"time":"25",
"type":"forecast"
},
{
"data":2823,
"time":"26",
"type":"forecast"
},
{
"data":993,
"time":"27",
"type":"forecast"
},
{
"data":221,
"time":"28",
"type":"forecast"
},
{
"data":456,
"time":"29",
"type":"forecast"
},
{
"data":876,
"time":"30",
"type":"forecast"
}
],
"2024年06日":[
{
"data":1520,
"time":"01",
"type":"actual"
},
{
"data":4244,
"time":"02",
"type":"actual"
},
{
"data":1567,
"time":"03",
"type":"actual"
},
{
"data":839,
"time":"04",
"type":"actual"
},
{
"data":141,
"time":"05",
"type":"actual"
},
{
"data":1432,
"time":"06",
"type":"actual"
},
{
"data":6634,
"time":"07",
"type":"actual"
},
{
"data":2242,
"time":"08",
"type":"actual"
},
{
"data":4454,
"time":"09",
"type":"actual"
},
{
"data":5420,
"time":"10",
"type":"actual"
},
{
"data":1234,
"time":"11",
"type":"actual"
},
{
"data":1432,
"time":"12",
"type":"actual"
},
{
"data":1099,
"time":"13",
"type":"actual"
},
{
"data":2344,
"time":"14",
"type":"actual"
},
{
"data":443,
"time":"15",
"type":"actual"
},
{
"data":6452,
"time":"16",
"type":"forecast"
},
{
"data":2221,
"time":"17",
"type":"forecast"
},
{
"data":8536,
"time":"18",
"type":"forecast"
},
{
"data":2323,
"time":"19",
"type":"forecast"
},
{
"data":3445,
"time":"20",
"type":"forecast"
},
{
"data":4765,
"time":"21",
"type":"forecast"
},
{
"data":1223,
"time":"22",
"type":"forecast"
},
{
"data":6666,
"time":"23",
"type":"forecast"
},
{
"data":1523,
"time":"24",
"type":"forecast"
},
{
"data":1323,
"time":"25",
"type":"forecast"
},
{
"data":2843,
"time":"26",
"type":"forecast"
},
{
"data":2993,
"time":"27",
"type":"forecast"
},
{
"data":2321,
"time":"28",
"type":"forecast"
},
{
"data":4546,
"time":"29",
"type":"forecast"
},
{
"data":8756,
"time":"30",
"type":"forecast"
}
],
"2024年07日":[
{
"data":"-",
"time":"01",
"type":"forecast"
},
{
"data":"-",
"time":"02",
"type":"forecast"
},
{
"data":"-",
"time":"03",
"type":"forecast"
},
{
"data":"-",
"time":"04",
"type":"forecast"
},
{
"data":"-",
"time":"05",
"type":"forecast"
},
{
"data":"-",
"time":"06",
"type":"forecast"
},
{
"data":"-",
"time":"07",
"type":"forecast"
},
{
"data":"-",
"time":"08",
"type":"forecast"
},
{
"data":"-",
"time":"09",
"type":"forecast"
},
{
"data":"-",
"time":"10",
"type":"forecast"
},
{
"data":"-",
"time":"11",
"type":"actual"
},
{
"data":"-",
"time":"12",
"type":"forecast"
},
{
"data":"-",
"time":"13",
"type":"forecast"
},
{
"data":"-",
"time":"14",
"type":"forecast"
},
{
"data":"-",
"time":"15",
"type":"forecast"
},
{
"data":"-",
"time":"16",
"type":"forecast"
},
{
"data":6589,
"time":"17",
"type":"forecast"
},
{
"data":5555,
"time":"18",
"type":"forecast"
},
{
"data":2323,
"time":"19",
"type":"forecast"
},
{
"data":3445,
"time":"20",
"type":"forecast"
},
{
"data":1765,
"time":"21",
"type":"forecast"
},
{
"data":9223,
"time":"22",
"type":"forecast"
},
{
"data":6323,
"time":"23",
"type":"forecast"
},
{
"data":1323,
"time":"24",
"type":"forecast"
},
{
"data":1323,
"time":"25",
"type":"forecast"
},
{
"data":2423,
"time":"26",
"type":"forecast"
},
{
"data":203,
"time":"27",
"type":"forecast"
},
{
"data":2321,
"time":"28",
"type":"forecast"
},
{
"data":4546,
"time":"29",
"type":"forecast"
},
{
"data":3356,
"time":"30",
"type":"forecast"
}
],
"2024年08日":[
{
"data":"-",
"time":"01",
"type":"actual"
},
{
"data":"-",
"time":"02",
"type":"actual"
},
{
"data":"-",
"time":"03",
"type":"actual"
},
{
"data":"-",
"time":"04",
"type":"actual"
},
{
"data":"-",
"time":"05",
"type":"actual"
},
{
"data":"-",
"time":"06",
"type":"actual"
},
{
"data":"-",
"time":"07",
"type":"actual"
},
{
"data":"-",
"time":"08",
"type":"actual"
},
{
"data":"-",
"time":"09",
"type":"actual"
},
{
"data":"12345",
"time":"10",
"type":"actual"
},
{
"data":"4444",
"time":"11",
"type":"actual"
},
{
"data":"7775",
"time":"12",
"type":"actual"
},
{
"data":"567",
"time":"13",
"type":"actual"
},
{
"data":"2345",
"time":"14",
"type":"actual"
},
{
"data":"-",
"time":"15",
"type":"actual"
},
{
"data":"-",
"time":"16",
"type":"actual"
},
{
"data":"-",
"time":"17",
"type":"actual"
},
{
"data":"-",
"time":"18",
"type":"actual"
},
{
"data":"-",
"time":"19",
"type":"actual"
},
{
"data":"-",
"time":"20",
"type":"actual"
},
{
"data":"-",
"time":"21",
"type":"actual"
},
{
"data":"-",
"time":"22",
"type":"actual"
},
{
"data":9877,
"time":"23",
"type":"actual"
},
{
"data":8654,
"time":"24",
"type":"actual"
},
{
"data":3456,
"time":"25",
"type":"actual"
},
{
"data":5432,
"time":"26",
"type":"actual"
},
{
"data":9999,
"time":"27",
"type":"actual"
},
{
"data":5555,
"time":"28",
"type":"actual"
},
{
"data":8888,
"time":"29",
"type":"actual"
},
{
"data":1111,
"time":"30",
"type":"actual"
}
]
},
"status":"success"
}