Skip to Content
代码示例Edges

动画边缘

React Flow 为默认边缘类型提供了一个简单的内置动画,但可以使用自定义边缘创建更高级的动画。以下是一系列示例,展示了边缘路径的不同使用方式

¥React Flow provides a simple built-in animation for the default edge type, but it is possible to create more advanced animations by using custom edges. Below are a collection of examples showing different ways an edge path might be used in

动画 SVG 元素

¥Animating SVG elements

可以使用 <animateMotion /> 元素沿路径为 SVG 元素设置动画。此示例创建一个自定义边,沿边缘路径为圆圈设置动画。

¥It is possible to animate an SVG element along a path using the <animateMotion /> element. This example creates a custom edge that animates a circle along the edge path.

import React from 'react'; import { BaseEdge, getSmoothStepPath, type EdgeProps } from '@xyflow/react'; export function AnimatedSVGEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, }: EdgeProps) { const [edgePath] = getSmoothStepPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, }); return ( <> <BaseEdge id={id} path={edgePath} /> <circle r="10" fill="#ff0073"> <animateMotion dur="2s" repeatCount="indefinite" path={edgePath} /> </circle> </> ); }

动画其他节点

¥Animating other nodes

如果你想要沿边缘为 SVG 制作更多动画,则可以使用 Web Animations API 来实现。此示例演示如何使用 offsetPath 属性和动画 offsetDistance 属性为沿边缘路径的流中的另一个节点设置动画。

¥If you want to animate more than SVG along an edge, you can do that with the Web Animations API. This example demonstrates how to animate another node in the flow along an edge path by using the offsetPath property and animating the offsetDistance property.

import React, { useEffect, useMemo } from 'react'; import { BaseEdge, getBezierPath, useReactFlow, type Edge, type EdgeProps, } from '@xyflow/react'; export type AnimatedNodeEdge = Edge<{ node: string }, 'animatedNode'>; export function AnimatedNodeEdge({ id, data = { node: '' }, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, }: EdgeProps<AnimatedNodeEdge>) { const { getNode, updateNode } = useReactFlow(); const [edgePath] = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, }); const selector = useMemo( () => `.react-flow__node[data-id="${data.node}"]`, [data.node], ); useEffect(() => { const node = document.querySelector(selector) as HTMLElement; if (!node) return; node.style.offsetPath = `path('${edgePath}')`; node.style.offsetRotate = '0deg'; // This property is fairly new and not all versions of TypeScript have it // in the lib.dom.d.ts file. If you get an error here, you can either // ignore it or add the property to the CSSStyleDeclaration interface // yourself. // // @ts-expect-error node.style.offsetAnchor = 'center'; let wasDraggable = getNode(data.node).draggable; updateNode(data.node, { draggable: false }); return () => { node.style.offsetPath = 'none'; updateNode(data.node, { draggable: wasDraggable }); }; }, [selector, edgePath]); useEffect(() => { const node = document.querySelector(selector) as HTMLElement; if (!node) return; const keyframes = [{ offsetDistance: '0%' }, { offsetDistance: '100%' }]; const animation = node.animate(keyframes, { duration: 2000, direction: 'alternate', iterations: Infinity, }); return () => { animation.cancel(); }; }, [selector]); return <BaseEdge id={id} path={edgePath} />; }

此示例中有一些重要的细节需要注意:

¥There are some important details in this example to take note of:

  • 动画运行时,动画节点的 draggable 属性设置为 false。这可以防止用户移动节点并破坏动画路径。

    ¥The animated node has its draggable property set to false while the animation is running. This prevents a user moving the node around and breaking the animation path.

  • 动画路径和动画本身设置在单独的 useEffect 钩子中。即使重新计算了边缘路径(例如,当拖动源节点或目标节点时),这也可以让动画继续流畅播放。

    ¥The animation path and the animation itself are set up in separate useEffect hooks. This lets the animation continue playing smoothly even if the edge path is recalculated (for example when the source or target nodes are dragged.)

Last updated on