如何在 React 中使用animejs?

IT技术 reactjs anime.js
2021-04-29 09:46:15

我已经从 npm 安装了animejs,并导入了所需的文件,但是在我的代码中添加动画(代码)时,它无法正常工作并显示错误。

这是我所做的一个小例子:

import React from 'react';
import anime from 'animejs';


 const test =()=>{


const animation = anime({
    targets: '.css-selector-demo .el',
    translateX: 250
  });

return(
    <div>
   {
   animation
   }
    </div>
)

}
export default test;

这是我得到的错误:

Error: Objects are not valid as a React child (found: object with keys {update,

begin, loopBegin, changeBegin, change, changeComplete, loopComplete, complete, loop, 
direction, autoplay, timelineOffset, id, children, animatables, animations, 
duration, delay, endDelay, finished, reset, set, tick, seek, pause, play, 
reverse, restart, passThrough, currentTime, progress, paused, began, loopBegan,
 changeBegan, completed, changeCompleted, reversePlayback, reversed, remaining}).
 If you meant to render a collection of children, use an array instead.

2个回答

正如@Shubham Khatri 指出的那样,已经存在react特定的包装器:react-animejsreact-anime包。如果您不想使用它,您可以使用anime.js,而无需使用React hooks 将其直接挂钩到React 中!

在这个例子中,我使用了一个useEffect钩子来启动动画,并用一个useRef钩子来存储跨重新渲染的动画变量,以便它可以用于重新启动(或对动画对象执行其他更新)。

你收到错误的原因是因为animation它不是一个 react 元素,所以 React 不知道如何渲染它。相反,将其视为组件内的副作用(因此适用于useEffect)。

function App() {
  const animationRef = React.useRef(null);
  React.useEffect(() => {
    animationRef.current = anime({
      targets: ".el",
      translateX: 250,
      delay: function(el, i) {
        return i * 100;
      },
      loop: true,
      direction: "alternate",
      easing: "easeInOutSine"
    });
  }, []);
  return (
    <div className="App">
      <button onClick={()=>animationRef.current.restart()}>Restart</button>
      <div className="el" />
    </div>
  );
}

ReactDOM.render(<App/>,document.querySelector('#root'));
.el {
  height: 16px;
  width: 16px;
  background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js" integrity="sha256-hBMojZuWKocCflyaG8T19KBq9OlTlK39CTxb8AUWKhY=" crossorigin="anonymous"></script>

<div id="root" />

设置 ref.current 是不明智的,因为它在技术上是一个只读属性,未来的版本可能会破坏它。

如果您需要访问该值,您应该将 useLayoutEffect 与 useState 结合使用。这是一个typescript示例:

import anime from "animejs";
import React, { useLayoutEffect, useState } from "react";

const [animationRef, setAnimationRef] = useState<ReturnType<typeof anime> | undefined>();

useLayoutEffect(() => {
    setAnimationRef(
        anime({
            // init props
        }),
    );
}, []); // Only run once.

注意:您可以毫无问题地将 useLayoutEffect 替换为 useEffect,以防您从中收到错误消息。特别是如果它被用在像 Next.js 这样的 SSR 上下文中