项目场景:
该场景中折线分为三段,普通部分,最大回撤部分,回补天数部分,分段点为数据中的最大值和最大值右侧的最小值。折线在绘制过程中经过分段点时,折线变色,最后实现三色折线。效果如图所示:
问题描述
1、通过判断最大点最小点在所有点的位置的比例来换算出画到最大点最小点时的时间,通过逻辑判断是否经过该时间点来变更线的颜色。做出来的效果是,当折线绘制经过分段点时,整根折线颜色进行变化,并未分段显示;
2、想使用如上个饼图问题那样的绘图方式,根据条件使index++,从而达到分段绘画的效果,但该方法因为逻辑原因,无法实现(个人感觉可实现,但是过于复杂,于是排除)。
原因分析:
1、因为画线的方法组件是通过给的点的坐标,将所有点连接起来绘制,所以即使根据时间变色,变得颜色也是整条线的颜色,而不能分段变色;
2、因为绘制饼图时,每一部分开始点为起始角度,结束点为结束角度,当当前角度大于结束角度时,让index++,起始角度等于结束角度就能进入下一部分的绘制,但是折线图的三段线的起始点和结束点不像饼图拥有相同的逻辑,导致无法统一条件使index++,从而无法使用while循环来绘制。
解决方案:
画了三条线进行叠加,三根线分别为:
1、最上层:第一段线(黑色部分);
2、中间层:第一段线+第二段线(黑色+红色部分)
3、最下层:整条线(黑色+红色+蓝色部分)
上层线的颜色覆盖住下层线的颜色,让三条线一起开始绘制,上层线画完停止,下层线继续画,从而达到效果。
代码如下:
data() {
return {
//...与该动效不相关的参数省略
points1: [], //全部三段线的数据
points2: [], //前两段线的数据
points3: [], //第一段线的数据
pointsArr: [],
lineColorChange: ['rgba(0,0,0,1)', 'rgba(212, 61, 66, 1)', 'rgba(85,142,236,1)'],//线的颜色
indexMax: 0,
indexMin: 0,
};
},
method:{
initChart(){ //表格初始化
//...省略部分与该功能无关的代码(判断是否要绘图的逻辑,绘图函数)
this.getIndexMaxOrMin();
this.getPoint1();
this.getPoint2();
this.getPoint3();
},
getIndexMaxOrMin() { //获取两个分段点
let max = Number.MIN_SAFE_INTEGER;
let min = Number.MAX_SAFE_INTEGER;
let min2 = Number.MAX_SAFE_INTEGER;
let data = this.config.line.data; //这线图的数据
let indexMin = 0; //最小值的脚标
let indexMin2 = 0; //如果最小值在最大值左侧,在右侧最小值的脚标
const len = data.length;
for (let i = 1; i < len; i++) {
if (data[i] > max) {
this.indexMax = i; //最大点脚标
max = data[i];
}
max = Math.max(max, data[i]);
if (data[i] < min) {
indexMin = i; //最小点脚标
min = data[i];
}
min = Math.min(min, data[i]);
}
for (let i = this.indexMax; i < len; i++) { //最大值右侧的最小值
if (data[i] < min2) {
indexMin2 = i;
min2 = data[i];
}
}
if (this.indexMax <= indexMin) { //获取最大值右侧的最小值脚标
this.indexMin = indexMin;
} else {
this.indexMin = indexMin2;
}
},
getPoint1() {
//全部三段数据(其中点的坐标)
let data = this.config.line.lineData1;
const len = data.length;
let xStep = 0;
if (len > 0) {
xStep = this.xWidth / len; //根据x轴宽度计算每个点之间的间距
}
for (let i = 0; i < len; i++) {
let x = this.config.startX + i * xStep; //点的x坐标(起始坐标+点的脚标*间距)
let y = this.config.startY + ((this.maxVal - data[i]) / this.dVal) * this.yHeight; //点的y坐标
this.points1.push({ x, y });
}
},
getPoint2() {
//前两段数据
this.points2 = this.points1.slice(0, this.indexMin);
},
getPoint3() {
//第一段数据
this.points3 = this.points1.slice(0, this.indexMax);
},
drawLine(speed) {
//...省略部分与该动效无关的折线属性的代码
const param = {
//全部三段数据
globalAlpha: 1,
lineColor: this.lineColorChange[2],
lineDash: [],
width: 6,
lineJoin: 'round',
lineList: this.points1, //组成该折线的点
};
const param1 = {
//第一段数据
globalAlpha: 1,
lineColor: this.lineColorChange[0],
lineDash: [],
width: 6,
lineJoin: 'round',
lineList: this.points3,
};
const param2 = {
//前两段数据
globalAlpha: 1,
lineColor: this.lineColorChange[1],
lineDash: [],
width: 6,
lineJoin: 'round',
lineList: this.points2,
};
this.$draw.drawLineByArray(this.ctx, param); //全部三段数据
this.$draw.drawLineByArray(this.ctx, param2); //前两段数据
this.$draw.drawLineByArray(this.ctx, param1); //第一段数据
},
}