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 大佬