React
-使用antd-mobile
实现圆弧倒计时
一、实现效果
二、实现代码
1、antd-mobile
官网
2、安装antd-mobile
npm i antd-mobile
或者
yarn add antd-mobile
3、检查package.json
里是否安装成功
4、对应代码
实现步骤:
- 【1】、自定义
state
:
realTime
:实际倒计时时间circlePercentage
:滚动圈滚动百分比- 【2】、初始化定时器为
null
;- 【3】、在
componentDidMount
里处理倒计时【注意:先关闭倒计时,再调用倒计时方法,是为了实现:每次进入页面,就让倒计时重新计时】;- 【4】、倒计时样式渲染:通过
antd-mobile
里的ProgressCircle
实现;- 【5】、在
componentWillUnmount
里清除倒计时;- 【6】、处理特殊情况 ——
ios
缓存情况:ios
返回页面时不会默认刷新页面,即不会进componentDidMount
。
page_answer.jsx
import React from 'react';
import answerStore from '@src/store/answer'; // 引入answerStore【answerStore相关的是我项目接口相关的内容和公用方法,小萝卜儿们可根据实际情况处理】
import { ProgressCircle } from 'antd-mobile'; // 【4】引入 进度圈
import './page_answer.less'; // 引入css
class Page_answer extends React.Component {
constructor(props) {
super(props);
}
// 【1】、自定义state
state = {
realTime: 0, // 实际倒计时时间
circlePercentage: 0, // 滚动圈滚动百分比
}
// 【2】、初始化定时器为null
timer = null; // 定时器
async componentDidMount() {
// async...await...表示先请求接口数据、渲染html
await answerStore.getQuestion(); // 请求接口-获取题目
/** 【3】用户从其他链接返回活动页面,倒计时重新计时 */
clearInterval(this.timer);
this.countDown();
// 【6】处理特殊情况 —— ios缓存情况。监听页面展示-针对情况:返回时页面为缓存而非刷新【缓存: 即页面未刷新、未调用接口请求数据】
const isIos = /ipad|iPhone|Mac/i.test(window.navigator.userAgent);
if (isIos) { // ios
window.addEventListener('pageshow', this.iosPageShow.bind(this), this);
} else { // Android
document.addEventListener("visibilitychange", this.androidPageShow.bind(this), this);
}
}
componentWillUnmount() {
// 【5】清除定时器
clearInterval(this.timer);
// 【6】处理特殊情况 —— ios缓存情况。
window.removeEventListener('pageshow', this.iosPageShow.bind(this), this);
document.removeEventListener("visibilitychange", this.androidPageShow.bind(this), this);
}
// 【6】ios下的页面展示
iosPageShow = () => {
console.info('ios visible');
// 在这儿写下缓存情况时 页面展示后需要进行的操作~【我封装成了一个函数,直接写到该函数里即可】
this.pageShow();
}
// 【6】android下的页面展示
androidPageShow = () => {
if (window.visibilityState === "visible") {
console.info('android visible');
// 在这儿写下缓存情况时 页面展示后需要进行的操作~【我封装成了一个函数,直接写到该函数里即可】
this.pageShow();
}
}
// 【6】封装函数-页面展示
pageShow = async (show) => {
if (show) {
console.info('visible');
// async...await...表示先请求接口数据、渲染html
await answerStore.getQuestion(); // 请求接口-获取题目
/** 用户从其他链接返回活动页面,倒计时重新计时 */
const {
// 倒计时时间
realTime
} = this.state;
const {
// 本题是否已经回答过了
answered
} = answerStore?.questionInfo || {};
// 清除定时器
clearInterval(this.timer);
// 当倒计时时间不为0 且 本题未回答过,从其他页面返回,会重新倒计时
realTime != 0 && !answered && this.countDown();
}
}
// 【3】倒计时
countDown = () => {
const { answerLimitTime } = answerStore?.questionInfo || {}; // 后端返的倒计时数据(单位: 毫秒)
const gotRealTime = (answerLimitTime * 1) / 1000; // 前端实际获取到的倒计时秒数
console.log('gotRealTime', gotRealTime);
// 设置初始值
this.setState({
realTime: gotRealTime,
circlePercentage: 0,
})
// 获取到滚动圈每次需自加的 滚动百分比
const percentage = 100 / gotRealTime;
// 先关闭倒计时
clearInterval(this.timer);
// 再定义倒计时
this.timer = setInterval(() => {
let { realTime } = this.state;
if (realTime <= 0) {
/** 倒计时结束 */
// 关闭倒计时
clearInterval(this.timer);
// 让滚动圈滚动百分比、倒计时时间都归置为0
this.setState({
circlePercentage: 0,
realTime: 0,
})
// 根据自己需求进行操作
answerStore.submitAnswer('', false); // 调用接口-提交答案
return;
}
// 时间每隔一秒减一秒 并 赋值到state里
realTime--;
this.setState({
realTime,
// 时间每隔一秒 滚动圈滚动百分比 自加 percentage
circlePercentage: this.state.circlePercentage + percentage,
})
console.log('目前滚动圈百分比', this.state.circlePercentage);
}, 1000)
}
render() {
const {
// 滚动圈滚动百分比
circlePercentage,
// 倒计时时间
realTime,
} = this.state;
return (
<div className="page_answer">
{/* 【4】倒计时 */}
<div className="box">
<ProgressCircle percent={circlePercentage} style={{ '--track-width': `${10 * remScale}px`, '--size': `${103 * remScale}px`, '--fill-color': '#e2734b', '--track-color': '#fff' }}>{realTime}</ProgressCircle>
</div>
</div>
);
}
}
export default Page_answer;
page_answer.less
.box{
width: 103px;
height: 103px;
position: relative;
background-color: #fff;
border-radius: 50%;
left: 322px;
top: 355px;
}
哒哒哒哒~