文章目录
- 打工搬砖记
- 秒薪的计算
- 文字弹出动画
- 根据时间数字变化
- 小结
打工搬砖记
先来一个小程序首页预览图,首页较为复杂的也就是“秒薪”以及弹出文字的动画。
已上线小程序“打工人搬砖记”,进行预览观看。
秒薪的计算
秒薪计算公式:秒薪 = 平均月薪/工作天数/(工作时间-午休时间)
平均月薪以及工作天数是用户自行设置的,一天工作多少秒这个比较难点需要计算一下。
"new Date(new Date(new Date().toLocaleDateString()).getTime()) " 代表获取今天0点的时间戳。
时间点乘60乘60乘1000再加上0点的时间戳得出时间点的时间戳
详细实现过程代码如下:
// 这是通过接口获取的数据,这里为了方便演示定易了一下
let workerStartArr=['9','30']
let noonStartArr=['11','30']
let noonEndArr=['1','30']
let workerEndArr=['18','30']
// 时间转换为时间戳
let workerStart = new Date(new Date().toLocaleDateString()).getTime() + parseInt(workerStartArr[0]) * 60 * 60 * 1000 - 1 + workerStartArr[1] * 60 * 1000
let noonStart = new Date(new Date().toLocaleDateString()).getTime() + parseInt(noonStartArr[0]) * 60 * 60 * 1000 - 1 + noonStartArr[1] * 60 * 1000
let noonEnd = new Date(new Date().toLocaleDateString()).getTime() + parseInt(noonEndArr[0]) * 60 * 60 * 1000 - 1 + noonEndArr[1] * 60 * 1000
let workerEnd = new Date(new Date().toLocaleDateString()).getTime() + parseInt(workerEndArr[0]) * 60 * 60 * 1000 - 1 + workerEndArr[1] * 60 * 1000
let newTime = Date.parse(new Date())
// 工作时长 多少秒
let secondWorker = (workerEnd - workerStart - (noonEnd - noonStart)) / 1000
// 秒薪
this.secondMoney = (this.userInfo.wage / this.userInfo.workDay / secondWorker).toFixed(4)
// 根据当前时间在哪个区间然后计算已经挣到的薪资
this.statusWork = 2
if(newTime < workerStart){
this.money = 0
this.titleTime = 0
this.statusWork = 1
} else if (newTime > workerStart && newTime < noonStart) {
this.money = ((newTime - workerStart) / 1000) * this.secondMoney
this.titleTime = noonStart - newTime
} else if (newTime > noonEnd && newTime < workerEnd) {
let haveMoney = (noonStart - workerStart)/1000 * this.secondMoney
this.money = ((newTime - noonEnd) / 1000) * this.secondMoney + haveMoney
this.titleTime = workerEnd - newTime
}else{
let haveMoney = (noonStart - workerStart)/1000 * this.secondMoney
this.money = ((workerEnd - noonEnd) / 1000) * this.secondMoney + haveMoney
this.titleTime = 0
this.statusWork = 1
}
文字弹出动画
用户点击人物后,人物会纵向的动一下,并且文字会先从人物头上冒出来,然后快速移动到手机屏幕中件。
通过CSS中animation动画结合JS中setTimeout()方法来实现。通过绑定class,然后控制active状态是true和false来实现动画过程。
<!-- 主体结构内容 -->
<view @click="setWork" class="basis_right">
<view :class="[active?'bubble_boxActive':'bubble_box']">
<image src="../../static/role/bubble.png" class="bubbleImg" mode=""></image>
<view class="bubble_text">
<text v-for="(item,index) in funnyList" :key="index" >{{item}}</text>
</view>
</view>
<image v-show="statusWork == 1" src="../../static/role/luXun_rest.png"
:class="[active?'luxunImgActive':'luxunImg']" mode=""></image>
<image v-show="statusWork == 2" src="../../static/role/luXun_active.png"
:class="[active?'luxunImgActive':'luxunImg']" mode=""></image>
</view>
<!-- 样式 -->
<style lang="scss">
.basis_right {
flex: 1;
position: relative;
.luxunImg {
position: absolute;
right: 30rpx;
bottom: 0;
width: 210rpx;
height: 350rpx;
}
.luxunImgActive {
position: absolute;
right: 30rpx;
bottom: 0;
width: 210rpx;
height: 350rpx;
animation: myMove 1s linear alternate 1;
}
@keyframes myMove {
0% {
height: 350rpx;
}
50% {
height: 300rpx;
}
100% {
height: 350rpx;
}
}
.bubble_box {
display: none;
}
.bubble_boxActive {
position: absolute;
right: 200rpx;
top: -180rpx;
width: 280rpx;
height: 280rpx;
display: flex;
align-items: center;
justify-content: center;
.bubbleImg {
position: absolute;
width: 100%;
height: 100%;
}
.bubble_text {
position: relative;
display: flex;
font-size: 24rpx;
flex-direction: column;
}
animation: myIdea 3s ease alternate infinite;
}
@keyframes myIdea {
0% {
transform: scale(0.1, 0.1);
right: 10rpx;
top: -100rpx;
}
30% {
transform: scale(0.3, 0.3);
right: 10rpx;
top: -240rpx;
}
50% {
transform: scale(1, 1);
right: 200rpx;
top: -180rpx;
}
100% {
transform: scale(1, 1);
right: 200rpx;
top: -180rpx;
}
}
}
</style>
// getFunny方法是我这请求后端的数据,active控制class样式切换,以及3秒执行一次
setWork() {
if (!this.active) {
getFunny({
data: {},
custom: {
auth: true,
toast: false,
catch: true
}
}).then((res) => {
this.funnyList =res.split(',')
})
this.active = true
setTimeout(() => {
this.active = false
}, 3000)
// 声音
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
innerAudioContext.sessionCategory = 'ambient';
innerAudioContext.src = '/static/lunch/music.mp3';
innerAudioContext.onPlay();
}
// this.statusWork = this.statusWork == 1 ? 2 : 1
},
根据时间数字变化
每秒顶部以及秒薪会变化,是使用到了uview中的u-count-down组件。感兴趣的可以看一下如何实现。不感兴趣的会用就行
组件内的部分代码如下:
<template>
<view class="u-count-down">
<slot>
<text class="u-count-down__text">{{ formattedTime }}</text>
</slot>
</view>
</template>
<script>
import props from './props.js';
import {
isSameSecond,
parseFormat,
parseTimeData
} from './utils';
/**
* u-count-down 倒计时
* @description 该组件一般使用于某个活动的截止时间上,通过数字的变化,给用户明确的时间感受,提示用户进行某一个行为操作。
* @tutorial https://uviewui.com/components/countDown.html
* @property {String | Number} time 倒计时时长,单位ms (默认 0 )
* @property {String} format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 (默认 'HH:mm:ss' )
* @property {Boolean} autoStart 是否自动开始倒计时 (默认 true )
* @property {Boolean} millisecond 是否展示毫秒倒计时 (默认 false )
* @event {Function} finish 倒计时结束时触发
* @event {Function} change 倒计时变化时触发
* @event {Function} start 开始倒计时
* @event {Function} pause 暂停倒计时
* @event {Function} reset 重设倒计时,若 auto-start 为 true,重设后会自动开始倒计时
* @example <u-count-down :time="time"></u-count-down>
*/
export default {
name: 'u-count-down',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
timer: null,
// 各单位(天,时,分等)剩余时间
timeData: parseTimeData(0),
// 格式化后的时间,如"03:23:21"
formattedTime: '0',
// 倒计时是否正在进行中
runing: false,
endTime: 0, // 结束的毫秒时间戳
remainTime: 0, // 剩余的毫秒时间
}
},
watch: {
time(n) {
this.reset()
}
},
mounted() {
this.init()
},
methods: {
init() {
this.reset()
},
// 开始倒计时
start() {
if (this.runing) return
// 标识为进行中
this.runing = true
// 结束时间戳 = 此刻时间戳 + 剩余的时间
this.endTime = Date.now() + this.remainTime
this.toTick()
},
// 根据是否展示毫秒,执行不同操作函数
toTick() {
if (this.millisecond) {
this.microTick()
} else {
this.macroTick()
}
},
macroTick() {
this.clearTimeout()
// 每隔一定时间,更新一遍定时器的值
// 同时此定时器的作用也能带来毫秒级的更新
this.timer = setTimeout(() => {
// 获取剩余时间
const remain = this.getRemainTime()
// 重设剩余时间
if (!isSameSecond(remain, this.remainTime) || remain === 0) {
this.setRemainTime(remain)
}
// 如果剩余时间不为0,则继续检查更新倒计时
if (this.remainTime !== 0) {
this.macroTick()
}
}, 30)
},
microTick() {
this.clearTimeout()
this.timer = setTimeout(() => {
this.setRemainTime(this.getRemainTime())
if (this.remainTime !== 0) {
this.microTick()
}
}, 50)
},
// 获取剩余的时间
getRemainTime() {
// 取最大值,防止出现小于0的剩余时间值
return Math.max(this.endTime - Date.now(), 0)
},
// 设置剩余的时间
setRemainTime(remain) {
this.remainTime = remain
// 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象
const timeData = parseTimeData(remain)
this.$emit('change', timeData)
// 得出格式化后的时间
this.formattedTime = parseFormat(this.format, timeData)
// 如果时间已到,停止倒计时
if (remain <= 0) {
this.pause()
this.$emit('finish')
}
},
// 重置倒计时
reset() {
this.pause()
this.remainTime = this.time
this.setRemainTime(this.remainTime)
if (this.autoStart) {
this.start()
}
},
// 暂停倒计时
pause() {
this.runing = false;
this.clearTimeout()
},
// 清空定时器
clearTimeout() {
clearTimeout(this.timer)
this.timer = null
}
},
beforeDestroy() {
this.clearTimeout()
}
}
</script>
<style
lang="scss"
scoped
>
@import "../../libs/css/components.scss";
$u-count-down-text-color:$u-content-color !default;
$u-count-down-text-font-size:15px !default;
$u-count-down-text-line-height:22px !default;
.u-count-down {
&__text {
color: $u-count-down-text-color;
font-size: $u-count-down-text-font-size;
line-height: $u-count-down-text-line-height;
}
}
</style>
小结
总的来说实现过程不难,难的是思路以及行动力。加油打工人!!!
后面写一篇关于轮盘的实现过程。