【问题标题】:Trigger a CSS animation once the element is in view with Material-UI使用 Material-UI 显示元素后触发 CSS 动画
【发布时间】:2020-04-30 04:57:33
【问题描述】:

我对元素进入视野后如何触发 CSS 动画进行了一些研究,我发现 the answer 使用了 IntersectionObserverelement.classList。 add('.some-class-name')

上面的方法是用纯 CSS 演示的,但我想用 Material-UI 来实现它。这是我的代码。

import React, { useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles((theme) => ({
  root: {
    height: '100vh'
  },
  box: {
    opacity: 0,
    width: 100,
    height: 100,
    backgroundColor: 'red'
  },
  animated: {
    animationName: '$fadein',
    animationDuration: '1s'
  },
  '@keyframes fadein': {
    '0%': {
      opacity: 0
    },
    '100%': {
      opacity: 1
    }
  },
}));

function App() {
  const classes = useStyles();
  
  useEffect(() => {
    const observer = new IntersectionObserver((entries, observer) => {
      entries.forEach((entry) => {
        if (entry.intersectionRatio > 0) {

          // trigger animation
          entry.target.classList.add('animated');

          // remove observer
          observer.unobserve(entry.target);
        }
      });
    });

    const element = document.getElementById('item');
    observer.observe(element);      
  }, []);
  
  return (
    <div>
      <div className={classes.root} />
      <div id="item" className={classes.box} />
    </div>
  );
};

export default App;

不幸的是,上面的代码不起作用,我认为这是因为 className 'animated' 不存在。我知道 Material-UI 具有生成唯一类名的内部逻辑,所以我的问题是如何找出“动画”的真实类名?或者,有没有更好的方法来解决这个问题?任何帮助将不胜感激。

【问题讨论】:

标签: javascript reactjs material-ui css-animations


【解决方案1】:

这是我想出来的。

import React, { useEffect, useState, useRef } from 'react';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles((theme) => ({
  root: {
    height: '100vh'
  },
  box: {
    opacity: 0,
    width: 100,
    height: 100,
    backgroundColor: 'red'
  },
  animated: {
    animationName: '$fadein',
    animationDuration: '1s',
    animationFillMode: 'forwards'
  },
  '@keyframes fadein': {
    '0%': {
      opacity: 0
    },
    '100%': {
      opacity: 1
    }
  }
}));

function App() {
  const classes = useStyles();

  const BoxSection = (props) => {
    const [isVisible, setVisible] = useState(false);
    const domRef = useRef();
    useEffect(() => {
      const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => setVisible(entry.isIntersecting));
      });
      observer.observe(domRef.current);
      return () => observer.unobserve(domRef.current);  // clean up
    }, []);
    return (
      <div className={`${classes.box} ${isVisible ? classes.animated : ''}`} ref={domRef}>
        {props.children}
      </div>
    );
  };

  return (
    <div>
      <div className={classes.root} />
      <BoxSection />
    </div>
  );
}

export default App;

基本上,我决定通过添加上面的类来使用状态来触发动画。我有一些来自this article 的指点,如果有人感兴趣的话。

【讨论】:

    猜你喜欢
    • 2021-07-10
    • 2014-03-11
    • 1970-01-01
    • 2019-11-30
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    相关资源
    最近更新 更多