React Flow 邊事件處理實戰:鼠標事件、鍵盤操作及連接規則設置(附完整代碼)

本文為《React Agent:從零開始構建 AI 智能體》專欄系列文章。 專欄地址:https://blog.csdn.net/suiyingy/category_12933485.html。項目地址:https://gitee.com/fgai/react-agent(含完整代碼示?例與實戰源)。完整介紹:https://blog.csdn.net/suiyingy/article/details/146983582。

????????邊可以響應多種用戶操作,如點擊、雙擊、鼠標懸停等。通過綁定相應的事件處理函數,實現邊的交互功能。點擊邊彈出其詳細信息窗口;鼠標懸停時顯示工具提示,說明邊所代表的關系含義。

1 鼠標懸停

????????下面程序為鼠標懸停事件示例,顯示邊的信息、改變線條顏色、寬度和線型。

import React, { useCallback, useState } from 'react';
import {ReactFlow,useNodesState,useEdgesState,addEdge,
} from 'reactflow';
import 'reactflow/dist/style.css';const initialNodes = [{ id: '1', position: { x: 0, y: 0 }, data: { label: '1' } },{ id: '2', position: { x: 0, y: 100 }, data: { label: '2' } },
];const initialEdges = [{ id: 'e1-2', source: '1', target: '2',type: 'default' }
];export default function FlowComponent() {const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);const [hoveredEdgeId, setHoveredEdgeId] = useState(null);const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)),[setEdges]);// 動態獲取邊樣式const getEdgeStyle = (edge) => {return hoveredEdgeId === edge.id ? {stroke: 'red',strokeWidth: 3,strokeDasharray: '5 5',}: {};};return (<div style={{ height: '500px', width: '100%' }}><ReactFlownodes={nodes}edges={edges.map(edge => ({...edge,style: getEdgeStyle(edge)}))}onNodesChange={onNodesChange}onEdgesChange={onEdgesChange}onConnect={onConnect}onEdgeMouseEnter={(event, edge) => setHoveredEdgeId(edge.id)}onEdgeMouseLeave={() => setHoveredEdgeId(null)}fitView/></div>);
}

????????運行程序后結果如下圖所示。

圖1 邊 - 鼠標懸停

2 鼠標單擊

????????下面程序為鼠標單擊事件示例,顯示邊的信息。

export default function App() {const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)),[setEdges],);const onEdgeClick = useCallback((event, edge) => {console.log('Clicked edge:', edge);// 這里可以添加更多邏輯,比如顯示模態框等}, []);return (<div style={{ height: '500px' }}><ReactFlownodes={nodes}edges={edges}onNodesChange={onNodesChange}onEdgesChange={onEdgesChange}onConnect={onConnect}onEdgeClick={onEdgeClick}fitView/></div>);
}

????????運行程序后結果如下圖所示。

圖2 邊 - 鼠標單擊

3 鼠標雙擊

????????下面程序為鼠標雙擊事件示例。

export default function App() {const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)),[setEdges],);const handleEdgeDoubleClick = (event, edge) => {alert(`雙擊了邊:${edge.id}`);// 這里可以添加更多自定義邏輯,比如:// - 刪除邊// - 編輯邊屬性// - 高亮關聯節點等};return (<div style={{ height: '500px' }}><ReactFlownodes={nodes}edges={edges}onNodesChange={onNodesChange}onEdgesChange={onEdgesChange}onConnect={onConnect}onEdgeDoubleClick={handleEdgeDoubleClick}fitView/></div>);
}

4 鍵盤事件

????????同樣地,邊也支持鍵盤事件,示例如下:

export default function App() {const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);// 處理連接線const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)),[setEdges],);// 鍵盤事件處理const handleKeyDown = useCallback((event) => {if (event.key === 'Delete') {alert('鍵盤Delete鍵被按下')}}, [setNodes, setEdges]);return (<div style={{ height: '500px', outline: 'none' }} tabIndex={0} onKeyDown={handleKeyDown}><ReactFlownodes={nodes}edges={edges}onNodesChange={onNodesChange}onEdgesChange={onEdgesChange}onConnect={onConnect}fitView/></div>);
}

5 連接事件

????????在 React Flow 中,邊的連接和斷開是常見操作。當用戶嘗試連接兩個節點時,系統需要驗證連接的合法性,如檢查節點的輸入輸出端口是否匹配、是否存在循環連接等。斷開連接時需要處理相關的數據更新和視覺效果變化。可以通過onConnect 和 onEdgesDelete 事件進行自定義邏輯處理。

????????onConnect示例程序如下所示。

export default function App() {const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);const onConnect = useCallback((params) => {// 查找源節點和目標節點const sourceNode = nodes.find(node => node.id === params.source);const targetNode = nodes.find(node => node.id === params.target);// 打印節點信息console.log('連接起始端點:', sourceNode);console.log('連接終止端點:', targetNode);// 添加連接邊setEdges((eds) => addEdge(params, eds));},[setEdges, nodes] // 添加nodes依賴確保獲取最新數據);return (<div style={{ height: '500px' }}><ReactFlownodes={nodes}edges={edges}onNodesChange={onNodesChange}onEdgesChange={onEdgesChange}onConnect={onConnect}fitView/></div>);
}

????????運行程序后結果如下圖所示。

圖3 onConnect 連接

6 連接規則

????????我們也可以設置連接規則,例如下面程序不允許自身內部進行連接。

import React, { useCallback } from 'react';
import { ReactFlow, Handle, useNodesState, useEdgesState, addEdge } from 'reactflow';
import 'reactflow/dist/style.css';
import { FiDatabase, FiCloud } from 'react-icons/fi';
import { toast, Toaster } from 'react-hot-toast'; // 添加Toast組件// 自定義節點組件 npm install react-hot-toast
const CustomNode = ({ id, data, selected }) => {return (<div className={`custom-node ${selected ? 'selected' : ''}`}><Handletype="target"position="top"className="!bg-teal-500"// isValidConnection={(connection) => //   connection.source !== id  // 禁止自連接// }/><div className="node-header"><FiCloud className="node-icon" /><h3 className="node-title">{data.label}</h3></div><div className="node-body"><FiDatabase className="node-icon" /><span className="node-info">{data.content}</span></div><Handletype="source"position="bottom"className="!bg-purple-500"/><Handletype="source"position="right"id={`${id}-output-2`}className="!bg-pink-500"style={{ top: '30%' }}/></div>);
};const initialNodes = [{ id: '1', position: { x: 0, y: 0 }, data: { label: '開始節點',content: '輸入數據源'},type: 'custom',},{ id: '2', position: { x: 200, y: 150 }, data: { label: '處理節點',content: '數據處理流程'},type: 'custom',},
];const initialEdges = [{ id: 'e1-2', source: '1', target: '2',animated: true,style: { stroke: '#94a3b8' },
}];const nodeTypes = {custom: CustomNode,
};// 節點樣式
const nodeStyle = `.custom-node {background: linear-gradient(145deg, #ffffff, #f1f5f9);border-radius: 8px;border: 2px solid #cbd5e1;box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);padding: 16px;min-width: 200px;transition: all 0.2s ease;}.custom-node.selected {border-color: #6366f1;box-shadow: 0 4px 15px rgba(99, 102, 241, 0.2);}.custom-node:hover {transform: translateY(-2px);}.node-header {display: flex;align-items: center;margin-bottom: 12px;border-bottom: 1px solid #e2e8f0;padding-bottom: 8px;}.node-title {margin: 0;font-size: 1.1rem;color: #1e293b;margin-left: 8px;}.node-body {display: flex;align-items: center;color: #64748b;}.node-icon {font-size: 1.2rem;margin-right: 8px;color: #6366f1;}.node-info {font-size: 0.9rem;}.react-flow__handle {width: 14px;height: 14px;border-radius: 3px;border: none;}
`;export default function App() {// 使用useNodesState管理節點狀態const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);// 連接處理回調const onConnect = useCallback((connection) => {// 根據不同的輸出端口設置邊樣式const edgeStyle = connection.sourceHandle?.endsWith('-output-2') ? { stroke: '#ec4899' } : { stroke: '#94a3b8' };return setEdges((eds) =>addEdge({...connection,animated: true,style: edgeStyle,}, eds));},[setEdges]);// 連接驗證邏輯const isValidConnection = useCallback((connection) => {// 禁止自連接if (connection.source === connection.target) {toast.error('不能連接到自身');// alert('不能連接到自身');return false;}// 檢查目標節點是否已有連接const targetConnections = edges.filter((edge) => edge.target === connection.target);if (targetConnections.length > 0) {toast.error('目標節點已有連接');console.log(`連接被禁止:節點 ${connection.target} 已有輸入連接`);return false;}return true;},[edges]);return (<div style={{ height: '100vh', background: '#f8fafc' }}><style>{nodeStyle}</style><Toaster position="top-right" /> {/* Toast消息容器 */}<ReactFlow nodes={nodes}edges={edges}onNodesChange={onNodesChange}  // 添加狀態變更處理器onEdgesChange={onEdgesChange}onConnect={onConnect}nodeTypes={nodeTypes}isValidConnection={isValidConnection}fitViewstyle={{ background: '#f8fafc' }}connectionLineStyle={{ stroke: '#94a3b8', strokeWidth: 2 }}defaultEdgeOptions={{type: 'smoothstep',animated: true,style: { strokeWidth: 2 }}}/></div>);
}

7 斷開事件

????????onEdgesDelete 示例程序如下所示。

export default function App() {const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);// 連接處理const onConnect = useCallback((params) => {const sourceNode = nodes.find(n => n.id === params.source);const targetNode = nodes.find(n => n.id === params.target);console.log('[連接建立] 起始節點:', sourceNode);console.log('[連接建立] 終止節點:', targetNode);setEdges((eds) => addEdge(params, eds));},[setEdges, nodes]);// 斷開連接處理const onEdgesDeleted = useCallback((deletedEdges) => {deletedEdges.forEach(edge => {const sourceNode = nodes.find(n => n.id === edge.source);const targetNode = nodes.find(n => n.id === edge.target);console.log('[連接斷開] 起始節點:', sourceNode);console.log('[連接斷開] 終止節點:', targetNode);});},[nodes]);return (<div style={{ height: '500px' }}><ReactFlownodes={nodes}edges={edges}onNodesChange={onNodesChange}onEdgesChange={onEdgesChange}onConnect={onConnect}onEdgesDelete={onEdgesDeleted}  // 添加斷開連接處理器fitView/></div>);
}

????????運行程序后結果如下圖所示。

圖4 onEdgesDelete 連接斷開

立即關注獲取最新動態

點擊訂閱《React Agent 開發專欄》,每周獲取智能體開發深度教程。項目代碼持續更新至React Agent 開源倉庫,歡迎 Star 獲取實時更新通知!FGAI 人工智能平臺:FGAI 人工智能平臺

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/84073.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84073.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/84073.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java小結(一)

java&#xff08;上&#xff09; 模塊一 1.JDK,JRE,JVM 知識點 核心內容 易混淆點 JDK定義 Java Development Kit&#xff08;Java開發工具包&#xff09;&#xff0c;包含開發所需全部工具 JDK包含JRE的關系容易混淆 JRE定義 Java Runtime Environment&#xff08;Jav…

ddns-go安裝介紹-強大的ipv6動態域名解析神器-家庭云計算專家

ddns-go 是一款輕量級開源動態域名解析工具&#xff0c;專注于解決動態IP環境下的域名綁定問題&#xff0c;尤其適配IPv6網絡環境。其核心功能包括&#xff1a; 1.IPv6動態解析&#xff1a;自動檢測本地IPv6地址變化&#xff08;支持網卡、接口或命令獲取&#xff09;&#xf…

Docker-mongodb

拉取 MongoDB 鏡像: docker pull mongo 創建容器并設置用戶&#xff1a; 要掛載本地數據目錄&#xff0c;請替換此路徑: /Users/Allen/Env/AllenDocker/mongodb/data/db docker run -d --name local-mongodb \-e MONGO_INITDB_ROOT_USERNAMEadmin \-e MONGO_INITDB_ROOT_PA…

WooCommerce緩存教程 – 如何防止緩存破壞你的WooCommerce網站?

我們在以前的文章中探討過如何加快你的WordPress網站的速度&#xff0c;并研究過各種形式的緩存。 然而&#xff0c;像那些使用WooCommerce的動態電子商務網站&#xff0c;在讓緩存正常工作方面往往會面臨重大挑戰。 在本指南中&#xff0c;我們將告訴你如何為WooCommerce設置…

貪心算法 Part04

總結下重疊區間問題 LC 452. 用最少數量的箭引爆氣球 和 LC 435. 無重疊區間 本質上是一樣的。 LC 452. 用最少數量的箭引爆氣球 是求n個區間當中 &#xff0c; 區間的種類數量 k。此處可以理解為&#xff0c;重疊在一起的區間屬于同一品種&#xff0c;沒有重疊的區間當然…

云原生CD工具-Argocd+ArgoRollout入門到精通

第一章 Argo CD簡介 課時1.1 Argo產品介紹 ARGO官網地址:https://argoproj.github.io/ 旗下產品有: Argo Workflows、ArgoCD 、Argo Rollouts 、Argo Events 課時1.2 什么是Argo CD Argo CD 是一個開源的持續交付工具, 是 Kubernetes 的聲明式 GitOps 持續交付工具。專…

數據分析與應用---數據可視化基礎

目錄 Matplotlib基礎繪圖 (一)、pyplot繪圖基礎語法與常用參數 1、pyplot基礎語法 (1) 創建畫布與創建子圖 (2) 添加畫布內容 (3) 保存與顯示圖形 案例代碼 2. 設置pyplot的動態rc參數 (二)、使用Matplotlib繪制進階圖形 1. 繪制散點圖----scatter 2. 繪制折線…

PP-YOLOE-SOD學習筆記1

項目&#xff1a;基于PP-YOLOE-SOD的無人機航拍圖像檢測案例全流程實操 - 飛槳AI Studio星河社區 一、安裝環境 先準備新環境py>3.9 1.先cd到源代碼的根目錄下 2.pip install -r requirements.txt 3.python setup.py install 這一步需要看自己的GPU情況&#xff0c;去飛漿…

力扣HOT100之二叉樹:114. 二叉樹展開為鏈表

這道題自己嘗試著做了一下&#xff0c;感覺還是得用遞歸來做比較簡單&#xff0c;但是一直想的是用前序遍歷來構造鏈表&#xff0c;導致怎么做都不對&#xff0c;去看了下靈神的題解&#xff0c;然后問了下GPT&#xff0c;現在終于弄明白了。雖然構造出來的鏈表的排列順序是按照…

Spring Boot 注解 @ConditionalOnMissingBean是什么

一句話總結&#xff1a; ConditionalOnMissingBean 是 Spring Boot 提供的一個 條件注解&#xff08;Conditional Annotation&#xff09;&#xff0c;意思是&#xff1a; 只有當 Spring 容器中 不存在 某個 Bean 時&#xff0c;當前的 Bean 或配置才會被加載。 這是一種典型的…

PyInstaller 如何在mac電腦上生成在window上可執行的exe文件

PyInstaller跨平臺打包限制 PyInstaller 無法直接從macOS生成Windows可執行文件&#xff0c;因為它需要訪問目標平臺的系統庫和Python環境來構建可執行文件。要在macOS上為Windows打包Python應用&#xff0c;需要通過以下方法之一&#xff1a; 方法一&#xff1a;使用虛擬機或…

零基礎設計模式——創建型模式 - 抽象工廠模式

第二部分&#xff1a;創建型模式 - 抽象工廠模式 (Abstract Factory Pattern) 我們已經學習了單例模式&#xff08;保證唯一實例&#xff09;和工廠方法模式&#xff08;延遲創建到子類&#xff09;。現在&#xff0c;我們來探討創建型模式中更為復雜和強大的一個——抽象工廠…

【通用智能體】Serper API 詳解:搜索引擎數據獲取的核心工具

Serper API 詳解&#xff1a;搜索引擎數據獲取的核心工具 一、Serper API 的定義與核心功能二、技術架構與核心優勢2.1 技術實現原理2.2 對比傳統方案的突破性優勢 三、典型應用場景與代碼示例3.1 SEO 監控系統3.2 競品廣告分析 四、使用成本與配額策略五、開發者注意事項六、替…

Flask-SQLAlchemy核心概念:模型類與數據庫表、類屬性與表字段、外鍵與關系映射

前置閱讀&#xff0c;關于Flask-SQLAlchemy支持哪些數據庫及基本配置&#xff0c;鏈接&#xff1a;Flask-SQLAlchemy_數據庫配置 摘要 本文以一段典型的 SQLAlchemy 代碼示例為引入&#xff0c;闡述以下核心概念&#xff1a; 模型類&#xff08;Model Class&#xff09; ? 數…

野火魯班貓(arrch64架構debian)從零實現用MobileFaceNet算法進行實時人臉識別(四)安裝RKNN Toolkit2

RKNN Toolkit2是用來將onnx模型轉成rknn專用模型&#xff0c;并可通過RKNN Toolkit Lite2或者RKNPU調用NPU進行加速計算的工具。 一開始我安裝很多次都無法成功安裝。后來跟售后技術對接&#xff0c;必須是PC平臺的Linux環境才可以。我的電腦是windows&#xff0c;所以我需要用…

基于深度學習的工件檢測系統設計與實現

在工業自動化領域&#xff0c;工件檢測一直是提高生產效率和產品質量的關鍵環節。傳統的人工檢測方法不僅效率低下&#xff0c;而且容易受到主觀因素的影響&#xff0c;導致誤判率較高。隨著深度學習技術的飛速發展&#xff0c;基于圖像識別的自動檢測系統逐漸成為研究熱點。今…

CyberSecAsia專訪CertiK首席安全官:區塊鏈行業亟需“安全優先”開發范式

近日&#xff0c;權威網絡安全媒體CyberSecAsia發布了對CertiK首席安全官Wang Tielei博士的專訪&#xff0c;雙方圍繞企業在進軍區塊鏈領域時所面臨的關鍵安全風險與防御策略展開深入探討。 Wang博士在采訪中指出&#xff0c;跨鏈橋攻擊、智能合約漏洞以及私鑰管理不當&#x…

Google C++ Style Guide 谷歌 C++編碼風格指南,深入理解華為與谷歌的編程規范——C和C++實踐指南

Google C 編程風格指南 Release Apr 07, 2017 0. ?享 ?? 4.45 ??? Benjy Weinberger, Craig Silverstein, Gregory Eitzmann, Mark Mentovai, Tashana Landray ?? YuleFox, Yang.Y, acgtyrant, lilinsanity 亯??享 ? Google Style Guide ? Google 開源…

當科技邂逅浪漫:在Codigger的世界里,遇見“愛”

520&#xff0c;一個充滿愛意的日子&#xff0c;人們用各種方式表達對彼此的深情。而在科技的世界里&#xff0c;我們也正經歷著一場特別的邂逅——Codigger&#xff0c;一個分布式操作系統的誕生&#xff0c;正在以它獨特的方式&#xff0c;重新定義我們與技術的關系。 Codigg…

嵌入式學習筆記 - Void類型的指針

void指針的基本概念和特性 void指針是一種特殊的指針類型&#xff0c;稱為“無類型指針”或“通用指針”。它的主要特點是&#xff1a; ?通用性?&#xff1a;void指針可以指向任何類型的數據&#xff0c;這使得它在處理不確定數據類型時非常有用。 ?靈活性?&#xff1a;由…