上一篇我写了NPM方式开发抖音时钟,但是对于小团队来说,没那么资金搞前后端分离,那在传统模式下如何使用Vue呢?这一篇就用CDN引入的方式再次实现抖音时钟,并对代码进行简化。
话不多说,开始吧!
文件目录如下:
以一个Springboot程序搭的框架
抖音时钟实现原理上一篇已经讲到了,所以这里不再过多阐述,直接看代码:
view/timer.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>时钟</title>
<!--引入vue最新包,调试时用vue.js,发布时用vue.min.js,否则无法调试-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!--引入时钟语言库-->
<script src="../store/timer.js"></script>
<!--引入时钟样式-->
<link rel="stylesheet" href="../css/timer.css" type="text/css">
</head>
<body>
<!--时钟入口-->
<div id="timer">
<Year :v="year"></Year>
<Month :v="month" :d="monthBox" :r="50"></Month>
<Week :v="week" :d="weekBox" :r="90"></Week>
<Day :v="day" :d="dayBox" :r="130"></Day>
<Apm :v="apm" :d="apmBox" :r="170"></Apm>
<Hour :v="hour" :d="hourBox" :r="200"></Hour>
<Minute :v="minute" :d="minuteBox" :r="250"></Minute>
<Second :v="second" :d="secondBox" :r="295"></Second>
<Swap></Swap>
</div>
<!--年份模板-->
<template id="yearComp">
<ul>
<li>{{yearLabel}}</li>
</ul>
</template>
<!--时间模板-->
<template id="timeComp">
<ul :style="{transform:`rotate(${-360 / list.length * (rotates - 1)}deg)`}">
<li v-for="(item,index) in list" :key="index"
:class="{hover: index == rotates -1}"
:style="{transform:`rotate(${360 / list.length * index}deg) translateX(${range}px)`}">
{{ item }}
</li>
</ul>
</template>
<!--切换按钮-->
<template id="switchComp">
<ul style="bottom: -35px;">
<li>
<input type="checkbox" id="checkbox" @click="swap" style="z-index: 9999999;position: relative;">
</li>
</ul>
</template>
</body>
<!--引入时钟初始化脚本,脚本必须放在模板之后,否则初始化会失败-->
<script src="../js/timer.js"></script>
</html>
这里将月、周、日、午时、小时、分钟、秒钟合同成了一个统一的时间模板timeComp,并将开关也封装成一个模板使用
再来看看js中如何实现
js/timer.js
/**
* 年份组件
*/
var _yearComp = {
template : '#yearComp',
props : ['v'],
data : function(){
return {
yearLabel : '1989'
}
},
watch : {
v : {
immediate:true,
handler : function(val){
this.yearLabel = val;
}
}
}
};
/**
* 时间组件
*/
var _timeComp = {
template : '#timeComp',
props : ['v','d','r'],
data : function(){
return {
rotates : '',
list : [],
range : 0
}
},
//vue的监听器是个坑,注意immediate:true,不加的话数据不会立刻生效,相当于监听器无效
//下面对数据监听的这种写法(handler写法)等同于v(val){}这种写法
watch : {
v : {
immediate:true,
handler : function(val){
this.rotates = val;
}
},
d : {
immediate:true,
handler : function(val){
this.list = val;
}
},
r : {
immediate:true,
handler : function(val){
this.range = val;
}
}
}
};
/**
* 切换组件
*/
var _switchComp = {
template : '#switchComp',
methods: {
swap(){
this.$parent.switchFont();
}
}
};
/**
* Vue初始化时,一定要将模板代码放在前面,否则无法识别模板
*/
new Vue({
el : '#timer',
//这里定义的是局部组件,可以对通用组件直接引用,若使用Vue.component方式(全局组件)引用组件,不能直接引用_timeComp,需将_timeComp中的代码全部写入组件中,否则无法实例出多个组件
components : {
'Year':_yearComp,
'Month':_timeComp,
'Week':_timeComp,
'Day':_timeComp,
'Apm':_timeComp,
'Hour':_timeComp,
'Minute':_timeComp,
'Second':_timeComp,
'Swap':_switchComp
},
data : function(){
return {
//当前时间
second : '',
minute : '',
hour : '',
apm : '',
day : '',
week : '',
month : '',
year : '2020',
//周期列表,初始化各种时间的语言库
secondBox : [],
minuteBox : [],
hourBox : [],
apmBox : [],
dayBox : [],
weekBox : [],
monthBox : [],
//当月天数,用于计算月份分割角度(网上有些把月份直接写成30天,设置成固定月份,存在bug)
days : 0,
//字体开关,默认简体
fontType : "Simplified"
}
},
methods: {
start() {
//装配时间语言库
this.makeDate();
//更新时间,获取实时时间
setInterval(
() => {
let date = new Date();
//组装年份
this.year = date.getFullYear();
//组装月份
this.month = date.getMonth() + 1;
//获取当月总天数
this.days = new Date(this.year,this.month,0).getDate();
//获取当年的天干地支信息
this.year = store.sky[this.year % 10] + store.land[this.year % 12];
//获取星期几
this.week = date.getDay();
//获取当天几号
this.day = date.getDate();
//获取当前小时(12小时制)
this.hour = (date.getHours() > 12 ? (date.getHours() -12) : date.getHours());
//获取当前分钟(从0分钟开始,因此分钟需增加1)
this.minute = date.getMinutes() + 1;
//获取当前秒钟(从0秒钟开始,因此秒钟需增加1)
this.second = date.getSeconds() + 1;
//获取当前是上午还是下午
if(this.hour > 12) {
this.apm = 2;
}else{
this.apm = 1;
}
//组装数据,更新语言库,让数据动起来
this.makeDate();
}
, 1000);
},
makeDate(){
//初始化数据
this.secondBox = [];
this.minuteBox = [];
this.hourBox = [];
this.apmBox = [];
this.dayBox = [];
this.weekBox = [];
this.monthBox = [];
//获取配置数据
let fdata = null;
if(this.fontType == "Simplified"){
fdata = store.format_Simplified;
}else{
fdata = store.format_Traditional;
}
//组装月
for(let i=1 ; i<= 12 ; i++){
if(i <= 10){
this.monthBox.push(fdata[i] + "月");
}else {
this.monthBox.push(fdata[10] + fdata[i % 10] + "月");
}
}
//组装周
for(let i=1 ; i<= 7 ; i++){
this.weekBox.push("星期" + fdata[i]);
}
//组装日
for(let i=1 ; i<= this.days ; i++){
if(i <= 10){
this.dayBox.push(fdata[i] + "日");
}else if(i < 20){
this.dayBox.push(fdata[10] + fdata[i % 10] + "日");
}else{
if(i % 10 == 0){
this.dayBox.push(fdata[parseInt(i / 10)] + fdata[10] + "日");
}else{
this.dayBox.push(fdata[parseInt(i / 10)] + fdata[10] + fdata[i % 10] + "日");
}
}
}
//组装午时
this.apmBox.push("上午");
this.apmBox.push("下午");
//组装小时
for(let i=1 ; i<= 12 ; i++){
if(i <= 10){
this.hourBox.push(fdata[i] + "点");
}else{
this.hourBox.push(fdata[10] + fdata[i % 10] + "点");
}
}
//组装分钟
for(let i=0 ; i< 60 ; i++){
if(i <= 10){
this.minuteBox.push(fdata[i] + "分");
}else if(i < 20){
this.minuteBox.push(fdata[10] + fdata[i % 10] + "分");
}else{
if(i % 10 == 0){
this.minuteBox.push(fdata[parseInt(i / 10)] + fdata[10] + "分");
}else{
this.minuteBox.push(fdata[parseInt(i / 10)] + fdata[10] + fdata[i % 10] + "分");
}
}
}
//组装秒
for(let i=0 ; i< 60 ; i++){
if(i <= 10){
this.secondBox.push(fdata[i] + "秒");
}else if(i < 20){
this.secondBox.push(fdata[10] + fdata[i % 10] + "秒");
}else{
if(i % 10 == 0){
this.secondBox.push(fdata[parseInt(i / 10)] + fdata[10] + "秒");
}else{
this.secondBox.push(fdata[parseInt(i / 10)] + fdata[10] + fdata[i % 10] + "秒");
}
}
}
},
//简体、繁体字体切换开关
switchFont(){
console.log(11);
this.fontType = (this.fontType == "Simplified" ? "Traditional" : "Simplified");
}
},
created() {
//页面加载完成后启动
this.start();
}
});
css样式不能使用SCSS方式写了,所以规规矩矩来吧
css/timer.css
#timer ul {
list-style-type: none;
padding: 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
height: 60px;
width: 60px;
transition: 0.1s 0.1s ease-in;
}
#timer ul li {
position: absolute;
height: 60px;
width: 60px;
color: rgb(204, 46, 46);
text-align: center;
font-size: 9px;
line-height: 60px;
}
.hover {
text-shadow: #009be5 0px 0px 10px,
#98f24e 0px 0px 20px,
#0c16d6 0px 0px 30px,
#b5e927 0px 0px 40px,
#d32cbe 0px 0px 70px,
#dc1313 0px 0px 80px,
#9a17c0 0px 0px 100px;
}
语言库没什么变化,还是原来的配方,但是得用js方式写了
store/timer.js
var store = {
format_Traditional : ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖', '拾', '佰', '仟', '万'],
format_Simplified : ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '百', '千', '万'],
sky : ['庚', '辛', '壬', '癸', '甲', '乙', '丙', '丁', '戊', '己'],
land : ['申', '酉', '戌', '亥','子', '丑', '寅', '卯', '辰', '巳', '午', '未']
}
运行效果: