关于angular:echarts中使用graph关系图并且以markLine为底图的相关知识积累

47次阅读

共计 3984 个字符,预计需要花费 10 分钟才能阅读完成。

之前写了一篇文章讲怎么在关系图里应用 markLine 作为底图,并且可能随着关系图的挪动而挪动
前文链接

最近来了新需要,如下
1. 点击某个节点,只留下与之相干的节点,再次点击,复原原样

2. 鼠标挪动节点下来与之相干的线条高亮

3. 把底图的标识文字居中


4. 增加一个下拉框筛选要展现的节点。

其实总结下来,第一个需要以及第二个需要和最初一个需要一部分是共通的,也就是其实都是对 ehcarts 所展现的数据的操作,不同的中央在于: 第一个和第二个需要只须要思考数据就行,最初一个需要须要思考底图也就是 markLine 的挪动以及某个区域内的节点数据没有了当前整体的挪动,也就是每一次点击树状下拉框,都要从新计算每个节点和 markLine 底图的地位。

本文章并非 手把手 教会怎么做出图中的成果,只是解说做这个我的项目中遇到的 问题 和具体的 解决思路


首先解决第一个需要,也就是点击某个节点,只展现这个节点相干的数据

解决思路:首先必定是拿到点击事件,而后点击节点的时候,拿到这个节点相干的数据,依据与之相干的某个筛选条件,把无关的数据筛选进去,赋值给echarts, 数据就展示进去了。

第二点是再次点击的时候,复原到点击之前的数据。

解决思路:数据隔离,本地保留一份展现数据的拷贝,而后点击的时候,应用 lodashcloneDeep办法拷贝本地的拷贝数据,点击的时候给点击的项计数 +1,同时把本地数据的拷贝中的对应项的计数 +1。当某个节点的计数为 2 的时候,清空所有计数。

也就是点击的时候,把点击节点的计数 +1,依据这个节点的某个条件筛选出无关的其余节点。
再次点击的时候,如果有节点的计数为 2,就把本地未经筛选的数据赋值回来,并且清空所有计数。

上代码解说

//html 代码
<div id="room-bar-chart" echarts [options]="echartOptions"
        (chartMouseOver)="mouseOver($event,'over')" (chartMouseOut)="mouseOver($event,'out')"
        (chartInit)="InitChart($event)" (chartClick)="chartClick($event)"
        (chartContextMenu)="chartDbClick($event,menu)" style="height: 650px;"></div>
// 要看的其实就是 chartClick 事件

//ts
chartClick($event: any){if($event.dataType==="edge") return // 点到线的时候就不做操作

        let series = _.cloneDeep(this.echartOptions.series[0]);// 备份以后 echarts 图的 series
        let name = $event.name// 拿到点击节点的名字

        let relative: any[] = []// 保留筛选出不论是 source 还是 target 与点击项无关的数据
        edgeList.forEach((item,index,array)=>{//edgeList 就是节点关系的数据
            if(item.source===name||item.target===name){// 如果指标节点或者起始节点是点击节点的 name
                relative.push(item)// 将其退出到关系数组中保留
            }
        })

        let seriesData:Array<any> = series.data// 拿到现有 echarts 图的数据
        let dataArray = []// 保留 展现的数据里与 relative 无关的数据
        for (let w = 0; w < seriesData.length; w++) {// 循环本体的数据
            let item = seriesData[w];
            let index = w;
            if (item.name == name) {// 找到本体上点击的数据
                item.count++
                this.echartOptions.series[0].data[index].count++// 数据改变到原始数据上

            } else {// 如果不是,把本体上其余节点的计数清 0
                this.echartOptions.series[0].data[index].count = 0// 数据改变到原始数据上
            }

            if (this.echartOptions.series[0].data[index].count >= 2) {// 如果同一个数据点击了两次
                this.echartOptions.series[0].data.forEach((element: { count: number;}) => {// 把所有数据的 count 计数清空
                    element.count = 0
                });
                this.setEchartsOption({series: series})// 重绘所有数据 重绘办法在上一篇文章里有。return
            }
            for (let x = 0; x < relative.length; x++) {let data = relative[x];
                if (item.name == data.source || item.name == data.target) {dataArray.push(item)
                }
            }
        }
        series.data = _.uniq(dataArray)// 去重
        this.setEchartsOption({series:series})
    }

这样点击某个节点的时候就可能实现第一次点击保留相干节点,第二次点击复原原样。


第二个需要,鼠标挪动下来的时候,高亮与之相干的线

解决思路:大体同第一个需要,捕捉鼠标挪动到某个节点之上的事件,筛选出与节点相干的线的数据,而后扭转线条的色彩就行,鼠标移出的时候,在把色彩改回原来的样子。

上代码解说

//html 代码
<div id="room-bar-chart" echarts [options]="echartOptions"
        (chartMouseOver)="mouseOver($event,'over')" (chartMouseOut)="mouseOver($event,'out')"
        (chartInit)="InitChart($event)" (chartClick)="chartClick($event)"
        (chartContextMenu)="chartDbClick($event,menu)" style="height: 650px;"></div>
// 关注 mouseOver 事件

//ts
  /** 鼠标挪动到节点上高亮与之相干的线 */
    mouseOver($event: any, type: string) {if ($event.dataType === "node") {//node 代表是节点,如果是线的话不进行操作
            // 数据的变动是否须要同步到原始数据上是须要考量的,这里应用深拷贝复制一份,和间接应用原始数据成果雷同。let series = this.echartsInstance.getOption().series[0]
            let name = $event.name
            if (type === "over") {// 因为移入移出我都用同一个办法,所以须要用参数判断是移入还是移出
                // console.log("series",series)
                series.links.forEach((item: { source: any; target: any; lineStyle: { curveness: any; color?: string; width?: number; opacity?: number;}; }) => {if (item.source === name || item.target === name) {// 如果无关
                        item.lineStyle = {
                            color: "#39adfa",
                            width: 1.5,
                            opacity: 1,
                            curveness: item.lineStyle ? item.lineStyle.curveness : 0
                        }
                    }
                })
                // console.log('鼠标移入 series',series)
            } else {
                // 如果单纯的数据赋值,比方不要上面的 series.links 的循环,外层的 linkStyle 款式是无奈利用
                // 到内层的 links.lineStyle 上的,所以须要把内层的 links.lineSyle 上的款式都加上才行
                // series = this.echartsInstance.getOption().series[0]
                series.links.forEach((item: { source: any; target: any; lineStyle: { curveness: any; color?: string; opacity?: number; width?: number;}; }) => {if (item.source === name || item.target === name) {
                        item.lineStyle = {
                            color: "#aaa",
                            curveness: item.lineStyle ? item.lineStyle.curveness : 0,
                            opacity: 0.7,
                            width: 0.8,
                        }
                    }
                })
            }
            this.setEchartsOption({series: series})
        } else if ($event.dataType === "edge") {}}

第三个需要,把 markLine 的文字居中

解决思路:一开始的想法就是对着官网的文档,想尽办法想要通过挪动 markLinelabel,后果官网文档里的 markLinelabel属性十分麻烦,positionstart 或者 end 的时候 x 轴方向无奈挪动,而为 insideStartTop 这类线条上属性,字体会旋转 90°,且不反对 rotate 属性扭转字体旋转角度,十分的头疼, 如下图

正文完
 0