我有一个带有多个组件的React单页应用程序。对于第5个组件(仅向下滚动时可见),我有一个counter。现在我正在使用react-countup库来实现计数器功能。但是,计数器将在页面加载后立即启动。向下滚动到组件后,是否可以开始计数。 动画在页面加载后仅发生一次(这很好),但是我希望计数器在页面加载后不立即开始,而是在用户第一次向下滚动到组件时开始。 我的代码如下:
render() {
return (
<div className={style.componentName}>
<h2>Heading</h2>
<div className={style.col}>
<div>My counter</div>
<CountUp className={style.countup} decimals={1} start={0} end={25} suffix=" %" duration={3} />
</div>
</div>)}
更新的代码:
import CountUp, { startAnimation } from 'react-countup';
import VisibilitySensor from 'react-visibility-sensor';
class className extends Component {
state = {
scrollStatus: true
};
onVisibilityChange = isVisible => {
if (isVisible) {
if (this.state.scrollStatus) {
startAnimation(this.myCountUp);
this.setState({ scrollStatus: false });
}
}
}
render() {
return (
<div className={style.componentName}>
<h2>Heading</h2>
<VisibilitySensor onChange={this.onVisibilityChange} offset = {{ top:
10}} delayedCall>
<CountUp className={style.countup} decimals={1} start={0} end={25}
suffix=" %" duration={3} ref={countUp => { this.myCountUp= countUp;}}/>
</VisibilitySensor>
</div>)}
}
答案 0 :(得分:2)
对于每个React CountUp's README,您可以使用startAnimation
钩子手动启动动画。将其与react-visibility-sensor之类的东西结合使用,您可以等待动画开始,直到在用户浏览器中可见为止。
import React, {Component} from 'react';
import CountUp, {startAnimation} from 'react-countup';
import './App.css';
import VisibilitySensor from 'react-visibility-sensor';
const style = {
componentName: {},
col: {},
countup: {},
};
class App extends Component {
constructor(props) {
super(props);
this.onVisibilityChange = this.onVisibilityChange.bind(this); // Bind for appropriate 'this' context
}
onVisibilityChange(isVisible) {
if (isVisible) {
startAnimation(this.myCountUp);
}
}
render() {
return (
<div className={style.componentName}>
<h2>Heading</h2>
<div className={style.col}>
<div>My counter</div>
<VisibilitySensor
onChange={this.onVisibilityChange}
delayedCall // Prevents react apps triggering elements as visible before styles are loaded
>
<CountUp className={style.countup} decimals={1} start={0} end={25} suffix=" %" duration={3}
ref={countUp => { this.myCountUp = countUp; }} // From react-countup README
/>
</VisibilitySensor>
</div>
</div>
);
}
}
export default App;
按原样,每次您滚动到计数时,它将startAnimation
。如果您只想执行一次,只需添加在第一个渲染后设置的状态(然后根据更改后的状态阻止它再次执行startAnimation
)即可。
为达到相同效果而采取的优雅方法(不推荐)包括:
duration
,end
,start
)设置为等于用户向下滚动时会改变的某种状态来使用onStart
道具(在动画开始之前调用)来延迟动画的开始,直到用户向下滚动为止编辑:更新以解决您的第二个问题
不幸的是,react-countup
库似乎没有公开阻止startAnimation
启动的方法。
但是我们可以通过使用state来操纵end
道具,从而获得一个相当优雅的解决方案:
import React, {Component} from 'react';
import CountUp, {startAnimation} from 'react-countup';
import './App.css';
import VisibilitySensor from 'react-visibility-sensor';
const style = {
componentName: {},
col: {},
countup: {},
};
class App extends Component {
state = {
didViewCountUp: false
};
onVisibilityChange = isVisible => {
if (isVisible) {
this.setState({didViewCountUp: true});
}
}
render() {
return (
<div className={style.componentName}>
<h2 style={{fontSize: '40em'}}>Heading</h2>
<VisibilitySensor onChange={this.onVisibilityChange} offset={{
top:
10
}} delayedCall>
<CountUp className={style.countup} decimals={1} start={0} end={this.state.didViewCountUp ? 25 : 0}
suffix=" %" duration={3} />
</VisibilitySensor>
</div>)
}
}
export default App;
答案 1 :(得分:2)
自去年以来,API可能已更改。我现在设法用此代码来完成这项工作:
import React from "react";
import CountUp from "react-countup";
const MyComponent = () => (
<>
<CountUp end={100} redraw={true}>
{({ countUpRef, start }) => (
<VisibilitySensor onChange={start} delayedCall>
<span ref={countUpRef} />
</VisibilitySensor>
)}
</CountUp>
</>
);
export default App;
我在标签内使用此组件,因此redraw={true}
道具仅在此处用于在tabChange上重绘动画。
答案 2 :(得分:2)
这是我使用基于类的组件的解决方案 注意:导入两个库先运行这段代码 反应可见性传感器 反应计数
import React from "react";
import CountUp from "react-countup";
import VisibilitySensor from 'react-visibility-sensor';
class CountDown extends React.Component {
render() {
return (
<React.Fragment>
<CountUp start={0} end={100} prefix="+" duration="2">
{({ countUpRef, start }) => (
<VisibilitySensor onChange={start} delayedCall>
<span ref={countUpRef} />
</VisibilitySensor>
)}
</CountUp>
</React.Fragment>
)
}
}
export default CountDown;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
答案 3 :(得分:1)
这是我的实现。它只运行一次,并且每次组件进入视口以检查可见性时都不会重新渲染。
依赖项:
1. 反应计数 v.4.3.2
2. 反应可见性传感器 v.5.1.1
import React, { useState } from "react";
import CountUp from "react-countup";
import VisibilitySensor from "react-visibility-sensor";
const Ticker = ({ className, ...rest }) => {
const [viewPortEntered, setViewPortEntered] = useState(false);
return (
<CountUp {...rest} start={viewPortEntered ? null : 0}>
{({ countUpRef }) => {
return (
<VisibilitySensor
active={!viewPortEntered}
onChange={isVisible => {
if (isVisible) {
setViewPortEntered(true);
}
}}
delayedCall
>
<h4 className={className} ref={countUpRef} />
</VisibilitySensor>
);
}}
</CountUp>
);
};
export default Ticker;
这里是使用方法:
<Ticker className="count" end={21} suffix="M+" />
答案 4 :(得分:0)
该库的文档可以手动启动计数器。一旦用户滚动到所需距离,我将使用该方法启动计数器。
import React, { Component } from 'react';
import CountUp, { startAnimation } from 'react-countup';
const MyComponent = () => (
<div>
<CountUp className="CountUp" start={0} end={100} duration={3} ref={(countUp) => {
this.myCountUp = countUp;
}} />
<button className="Button" onClick={(event) => {
startAnimation(this.myCountUp);
}}>Count me up!</button>
</div>
);
export default App;
Link to Github。阅读自述文件的最底部。
答案 5 :(得分:0)
您可以查看我的功能组件来实现
import React from "react";
import { Box } from "@material-ui/core";
import CountUp from "react-countup";
import VisibilitySensor from "react-visibility-sensor";
export default function Counter() {
const [focus, setFocus] = React.useState(false);
return (
<Box component="div">
<CountUp start={focus ? 0 : null} end={100} duration={5} redraw={true}>
{({ countUpRef }) => (
<div>
<span ref={countUpRef} />
<VisibilitySensor
onChange={isVisible => {
if (isVisible) {
setFocus(true);
}
}}
>
<a>+</a>
</VisibilitySensor>
</div>
)}
</CountUp>
</Box>
);
}