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

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

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

2.鼠标移动节点上去与之相关的线条高亮
echarts中使用graph关系图并且以markLine为底图的相关知识积累_第1张图片
3.把底图的标识文字居中
echarts中使用graph关系图并且以markLine为底图的相关知识积累_第2张图片
echarts中使用graph关系图并且以markLine为底图的相关知识积累_第3张图片
4.添加一个下拉框筛选要展示的节点。

其实总结下来,第一个需求以及第二个需求和最后一个需求一部分是共通的,也就是其实都是对ehcarts所展示的数据的操作,不同的地方在于:第一个和第二个需求只需要考虑数据就行,最后一个需求需要考虑底图也就是markLine的移动以及某个区域内的节点数据没有了以后整体的移动,也就是每一次点击树状下拉框,都要重新计算每个节点和markLine底图的位置。

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


首先解决第一个需求,也就是点击某个节点,只展示这个节点相关的数据

解决思路:首先肯定是拿到点击事件,然后点击节点的时候,拿到这个节点相关的数据,根据与之相关的某个筛选条件,把有关的数据筛选出来,赋值给echarts,数据就展现出来了。

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

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

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

上代码讲解

//html 代码
//要看的其实就是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 = 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 代码
//关注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属性改变字体旋转角度,非常的头疼,如下图
echarts中使用graph关系图并且以markLine为底图的相关知识积累_第4张图片

你可能感兴趣的:(echarts中使用graph关系图并且以markLine为底图的相关知识积累)