You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:25:31