1
头图

2021-12-17更新
QQ录屏20211215105815(4).gif

如上图所示,固定XY轴的功能也很简单只需要在options里的markLine里面的设置加上两个配置就行
image.png

image.png

2021-12-16更新

突然之间发现下面的洋洋洒洒一大堆代码其实毫无作用,
想要markLine跟着关系图一起移动,只需要在mouseup事件里加上
this.echarsInstance.setOption({series:seriesData})就行

如下

InitChart($event:echarts.ECharts){
        this.echarsInstance = $event;//拿到echarts对象

        this.echarsInstance.getZr().on('mouseup',params=>{
            if(this.echarsInstance.containPixel({seriesIndex:[0]},[params.offsetX,params.offsetY])){

                let series:any = this.echarsInstance.getOption()['series']
                let seriesData = series[0];
                this.echarsInstance.setOption({series:seriesData})//更新配置

            }
        })
    }

吐血


QQ录屏20211215105815(1).gif
如上图所示,公司现在给了需求,需要在移动garph(关系图)的时候,markLine做成的底图也要随之一起移动。

话不多说,直接开干


2021-12-15

首先需要明确的就是,在我接手的时候,底图是确定的,也就是这么个状态
QQ录屏20211215105815.gif

可以看到整体都已经搭建起来了,也就是我并不需要从零开始搭建代码,也就是garphoption我是不用改什么的,但是问题就是移动关系图的时候,markLine并不会随之一起移动。

当然,遇事不决查官方文档,很可惜,官方文档里并没有给出markLine移动相关的API
image.png

似乎官方对markLine定位就是一种定死的标线,不会移动也不会变化。那么,对此就毫无办法了吗?

那肯定是有办法的,

换个角度想既然可以生成固定的markLine,那笨一点,我在鼠标按下去的时候记录一下点击的位置,抬起的时候把抬起的位置和按下去的时候位置比对,就可以得到计算后的位置,将其把markLine中每一条线的坐标分别减去计算后的位置,然后再把echarts的图刷新一下,不就得到了markLine改变位置后的图吗?

纸上谈兵不如实际操练,必须立刻马上开始敲代码

首先,公司里没有直接使用echarts,而是使用了封装一层的ngx-echarts,大家感兴趣可以去查一下,ngx-echarts用起来很简单,也十分的好用,具体使用在此不表
image.png

首先上html代码

<div style="height: 700px;" (chartInit)="InitChart($event)"
echarts [options]="echartOptions"></div>

其中echarts就是ngx-echarts提供的指令了
chartInit是其暴露的方法,就是在图形加载以后触发的事件,其中$event就是Echarts实例对象了,options当然就是echarts图形需要的相关options了,echartsOptions大概的参数如下,想必使用过echarts画过图形之类的朋友对这些配置应该很熟悉
image.png

然后就是ts里面的代码了

//首先拿到echarts对象
InitChart($event:echarts.ECharts){
    this.echarsInstance = $event;//拿到echats对象
}

为什么要拿到eccharts对象呢,直接用echarts官方的事件不就行了吗,比如ngx-charts里面提供的事件
image.png

笔者当然不是饭吃太多了多敲代码消化下
是因为这些事件针对的真的只是图形自身,敲重点,图形自身

我们来对比一下效果看看

//html
<div style="height: 700px;"  echarts [options]="echartOptions"
(chartClick)="testClick($event)"></div>

//ts
testClick($event:any){
    console.log('自带的点击事件',$event)
}

上面使用的是echarts官方暴露的事件(虽然被ngx-echarts包装了一层,方便调用)

QQ录屏20211215105815(2).gif

可以看到,我的鼠标一直都是点击状态的,但是只有点击到关系图本身的时候,才会触发testClick的点击事件,也即是图形节点本身。

换用实例触发事件来看看

//html
<div style="height: 700px;" echarts [options]="echartOptions"
(chartInit)="InitChart($event)"></div>

//ts
InitChart($event:echarts.ECharts){
    this.echarsInstance = $event;
    this.echarsInstance.getZr().on('mousedown',params=>{
        console.log('利用echats对象的点击事件',params)
    })
}

QQ录屏20211215105815(3).gif

可以看到不论是点击到markLine所画的底图上,还是关系图的节点上, 事件都能够正常触发。

所以,要拿到实例本身,然后进行事件的操作

继续上代码

  InitChart($event:echarts.ECharts){
        this.echarsInstance = $event;//拿到echarts对象
        let xoffset:Array<number> = [0,0,0];//分别是鼠标按下时候的x位置,鼠标抬起时候的x值,两者的差值
        let yoffset:Array<number> = [0,0,0];//如上,y轴相关的值
        this.echarsInstance.getZr().on('mousedown',params=>{//echarts对象的鼠标按下事件
            if(this.echarsInstance.containPixel({seriesIndex:[0]},[params.offsetX,params.offsetY])){//重要 判断鼠标点击的位置是否在图形内部
                let transform = this.pixelToLocation([params.offsetX,params.offsetY]);//重要 将鼠标点击的像素点,转化为图形所在的坐标系,如果没有经过转换,移动以后就会有误差
                xoffset[0] = transform[0];
                yoffset[0] = transform[1]
                console.log('利用echats对象的点击事件',params)
            }
        })

        this.echarsInstance.getZr().on('mouseup',params=>{
            if(this.echarsInstance.containPixel({seriesIndex:[0]},[params.offsetX,params.offsetY])){
                let transform = this.pixelToLocation([params.offsetX,params.offsetY]);
                xoffset[1] = transform[0];
                yoffset[1] = transform[1];
                xoffset[2] = xoffset[0] - xoffset[1];
                yoffset[2] = yoffset[2] - yoffset[2];

                let series:any = this.echarsInstance.getOption()['series']
                let seriesData = series[0];
                let markLineData = [];
                if(seriesData.markLine){
                    markLineData = seriesData.markLine.data;
                    if(markLineData){
                        markLineData.forEach((item: any) => {
                            item[0].coord = [ item[0].coord[0]-xoffset[2] , item[0].coord[1]-yoffset[2] ];
                            item[1].coord = [ item[1].coord[0]-xoffset[2] , item[1].coord[1]-yoffset[2] ];
                        });
                    }
                    seriesData.markLine.data = markLineData;
                }

                // this.setEchartsOption({series:seriesData})
                this.echarsInstance.setOption({series:seriesData})//将改变后的数据覆盖echarts的配置

            }
        })
    }

解释下其中比较重要的代码

this.echarsInstance.containPixel({seriesIndex:[0]},[params.offsetX,params.offsetY]))
是官方文档里面的一个方法,描述如下

判断给定的点是否在指定的坐标系或者系列上

image.png

也就是判断你给定的xy的数据是否为第一个值的坐标系内,是就返回true

坐标转换方法

pixelToLocation(array:Array<number>){
    return this.echartsInstance.convertFromPixel({seriesIndex:0},array)
}

官方文档里面的描述

转换像素坐标值到逻辑坐标系上的点。

也就是将鼠标的像素点,转换为坐标系上的位置。

经此一番操作,终于markLine能随着关系图的移动而移动啦,至于鼠标滚轮放大缩小,操作其实和鼠标按下松开的操作差不多,只多了一个请求节流的操作。在这里暂且不表,如果有各位朋友需要再写出。

希望各位看官不要吝啬手里的赞,有缘再见。


munergs
30 声望8 粉丝

现在即是最好。