You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
311 lines
6.4 KiB
311 lines
6.4 KiB
<template>
|
|
<view class="">
|
|
<view class="circle" :style="[circle]">
|
|
<view class="left" :style="[size]">
|
|
<view class="left-circle" :style="[
|
|
{'transform': rotatea},
|
|
{'animation':is_reversal?stycircle2:stycircle1},
|
|
{'transform': rotatea},
|
|
{'animation-delay':is_reversal?0:animationDelay },
|
|
{'animation-play-state':pause_text},
|
|
{'-webkit-animation-play-state': pause_text},
|
|
size,
|
|
leftCircle,
|
|
]">
|
|
</view>
|
|
</view>
|
|
<view class="right" :style="[size]">
|
|
<view class="right-circle" :style="[
|
|
{'transform':is_reversal?rotatea:rotateb},
|
|
{'animation':stycircle2},
|
|
{'animation-delay': is_reversal?animationDelay:0},
|
|
{'animation-play-state':pause_text},
|
|
{'-webkit-animation-play-state': pause_text},
|
|
size,
|
|
rightcircle,]">
|
|
</view>
|
|
</view>
|
|
<view class="inner" :style="[inner]">
|
|
<slot></slot>
|
|
</view>
|
|
<view class="circle_line" :style="[scale]" v-if="isScale"></view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
/*
|
|
* countDown 圆环计时器,不使用canvas,仅css实现,圆环中间支持自定义添加内容
|
|
* @property {Number} times 时间 (单位毫秒)
|
|
* @property {Number} widths 圆环的总体大小 (单位upx)
|
|
* @property {Number} breadth 圆环中间区域的大小 (单位upx)
|
|
* @property {String} activeColor 圆环中间区域的背景色
|
|
* @property {String} defaultColor 圆环中间区域默认的背景颜色
|
|
* @property {Boolean} isScale 是否显示圆环刻度
|
|
* @property {Number} scaleNun 圆环刻度个数
|
|
* @property {Number} scaleAngle 圆环刻度角度值
|
|
* @property {Boolean} is_reversal 是否反转
|
|
*/
|
|
export default {
|
|
props: {
|
|
times: {
|
|
type: Number,
|
|
default: () => 10000
|
|
},
|
|
widths: {
|
|
type: Number,
|
|
default: () => 200
|
|
},
|
|
breadth: {
|
|
type: Number,
|
|
default: () => 30
|
|
},
|
|
activeColor: {
|
|
type: String,
|
|
default: () => '#01B862'
|
|
},
|
|
defaultColor: {
|
|
type: String,
|
|
default: () => '#EDF0F0'
|
|
},
|
|
isScale: {
|
|
type: Boolean,
|
|
default: () => false,
|
|
},
|
|
scaleNun: {
|
|
type: Number,
|
|
default: () => 40
|
|
},
|
|
scaleAngle: {
|
|
type: Number,
|
|
default: () => 6
|
|
},
|
|
is_reversal: {
|
|
type: Boolean,
|
|
default: () => false
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
stycircle1: {},
|
|
stycircle2: {},
|
|
animationDelay: 0,
|
|
timer: null,
|
|
timeAll: 0, //时间
|
|
pause_text: 'paused', //暂停
|
|
finish: false, //结束标识 true结束 false未开始
|
|
is_continue: true, //结束标识 true可以继续 false已继续
|
|
rotatea: 'rotate(180deg)',
|
|
rotateb: 'rotate(-180deg)'
|
|
}
|
|
},
|
|
beforeDestroy() { //销毁后
|
|
clearInterval(this.timer)
|
|
},
|
|
mounted() {
|
|
this.timeAll = JSON.parse(JSON.stringify(this.times))
|
|
},
|
|
|
|
methods: {
|
|
start() { //开始事件
|
|
if (this.finish) {
|
|
return
|
|
}
|
|
this.finish = true
|
|
this.$nextTick(() => {
|
|
if (this.times < 1000) {
|
|
uni.showToast({
|
|
title: '时间最少1s',
|
|
icon: 'none',
|
|
duration: 1500,
|
|
mask: true
|
|
});
|
|
} else {
|
|
clearInterval(this.timer)
|
|
let time = Number((this.times / 2).toFixed(2))
|
|
this.stycircle2 = `progross2 ${time}ms linear forwards`
|
|
this.animationDelay = `${time}ms`
|
|
this.stycircle1 = `progross1 ${time}ms linear forwards`
|
|
this.pause_text = 'running'
|
|
this.setIn()
|
|
}
|
|
})
|
|
},
|
|
setIn(e) { //计时器
|
|
this.timer = setInterval(() => {
|
|
let times_num = this.times - 100
|
|
this.$emit('update:times', times_num)
|
|
if (e) {
|
|
this.pause_text = 'running'
|
|
}
|
|
if (this.times <= 100) {
|
|
this.finish = true
|
|
setTimeout(() => {
|
|
this.$emit('endTime')
|
|
this.$emit('update:times', this.timeAll)
|
|
}, 100)
|
|
clearInterval(this.timer)
|
|
}
|
|
}, 100)
|
|
},
|
|
pause() { //暂停
|
|
if (!this.finish) {
|
|
return
|
|
}
|
|
this.pause_text = 'paused'
|
|
this.is_continue = false
|
|
clearInterval(this.timer)
|
|
this.$emit('pauseNum', this.times)
|
|
},
|
|
goOn() { //继续
|
|
if (this.is_continue) {
|
|
return
|
|
}
|
|
this.is_continue = true
|
|
this.setIn(true)
|
|
},
|
|
reset() { //重置
|
|
// console.log('重置');
|
|
this.stycircle2 = `progross 0s linear forwards`
|
|
this.stycircle1 = `progross 0s linear forwards`
|
|
this.animationDelay = 0
|
|
clearInterval(this.timer)
|
|
this.finish = false
|
|
this.is_continue = true
|
|
this.$emit('update:times', this.timeAll)
|
|
},
|
|
},
|
|
computed: {
|
|
circle() {
|
|
const {
|
|
widths,
|
|
defaultColor
|
|
} = this
|
|
return {
|
|
width: `${widths}rpx`,
|
|
height: `${widths}rpx`,
|
|
background: defaultColor
|
|
}
|
|
},
|
|
size() {
|
|
const {
|
|
widths
|
|
} = this
|
|
return {
|
|
width: `${widths/2 + 2}rpx`,
|
|
height: `${widths + 2}rpx`
|
|
}
|
|
},
|
|
leftCircle() {
|
|
const {
|
|
widths,
|
|
activeColor
|
|
} = this
|
|
return {
|
|
borderTopLeftRadius: `${widths}rpx`,
|
|
borderBottomLeftRadius: `${widths}rpx`,
|
|
background: activeColor
|
|
}
|
|
},
|
|
rightcircle() {
|
|
const {
|
|
widths,
|
|
activeColor
|
|
} = this
|
|
return {
|
|
borderTopRightRadius: `${widths}rpx`,
|
|
borderBottomRightRadius: `${widths}rpx`,
|
|
background: activeColor
|
|
}
|
|
},
|
|
inner() {
|
|
const {
|
|
widths,
|
|
breadth
|
|
} = this
|
|
return {
|
|
width: `${widths - breadth }rpx`,
|
|
height: `${widths - breadth }rpx`,
|
|
}
|
|
},
|
|
scale() {
|
|
const {
|
|
defaultColor,
|
|
scaleNun,
|
|
scaleAngle
|
|
} = this
|
|
return {
|
|
background: `repeating-conic-gradient(${defaultColor} 0 ${scaleAngle}deg, rgba(0, 0, 0, 0) 0deg ${360 / scaleNun}deg)`
|
|
}
|
|
}
|
|
},
|
|
watch: {
|
|
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.circle {
|
|
border-radius: 50%;
|
|
position: relative;
|
|
}
|
|
|
|
.circle_line {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.left,
|
|
.right {
|
|
position: absolute;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.left-circle {
|
|
transition: all .5s;
|
|
transform-origin: right center;
|
|
}
|
|
|
|
.right-circle {
|
|
transition: all .5s;
|
|
transform-origin: left center;
|
|
}
|
|
|
|
@keyframes progross1 {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
@keyframes progross2 {
|
|
to {
|
|
transform: rotate(0deg);
|
|
}
|
|
}
|
|
|
|
.right {
|
|
right: 0;
|
|
}
|
|
|
|
.inner {
|
|
background: #fff;
|
|
position: absolute;
|
|
z-index: 999;
|
|
border-radius: 50%;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
border: 2upx solid #fff;
|
|
overflow: hidden;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
</style> |