为 React-Leaflet CSS SVG 路由动画附加 onAnimationEnd
attaching onAnimationEnd for React-Leaflet CSS SVG route animation
我正在使用以下方法为在 React Leaflet 中绘制的路线制作动画,效果很好。但是我想对 CSS 使用 onAnimationEnd
。我不知道在哪里可以找到该元素并附加 eventListener。
export default function Map()
{
...
const RoutingMachineRef = useRef(null);
useEffect(() =>
{
RoutingMachineRef.current.setWaypoints([start, end]);
},[RoutingMachineRef, start, end]);
...
return(
<MapContainer>
<RoutingMachine ref={RoutingMachineRef} waypoints={[start, end]} />
</MapContainer>
)
};
RoutingMachine.js
const createRoutingMachineLayer = (props) =>
{
const { waypoints } = props;
const instance = L.Routing.control(
{
waypoints,
// router: router,
lineOptions: {
styles: [ {className:'animate'} ]
},
show: false,
addWaypoints: false,
routeWhileDragging: false,
draggableWaypoints: false,
fitSelectedRoutes: true,
showAlternatives: false,
createMarker: function() { return null; },
})
return instance
}
const RoutingMachine = createControlComponent(createRoutingMachineLayer)
export default RoutingMachine;
CSS:
path.leaflet-interactive.animate {
stroke-dasharray: 1920;
stroke-dashoffset: 1920;
animation: dash 20s linear 3s forwards;
}
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
你设置得很好。您的 RoutingMachine
组件写得很好,您已经有了对它的引用。伟大的。让我们在控制台中检查 RoutingMachineRef
:
如您所见,如果您深入挖掘,可以在 RoutingMachineRef.current._line._layers[some_layer_id]._path
找到 svg 路径组件。但是 小心 因为有时 leaflet 路由机器会绘制多个图层(单独的 svg 图层用于圆形线帽等)。您实际上可以通过 RoutingMachineRef.
直接访问这些 dom 元素
我不确定其中哪一个在您的代码中获得了 .animate
css class,但您可以将事件侦听器添加到其中的每一个。我想只有其中一个会真正动画化(那里可能是一个有问题的假设),所以事件侦听器只会触发一次,当具有 .animate
class 的那个停止动画时:
const RoutingMachineRef = useRef(null);
useEffect(() => {
RoutingMachineRef.current.setWaypoints([start, end]);
const pathComponents = Object.values(RoutingMachineRef.current._line._layers);
pathComponents.forEach((component) => {
component._path.addEventListener("animationend", () => {
// animateend callback code here
});
});
},[RoutingMachineRef, start, end]);
我创建了一个codesandbox来帮助演示。我没有任何实际的动画,所以我只是添加了一个点击监听器。当页面加载出来,路由出现后,点击它,可以看到它正在监听点击事件。
Sample Codesandbox
我编写的 codesandbox 与我们的代码略有不同,因为您似乎有一些状态变量 start
和 end
触发 useEffect 到 运行。对于我的情况,我没有这样的状态变量来帮助触发 useEffect - 我希望它在挂载时为 运行。但是 小心 因为你不能指望你的 useEffect 能够在挂载时正确地使用 ref 变量,因为 refs 不是在第一次渲染之后创建的。但另一方面,试图通过在 dep 数组中插入一个 ref 来触发 useEffects 充满了问题。所以我在 routingMachine 传单实例的事件 routesfound
上添加了一个侦听器,它将状态变量 routerReady
设置为 true,然后我将 that 包含在 dep 数组中。这里的逻辑是,一旦创建了路由机器并完成了第一次搜索,我就会触发一个 useEffect 来添加这些事件侦听器。您可能需要调整此逻辑以满足您的需要 - 如果您的 waypoints 是动态的,您将需要在每次绘制新路线时添加侦听器,因为它是一个全新的 svg 路径。
我正在使用以下方法为在 React Leaflet 中绘制的路线制作动画,效果很好。但是我想对 CSS 使用 onAnimationEnd
。我不知道在哪里可以找到该元素并附加 eventListener。
export default function Map()
{
...
const RoutingMachineRef = useRef(null);
useEffect(() =>
{
RoutingMachineRef.current.setWaypoints([start, end]);
},[RoutingMachineRef, start, end]);
...
return(
<MapContainer>
<RoutingMachine ref={RoutingMachineRef} waypoints={[start, end]} />
</MapContainer>
)
};
RoutingMachine.js
const createRoutingMachineLayer = (props) =>
{
const { waypoints } = props;
const instance = L.Routing.control(
{
waypoints,
// router: router,
lineOptions: {
styles: [ {className:'animate'} ]
},
show: false,
addWaypoints: false,
routeWhileDragging: false,
draggableWaypoints: false,
fitSelectedRoutes: true,
showAlternatives: false,
createMarker: function() { return null; },
})
return instance
}
const RoutingMachine = createControlComponent(createRoutingMachineLayer)
export default RoutingMachine;
CSS:
path.leaflet-interactive.animate {
stroke-dasharray: 1920;
stroke-dashoffset: 1920;
animation: dash 20s linear 3s forwards;
}
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
你设置得很好。您的 RoutingMachine
组件写得很好,您已经有了对它的引用。伟大的。让我们在控制台中检查 RoutingMachineRef
:
如您所见,如果您深入挖掘,可以在 RoutingMachineRef.current._line._layers[some_layer_id]._path
找到 svg 路径组件。但是 小心 因为有时 leaflet 路由机器会绘制多个图层(单独的 svg 图层用于圆形线帽等)。您实际上可以通过 RoutingMachineRef.
我不确定其中哪一个在您的代码中获得了 .animate
css class,但您可以将事件侦听器添加到其中的每一个。我想只有其中一个会真正动画化(那里可能是一个有问题的假设),所以事件侦听器只会触发一次,当具有 .animate
class 的那个停止动画时:
const RoutingMachineRef = useRef(null);
useEffect(() => {
RoutingMachineRef.current.setWaypoints([start, end]);
const pathComponents = Object.values(RoutingMachineRef.current._line._layers);
pathComponents.forEach((component) => {
component._path.addEventListener("animationend", () => {
// animateend callback code here
});
});
},[RoutingMachineRef, start, end]);
我创建了一个codesandbox来帮助演示。我没有任何实际的动画,所以我只是添加了一个点击监听器。当页面加载出来,路由出现后,点击它,可以看到它正在监听点击事件。
Sample Codesandbox
我编写的 codesandbox 与我们的代码略有不同,因为您似乎有一些状态变量 start
和 end
触发 useEffect 到 运行。对于我的情况,我没有这样的状态变量来帮助触发 useEffect - 我希望它在挂载时为 运行。但是 小心 因为你不能指望你的 useEffect 能够在挂载时正确地使用 ref 变量,因为 refs 不是在第一次渲染之后创建的。但另一方面,试图通过在 dep 数组中插入一个 ref 来触发 useEffects 充满了问题。所以我在 routingMachine 传单实例的事件 routesfound
上添加了一个侦听器,它将状态变量 routerReady
设置为 true,然后我将 that 包含在 dep 数组中。这里的逻辑是,一旦创建了路由机器并完成了第一次搜索,我就会触发一个 useEffect 来添加这些事件侦听器。您可能需要调整此逻辑以满足您的需要 - 如果您的 waypoints 是动态的,您将需要在每次绘制新路线时添加侦听器,因为它是一个全新的 svg 路径。