擊將元素聚焦到視圖中心的配置與實(shí)現(xiàn)原理)
數(shù)據(jù)可視化前端圖表庫(kù)【免費(fèi)下載鏈接】G6? A Graph Visualization Framework in JavaScript.項(xiàng)目地址https://gitcode.com/gh_mirrors/g6/G6點(diǎn)擊查看免費(fèi)下載導(dǎo)讀FocusElement 是 G6JavaScript 圖可視化框架內(nèi)置的交互Behavior之一核心能力是點(diǎn)擊圖上的節(jié)點(diǎn)、邊或 Combo將其平滑地聚焦平移到視圖中心幫助用戶在海量圖數(shù)據(jù)中快速定位與關(guān)注特定元素。本文將以 FocusElement.zh.md 為骨架完整講解其配置項(xiàng)、動(dòng)畫(huà)控制、條件啟用與組合鍵觸發(fā)等實(shí)戰(zhàn)用法并結(jié)合 focus-element.ts 源碼與單元測(cè)試剖析其事件綁定、按鍵校驗(yàn)與底層視口平移的實(shí)現(xiàn)鏈路。讀完本文你將能夠在自己的 G6 應(yīng)用中一鍵接入點(diǎn)擊聚焦交互并按需定制動(dòng)畫(huà)、觸發(fā)條件與快捷鍵。概述FocusElement 是什么FocusElement 是 G6 中用于實(shí)現(xiàn)元素聚焦功能的內(nèi)置交互支持通過(guò)點(diǎn)擊元素將其聚焦到視圖中心。該交互能夠幫助用戶快速定位和關(guān)注特定的圖元素典型使用場(chǎng)景包括快速將關(guān)注的節(jié)點(diǎn)或邊居中顯示在節(jié)點(diǎn)數(shù)量龐大、畫(huà)布被縮放平移后通過(guò)點(diǎn)擊迅速找回目標(biāo)元素與折疊/展開(kāi)collapse-expand等交互組合使用聚焦操作后自動(dòng)展開(kāi)查看子結(jié)構(gòu)。從實(shí)現(xiàn)層面看它屬于 G6behaviors內(nèi)置交互之一與drag-canvas、zoom-canvas、click-select等交互統(tǒng)一注冊(cè)在 packages/g6/src/behaviors/index.ts 中無(wú)需額外安裝任何插件即可直接使用。基本用法兩種配置方式在Graph配置中添加behaviors: [focus-element]即可啟用該交互。1. 快速配置靜態(tài)使用字符串形式直接聲明適用于不需要自定義參數(shù)的場(chǎng)景const graph new Graph({ // 其他配置... behaviors: [focus-element], });2. 對(duì)象配置推薦使用對(duì)象形式進(jìn)行配置支持自定義動(dòng)畫(huà)等參數(shù)const graph new Graph({ // 其他配置... behaviors: [ { type: focus-element, animation: { duration: 500, easing: ease-in, }, }, ], });兩種寫(xiě)法在FocusElement內(nèi)部最終都會(huì)被合并為完整的選項(xiàng)對(duì)象源碼中通過(guò)Object.assign({}, FocusElement.defaultOptions, options)見(jiàn) focus-element.ts將默認(rèn)配置與用戶配置合并因此未顯式聲明的配置項(xiàng)會(huì)自動(dòng)回落到默認(rèn)值。配置項(xiàng)詳解FocusElement 的全部配置項(xiàng)如下表所示配置項(xiàng)說(shuō)明類(lèi)型默認(rèn)值必選type交互類(lèi)型名稱(chēng)stringfocus-element?animation聚焦動(dòng)畫(huà)效果設(shè)置ViewportAnimationEffectTiming{ duration: 500, easing: ease-in }enable是否啟用聚焦功能boolean | ((event: IElementEvent) boolean)truetrigger同時(shí)按下快捷鍵才能聚焦元素按鍵參考 MDN Key Values若設(shè)為空數(shù)組則無(wú)需按下其他按鍵配合string[] | (Control|Shift|Alt|......)[][]各配置項(xiàng)與源碼的對(duì)應(yīng)關(guān)系如下定義于 focus-element.tstype交互注冊(cè)名字符串形式聲明時(shí)即使用focus-element作為默認(rèn) typeanimation聚焦時(shí)的動(dòng)畫(huà)配置可傳boolean或動(dòng)畫(huà)對(duì)象詳見(jiàn)下文ViewportAnimationEffectTimingenable既可以是布爾值也可以是接收點(diǎn)擊事件、返回布爾值的函數(shù)用于按事件條件動(dòng)態(tài)決定是否聚焦trigger組合鍵配置。默認(rèn)值為空數(shù)組[]表示點(diǎn)擊即可觸發(fā)一旦配置了組合鍵如[Control]則必須按住Control再點(diǎn)擊元素才能觸發(fā)聚焦。ViewportAnimationEffectTiming聚焦動(dòng)畫(huà)的類(lèi)型定義如下type ViewportAnimationEffectTiming | boolean // true 啟用默認(rèn)動(dòng)畫(huà)false 禁用動(dòng)畫(huà) | { easing?: string; // 動(dòng)畫(huà)緩動(dòng)函數(shù)ease-in-out、ease-in、ease-out、linear duration?: number; // 動(dòng)畫(huà)持續(xù)時(shí)間(毫秒) };傳true使用默認(rèn)動(dòng)畫(huà){ duration: 500, easing: ease-in }與 FocusElement.defaultOptions 一致傳false禁用動(dòng)畫(huà)視圖瞬間平移傳對(duì)象自定義duration毫秒與easing緩動(dòng)函數(shù)實(shí)現(xiàn)平滑過(guò)渡。代碼示例基礎(chǔ)聚焦功能最小可用配置點(diǎn)擊任意元素即可聚焦const graph new Graph({ container: container, width: 800, height: 600, behaviors: [focus-element], });自定義動(dòng)畫(huà)效果使用 800ms 的ease-in-out緩動(dòng)動(dòng)畫(huà)讓聚焦過(guò)程更柔和const graph new Graph({ // 其他配置... behaviors: [ { type: focus-element, animation: { duration: 800, easing: ease-in-out, }, }, ], });條件性啟用聚焦通過(guò)enable函數(shù)按點(diǎn)擊目標(biāo)的類(lèi)型決定是否聚焦——例如只對(duì)節(jié)點(diǎn)啟用聚焦邊不聚焦const graph new Graph({ // 其他配置... behaviors: [ { type: focus-element, enable: (event) { // 只對(duì)節(jié)點(diǎn)啟用聚焦邊不聚焦 return event.target.type node; }, }, ], });組合鍵觸發(fā)聚焦僅當(dāng)按住Control鍵的同時(shí)點(diǎn)擊元素時(shí)才觸發(fā)聚焦可避免與點(diǎn)擊選中等其他點(diǎn)擊類(lèi)交互沖突const graph new Graph({ // 其他配置... behaviors: [ { type: focus-element, trigger: [Control], }, ], });實(shí)際案例聚焦 折疊展開(kāi)的組合以下案例同時(shí)啟用collapse-expand與focus-element兩種交互點(diǎn)擊 Combo 可折疊/展開(kāi)點(diǎn)擊節(jié)點(diǎn)可將該節(jié)點(diǎn)聚焦到視圖中心。在數(shù)據(jù)中設(shè)置了兩個(gè)層級(jí)嵌套的 Combo便于觀察聚焦后的視口變化import { Graph } from antv/g6; const data { nodes: [ { id: node1, combo: combo1, style: { x: 110, y: 150 } }, { id: node2, combo: combo1, style: { x: 190, y: 150 } }, { id: node3, combo: combo2, style: { x: 150, y: 260 } }, ], edges: [{ source: node1, target: node2 }], combos: [{ id: combo1, combo: combo2 }, { id: combo2 }], }; const graph new Graph({ container: container, node: { style: { labelText: (d) d.id }, }, data, behaviors: [collapse-expand, focus-element], }); graph.render();該案例對(duì)應(yīng)站點(diǎn)在線示例 packages/site/docs/manual/behavior/FocusElement.zh.md 中的嵌入式 Demo也復(fù)現(xiàn)于倉(cāng)庫(kù)測(cè)試用例 behavior-focus-element.ts其中包含 4 個(gè)節(jié)點(diǎn)、4 條邊與 1 個(gè) Combo 的完整圖數(shù)據(jù)可直接運(yùn)行驗(yàn)證。源碼級(jí)實(shí)現(xiàn)原理事件綁定對(duì) node / edge / combo 三類(lèi)元素統(tǒng)一監(jiān)聽(tīng)點(diǎn)擊FocusElement繼承自BaseBehavior構(gòu)造時(shí)創(chuàng)建Shortcut實(shí)例并綁定事件。其關(guān)鍵代碼如下focus-element.tsprivate bindEvents() { const { graph } this.context; this.unbindEvents(); ELEMENT_TYPES.forEach((type) { graph.on(${type}:${CommonEvent.CLICK}, this.focus); }); }其中ELEMENT_TYPES定義于 packages/g6/src/constants/element.ts[node, edge, combo]。因此節(jié)點(diǎn)、邊、Combo 三類(lèi)元素上的點(diǎn)擊事件都會(huì)被統(tǒng)一接管這也解釋了為何文檔概述中說(shuō)點(diǎn)擊元素節(jié)點(diǎn)或邊均可聚焦。destroy()時(shí)通過(guò)unbindEvents()逐一解綁避免內(nèi)存泄漏。校驗(yàn)鏈路destroyed 狀態(tài)、組合鍵與 enable 條件點(diǎn)擊事件觸發(fā)后focus處理器首先經(jīng)過(guò)validate校驗(yàn)focus-element.tsprivate validate(event: IElementEvent) { if (this.destroyed || !this.isKeydown()) return false; const { enable } this.options; if (isFunction(enable)) return enable(event); return !!enable; }校驗(yàn)共三層生命周期檢查交互已被銷(xiāo)毀destroyed時(shí)直接忽略組合鍵檢查isKeydown()判斷當(dāng)前按鍵是否與trigger配置一致focus-element.ts。trigger為空數(shù)組時(shí)直接返回true否則通過(guò)Shortcut.match(trigger)校驗(yàn)Shortcut工具類(lèi)支持Control、Alt、Meta、Shift等修飾鍵的組合匹配見(jiàn) packages/g6/src/utils/shortcut.tsenable 條件enable為函數(shù)時(shí)調(diào)用它并根據(jù)返回值決定為布爾值時(shí)直接作為開(kāi)關(guān)。聚焦落地graph.focusElement → viewport.focusElements校驗(yàn)通過(guò)后調(diào)用graph.focusElement(event.target.id, this.options.animation)執(zhí)行聚焦focus-element.ts。該 API 定義于 packages/g6/src/runtime/graph.tspublic async focusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promisevoid { await this.context.viewport?.focusElements(Array.isArray(id) ? id : [id], { animation }); }focusElement支持傳入單個(gè) ID 或 ID 數(shù)組底層委托給視口控制器viewport.focusElementspackages/g6/src/runtime/viewport.tspublic async focusElements(ids: ID[], options: FocusOptions {}): Promisevoid { const { element } this.context; if (!element) return; const getBoundsOf (el: Element) options.shapes ? el.getShape(options.shapes).getRenderBounds() : el.getRenderBounds(); const elementsBounds getCombinedBBox(ids.map((id) getBoundsOf(element.getElement(id)!))); await this.focus(elementsBounds, options); }實(shí)現(xiàn)要點(diǎn)對(duì)每個(gè)目標(biāo)元素取其渲染包圍盒RenderBounds多個(gè)元素時(shí)合并為組合包圍盒g(shù)etCombinedBBox因此聚焦一組元素時(shí)會(huì)以這組元素的整體中心為對(duì)齊基準(zhǔn)隨后調(diào)用內(nèi)部focus方法viewport.ts將元素包圍盒中心從畫(huà)布坐標(biāo)轉(zhuǎn)換為視口坐標(biāo)計(jì)算與視口中心的位移差delta最終通過(guò)transform({ mode: relative, translate: ... }, animation)以相對(duì)平移方式將元素移動(dòng)到視圖中心并傳入動(dòng)畫(huà)配置實(shí)現(xiàn)平滑過(guò)渡。測(cè)試驗(yàn)證倉(cāng)庫(kù)中針對(duì)該交互提供了單元測(cè)試與回歸測(cè)試packages/g6/tests/unit/behaviors/focus-element.spec.ts分別模擬NodeEvent.CLICK點(diǎn)擊 node-1 至 node-4以及ComboEvent.CLICK點(diǎn)擊 combo-1逐次斷言視口聚焦結(jié)果與快照一致覆蓋節(jié)點(diǎn)聚焦與Combo 聚焦兩類(lèi)場(chǎng)景packages/g6/tests/bugs/focus-element.spec.ts聚焦元素相關(guān)的缺陷回歸用例防止該功能在后續(xù)迭代中回歸。小結(jié)FocusElement 用極簡(jiǎn)的配置一行focus-element為 G6 圖應(yīng)用注入了點(diǎn)擊即聚焦的交互能力。通過(guò)本文介紹的animation、enable、trigger三個(gè)核心配置你可以分別控制動(dòng)畫(huà)效果、聚焦條件和觸發(fā)方式靈活適配選中、編輯等各類(lèi)場(chǎng)景結(jié)合源碼可以看到其背后是三類(lèi)元素統(tǒng)一監(jiān)聽(tīng) → 三層校驗(yàn) →focusElementAPI → 視口相對(duì)平移的完整調(diào)用鏈理解了這條鏈路你也能在此基礎(chǔ)上實(shí)現(xiàn)自定義的聚焦邏輯例如聚焦到特定坐標(biāo)、或批量聚焦多個(gè)元素。贊分享數(shù)據(jù)可視化前端圖表庫(kù)【免費(fèi)下載鏈接】G6? A Graph Visualization Framework in JavaScript.項(xiàng)目地址https://gitcode.com/gh_mirrors/g6/G6點(diǎn)擊查看免費(fèi)下載相關(guān)推薦如何高效使用football.json3個(gè)實(shí)戰(zhàn)技巧構(gòu)建免費(fèi)足球數(shù)據(jù)分析應(yīng)用如何高效使用football.json3個(gè)實(shí)戰(zhàn)技巧構(gòu)建免費(fèi)足球數(shù)據(jù)分析應(yīng)用 football.json是一個(gè)提供免費(fèi)開(kāi)源足球JSON數(shù)據(jù)的專(zhuān)業(yè)項(xiàng)目讓你無(wú)需A數(shù)據(jù)可視化前端圖表庫(kù)G6 FocusElement 行為完全指南點(diǎn)擊元素居中聚焦、動(dòng)畫(huà)與按鍵觸發(fā)配置G6 FocusElement 行為完全指南點(diǎn)擊元素居中聚焦、動(dòng)畫(huà)與按鍵觸發(fā)配置 本篇技術(shù)指南聚焦于 G6JavaScript 圖可視化框架內(nèi)置交互行為數(shù)據(jù)可視化前端圖表庫(kù)8個(gè)顛覆性應(yīng)用場(chǎng)景探索Webots如何重塑機(jī)器人仿真行業(yè)8個(gè)顛覆性應(yīng)用場(chǎng)景探索Webots如何重塑機(jī)器人仿真行業(yè) 在機(jī)器人技術(shù)快速發(fā)展的今天許多開(kāi)發(fā)者面臨著一個(gè)共同的困境如何在沒(méi)有昂貴硬件設(shè)備的情況下驗(yàn)證復(fù)雜科研自動(dòng)駕駛物理引擎上一篇如何永久保存微信聊天記錄WeChatMsg開(kāi)源工具全解析下一篇ESP32 Arduino開(kāi)發(fā)終極指南從零開(kāi)始構(gòu)建智能物聯(lián)網(wǎng)項(xiàng)目創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考