小程序实现一个 倒计时组件

小程序实现一个 倒计时组件

需求背景

  • 要做一个倒计时,可能是天级别,也可能是日级别,时级别,而且每个有效订单都要用,就做成组件了

效果图

Sep-14-2023 16-16-49.gif

Sep-14-2023 16-54-44.gif

需求分析

  1. 需要一个未来的时间戳,或者在服务度直接下发一个未来到现在时间差,我们只需要做倒计时
  2. 进入页面,看是否已经结束, 如果没结束就调用倒计时函数
  3. 每隔1000,做时间戳(毫秒) -1000。边做tick ,边做时间格式化。
  4. 每次调用前,先清除上一个定时器
  5. 组件销毁的时候,也要清除一下定时器

代码实现

  1. 设置初始值,也是1秒,这里单位时毫秒
const interval = 1000;
  1. 进入页面,初始化完成。开始判断是否结束
lifetimes: {
		ready() {
			this.startCountdown();
		},
		detached() {
			clearTimeout(this.timer);
		},
	},

startCountdown() {
    const lastTime = this.initTime(this.properties.expireTime); // 这一步,如果服务端返回了未来到现在的差值,则不需要自己计算时间差了
    // 如果最终时间 < 1000ms 说明 已经过期了,就不用展示倒计时了.
    if (lastTime > interval) {
    // 格式化要展示的数据
    this.defaultFormat(lastTime);
    this.setData({
            isCountOver: true, // 标识可以显示倒计时
            lastTime, // set lastTime
    });
    // 调用倒计时函数,主要的逻辑就是每隔1000ms ,让lastTime - 1000
        this.tick();
        }
    },

初始化时间: 如果服务度返回了时间差,这一步不用处理

//初始化时间
initTime(expireTime) {
    let lastTime = Number(new Date(expireTime * 1000)) - new Date().getTime();
    console.log('lastTime', lastTime);
    return Math.max(lastTime, 0);
},

时间的格式化处理,这里都是固定代码,没什么含量

//默认处理时间格式
defaultFormat(time) {
    const days = 60 * 60 * 1000 * 24;
    const hours = 60 * 60 * 1000;
    const minutes = 60 * 1000;
    const d = Math.floor(time / days);
    const h = Math.floor((time % days) / hours);

    const m = Math.floor((time % hours) / minutes);
    const s = Math.floor((time % minutes) / 1000);

    this.setData({
            d: this.fixedZero(d),
            h: this.fixedZero(h),
            m: this.fixedZero(m),
            s: this.fixedZero(s),
    });
},
// 格式化时间加0
fixedZero(val) {
        return val < 10 ? `0${val}` : val;
},

tick 倒计时函数

tick() {
    let { lastTime } = this.data;
    this.timer = setTimeout(() => {
    // 每次定时器之前,先把上一个定时器清除
        clearTimeout(this.timer);
    // 如果倒计时结束,这是结束的状态
            if (lastTime < interval) {
                    this.setData({
                            lastTime: 0,
                            isCountOver: false,
                    });
            } else {
    // 如果倒计时正常,则每次 -1000 ,并且格式化时间。再次调用tick,直到倒计时结束
                    lastTime -= 1000;
                    this.setData(
                            {
                                    lastTime,
                            },
                            () => {
                                    this.defaultFormat(lastTime);
                                    this.tick();
                            },
                    );
            }
    }, interval);
    },

完整代码

  • 父组件(我这里传了一个比较大的时间戳,2024,10.1结束的时间戳)
<order-time expireTime="{{ 1727712000 }}">
    <view slot="desc">还剩</view>
</order-time>

  • 子组件 (wxml)
<view wx:if="{{ isCountOver }}" class="timer-wrap">
	<slot name="desc" />
	<view class="reset-time">
		<text wx:if="{{ d != '00' }}"> {{ d }}</text>
		{{ h }}:{{ m }}:{{ s }}</view
	>
</view>
<view wx:else class="reset-time"> {{ emptyType === '1' ? '已超时': '' }} </view>

  • 子组件 (js)
let interval = 1000;
Component({
	options: {
		multipleSlots: true,
	},
	properties: {
		expireTime: {
			type: String,
		},
		emptyType: {
			type: String,
			value: '1',
		},
	},

	lifetimes: {
		ready() {
			this.startCountdown();
		},
		detached() {
			clearTimeout(this.timer);
		},
	},

	/**
	 * 组件的初始数据
	 */
	data: {
		d: 0, //天
		h: 0, //时
		m: 0, //分
		s: 0, //秒
		lastTime: '', //倒计时的时间戳
		isCountOver: false, // 倒计时是否完成
	},

	/**
	 * 组件的方法列表
	 */
	methods: {
		startCountdown() {
			const lastTime = this.initTime(this.properties.expireTime);

			if (lastTime > interval) {
				this.defaultFormat(lastTime);
				this.setData({
					isCountOver: true,
					lastTime,
				});

				this.tick();
			}
		},
		//默认处理时间格式
		defaultFormat(time) {
			const days = 60 * 60 * 1000 * 24;
			const hours = 60 * 60 * 1000;
			const minutes = 60 * 1000;
			const d = Math.floor(time / days);
			const h = Math.floor((time % days) / hours);

			const m = Math.floor((time % hours) / minutes);
			const s = Math.floor((time % minutes) / 1000);

			this.setData({
				d: this.fixedZero(d),
				h: this.fixedZero(h),
				m: this.fixedZero(m),
				s: this.fixedZero(s),
			});
		},

		//定时事件
		tick() {
			let { lastTime } = this.data;
			this.timer = setTimeout(() => {
				clearTimeout(this.timer);
				if (lastTime < interval) {
					this.setData({
						lastTime: 0,
						isCountOver: false,
					});
				} else {
					lastTime -= 1000;
					this.setData(
						{
							lastTime,
						},
						() => {
							this.defaultFormat(lastTime);
							this.tick();
						},
					);
				}
			}, interval);
		},

		//初始化时间
		initTime(expireTime) {
			let lastTime = Number(new Date(expireTime * 1000)) - new Date().getTime();
			console.log('lastTime', lastTime);
			return Math.max(lastTime, 0);
		},

		// 格式化时间加0
		fixedZero(val) {
			return val < 10 ? `0${val}` : val;
		},
	},
});


  • 遇到相关变量,自己更改即可

End: 写作粗陋,有纰漏,建议之处,多多指教~~~

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 uni-app 小程序实现环形倒计时,可以使用 uni-canvas 组件结合 JavaScript 实现。以下是一个简单的实现过程: 1. 在页面中添加一个 uni-canvas 组件,设置宽度和高度,并设置 canvas-id 属性,例如: ``` <uni-canvas canvas-id="countdown" style="width: 200px; height: 200px;"></uni-canvas> ``` 2. 在页面的 JavaScript 中,获取到 canvas 绘图上下文对象,并设置绘图相关属性,例如: ``` const ctx = uni.createCanvasContext('countdown', this); const radius = 80; // 环形半径 const lineWidth = 10; // 环形线宽 const countDownTime = 60; // 倒计时时间,单位为秒 let remainingTime = countDownTime; // 剩余时间 const timer = setInterval(() => { remainingTime--; drawCountDown(remainingTime); if (remainingTime <= 0) { clearInterval(timer); } }, 1000); function drawCountDown(remainingTime) { const angle = (2 * Math.PI / countDownTime) * (countDownTime - remainingTime); ctx.clearRect(0, 0, 200, 200); // 清空画布 ctx.beginPath(); ctx.arc(100, 100, radius, -Math.PI / 2, angle - Math.PI / 2, false); ctx.setStrokeStyle('#ff0000'); ctx.setLineWidth(lineWidth); ctx.stroke(); ctx.closePath(); ctx.draw(); } ``` 3. 在 drawCountDown 函数中,根据剩余时间计算出当前的环形绘制角度,并绘制环形。其中,使用 arc 方法绘制环形,设置起始角度为 -Math.PI / 2,结束角度为当前角度减去 -Math.PI / 2,圆心坐标为 (100, 100)。 4. 使用 setInterval 方法每隔 1 秒钟更新一次剩余时间,并重新绘制环形,直到倒计时结束。 以上是一个简单的 uni-app 小程序实现环形倒计时的过程,你可以根据需要进行进一步的优化和美化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值