前言
最近闲着没事, 就翻翻文章看, 突然想到以前写过的一些demo, 其中有一个是iPhone时钟
. 不过当时是用jquery
写的, 现在也在玩vue
了, 所以就想着用vue
重写一下.
预览
先看效果图吧 (没有动态图片 T_T):
代码
然后是就是代码部分了
模版文件(.vue)
<script>
/**
* @desc 时钟组件
*/
export default {
name: 'v-clock',
props: {
size: {
type: Number,
default: () => 300
}
},
data: () => ({ time: new Date(), isRunning: false }),
computed: {
fontSize() {
const size = this.size / 300 * 16
return size > 12 ? `${size}px` : '12px'
},
scales() {
const radius = this.size / 2 * 0.8
const arr = []
for (let i = 1; i <= 12; i++) {
const radian = 30 * Math.PI / 180 * i - 0.5 * Math.PI
const left = radius * Math.cos(radian) + this.size * 0.45
const top = radius * Math.sin(radian) + this.size * 0.45
arr.push({
num: i,
left: `${left.toFixed(2)}px`,
top: `${top.toFixed(2)}px`
})
}
return arr
},
hourHand() {
const hourDeg = 30 * (this.time.getHours() % 12)
const minuteDeg = 0.5 * this.time.getMinutes()
return `translate(-50%, 0) rotate(${hourDeg + minuteDeg - 180}deg)`
},
minuteHand() {
const minuteDeg = 6 * this.time.getMinutes()
const secondDeg = 0.1 * this.time.getSeconds()
return `translate(-50%, 0) rotate(${minuteDeg + secondDeg - 180}deg)`
},
secondHand() {
return `translate(-50%, -10%) rotate(${6 * this.time.getSeconds() - 180}deg)`
}
},
mounted() {
this.isRunning = true
const tick = () => {
if (!this.isRunning) {
return
}
this.time = new Date()
const timer = setTimeout(() => {
clearTimeout(timer)
tick()
}, 1000)
}
tick()
},
destroyed() {
this.isRunning = false
}
}
</script>
<template>
<div
:style="{width:`${size}px`,height:`${size}px`}"
>
<div :class="$style['black-dail']">
<div :class="$style['white-dail']">
<span
v-for="v in scales"
:key="`ds-${v.num}`"
:class="$style['degree-scale']"
:style="{left:v.left,top:v.top,fontSize}"
>{{v.num}}</span>
<b :class="$style['hour-hand']" :style="{transform:hourHand}"></b>
<b :class="$style['minute-hand']" :style="{transform:minuteHand}"></b>
<b :class="$style['second-hand']" :style="{transform:secondHand}"></b>
</div>
</div>
</div>
</template>
<style lang="scss" module>
@import './styles.scss';
</style>
样式文件(.scss)
.black-dail {
width: 100%;
height: 100%;
padding: 5%;
border-radius: 20%;
background-color: #000;
box-sizing: border-box;
}
.white-dail {
position: relative;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #fff;
}
.degree-scale {
position: absolute;
display: block;
// font-size: 16px;
width: 2em;
height: 2em;
text-align: center;
line-height: 2;
transform: translate(-50%, -50%);
}
.hour-hand,
.minute-hand,
.second-hand {
position: absolute;
top: 50%;
left: 50%;
}
.hour-hand {
width: 2.5%;
height: 30%;
background-color: #000;
transform-origin: 50% 0;
transform: translate(-50%, 0) rotate(0);
&::after {
position: absolute;
top: 0;
left: 50%;
display: block;
content: '';
width: 200%;
padding-top: 200%;
border-radius: 50%;
background-color: #000;
transform: translate(-50%, -50%);
}
}
.minute-hand {
width: 2%;
height: 40%;
background-color: #000;
transform-origin: 50% 0;
transform: translate(-50%, 0) rotate(0);
}
$second-color: rgb(255, 74, 74);
.second-hand {
width: 1%;
height: 50%;
background-color: $second-color;
transform-origin: 50% 10%;
transform: translate(-50%, -10%) rotate(0);
&::after {
position: absolute;
top: 10%;
left: 50%;
display: block;
content: '';
width: 300%;
padding-top: 300%;
border-radius: 50%;
background-color: $second-color;
transform: translate(-50%, -50%);
}
}
dom部分
这个也没啥好说的了, '黑色的底盘 + 白色圆盘 + 刻度*12 + 时针 + 分针 + 秒针'.
除了刻度的位置是计算出来的之外, 其他的基本用样式就ok了.
逻辑部分
然后来说说逻辑部分的代码.
刻度的位置计算
scales() {
const radius = this.size / 2 * 0.8
const arr = []
for (let i = 1; i <= 12; i++) {
const radian = 30 * Math.PI / 180 * i - 0.5 * Math.PI
const left = radius * Math.cos(radian) + this.size * 0.45
const top = radius * Math.sin(radian) + this.size * 0.45
arr.push({
num: i,
left: `${left.toFixed(2)}px`,
top: `${top.toFixed(2)}px`
})
}
return arr
},
this.size
就是这个时钟的尺寸了, 先定义半径radius
. arr
就是12个刻度的数组.
这里计算各个刻度坐标使用的方法是圆的参数方程
,left
和top
就相当于坐标轴上的x
和y
.radian
部分需要减去90度, 因为0度刚好是3点钟
, 需要往回走到12点钟
.
然后是top, left
最后要加this.size * 0.45
, 因为白色的圆盘的尺寸在样式里面定义的是总大小的90%.
秒针/分针/时针 的旋转角度的计算
this.time
既是当前的时间
时针
计算当前的小时后, %12
转成12小时制, 每一小时的角度是30度; 当前的分钟, 每一分钟的角度是6度.然后把总的旋转角度加起来. 秒针因为度数太小, 就没有算进去.
分钟和秒针同理. 还有记得减去180度, 这里是因为一开始定义的样式的问题(0度指向6点钟).
计时器
计时器也是简单的每秒钟执行一个回调而已, 要记得组件卸载时关闭计时功能.
以上
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。