先来看一下效果图吧
循环倒计时
单个倒计时
接下来看一下具体代码吧
循环倒计时
wxml
<!--pages/commodity/commodity-time-limit/index.wxml-->
<wxs module="format" src="../../../../wxs/format.wxs"></wxs>
<wxs module="filter" src="../../../../wxs/filter.wxs"></wxs>
<!-- 顶部 S -->
<view class="head-top">
<image class="back" src="https://ico.dongtiyan.com/tu-105.png"></image>
<view class="navbar custom-class"
style='height:{{navHeight}}px;background: url("https://ico.dongtiyan.com/tu-163.png"); background-size: 100% 100%;position: fixed;top:0'>
<view class="navbar-action-wrap navbar-action-group row item-center" style='top:{{navTop + 7}}px;' bindtap="goBack">
<image src="https://ico.dongtiyan.com/tu-109.png"></image>
<view class="navbar-title" style="top:{{navTop}}">秒杀专区</view>
</view>
</view>
<!-- 头部 S -->
<view class="time-limit-top">
<view class="top-title {{Index==index? 'active': ''}}" wx:for="{{topList}}" wx:key="index" data-index="{{index}}"
bindtap="chooseCut">
<view>{{item.title}}</view>
<view class="desc {{Index==index? 'actives': ''}}">{{item.desc}}</view>
</view>
</view>
<!-- 头部 E -->
</view>
<!-- 轮播 S -->
<view class="banner">
<!-- 轮播图 S -->
<swiper class="viewpager" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}"
circular="{{circular}}" bindchange="changeSwiper">
<swiper-item wx:for="{{slideshow}}" wx:key="index">
<navigator url="../../../{{item.url}}" hover-class="none" style="display: inline;">
<image src="{{item.image}}" class="image"></image>
</navigator>
</swiper-item>
</swiper>
<view class="dots">
<block wx:for="{{slideshow}}" wx:key="index">
<view class="dot {{index == currentSwiper ? 'active-z' : ''}}"></view>
</block>
</view>
<!-- 轮播图 E -->
</view>
<!-- 写入内容 S -->
<block wx:if="{{goodsList.length != 0}}">
<view class="list1">
<!-- 轮播 E -->
<!-- 写入内容 S -->
<view class="seckill-top">
<view class="seckill-top-left">
<image src="https://ico.dongtiyan.com/tu-107.png"></image>
<view class="seckill-top-size">限时抢购</view>
<image src="https://ico.dongtiyan.com/tu-106.png"></image>
<view class="seckill-top-size">正品保障</view>
</view>
<!-- <view class="seckill-top-right">
<view class="distance-time">距结束还剩{{remainTime}}</view>
<view class="count-down-time">
<view class="time">{{hour}}</view>
<view class="space-mark">:</view>
<view class="time">{{minute}}</view>
<view class="space-mark">:</view>
<view class="time">{{second}}</view>
</view>
</view> -->
</view>
<!-- list -->
<view class="seckill-module">
<view class="seckill-goods">
<view class="seckill-goods-item" wx:for="{{goodsList}}" wx:key="index" bindtap="chooseSeckillDetail"
data-goodsid="{{item.goods_id}}" data-shopid="{{item.shop_id}}" data-index="{{index}}">
<block wx:if="{{newTime > item.seckill_end_time}}">
<view class="has-gone">已结束</view>
</block>
<block wx:else>
<block wx:if="{{item.store_count == 0}}">
<view class="has-gone">已抢光</view>
</block>
</block>
<view class="seckill-goods-image">
<image src="{{item.goods_pic_url}}"></image>
</view>
<view class="seckill-goods-info">
<view class="seckill-goods-name">{{item.goods_name}}</view>
<view class="seckill-goods-desc">
<view class="seckill-goods-desc-title">
<block wx:if="{{item.is_selected == 1}}">
<text>精选</text>
</block>
<block wx:if="{{item.is_postage == 0}}">
<text>包邮</text>
</block>
<block wx:if="{{item.is_new == 1}}">
<text>新品</text>
</block>
</view>
<view class="seckill-goods-count-down-layout">
<view class="seckill-goods-count-down">
<text class="seckill-goods-count-down-left" wx:if="{{Index == 0}}">截止时间:</text>
<text class="seckill-goods-count-down-left" wx:if="{{Index == 1}}">即将开始:</text>
<text>
<text>{{item.endTime.day}}</text>
<text>天 </text>
<text>{{item.endTime.hou}}</text>
<text> : </text>
<text>{{item.endTime.min}}</text>
<text> : </text>
<text>{{item.endTime.sec}}</text>
</text>
</view>
</view>
</view>
<view class="seckill-goods-btn">
<view class="seckill-goods-btn-left">
<text>¥ </text>
<text>{{item.shop_price}}</text>
</view>
<view class="seckill-goods-btn-right" wx:if="{{newTime < item.seckill_end_time}}">购买</view>
<view class="seckill-goods-btn-rights" wx:else>已结束</view>
</view>
</view>
</view>
</view>
</view>
<!-- 写入内容 E -->
</view>
<!-- 写入内容 E -->
<view class="loading" hidden="{{!loadMore}}">加载中...</view>
<view class="loading" hidden="{{!loadAll}}">已经加载完了~</view>
</block>
<block wx:else>
<view class="kong">
抱歉! 商品跑丢了~
</view>
</block>
wxss
/* pages/commodity/commodity-time-limit/index.wxss */
/* 顶部 S */
.head-top {
width: 100%;
height: 351rpx;
}
.head-top .back {
width: 100%;
height: 351rpx;
z-index: -1;
}
.navbar {
width: 100%;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
z-index: 10;
flex-shrink: 0;
}
.navbar-title {
width: 100%;
box-sizing: border-box;
padding-left: 40px;
padding-right: 105px;
line-height: 35px;
text-align: center;
margin: 0 auto;
/* position: absolute; */
position: fixed;
left: 0;
z-index: 10;
color: #fff;
font-size: 13px;
font-weight: Medium;
font-family: "PingFang-SC-Medium";
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
display: flex;
}
.navbar-action-wrap {
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
/* position: absolute; */
left: 10px;
z-index: 11;
line-height: 1;
position: fixed;
}
.navbar-action-wrap image {
width: 12px;
height: 18px;
}
.navbar-action-group {
border-radius: 20px;
overflow: hidden;
}
.navbar-action_item {
padding: 3px 0;
color: #333;
}
.navbar-action-group .navbar-action_item {
border-right: 1px solid #f0f0f0;
padding: 3px 14px;
}
.navbar-action-group .last {
border-right: none;
}
.navbar-title-size {
font-size: 10px;
margin-right: 20rpx;
align-self: center;
margin: 0 auto;
}
.navbar-title-size.active {
color: red;
border-bottom: 2px solid red;
}
.scroll-box {
position: absolute;
height: 100%;
}
/* 顶部 E */
.time-limit-top {
height: 100rpx;
display: flex;
align-self: center;
justify-content: space-between;
margin-top: -208rpx;
margin-left: 94rpx;
margin-right: 94rpx;
}
.time-limit-top .top-title {
width: 178rpx;
height: 90rpx;
align-self: center;
text-align: center;
color: #fff;
font-size: 32rpx;
border-radius: 10rpx;
}
.time-limit-top .top-title .desc {
font-size: 24rpx;
margin-top: 13rpx;
color: #FACACA;
}
.active {
background: #FFFFFF;
color: #FE5669 !important;
}
.actives {
color: #FE7D8B;
}
/* 正在秒杀 下期预告 */
/* 轮播图 */
.banner {
height: 240rpx;
margin-left: 20rpx;
margin-right: 20rpx;
text-align: center;
margin-top: -60rpx;
}
.viewpager {
width: 100%;
height: 240rpx;
border-radius: 0.5rem;
margin-bottom: 22rpx;
overflow: hidden;
}
.viewpager .image {
width: 100%;
height: 100%;
border-radius: 0.5rem;
}
/*用来包裹所有的小圆点 */
.dots {
height: 36rpx;
display: flex;
flex-direction: row;
justify-content: center;
margin-top: -50rpx;
z-index: 99;
position: relative;
}
/*未选中时的小圆点样式 */
.dot {
width: 7rpx;
height: 6rpx;
border-radius: 3rpx;
margin-right: 26rpx;
background-color: #FFFFFF;
}
/*选中以后的小圆点样式 */
.active-z {
width: 26rpx;
height: 6rpx;
border-radius: 3rpx;
background-color: #E5627B;
}
/* 写入内容 */
.seckill-top {
background: #fff;
height: 88rpx;
margin: 14rpx 20rpx 0;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20rpx;
}
.seckill-top-left {
font-size: 24rpx;
color: #000000;
display: flex;
align-self: center;
}
.seckill-top-left image:nth-child(1){
width: 25rpx;
height: 27rpx;
margin-right: 9rpx;
padding-top: 4rpx;
}
.seckill-top-left .seckill-top-size {
margin-right: 39rpx;
}
.seckill-top-left image:nth-child(3) {
width: 22rpx;
height: 26rpx;
margin-right: 8rpx;
padding-top: 4rpx;
}
.seckill-top-right {
font-size: 24rpx;
color: #666666;
display: flex;
align-items: center;
}
.seckill-top-right .distance-time {
margin-right: 14rpx;
}
.count-down-time {
display: flex;
align-items: center;
font-size: 24rpx;
}
.seckill-top-right .count-down-time .time {
width: 34rpx;
text-align: center;
color: #FFFFFF;
background: #000000;
}
.seckill-top-right .count-down-time .space-mark {
margin: 0 10rpx;
}
/* 秒杀抢购 */
.seckill-module {
background-color: #FFFFFF;
margin: 0 20rpx 20rpx;
border-bottom-left-radius: 20rpx;
border-bottom-right-radius: 20rpx;
padding-top: 20rpx;
}
.seckill-goods-item {
margin: 0 0 40rpx;
padding-bottom: 20rpx;
display: flex;
}
.seckill-goods-item:last-child {
margin: 10rpx 0 20rpx;
}
.seckill-goods-image {
width: 238rpx;
height: 238rpx;
border-radius: 20rpx;
overflow: hidden;
margin: 0 20rpx;
}
.has-gone {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background-color: #000000;
opacity: 0.5;
font-size: 30rpx;
color: #FFFFFF;
text-align: center;
line-height: 120rpx;
position: absolute;
left: 100rpx;
margin-top: 70rpx;
}
.seckill-goods-image image {
width: 100%;
height: 100%;
}
.seckill-goods-info {
padding: 0 16rpx;
}
.seckill-goods-name {
font-size: 28rpx;
color: #333333;
font-weight: bold;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
width: 400rpx;
}
.seckill-goods-desc {
margin: 10rpx 0 20rpx;
}
.seckill-goods-desc-title {
font-size: 20rpx;
color: #F28D37;
padding: 5rpx 10rpx;
border-radius: 10rpx;
}
.seckill-goods-desc-title text {
background-color: #FFF3E8;
margin-right: 10rpx;
padding: 2rpx 10rpx;
border-radius: 5rpx;
}
.seckill-goods-count-down-layout {
text-align: right;
}
.seckill-goods-count-down {
width: 100%;
font-size: 24rpx;
color: #F0133C;
margin-top: 20rpx;
}
.seckill-goods-count-down text:nth-child(1) {
margin-right: 10rpx;
}
.seckill-goods-count-down text:nth-child(2) text:nth-child(1),
.seckill-goods-count-down text:nth-child(2) text:nth-child(3),
.seckill-goods-count-down text:nth-child(2) text:nth-child(5) {
border-radius: 6rpx;
}
.seckill-goods-btn {
display: flex;
justify-content: space-between;
align-items: center;
}
.seckill-goods-btn-left {
color: #F72149;
font-size: 40rpx;
font-weight: bold;
}
.seckill-goods-btn-left text:nth-child(1) {
font-size: 24rpx;
}
.seckill-goods-btn-right {
font-size: 30rpx;
color: #FFFFFF;
background-color: #F72149;
width: 115rpx;
text-align: center;
height: 42rpx;
line-height: 42rpx;
border-radius: 10rpx;
}
.seckill-goods-btn-rights {
font-size: 30rpx;
color: #999999;
background-color: #f6f6f6;
width: 115rpx;
text-align: center;
height: 42rpx;
line-height: 42rpx;
border-radius: 10rpx;
}
.kong {
text-align: center;
color: #999999;
font-size: 24rpx;
margin-top: 300rpx;
}
js
Page({
data: {
goodsList: [
{
seckill_end_time: 1606751700
seckill_strat_time: 1604224200
}
],
datetimeDown: "", // 开始倒计时时间
// 秒杀倒计时
hour: "", // 时
minute: "", // 分
second: "", // 秒
loadMore: false, // 上拉加载的变量, 默认false 隐藏
loadAll: false, // 没有数据的变量, 默认false , 隐藏
newTime: 0, // 当前时间戳
},
/**
* 秒杀倒计时
*/
timeFormat(param) {//小于10的格式化函数
return param < 10 ? '0' + param : param;
},
countDown: function () {
// 获取当前时间, 同样得到活动结束时间数组
let newTime = Date.parse(new Date()) / 1000; // 当前时间
let seckill = this.data.goodsList;
seckill.forEach(i => {
let endTime = ''
if (this.data.Index == 0) { // Index判断当前是秒杀还是预告商品, 根据项目需求
endTime = i.seckill_end_time;
} else if (this.data.Index == 1) {
endTime = i.seckill_strat_time;
}
let obj = null;
let time = (endTime - newTime);
// 如果活动未结束,对时间进行处理
if (time > 0) {
// 获取天、时、分、秒
let day = parseInt(time / (60 * 60 * 24));
let hou = parseInt(time % (60 * 60 * 24) / 3600);
let min = parseInt(time % (60 * 60 * 24) % 3600 / 60);
let sec = parseInt(time % (60 * 60 * 24) % 3600 % 60);
obj = {
day: this.timeFormat(day),
hou: this.timeFormat(hou),
min: this.timeFormat(min),
sec: this.timeFormat(sec)
}
} else {//活动已结束,全部设置为'00'
obj = {
day: '00',
hou: '00',
min: '00',
sec: '00'
}
clearTimeout(this.countDown)
}
i.endTime = obj;
})
// 渲染,然后每隔一秒执行一次倒计时函数
this.setData({ goodsList: seckill, newTime: newTime }) // newTime当前时间戳,是为了判断当前商品是否结束或开始根据需求修改就好
setTimeout(this.countDown, 1000);
},
})
主要是js,有什么不懂的可以下方留言,或者有更好的解决方案
单个倒计时
wxml
<view class="count-down-show">
<view class="time">{{txtTime.day}}</view>
<view class="space-mark">天</view>
<view class="time">{{txtTime.hou}}</view>
<view class="space-mark">:</view>
<view class="time">{{txtTime.min}}</view>
<view class="space-mark">:</view>
<view class="time">{{txtTime.sec}}</view>
</view>
js
Page({
data: {
datetimeDown:'2020/11/30, 23:55:00', // 结束时间
detetimeStrat: '2020/11/29, 23:55:00', // 开始时间
},
/**
* 倒计时
*/
timeFormat(param) {//小于10的格式化函数
return param < 10 ? '0' + param : param;
},
countDown: function () {
var _this = this;
var time = 0;
var obj = {};
let endTime = 0;
if(_this.data.statusindex != 1) {
endTime = new Date(_this.data.datetimeDown.replace(/-/g, '/')).getTime(); // 结束时间戳
} else {
endTime = new Date(_this.data.detetimeStrat.replace(/-/g, '/')).getTime(); // 开始时间戳
}
let timestamp = new Date().getTime(); // 当前时间戳
time = (endTime - timestamp) / 1000; // 时间差
if(time > 0) {
var day = parseInt(time / (60 * 60 * 24));
var hou = parseInt(time % (60 * 60 * 24) / 3600);
var min = parseInt(time % (60 * 60 * 24) % 3600 / 60);
var sec = parseInt(time % (60 * 60 * 24) % 3600 % 60);
obj = {
day: _this.timeFormat(day),
hou: _this.timeFormat(hou),
min: _this.timeFormat(min),
sec: _this.timeFormat(sec)
}
} else { // 活动结束
obj = {
day: "00",
hou: "00",
min: "00",
sec: "00"
}
if(_this.data.statusindex == 1) {
_this.setData({
statusindex: 0
})
_this.data.timeIntervalSingle
} else {
_this.setData({
statusIndex: 1
})
clearTimeout(_this.data.timeIntervalSingle); //清除定时器
}
}
var timeIntervalSingle = setTimeout(_this.countDown, 1000);
_this.setData({
timeIntervalSingle,
txtTime: obj,
timestamp: timestamp
})
},
})
以上就是所有代码有什么不懂的可以下方留言
如果对你有用,关注一下博主的小程序,登录一下给予支持,以后有什么开源好用的源码都会上传到小程序