G6 图可视化引擎——入门教程——图的交互 Behavior
G6 封裝了一系列交互方法,方便用戶直接使用。本文將為 Tutorial 案例 增加簡單的交互:hover 節點、點擊節點、點擊邊、放縮畫布、拖拽畫布。本節目標效果如下:
基本概念
交互行為 Behavior
G6 中的交互行為。G6 內置了一系列交互行為,用戶可以直接使用。簡單地理解,就是可以一鍵開啟這些交互行為:
- drag-canvas:拖拽畫布;
- zoom-canvas:縮放畫布。
交互管理 Mode
Mode 是 G6 交互行為的管理機制,一個 mode 是多種行為 Behavior 的組合,允許用戶通過切換不同的模式進行交互行為的管理。
交互狀態 State
狀態 State 是 G6 中的狀態機制。用戶可以為圖中的元素(節點/邊)設置不同的狀態及不同狀態下的樣式。在狀態發生變化時,G6 自動更新元素的樣式。例如,可以為節點設置狀態 ‘click’ 為 true 或 false,并為節點設置 ‘click’ 的樣式為加粗節點邊框。當 ‘click’ 狀態被切換為 true 時,節點的邊框將會被加粗,‘click’ 狀態被切換為 false 時,節點的樣式恢復到默認。
使用方法
拖拽、縮放——內置的交互行為
在 G6 中使用內置 Behavior 的方式非常簡單,只需要在圖實例化時配置 modes。
拖拽和縮放屬于 G6 內置交互行為,修改代碼如下:
const graph = new G6.Graph({// ... // 其他配置項modes: {default: ['drag-canvas', 'zoom-canvas', 'drag-node'], // 允許拖拽畫布、放縮畫布、拖拽節點}, });除了直接使用內置交互名稱外,也可以為 Behavior 配置參數,例如放縮畫布的敏感度、最大/最小放縮程度等。
上面代碼中的 modes 定義了 G6 的模式,default 是默認的模式,還可以允許有其他的模式,比如:編輯模式 edit 等。不同的模式,用戶能進行的行為可以不同,比如默認模式能拖拽畫布,編輯模式不允許拖拽畫布:
// 舉例解釋不同模式 modes: {default: ['drag-canvas'],edit: [] }Hover、Click 改變樣式——狀態式交互
有時我們希望通過交互可以將元素樣式變成特定樣式,如我們看到的圖 1 中,鼠標 hover 節點、點擊節點、點擊邊時,樣式發生了變化。這里涉及到了 G6 中 狀態 State 的概念。簡單地說,是否 hover 、click 、任何操作(可以是自己起的狀態名),都可以稱為一種狀態(state)。用戶可以自由設置不同狀態下的元素樣式。要達到交互更改元素樣式,需要兩步:
設置各狀態下的元素樣式
在實例化圖時,通過 nodeStateStyles 和 edgeStateStyles 兩個配置項可以配置元素在不同狀態下的樣式。
為達到 Tutorial 案例 中的效果:
- 鼠標 hover 節點時,該節點顏色變淺;
- 點擊節點時,該節點邊框加粗變黑;
- 點擊邊時,該邊變成藍色。
下面代碼設置了節點分別在 hover 和 click 狀態為 true 時的樣式,邊在 click 狀態為 true 時的樣式:
const graph = new G6.Graph({// ... // 其他配置項// 節點不同狀態下的樣式集合nodeStateStyles: {// 鼠標 hover 上節點,即 hover 狀態為 true 時的樣式hover: {fill: 'lightsteelblue',},// 鼠標點擊節點,即 click 狀態為 true 時的樣式click: {stroke: '#000',lineWidth: 3,},},// 邊不同狀態下的樣式集合edgeStateStyles: {// 鼠標點擊邊,即 click 狀態為 true 時的樣式click: {stroke: 'steelblue',},}, });監聽事件并切換元素狀態
G6 中所有元素監聽都掛載在圖實例上,如下代碼中的 graph 對象是 G6.Graph 的實例,graph.on() 函數監聽了某元素類型(node / edge)的某種事件。
// 在圖實例 graph 上監聽 graph.on('元素類型:事件名', e => {// do something });現在,我們通過下面代碼,為 Tutorial 案例 增加點和邊上的監聽事件,并在監聽函數里使用 graph.setItemState() 改變元素的狀態:
// 鼠標進入節點 graph.on('node:mouseenter', e => {const nodeItem = e.item; // 獲取鼠標進入的節點元素對象graph.setItemState(nodeItem, 'hover', true); // 設置當前節點的 hover 狀態為 true });// 鼠標離開節點 graph.on('node:mouseleave', e => {const nodeItem = e.item; // 獲取鼠標離開的節點元素對象graph.setItemState(nodeItem, 'hover', false); // 設置當前節點的 hover 狀態為 false });// 點擊節點 graph.on('node:click', e => {// 先將所有當前是 click 狀態的節點置為非 click 狀態const clickNodes = graph.findAllByState('node', 'click');clickNodes.forEach(cn => {graph.setItemState(cn, 'click', false);});const nodeItem = e.item; // 獲取被點擊的節點元素對象graph.setItemState(nodeItem, 'click', true); // 設置當前節點的 click 狀態為 true });// 點擊邊 graph.on('edge:click', e => {// 先將所有當前是 click 狀態的邊置為非 click 狀態const clickEdges = graph.findAllByState('edge', 'click');clickEdges.forEach(ce => {graph.setItemState(ce, 'click', false);});const edgeItem = e.item; // 獲取被點擊的邊元素對象graph.setItemState(edgeItem, 'click', true); // 設置當前邊的 click 狀態為 true });完整代碼
至此,完整代碼如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" /><title>Tutorial Demo</title> </head> <body> <div id="mountNode"></div> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.1.0/build/g6.js"></script> <script>const graph = new G6.Graph({container: 'mountNode',width: 800,height: 600,// 節點默認配置defaultNode: {labelCfg: {style: {fill: '#fff',},},},// 邊默認配置defaultEdge: {labelCfg: {autoRotate: true,},},// 節點在各狀態下的樣式nodeStateStyles: {// hover 狀態為 true 時的樣式hover: {fill: 'lightsteelblue',},// click 狀態為 true 時的樣式click: {stroke: '#000',lineWidth: 3,},},// 邊在各狀態下的樣式edgeStateStyles: {// click 狀態為 true 時的樣式click: {stroke: 'steelblue',},},// 布局layout: {type: 'force',linkDistance: 200,preventOverlap: true,nodeStrength: -30,edgeStrength: 0.1,},// 內置交互modes: {default: ['drag-canvas', 'zoom-canvas', 'drag-node'],},});const main = async () => {const response = await fetch('https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json',);const remoteData = await response.json();const nodes = remoteData.nodes;const edges = remoteData.edges;nodes.forEach(node => {if (!node.style) {node.style = {};}node.style.lineWidth = 1;node.style.stroke = '#666';node.style.fill = 'steelblue';switch (node.class) {case 'c0': {node.shape = 'circle';node.size = 30;break;}case 'c1': {node.shape = 'rect';node.size = [35, 20];break;}case 'c2': {node.shape = 'ellipse';node.size = [35, 20];break;}}});edges.forEach(edge => {if (!edge.style) {edge.style = {};}edge.style.lineWidth = edge.weight;edge.style.opacity = 0.6;edge.style.stroke = 'grey';});graph.data(remoteData);graph.render();// 監聽鼠標進入節點graph.on('node:mouseenter', e => {const nodeItem = e.item;// 設置目標節點的 hover 狀態 為 truegraph.setItemState(nodeItem, 'hover', true);});// 監聽鼠標離開節點graph.on('node:mouseleave', e => {const nodeItem = e.item;// 設置目標節點的 hover 狀態 falsegraph.setItemState(nodeItem, 'hover', false);});// 監聽鼠標點擊節點graph.on('node:click', e => {// 先將所有當前有 click 狀態的節點的 click 狀態置為 falseconst clickNodes = graph.findAllByState('node', 'click');clickNodes.forEach(cn => {graph.setItemState(cn, 'click', false);});const nodeItem = e.item;// 設置目標節點的 click 狀態 為 truegraph.setItemState(nodeItem, 'click', true);});// 監聽鼠標點擊節點graph.on('edge:click', e => {// 先將所有當前有 click 狀態的邊的 click 狀態置為 falseconst clickEdges = graph.findAllByState('edge', 'click');clickEdges.forEach(ce => {graph.setItemState(ce, 'click', false);});const edgeItem = e.item;// 設置目標邊的 click 狀態 為 truegraph.setItemState(edgeItem, 'click', true);});};main(); </script> </body> </html>總結
以上是生活随笔為你收集整理的G6 图可视化引擎——入门教程——图的交互 Behavior的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: G6 图可视化引擎——入门教程——使用图
- 下一篇: G6 图可视化引擎——入门教程——插件与