如何自定义React-Flow控件?个人项目替换原生控件需求
自定义React-Flow控件实现缩放、适配、百分比显示及节点添加功能
实现步骤与代码示例
直接禁用React-Flow原生控件,通过useReactFlow钩子获取核心操作方法与视图状态,自定义固定在右下角的控件栏,同时集成抽屉组件用于节点添加。
1. 核心组件实现
import React, { useState } from 'react'; import { ReactFlow, useReactFlow, addEdge, Background } from 'reactflow'; import 'reactflow/dist/style.css'; // 自定义节点添加抽屉 const NodeDrawer = ({ isOpen, onClose, onAddNode }) => { if (!isOpen) return null; return ( <div className="drawer-overlay" onClick={onClose}> <div className="drawer-content" onClick={(e) => e.stopPropagation()}> <button className="drawer-close" onClick={onClose}>×</button> <h3>添加新节点</h3> <button className="add-node-btn" onClick={() => { onAddNode({ id: `node-${Date.now()}`, position: { x: 100, y: 100 }, data: { label: `新节点 ${Date.now()}` } }); onClose(); }} > 添加默认节点 </button> {/* 可扩展更多节点类型选择项 */} </div> </div> ); }; // 自定义控件组件 const CustomControls = ({ zoom, zoomIn, zoomOut, fitView, toggleDrawer }) => { const zoomPercent = Math.round(zoom * 100); return ( <div className="custom-controls"> <button className="control-btn" onClick={zoomIn}>🔍+</button> <button className="control-btn" onClick={zoomOut}>🔍-</button> <button className="control-btn" onClick={fitView}>📐</button> <div className="zoom-percent">{zoomPercent}%</div> <button className="control-btn add-node-btn" onClick={toggleDrawer}>➕</button> </div> ); }; // 主应用组件 const FlowApp = () => { const [isDrawerOpen, setIsDrawerOpen] = useState(false); const { zoom, zoomIn, zoomOut, fitView, setNodes, nodes, edges, onNodesChange, onEdgesChange, onConnect } = useReactFlow({ nodes: [], edges: [], controls: false, // 禁用原生控件 }); const handleAddNode = (newNode) => { setNodes(prevNodes => [...prevNodes, newNode]); }; return ( <div style={{ height: '100vh', position: 'relative' }}> <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={(params) => setEdges((eds) => addEdge(params, eds))} fitView > <Background /> <CustomControls zoom={zoom} zoomIn={zoomIn} zoomOut={zoomOut} fitView={fitView} toggleDrawer={() => setIsDrawerOpen(!isDrawerOpen)} /> </ReactFlow> <NodeDrawer isOpen={isDrawerOpen} onClose={() => setIsDrawerOpen(false)} onAddNode={handleAddNode} /> </div> ); }; export default FlowApp;
2. 样式配置(添加到全局CSS或CSS模块)
/* 自定义控件 - 固定右下角 */ .custom-controls { position: absolute; bottom: 20px; right: 20px; display: flex; flex-direction: column; gap: 8px; background: white; padding: 10px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .control-btn { width: 36px; height: 36px; border: none; border-radius: 4px; background: #f0f0f0; cursor: pointer; font-size: 16px; transition: background 0.2s; } .control-btn:hover { background: #e0e0e0; } .zoom-percent { text-align: center; font-size: 12px; padding: 4px 0; color: #666; } .add-node-btn { background: #4CAF50; color: white; } .add-node-btn:hover { background: #45a049; } /* 抽屉样式 */ .drawer-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 1000; display: flex; justify-content: flex-end; } .drawer-content { width: 300px; height: 100%; background: white; padding: 20px; overflow-y: auto; } .drawer-close { border: none; background: none; font-size: 24px; cursor: pointer; float: right; } .add-node-btn { margin-top: 20px; padding: 10px; width: 100%; }
关键功能说明
- 缩放控制:直接调用
useReactFlow提供的zoomIn/zoomOut方法,默认每次缩放步长为0.2,可通过ReactFlow配置项调整 - 视图适配:调用
fitView()方法,可传入fitView({ padding: 0.2 })参数调整视图边距 - 百分比显示:将
zoom状态值乘以100并取整,实时展示当前缩放比例 - 节点添加抽屉:通过
useState控制抽屉显隐,点击添加按钮时调用setNodes更新节点列表,可扩展为支持选择不同节点类型的表单
内容的提问来源于stack exchange,提问作者QianChi
相关产品推荐
相关产品推荐

