通过官方文档,可知高亮相邻节点分为两种方法,文档描述并不是很清楚,对刚接触这个库的小白并不是很友好,慢慢总结慢慢来吧

内置的高亮节点

是通过内置的Behavior activate-relations来实现,Behavior 是 G6 提供的定义图上交互事件的机制。与交互模式 Mode配合使用

activate-relations:当鼠标移到某节点时,突出显示该节点以及与其直接关联的节点和连线;

  • 参数:

    • trigger: 'mouseenter'。表示出发机制,可以是 mouseenterclick
    • activeState: 'active'。活跃节点状态,默认为 active,可以与 graph 实例的 xxxStateStyles 结合实现丰富的视觉效果。
    • inactiveState: 'inactive'。非活跃节点状态,默认值为 inactive。同样可以与 graph 实例的 xxxStateStyles 结合实现丰富的视觉效果。
    • 文档上还提到了另外两个参数,但是本案例中并未使用,暂不做说明 resetSelectedshouldUpdate(e)
  • 具体用法
let drawGraph = document.getElementById("drawGraph");
this.graphWidth = drawGraph.scrollWidth;
this.graphHeight = drawGraph.scrollHeight || 1200; graphG = new this.G6.Graph({
container: "drawGraph",
width: this.graphWidth,
height: this.graphHeight,
modes: {
default: [
{ type: "activate-relations", activeState: 'active', inactiveState: 'inactive' },
],
// default: ['activate-relations'] // 由于活跃节点及非活跃节点状态均采用默认值,因此可以简写为这种形式
},
nodeStateStyles:{}, // 配置节点状态样式
edgeStateStyles:{}, // 配置边状态样式
comboStateStyles:{}, // 配置分组状态样式
}
graphG.data(data);
graphG.render();

如果仅采用内置的高亮节点,会采用默认的样式,最终的渲染效果为:

自定义高亮

这种方式是通过自定义状态,在通过实例提供的setItemState clearItemStates设置和清除目标的状态信息,同样需要与graph 实例的 xxxStateStyles 结合实现。

graphG = new this.G6.Graph({
container: "drawGraph",
width: this.graphWidth,
height: this.graphHeight,
nodeStateStyles:{ // 配置节点状态样式,此处就先写一个,后续会有完整的案例分享
highlight: {
fill: "#db4437",
shadowColor: '#fff',
stroke: "#db4437",
cursor: "pointer",
'text-shape': {
lineWidth: 1,
fill: "#db4437",
stroke: "#db4437",
},
},
},
edgeStateStyles:{}, // 配置边状态样式
comboStateStyles:{}, // 配置分组状态样式
}
graphG.data(data);
graphG.render();
graphG.on("combo:mouseenter", (e) => {
let edgeItem = e.item
graphG.setItemState(edgeItem, 'highlight', true)
edgeItem.getEdges().forEach(edge => {
graphG.setItemState(edge.getTarget(), 'highlight', true)
graphG.setItemState(edge.getSource(), 'highlight', true)
graphG.setItemState(edge, 'highlight', true)
})
graphG.paint()
graphG.setAutoPaint(true)
}); graphG.on('combo:mouseleave', (e) => {
graphG.setAutoPaint(false)
graphG.getNodes().forEach(node => {
graphG.clearItemStates(node)
})
graphG.getEdges().forEach(edge => {
graphG.clearItemStates(edge)
})
graphG.getCombos().forEach(combo => {
graphG.clearItemStates(combo)
})
graphG.paint()
graphG.setAutoPaint(true)
})

如果仅采用自定义高亮节点,最终的渲染效果为:

自定义高亮时保持原始颜色

通过上面的案例,可以看出,combo:mouseenter时相关联的边和点全部高亮,并且统一了连线的颜色,此时可能会与我们的需求相违背,可能连线还是想要保持原来的颜色,因为不同的颜色描述两点之间的不同类型的指向关系。那么此时在处理鼠标事件时,需要获取要节点和连线 原始样式。

graphG.on("combo:mouseenter", (e) => {
let comboItem = e.item;
const originStyle = comboItem._cfg.originStyle["circle-combo"].fill;
comboItem._cfg.styles.highlight.fill = originStyle;
graphG.setItemState(comboItem, "highlight", true);
comboItem.getEdges().forEach((edge) => {
const originStyle = edge._cfg.originStyle["edge-shape"].stroke; // 获取边edge 原始颜色
edge._cfg.styles.highlight.stroke = originStyle;
let edgeSource = edge.getSource();
let edgeTarget = edge.getTarget(); if ( edgeSource._cfg.type === "combo" && edgeSource._cfg.model.id =="100-600" ) {
const originStyle = edgeSource._cfg.originStyle["circle-combo"].fill; // 获取分组combo 原始颜色
edgeSource._cfg.styles.highlight.fill = originStyle;
}
if ( edgeTarget._cfg.type === "combo" && edgeTarget._cfg.model.id =="100-600" ) {
const originStyle = edgeTarget._cfg.originStyle["circle-combo"].fill;
edgeTarget._cfg.styles.highlight.fill = originStyle;
}
graphG.setItemState(edgeSource, "highlight", true);
graphG.setItemState(edgeTarget, "highlight", true);
graphG.setItemState(edge, "highlight", true);
});
});

那么此时最终的效果为:

总结

其实两种方法与异曲同工之妙,都是进行状态的处理,只不过一个是帮我们处理了一部分状态与样式,可以直接拿来用,但往往内置的样式与我们实际使用时不相符,因此可以使用两者结合的方式,最终效果及完整demo,采用随机数来模拟实体与关系。

案例完整代码

<template>
<div>
<div id="drawGraph"></div>
</div>
</template> <script>
let graphG = null
export default {
mounted() {
this.initData();
},
methods: {
initData() {
let combos = [
{ id: '100-600', label: '100-600' },
{ id: '100-200', label: '100-200' },
{ id: '200-300', label: '200-300' },
{ id: '300-400', label: '300-400' },
{ id: '400-500', label: '400-500' },
{ id: '500-600', label: '500-600' },
]
let edges = [
{ source: '100-600', target: '100-200' },
{ source: '100-600', target: '200-300' },
{ source: '100-600', target: '300-400' },
{ source: '100-600', target: '400-500' },
{ source: '100-600', target: '500-600' },
]
// 生成(20-30)随机数 模拟节点node
let randomCount = Math.floor(Math.random() * 10) + 20;
let row_clo = Math.floor(Math.sqrt(randomCount));
let origin = [-150, 50], row = 110, clo = 150;
let nodes = []
for (let i = 0; i < randomCount; i++) {
let randomNum = String(Math.floor(Math.random() * 500) + 100); // 生成100-600之间的随机数,并与combo进行连线
let rowindex = Math.floor(i / row_clo);
let cloindex = i % row_clo;
let x = origin[0] + clo * cloindex
let y = origin[1] + row * rowindex
let node = {
label: randomNum,
id: randomNum,
x,
y,
style: {
fillOpacity: 0.5,
cursor: "pointer",
fill: randomNum % 5 == 0 ? "#81C7D4" : "#986DB2"
}
}
let index = Math.floor(randomNum / 100)
let edge = {
source: combos[index].id,
target: randomNum,
lineWidth: 1,
style: {
lineDash: [3, 3],
lineWidth: 0.5,
stroke: "#00AA90"
}
}
nodes.push(node)
edges.push(edge)
}
let data = { combos, edges, nodes }
console.log(data);
this.makeRelationData(data);
},
// 分组 点 连线处理
makeRelationData(data) {
if (graphG) {
graphG.destroy();
}
let drawGraph = document.getElementById("drawGraph");
this.graphWidth = drawGraph.scrollWidth;
this.graphHeight = drawGraph.scrollHeight || 1200;
let origin = [this.graphWidth / 2, 100];
let row = 150, clo = 180;
let combos = data.combos
let row_clo = Math.floor(Math.sqrt(combos.length));
for (let i = 0; i < combos.length; i++) {
let rowindex = Math.floor(i / row_clo) + 1;
let cloindex = (i % row_clo) + 1;
// 分组默认样式设置
if (i === 0) {
combos[i].x = this.graphWidth / 3
combos[i].y = this.graphHeight / 3
combos[i].style = {
fill: "#a5e4f0",
opacity: 0.5,
cursor: "pointer",
};
} else {
// 分组定位
combos[i].x = origin[0] + clo * cloindex;
combos[i].y = origin[1] + row * rowindex;
if (i % 2 === 1) {
combos[i].y += 40;
}
combos[i].style = {
fill: "#f6cd6b",
fillOpacity: 0.2,
}
}
}
this.drawQfast(data)
},
drawQfast(data) {
graphG = new this.G6.Graph({
container: "drawGraph",
width: this.graphWidth,
height: this.graphHeight,
modes: {
default: [
{ type: "zoom-canvas", enableOptimize: true, optimizeZoom: 0.2 },
{ type: "drag-canvas", enableOptimize: true },
{ type: "drag-node", enableOptimize: true, onlyChangeComboSize: true },
{ type: "drag-combo", enableOptimize: true, onlyChangeComboSize: true },
{ type: "activate-relations", activeState: 'active', inactiveState: 'inactive' },
],
},
defaultEdge: {
type: 'cubic-horizontal',
lineWidth: 1,
style: {
endArrow: true,
stroke: "#FAD069",
},
},
defaultNode: {
type: "circle",
size: 15,
labelCfg: {
position: "bottom",
style: {
fontSize: 15,
},
},
},
defaultCombo: {
cursor: "pointer",
opacity: 0,
type: "circle",
lineWidth: 1,
collapsed: true,
labelCfg: {
position: "top",
refY: 5,
style: {
fontSize: 16,
},
},
},
nodeStateStyles: {
highlight: {
fill: "#db4437",
shadowColor: '#fff',
stroke: "#db4437",
cursor: "pointer",
'text-shape': {
lineWidth: 1,
fill: "#db4437",
stroke: "#db4437",
},
},
inactive: {
stroke: '#eee',
lineWidth: 1,
'text-shape': {
fill: "#eee",
stroke: "#eee",
},
},
},
edgeStateStyles: {
hover: {
lineWidth: 3,
},
highlight: {
stroke: '#00AA90',
lineWidth: 3,
},
},
comboStateStyles: {
highlight: {
fill: "#f6cd6b",
opacity: 0.7,
cursor: "pointer",
'text-shape': {
fill: "#A5E4F0",
stroke: "#A5E4F0",
lineWidth: 1,
},
},
inactive: {
stroke: '#eee',
lineWidth: 1,
'text-shape': {
fill: "#eee",
stroke: "#eee",
},
},
},
});
graphG.data(data);
graphG.render(); // 渲染图 graphG.on("edge:mouseenter", (e) => {
graphG.setItemState(e.item, "hover", true);
}); graphG.on("edge:mouseleave", (e) => {
graphG.setItemState(e.item, "hover", false);
});
graphG.on("combo:mouseenter", (e) => {
let comboItem = e.item;
const originStyle = comboItem._cfg.originStyle["circle-combo"].fill;
comboItem._cfg.styles.highlight.fill = originStyle;
graphG.setItemState(comboItem, "highlight", true);
comboItem.getEdges().forEach((edge) => {
const originStyle = edge._cfg.originStyle["edge-shape"].stroke; // 获取边edge 原始颜色
edge._cfg.styles.highlight.stroke = originStyle;
let edgeSource = edge.getSource();
let edgeTarget = edge.getTarget(); if ( edgeSource._cfg.type === "combo" && edgeSource._cfg.model.id =="100-600" ) {
const originStyle = edgeSource._cfg.originStyle["circle-combo"].fill; // 获取分组combo 原始颜色
edgeSource._cfg.styles.highlight.fill = originStyle;
}
if ( edgeTarget._cfg.type === "combo" && edgeTarget._cfg.model.id =="100-600" ) {
const originStyle = edgeTarget._cfg.originStyle["circle-combo"].fill;
edgeTarget._cfg.styles.highlight.fill = originStyle;
}
graphG.setItemState(edgeSource, "highlight", true);
graphG.setItemState(edgeTarget, "highlight", true);
graphG.setItemState(edge, "highlight", true);
});
}); graphG.on('combo:mouseleave', () => {
graphG.setAutoPaint(false)
graphG.getNodes().forEach(node => {
graphG.clearItemStates(node)
})
graphG.getEdges().forEach(edge => {
graphG.clearItemStates(edge)
})
graphG.getCombos().forEach(combo => {
graphG.clearItemStates(combo)
})
graphG.paint()
graphG.setAutoPaint(true)
}) },
}
};
</script>

可视化—AntV G6 高亮相邻节点的两种方式的更多相关文章

  1. 【C#表达式树 六】表达式树中创建节点的两种方式

    创建表达式树节点的两种方式1.用expression的静态方法MakeBinary|MakeUnary(ExpressionType,参数)的方式创建表达式树节点: BinaryExpression ...

  2. jQuery 获取DOM节点的两种方式

    jQuery中包裹后的DOM对象实际上是一个数组,要获得纯粹的DOM对象可以有两种方式: 1.使用数组索引方式访问,例如: var dom = $(dom)[0]; 如: $("#id&qu ...

  3. MongoDB添加secondary节点的两种方法

    前段时间维护的一个事业群的其中一条业务线的开发找到运维,提出来了一个MongoDB的优化问题,那段时间MongoDB正在从op管理移交给db进行维护,整个部门都对MongoDB的运维经验缺乏,Mong ...

  4. Keras中间层输出的两种方式,即特征图可视化

    训练好的模型,想要输入中间层的特征图,有两种方式: 1. 通过model.get_layer的方式.创建新的模型,输出为你要的层的名字. 创建模型,debug状态可以看到模型中,base_model/ ...

  5. 数据可视化之DAX篇(十)在PowerBI中累计求和的两种方式

    https://zhuanlan.zhihu.com/p/64418286 假设有一组数据, 已知每一个产品贡献的利润,如果要计算前几名产品的贡献利润总和,或者每一个产品和利润更高产品的累计贡献占总体 ...

  6. System.Web.Http.Cors配置跨域访问的两种方式

    System.Web.Http.Cors配置跨域访问的两种方式 使用System.Web.Http.Cors配置跨域访问,众多大神已经发布了很多文章,我就不在详细描述了,作为小白我只说一下自己的使用心 ...

  7. 简介C#读取XML的两种方式

    简介C#读取XML的两种方式 作者: 字体:[增加 减小] 类型:转载 时间:2013-03-03 在程序中访问进而操作XML文件一般有两种模型,分别是使用DOM(文档对象模型)和流模型,使用DOM的 ...

  8. Log4Net日志记录两种方式

     简介 log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台.文件.数据库等)的工具.     log4net是Ap ...

  9. 【剑指offer】递归循环两种方式反转链表

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/25737023 本文分别用非递归和递归两种方式实现了链表的反转,在九度OJ上AC. 题目描写 ...

  10. jQuery中开发插件的两种方式

    jQuery中开发插件的两种方式(附Demo) 做web开发的基本上都会用到jQuery,jQuery插件开发两种方式:一种是类扩展的方式开发插件,jQuery添加新的全局函数(jQuery的全局函数 ...

随机推荐

  1. 关于docker创建容器报错-docker: Error response from daemon: runtime "io.containerd.runc.v2" binary not installed

    今天在对一台服务器(docker相关的业务服务器)进行OS补丁时,默认使用的 yum update -y 对所有的安装包进行了升级 升级完成后,让应用方检查确认应用及功能是否一切正常,如果不正常,严重 ...

  2. Linux安装中文字体(已验证)

    1.安装字体命令 sudo apt install -y fontconfig 2.查看已安装的字体 (1)查看linux已安装字体 fc-list (2)查看linux已安装中文字体 fc-list ...

  3. 运行eeui项目不出现 WiFI真机同步 IP地址

    从git上 clone项目之后,安装依赖  npm install eeui环境配置    npm install eeui-cli -g 问题:npm run dev  后项目一直不出现 WiFI真 ...

  4. pthread_mutex_t & pthread_cond_t 总结

    pthread_mutex_t & pthread_cond_t 总结 一.多线程并发 1.1 多线程并发引起的问题 我们先来看如下代码: #include <stdio.h> # ...

  5. super关键字的使用

    1.super理解为:父类的 2.super可以用来调用:属性.方法.构造器 3.super的使用:调用属性和方法 3.1 我们可以在子类的方法或构造器中.通过使用"super.属性&quo ...

  6. 数据结构中的哈希表(java实现)利用哈希表实现学生信息的存储

    哈希表 解释 哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方 内存结构分析图 1.定义一个类为结点,存储的信息 2.定义链表的相关操作 3.定义一个数组存 ...

  7. Vitepress搭建组件库文档(上)—— 基本配置

    在 vite 出现以前,vuepress 是搭建组件库文档不错的工具,支持以 Markdown 方式编写文档.伴随着 vite 的发展,vitepress 已经到了 1.0.0-alpha.22 版本 ...

  8. AR人体姿态识别,实现无边界的人机交互

    近年来,AR不断发展,作为一种增强现实技术,给用户带来了虚拟和现实世界的融合体验.但用户已经不满足于单纯地将某件虚拟物品放在现实场景中来感受AR技术,更想用身体姿势来触发某个指令,达到更具真实感的人机 ...

  9. Dropout原理分析

    工作流程 dropout用于解决过拟合,通过在每个batch中删除某些节点(cell)进行训练,从而提高模型训练的效果. 通过随机化一个伯努利分布,然后于输入y进行乘法,将对应位置的cell置零.然后 ...

  10. 聊一聊对一个 C# 商业程序的反反调试

    一:背景 1.讲故事 前段时间有位朋友在微信上找到我,说他对一个商业的 C# 程序用 WinDbg 附加不上去,每次附加之后那个 C# 程序就自动退出了,问一下到底是怎么回事?是不是哪里搞错了,有经验 ...