uniapp开发个倒计时小程序
前言
这是使用
UNIAPP
Uview
开发出来的可得计时小程序,是一款简约、方便的倒计时器微信小程序,您可以设置在上面设定未来的何时何分何秒后通知你。
我们先看看我们的成品效果图,是不是觉得很nice!
接下来,让我们来实现它
在uniapp
中创建一个新的uniapp
项目,这里我就命名为codeTime了
我们需要用到的uView
里边的CountDown
组件,所以我们需要先安装uView
,在项目所在位置打开终端,执行 (因为我们的项目是通过hbx创建的,没有package.json
文件)
npm init -y
npm install uview-ui
安装之后,需要在项目中配置下(引入uView
框架)
// main.js
import uView from "uview-ui";
Vue.use(uView);
# uni.scss
@import 'uview-ui/theme.scss';
# app.vue
<style lang="scss">
@import "uview-ui/index.scss";
/*每个页面公共css */
</style>
// pages.json
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
配置完后,我们可以使用console.log(this.$u.config.v);
,查看版本,检测是否安装及配置成功
onShow: function() {
console.log(this.$u.config.v);
},
我们还需要改下uView
框架中的CountDown
组件文件,因为需要我们这个项目需要用到暂停倒计时,但是该组件没有提供改方法
在CountDown
组件中的props
对象中加入属性
pause: {
type: Boolean,
default: false
}
修改CountDown
组件中的start
方法,利用父组件传入的pause
属性,来判断是否执行seconds --
,也就即是否进行减秒操作
// 倒计时
start() {
// 避免可能出现的倒计时重叠情况
this.clearTimer();
if (this.timestamp <= 0) return;
this.seconds = Number(this.timestamp);
this.formatTime(this.seconds);
this.timer = setInterval(() => {
if (!this.pause) {
this.seconds--;
// 发出change事件
this.$emit('change', this.seconds);
if (this.seconds < 0) {
return this.end();
}
this.formatTime(this.seconds);
} }, 1000);
},
CountDown组件说明文档: www.uviewui.com/components/…
我们把pages
文件夹下面的index.vue
文件整理下
<template>
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
},
methods: {
}
}
</script>
<style lang="scss">
</style>
我们项目组件主体分为三大部分
- 笔记组件
- note.vue
- 时间选择器组件
- date-selector
- 控制按钮组件
- controller-area
现在我们就按这个顺序来书写我们各部分的组件,到后面我们将这些组件插入到index.vue中
note组件
note.vue
,其实它只是一个简单的input组件,没有任何逻辑处理的组件,也是这个项目中最简单的一个组件,没有之一哈哈
<template>
<view class="c-title">
<input class="c-input" type="text" :value="note" placeholder="#添加计时内容" placeholder-class="c-input-pla" />
</view>
</template>
<script>
export default {
name:"note",
}
</script>
<style lang="scss">
.c-title {
padding: 50rpx 20rpx 20rpx 20rpx;
margin: 20rpx;
color: #007aff;
width: 90%;
height: 60rpx;
.c-input {
text-align: center;
font-size: 45rpx;
line-height: 45rpx;
height: 60rpx;
}
.c-input-pla {
color: #e7e7e7;
}
}
</style>
在index.vue
中引入它看看效果如何
<template>
<view class="c-container">
<note></note>
</view>
</template>
<style lang="scss" scoped>
.c-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>
date-selector组件
这是一个时间选择器组件,也就是我们用户选择时间用到的组件,这里用到的是uniapp
自带的组件,叫做picker-view
嵌入页面的滚动选择器,该组件文档地址 uniapp.dcloud.io/component/p…
<template>
<view class="u-picker-body">
<picker-view :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart"
@pickend="pickend">
<picker-view-column>
<view class="u-column-item" v-for="(item, index) in hours" :key="index">
{{ formatNumber(item) }}
<text class="c-text" v-if="showTimeTag">时</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="u-column-item" v-for="(item, index) in minutes" :key="index">
{{ formatNumber(item) }}
<text class="c-text" v-if="showTimeTag">分</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="u-column-item" v-for="(item, index) in seconds" :key="index">
{{ formatNumber(item) }}
<text class="c-text" v-if="showTimeTag">秒</text>
</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
name:"date-selector",
created(){
this.initTimeList()
},
data() {
return {
moving: false, // 列是否还在滑动中,微信小程序如果在滑动中就点确定,结果可能不准确
hours: [],
minutes: [],
seconds: [],
hour: 0,
minute: 0,
second: 0,
valueArr: [],
timestamp:300
};
},
props:{
showTimeTag:{
type:Boolean,
default:false
}
},
methods:{
// 初始化
initTimeList(){
// 生成 时,分,秒
this.valueArr.push(0);
this.setHours();
this.valueArr.push(0);
this.setMinutes();
this.valueArr.push(0);
this.setSeconds();
},
getIndex(arr, val) {
let index = arr.indexOf(val);
// 如果index为-1(即找不到index值),~(-1)=-(-1)-1=0,导致条件不成立
return ~index ? index : 0;
},
// 小于10前面补0,用于月份,日期,时分秒等
formatNumber(num) {
return num < 10 ? '0' num : String(num);
},
// 标识滑动开始,只有微信小程序才有这样的事件
pickstart() {
// #ifdef MP-WEIXIN
this.moving = true;
// #endif
},
// 标识滑动结束
pickend() {
// #ifdef MP-WEIXIN
this.moving = false;
this.$emit('pickend',this.timestamp)
// #endif
},
setHours() {
this.hours = this.generateArray(0, 23);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour));
},
setMinutes() {
this.minutes = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute));
},
setSeconds() {
this.seconds = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second));
},
// 生成递进的数组
generateArray(start, end) {
// 转为数值格式,否则用户给end-year等传递字符串值时,下面的end 1会导致字符串拼接,而不是相加
start = Number(start);
end = Number(end);
end = end > start ? end : start;
// 生成数组,获取其中的索引,并剪出来
return [...Array(end 1).keys()].slice(start);
},
// 用户更改picker的列选项
change(e) {
this.valueArr = e.detail.value;
let i = 0;
this.hour = this.hours[this.valueArr[i ]];
this.minute = this.minutes[this.valueArr[i ]];
this.second = this.seconds[this.valueArr[i ]];
this.getTimeToSecond(this.hour, this.minute, this.second);
},
// 将picker的时间专成秒数
getTimeToSecond(hour, minute, second) {
let time = 0;
if (hour) {
time = hour * 60 * 60;
}
if (minute) {
time = minute * 60;
}
if (second) {
time = second;
}
this.timestamp = time;
},
quickSetMinutes(minutes){
this.valueArr[0] = 0;
this.valueArr[1] = minutes;
this.valueArr[2] = 0;
this.setHours()
this.setMinutes()
this.setSeconds()
}
}
}
</script>
<style lang="scss">
.u-picker-body {
margin: 0;
width: 100%;
height: 500rpx;
overflow: hidden;
background-color: #ffffff;
.u-picker-view {
height: 100%;
width: 700rpx;
box-sizing: border-box;
margin: 0 auto;
.u-column-item {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
font-size: 50rpx;
color: #000000;
padding: 0 8rpx;
.c-text {
font-size: 24rpx;
padding-left: 8rpx;
}
}
}
}
</style>
同样,我们在index.vue
中引入它,在此之前,我们还要引入我们魔改后的CountDown
组件并传入需要的一些参数(timestamp
autoplay
...
),之后再引用我们写好的dateSelector
组件,记得加上v-if
,当start
为true
时,说明当前正在倒计时,我们需要把时间选择器隐藏起来。(其实这里使用v-show
更好,但是uniapp
本身不支持v-show
,因为v-if
会把元素重新渲染,这个之后再用style
的display
来控制吧,目前先这样子吧)
<template>
<view class="c-container">
<note></note>
<view class="c-countdown" v-if="start">
<u-count-down ref="uCountDown" :timestamp="timestamp" :autoplay="autoplay" :show-days="false"
:font-size="100" :separatorSize="65" :pause="pause"></u-count-down>
</view>
<date-selector v-else ref="dateSelectorRef" showTimeTag @pickend="pickend"></date-selector>
</view>
</template>
<script>
export default {
data() {
return {
start: false, // 是否开始倒计时
pause: false, // 是否处于暂停状态
autoplay: false,
timestamp: 300, // 默认五分钟
};
},
methods: {
pickend(timestamp) {
this.timestamp = timestamp
},
}
};
</script>
controller-area组件
整个项目的按钮组件都在这里边,它的按钮功能主要是控制倒计时器 CountDown
的的进行和暂停以及重置功能
<template>
<view class="c-controller">
<!-- 快捷设置按钮
<view :animation="animationQuickChooseTime" class="c-default-list">
<view v-for="(time,index) in defaultTimeList" v-if="defaultTimeList.length!==0"
@tap="selectDefaultTime(time,index)" :key="time">
<view :class="[index == selectIndex&&time*60==timestamp?'c-time-item-sel':'c-time-item']">
<view class="c-time-num">
{{time}}
</view>
<view :class="[index == selectIndex&&time*60==timestamp?'c-time-text-sel':'c-time-text']">
分钟
</view>
</view>
</view>
</view>
<!-- 控制按钮
<view class="c-controller-area">
<view :animation="animationToLeftData" class="c-button" style="z-index: 1;" @tap="startCountTime()">
<image v-if="start" class="c-icon" src="../../static/restart.png"></image>
<image v-else class="c-icon" src="../../static/start.png"></image>
</view>
<view :animation="animationToRightData" class="c-button" @tap="stopCountTime()">
<image v-if="!pause" class="c-icon" src="../../static/stop.png"></image>
<image v-else class="c-icon" src="../../static/start.png"></image>
</view>
</view>
</view>
</template>
<script>
export default {
name: "controller-area",
data() {
return {
// 动画
animationToLeftData: {},
animationToRightData: {},
animationQuickChooseTime: {},
selectIndex: null
};
},
methods: {
startCountTime() {
if (this.start) {
// 正在计时,停止它
this.$emit('startCountTime', this.start)
// 执行动画
let leftButton = uni.createAnimation({
transformOrigin: "50% 50%",
duration: 500,
timingFunction: "ease",
delay: 0
})
// 执行动画
let rightButton = uni.createAnimation({
transformOrigin: "50% 50%",
duration: 500,
timingFunction: "ease",
delay: 0
})
// 执行动画
let quickChooseTimeButton = uni.createAnimation({
transformOrigin: "50% 50%",
duration: 300,
timingFunction: "ease",
delay: 0
})
leftButton.translateX(0).step()
this.animationToLeftData = leftButton.export()
rightButton.translateX(0).opacity(0).step()
this.animationToRightData = rightButton.export()
quickChooseTimeButton.scale(1.1).step()
quickChooseTimeButton.scale(1).step()
this.animationQuickChooseTime = quickChooseTimeButton.export()
} else {
// 没有计时,开始计时
this.$emit('startCountTime', this.start)
// 执行动画
let leftButton = uni.createAnimation({
transformOrigin: "50% 50%",
duration: 500,
timingFunction: "ease",
delay: 0
})
// 执行动画
let rightButton = uni.createAnimation({
transformOrigin: "50% 50%",
duration: 500,
timingFunction: "ease",
delay: 0
})
// 执行动画
let quickChooseTimeButton = uni.createAnimation({
transformOrigin: "50% 50%",
duration: 500,
timingFunction: "ease",
delay: 0
})
leftButton.translateX(-60).step()
this.animationToLeftData = leftButton.export()
rightButton.opacity(1).translateX(60).step()
this.animationToRightData = rightButton.export()
quickChooseTimeButton.scale(0).step()
this.animationQuickChooseTime = quickChooseTimeButton.export()
}
},
stopCountTime() {
this.$emit('stopCountTime')
},
selectDefaultTime(time, index) {
this.$emit('clickSetTime', time)
this.selectIndex = index;
},
},
props: {
timestamp: {
type: Number,
default: 0
},
defaultTimeList: {
type: Array,
default: []
},
pause: {
type: Boolean,
default: false
},
start: {
type: Boolean,
default: false
}
}
}
</script>
<style lang="scss">
.c-controller {
position: absolute;
top: 750rpx;
left: 0;
height: 400rpx;
width: 100%;
.c-default-list {
display: flex;
justify-content: center;
position: absolute;
top:0;
left: 0;
right: 0;
bottom: 0;
margin:auto;
.c-time-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 125rpx;
height: 125rpx;
border-radius: 50%;
padding: 20rpx;
margin: 20rpx;
background-color: #eeeeee;
}
.c-time-item-sel {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 125rpx;
height: 125rpx;
border-radius: 50%;
padding: 20rpx;
margin: 20rpx;
color: #FFFFFF;
background-color: #007aff;
}
.c-time-item,
.c-time-item-sel {
.c-time-num {
font-size: 45rpx;
}
.c-time-text {
font-size: 20rpx;
color: #808080;
}
.c-time-text-sel {
font-size: 20rpx;
color: #d0f0f7;
}
}
}
.c-controller-area {
height: 200rpx;
width: 100%;
position: absolute;
top: 200rpx;
left: 0;
margin: 0;
.c-button {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 125rpx;
height: 125rpx;
border-radius: 50%;
background-color: #ffffff;
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.1), 0 3px 10px 0 rgba(0, 0, 0, 0.15);
top:0;
left: 0;
right: 0;
bottom: 0;
margin:auto;
/* 宽度的一半 */
.c-icon {
width: 50rpx;
height: 50rpx;
}
}
}
}
</style>
继续在index.vue
中引入,在script
标签中,继续加入一些需要的属性和方法
<template>
<view class="c-container">
<note></note>
<view class="c-countdown" v-if="start">
<u-count-down ref="uCountDown" :timestamp="timestamp" :autoplay="autoplay" :show-days="false"
:font-size="100" :separatorSize="65" :pause="pause"></u-count-down>
</view>
<date-selector v-else ref="dateSelectorRef" showTimeTag @pickend="pickend"></date-selector>
<controller-area @startCountTime="startCountTime" @stopCountTime="stopCountTime" @clickSetTime="clickSetTime"
:defaultTimeList="defaultTime" :timestamp="timestamp" :pause="pause" :start="start" class="">
</controller-area>
</view>
</template>
// 在index.vue中对应位置进行代码补充
data() {
return {
defaultTime: [5, 10, 15],
};
},
methods: {
// 开始倒计时
startCountTime() {
if (this.start) {
// 正在计时,停止它
console.log('restart');
this.start = false;
this.pause = false;
} else {
// 没有计时,开始计时
console.log('start');
this.start = true;
this.autoplay = true;
this.pause = false;
}
},
stopCountTime() {
this.pause = !this.pause;
},
clickSetTime(minutes) {
this.timestamp = minutes * 60;
this.$refs.dateSelectorRef.quickSetMinutes(minutes)
},
}
到了这里我们的三大组件已经书写好啦,接下来我们就要在index.vue
文件中进行一个引用,和一些逻辑方法的书写
index.vue
附上最终index.vue
的代码
<template>
<view class="c-container">
<note></note>
<view class="c-countdown" v-if="start">
<u-count-down ref="uCountDown" :timestamp="timestamp" :autoplay="autoplay" :show-days="false"
:font-size="100" :separatorSize="65" :pause="pause"></u-count-down>
</view>
<date-selector v-else ref="dateSelectorRef" showTimeTag @pickend="pickend"></date-selector>
<controller-area @startCountTime="startCountTime" @stopCountTime="stopCountTime" @clickSetTime="clickSetTime"
:defaultTimeList="defaultTime" :timestamp="timestamp" :pause="pause" :start="start" class="">
</controller-area>
</view>
</template>
<script>
export default {
data() {
return {
start: false, // 是否开始倒计时
pause: false, // 是否处于暂停状态
autoplay: false,
timestamp: 300, // 默认五分钟
defaultTime: [5, 10, 15],
};
},
methods: {
// 开始倒计时
startCountTime() {
if (this.start) {
// 正在计时,停止它
console.log('restart');
this.start = false;
this.pause = false;
} else {
// 没有计时,开始计时
console.log('start');
this.start = true;
this.autoplay = true;
this.pause = false;
}
},
pickend(timestamp) {
this.timestamp = timestamp
},
stopCountTime() {
this.pause = !this.pause;
},
clickSetTime(minutes) {
this.timestamp = minutes * 60;
this.$refs.dateSelectorRef.quickSetMinutes(minutes)
},
}
};
</script>
<style lang="scss" scoped>
.c-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.c-countdown {
margin-top: 50rpx;
}
</style>
到这里 终于写完了!看看项目效果如何吧!
最后
该小程序项目完整的GIT仓库地址:github.com/eatmans/cod…
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanekkj
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01