zoukankan      html  css  js  c++  java
  • React实现块依次从下到上进入的动画

    app.js

    import React, { useEffect, useState } from 'react';
    
    import Nav from './components/Nav';
    import Footer from './components/Footer';
    import About from './components/About';
    import Product from './components/Product';
    import Service from './components/Service';
    import Value from './components/Value';
    import JoinUs from './components/JoinUs';
    import ContactUs from './components/ContactUs';
    
    import './index.scss';
    import { IntlProvider, addLocaleData } from 'react-intl';
    import zh_CN from '@/locales/zh-CN';
    import en_US from '@/locales/en-US';
    
    const getLang = () => {
        const search = window.location.search;
        const params = new URLSearchParams(search);
        return params.get('lang') || 'en';
    };
    
    const App = () => {
        const [scrollTop, setScrollTop] = useState(0);
        const [locale, setLocale] = useState(getLang());
        const messages = {
            zh: zh_CN,
            en: en_US
        };
        const handleScroll = () => {
            const top =
                document.documentElement.scrollTop || document.body.scrollTop;
            setScrollTop(top);
        };
    
        useEffect(() => {
            handleScroll();
            window.addEventListener('scroll', handleScroll);
            return () => {
                window.removeEventListener('scroll', handleScroll);
            };
        }, []);
    
        return (
            <IntlProvider locale="en" messages={messages[locale]}>
                <div className={`page-content ${locale}`}>
                    <Nav scrollTop={scrollTop} />
                    <About locale={locale} />
                    <Product scrollTop={scrollTop} />
                    <Service scrollTop={scrollTop} />
                    <Value scrollTop={scrollTop} />
                    <JoinUs scrollTop={scrollTop} />
                    <ContactUs locale={locale} scrollTop={scrollTop} />
                    <Footer />
                </div>
            </IntlProvider>
        );
    };
    export default App;

    在app.js中传递scrollTop给组件,用来计算动画触发时的高度

    随便一个组件的代码:

    import React, { useState, useEffect, useRef } from 'react';
    import { Animate } from 'react-move';
    import { FormattedMessage } from 'react-intl';
    import { easeQuadInOut } from 'd3-ease';
    import Location from '@/assets/svg/location.svg';
    import ArrowUp from '@/assets/svg/arrow-down.svg';
    import Globe from '@/assets/images/globe.png';
    import './index.scss';
    
    const JoinUs = ({ scrollTop }) => {
        const ref = useRef();
        const [options, setOptions] = useState(false);
        const showOption = () => {
            setOptions(!options);
        };
    
        const handleScroll = top => {
            const obj = ref.current;
            const clientHeight = document.documentElement.clientHeight;
            const diff = clientHeight - obj.offsetTop + top;
    
            const doms = document.querySelectorAll('.section-joinus__select');
            Array.from(doms).forEach((item, index) => {
                if (diff > 0 && !item.style.animation) {
                    item.style.animation = `slideUpBox 1s ease-in ${0.2 *
                        index}s forwards`;
                }
            });
    
            const domText = document.querySelector('.section-joinus__resc');
            if (diff > 0 && !domText.style.animation) {
                domText.style.animation = `slideUp 1s ease-in forwards`;
            }
        };
    
        useEffect(() => {
            handleScroll(scrollTop);
        }, [scrollTop]);
    
        const [items, setItems] = useState([
            {
                id: 0,
                country: <FormattedMessage id="component.join.country1" />,
                work1: <FormattedMessage id="component.join.work1" />,
                work2: <FormattedMessage id="component.join.work2" />,
                btntxt: <FormattedMessage id="component.join.btntxt" />
            },
            {
                id: 1,
                country: <FormattedMessage id="component.join.country2" />,
                work1: <FormattedMessage id="component.join.work3" />,
                work2: <FormattedMessage id="component.join.work4" />,
                btntxt: <FormattedMessage id="component.join.btntxt" />
            }
        ]);
    
        return (
            <div className="section section-joinus" ref={ref}>
                <div className="padding37">
                    <div className="page-wrapper-inner">
                        <h4>
                            <FormattedMessage id="component.join.inner" />
                        </h4>
                        <div className="section-joinus__resc">
                            <FormattedMessage id="component.join.resc" />
                        </div>
                        {items.map((item, index) => (
                            <div className="section-joinus__select" key={index}>
                                <div
                                    className="country"
                                    onClick={() => showOption()}
                                >
                                    <i className="i-pos">
                                        <Location />
                                    </i>
                                    <span>{item.country}</span>
                                    <i className="i-up">
                                        <ArrowUp />
                                    </i>
                                </div>
                                <div
                                    className="option"
                                    style={{
                                        height:
                                            index === 0
                                                ? options
                                                    ? '0'
                                                    : '200px'
                                                : options
                                                ? '200px'
                                                : '0'
                                    }}
                                >
                                    <ul>
                                        <li>{item.work1}</li>
                                        <li>{item.work2}</li>
                                    </ul>
                                    <button>{item.btntxt}</button>
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
    
                <p className="section-joinus__china">
                    <FormattedMessage id="component.join.china" />
                </p>
                <p className="section-joinus__singa">
                    <FormattedMessage id="component.join.singa" />
                </p>
                <i className="section-joinus__circleChina"></i>
                <i className="section-joinus__circleSinga"></i>
                <div className="section-joinus__bg">
                    <img src={Globe} />
                </div>
            </div>
        );
    };
    export default JoinUs;
    

      

    ps:

    forwards:当动画完成后,保持最后一个属性值(在最后一个关键帧中定义)。

    ------from  大佬

  • 相关阅读:
    在客户端判断上传文件大小(不支持opera)
    javascript冒泡排序(javascript算法学习)
    提高js性能方法(让js只判断一次)
    ie8本地预览报错的解决
    负载均衡获取客户端IP
    遍历变量里面所有的属性
    HttpWebrequest的使用
    C#调用EnyimMemcached
    MySQL国内省市直辖区
    Log4Net使用
  • 原文地址:https://www.cnblogs.com/nangras/p/11555620.html
Copyright © 2011-2022 走看看