“其实echarts默认是不支持动态markLine的.”



咳咳,为了不触发我的flag属性,我改一下我刚刚的发言

截止2018年11月14日,本人还没有看到echarts官档上支持动态markLine.



这就让我很尴尬了啊.因为我接到一个需求.

这个需求呢,是这样的:
画个图, 三条线, 一个代表上限, 一个代表下限, 一个是实际值.
实际值超过上限或者下限的地方标红一下.

实际内容下来了之后呢…我就有点懵逼了…

怎么这个上限和这个下限还是个数组格式的呢…

老规矩, 先百度, 心中默念, 来来来, 来来来, 来个不用改就可以直接用的代码吧~~

什么都没有!!! 别人公司的需求都不上班的吗!!!

android echarts 动态 echarts动态设置markerline_echarts

行吧行吧,我想想办法…想想办法…啊啊啊啊啊啊啊啊啊啊我靠,echarts也不是我开发的啊
它支不支持我怎么知道啊啊啊啊啊啊啊啊…有毒吧有毒吧…

好吧, 我热爱这个世界…啊啊啊啊啊啊啊啊啊啊啊…

热爱世界…热爱世界…冷静…冷静…

其实我的思路也很简单= =markLine也是line, 我做两个line放上去也行吧

实现思路: 做两条模拟仿真MarkLine线

说干咱就干,这个线其实画起来也挺简单的

android echarts 动态 echarts动态设置markerline_js_02

看看这个样式是不是很像markLine.

option = {
    xAxis: {
        type: 'value',
        data: [0,1,2]
    },
    yAxis: {
        type: 'value'
    },
    series: [{
        data: [0,1,2],
        type: 'line',
        symbol: 'none', // 不要有每个点默认的那个小圆球
        lineStyle: {
            normal: {
                color: 'gray', // 颜色置灰
                width: 1, // 宽度1就行了
                type: 'dashed' // line样式为虚线
            }
        }
    }]
};

好的,我们现在有这个MarkLine线了,可以在data里面自己填充数据.

我再看一下这个需求,嗯?超过还要红色的线???

啊啊啊啊啊啊啊啊啊啊我刀呢我刀呢我刀呢!!! 人间不值得…

android echarts 动态 echarts动态设置markerline_js_03

看了一眼自己的银行卡余额,算了算了,回来继续写…

实现思路: 把点集合拆开,不要放到一个series里面

怎么个意思?

就是说,我每两个点做一个小线段,高于max MarkLine, 低于min MarkLine的我就写它的itemStyle为红色,别的我就写黑色;

我定义了两个变量:

const red: any = { type: 'line', data: [], lineStyle: {normal: {color: 'red'}}};
const normal: any = { type: 'line', data: [], lineStyle: { normal: {color: 'black'}}};

可以说是相当简单了,下图示例是对应的程序部分
a代表当前实际值的坐标, b代表下一个实际值的坐标
c代表当前最大值的坐标,d代表下一个最大值的坐标
e代表当前最小值的坐标,f代表下一个最小值的坐标

这边特别说明一点就是,我这样来写是因为当x轴和y轴都是value类型的时候, echart支持在series中data:[[0,1], [1,2]]这种写法,x轴和y轴组成一个直角坐标系, 每一个[x, y]都表示一个点,默认是按顺序将data里面的点连起来

不明白的可以去看看官方示例:
http://echarts.baidu.com/examples/editor.html?c=line-pen

(之前特别留意了这个特性是因为觉得空闲的时候可以用echarts画个画什么的,没想到还可以在这种地方有正经用途…)

if (a.y > c.y && b.y > d.y) {
   red.data = [a, b];
   series.push(red);
} else if (a.y < e.y && b.y < f.y) {
   red.data = [a, b];
   series.push(red);
} else {
   normal.data = [a, b];
   series.push(normal);
}

emmmmmmmmmmmmmmmmmm展示一下效果图

android echarts 动态 echarts动态设置markerline_数据_04

android echarts 动态 echarts动态设置markerline_js_05

这这这…虽然知道肯定会在精度方面有些问题,没想到居然这么丑…

出现这个的原因吧,是因为每两个数据点之间太宽了,我自己造的数据太少了,就出现了这个情况.
但是实际情况中也会有这种情况.
强迫症如我那肯定是忍不了忍不了忍不了…唉,改吧改吧…

下面我们开始复习初中基础课程—二元一次方程组

下面是我写的func, 将两条线ab和cd之间的交点求出,并将线段ab切成两部分ax, xb
这个n1, n2就是我们y=kx + c的参数k, c1, c2就是参数c
(不知道是不是因为预感今天要做这个需求,昨晚我还梦见了我初中数学老师,噩梦阿…骂了我整整一宿, 不过也说不定是因为昨天我在做傅里叶变换的需求= =,唉,最近都是数学相关的, 不做噩梦才怪)

cross(a, b, c, d) {
    const n1 = (b.y - a.y) / (b.x - a.x);
    const n2 = (d.y - c.y) / (d.x - c.x);
    const c1 = b.y - n1 * b.x;
    const c2 = d.y - n2 * d.x;
    const x = ( c2 - c1 ) / ( n1 - n2 );
    const y = n1 * x + c1;
    return [[a, [x,y]], [[x, y], b]]
  }

好了,交点也求出来了.

将之前的if…else…完善一下

if (a.y > c.y && b.y > d.y) {
  red.data = [a, b];
  series.push(red);
} else if (a.y < e.y && b.y < f.y) {
  red.data = [a, b];
  series.push(red);
} else if((a.y > c.y && b.y < d.y)){
  const data = this.cross(a, b, c,  d);
  red.data = data[0];
  series.push(red);
  normal.data = data[1];
  series.push(normal);
} else if((a.y < c.y && b.y > d.y)) {
  const data = this.cross(a, b, c,  d);
  red.data = data[1];
  series.push(red);
  normal.data = data[0];
  series.push(normal);
} else if ((a.y > e.y && b.y < f.y)) {
  const data = this.cross(a, b, e,  f);
  red.data = data[1];
  series.push(red);
  normal.data = data[0];
  series.push(normal);
} else if (a.y < e.y && b.y > f.y) {
  const data = this.cross(a, b, e,  f);
  red.data = data[0];
  series.push(red);
  normal.data = data[1];
  series.push(normal);
} else {
  normal.data = [a, b];
  series.push(normal);
}

附上效果图(像tooltip修改formatter什么做显示上的修改,细节部分大家都自己按照自己的需求进行修改吧,就不是很麻烦了)

android echarts 动态 echarts动态设置markerline_js_06

还有两种越级操作我没有写,就是如果上一个点从低于下限一跃而上越过上限以及从超过上限一跃而下低于下限,这个作为思考题留在后面(我是实际数据上上来之后才发现这个问题的啊哈哈哈哈哈,后来修复了,但是懒得再更新内容了~大家可以自己思考啊哈哈)

我觉得我写得可以说是精细入微了,从研究思路到具体操作都一步步写的清清楚楚了.