目录
项目实现图片GIF

项目思想

首先将数字分为6列加2个引号,完成想像图中的排列(每一列设置inline-block属性,然后设置顶部对齐),然后我们再将2个引号垂直居中,并通过setInterval()方法获得实时的时间,把更新的时间处理成字符串,例如16:29:05,我们处理为162905然后依次取出每一位,把他和图片中对应的那一列中的数字进行对应,即把那一列中对应的数字居中对齐就行了。
详细版(带大量解释)
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="dynamicClock.css">
<script src="https://www.jq22.com/jquery/jquery-3.3.1.js"></script>
</head>
<body>
<div class="wrapper">
<div class="column">
<div>0</div>
<div>1</div>
<div>2</div>
</div>
<div class="column ten"></div>
<div class="colon">:</div>
<div class="column six"></div>
<div class="column ten"></div>
<div class="colon">:</div>
<div class="column six"></div>
<div class="column ten"></div>
</div>
<script src="dynamicClock.js"></script>
</body>
</html>
CSS代码
*{
margin: 0;
padding: 0;
}
.wrapper{
/* border: 5px solid pink;*/
text-align: center;
}
.column,
.colon{
display: inline-block;
vertical-align: top;
/*基于顶部对齐,不设置的话默认每列是底部对齐,然后向上把容器撑开,而底部的位置我们在居中的时候是不好计算的,所以我们这里设置向上对齐;*/
font-size: 80px;
line-height: 80px;
}
.colon{
transform: translateY(calc(50vh - 40px));
/*
1.设置居中,用其他方法会脱离文档流,这样的话会和数字重叠
2.1vh代表你现在屏幕高度的1%,同理1vw代表你现在屏幕宽度的1%
3.clac()可以把计算完的像素值返回,这里注意-40px不能连写,-号和30px之间要有空格,不然会翻译为负号而不是减号,而2个数字无法计算。
4.transform:none|transform-functions,常用的函数有translate()、scale()、rotate()、skew()等,我们这里用的translateY相当于在Y轴方平移
*/
}
.opacity0{
opacity: 1;
}
.opacity1{
opacity: 0.5;
}
.opacity2{
opacity: 0.4;
}
.opacity3{
opacity: 0.25;
}
.opacity4{
opacity: 0.1;
}
.opacity5{
opacity: 0;
}
.wrapper{
overflow: hidden;
width: 100%;
}
.column{
transition: all 300ms ease-in;
/*设置过度的内容、总时长以及过度的方法;*/
}
JS代码
//透明度的等级数列,在setOpacityClass函数中使用,用于设置不同类别的透明度。
var opacityName = ['opacity0','opacity1','opacity2','opacity3','opacity4','opacity4','opacity4','opacity4','opacity4','opacity5']
// 创建0-9或0-5加入每一列中
function joinTime(){
for (var i = 0; i < 10; i++) {
var number = '<div>' + i + '</div>';
$('.ten').append(number);
// $(选择器1).append(字符串),相当于把字符串添加到选择器1的每个doom节点
// $(选择器1).append(选择器2),相当于把选择器2中的所有doom节点剪切后加入选择器1中的每个doom节点中
// $(选择器1).append(function(index,html){}),相当于把函数中返回的数据加入选择器1的每个doom节点中,选择器1中有几个doom节点就会执行几次,
// 每次对应一个index和html,index对应选择1中正在添加的doom节点的序号,是从0开始的,而html是该doom节点下所有的内容,是字符串的形式
}
for (var i = 0; i < 6; i++) {
var number = '<div>' + i + '</div>';
$('.six').append(number);
}
}
joinTime();
//每隔一段时间得到最新的时间,并更新到网页中
setInterval(function(){
// setInterval(code,milliseconds,arg1,arg2...args),code代表js中的代码或函数,代码的话用字符串的形式传递,注意有双重引号需要用单引号括双引号,或反的,milliseconds代表毫秒数,
//args代表传输的参数,可以写多个,会传入code中函数中,例如code写成function(a,b,c,d....){}则a,b,c...会依次与arg1,arg2,arg3...结合,也可以使用arguments查看使用。
//每过多少毫秒调用code中的内容,注意code中直接写F()而不加引号,会立即执行,且只执行1次,因为他要当做js中的代码需要加引号,要当做函数需要去掉()号。
var time = new Date();
var hours = time.getHours(),
seconds = time.getSeconds(),
minutes = time.getMinutes();
// console.log(hours+':'+minutes+':'+seconds);
var standardTime = timeString(hours, seconds ,minutes ,true)//更改为false为12小时。
// console.log(standardTime);
achieveTime(standardTime, $('.column'));//传document.getElementsByClassName('column')也行。
},200);
//将hours,seconds,minutes传入,有些的可能需要添加0,得到符合规范的字符串我们设置2种返回结果,1种是24小时制,1种是12小时制。
function timeString(hours, seconds, minutes,is24Hours){
// 方法1
// if(is24Hours){
// //返回24小时制的时间,处理hours,minutes,seconds如果小于10我们在前面加个‘0’
// if(hours < 10){
// hours = '0' + hours;
// }else{
// hours += '';
// }
// if (minutes < 10) {
// minutes = '0' + minutes;
// }else{
// minutes += '';
// }
// if (seconds < 10) {
// seconds = '0' + seconds;
// }else{
// seconds += '';
// }
// }else{
// //返回12小时制的,将hours%12,后再判断小于10即可,这里就不写了,可以把方法1注释了,直接用方法2.
// }
// var timeS = hours + minutes + seconds;
//方法2
timeS = [is24Hours ? hours : hours % 12 || 12,minutes,seconds].reduce(function(p, n){
return p + ('0' + n).slice(-2);
});
// arr.reduce(function(total, currentValue, index, array){return},initialValue) 该函数叫累加器,
// 函数根据执行arr.length次,第一次total的值为initialValue,currentValue,index对应arr[0]和0,而array始终对应arr不变,然后return的值返回第二次的total中,
// 再执行一遍函数以此类推,最后把return的值返回给total的值后,再将total返回,这也是为什么当arr.length=1时,
// 我们写入initialValue的值后返回结果为undefined,所以我们使用时注意一定要定义return的值,如果没有定义的话每次会将undefined返回total。
// 参数中只有total和current是必须定义的,然后在不写initialValue时,该函数的total值默认为arr[0]的,index、currentValue的值都会从第二个数开始,即index为1。
// 还有1种特殊情况,即arr.length=1时,如果不定义initialValue的值,那么该函数直接返回arr[0],不会运行function内的代码。
// String/Array.slice(start,end)
// 该函数将数组或字符串的[start]——[end-1]位返回成一个数组或字符串,参数可以填负数,加上length转换为正数后计算,可以不写end,表示从[strat]选到尾,还可以都不写,
// 会将内容完全返回,注意返回的是浅拷贝,即如果数组的内容包含引用,他复制的是引用。最后该函数是不改变原数组和字符串的
// timeS = timeS.length == 6 ? timeS : '0' + timeS;
return timeS.length == 6 ? timeS : '0' + timeS
// p初始为数组第一位,n为数组的第二位,加完后的值再赋予p,n为数组的第三位。最后返回累加成果。如果小时为0,可能出现5位数的情况。
}
function achieveTime(standardTime, elem){
// Array.from(object,mapFunction(value,index){return},thisValue)方法用于通过拥有length属性的对象或可迭代的对象来返回一个数组,常用于类数组转化为数组。
// object是要转换为数组的对象是必填的,其他可以不填,mapFunction是object数组中每个数需要执行的函数,执行object.length次,每次value代表当前的值即object[index],
// index代表当前的索引号,每次的最后会将return语句中的值返回给自身即object[index],thisValue代表的是mapFunction运行过程中的this指向,默认为window。
Array.from(elem).forEach(function(ele,index){
//array.forEach(function(currentValue, index, arr),thisValue);数组中每个元素都执行一遍function。
//其中只有currentValue为必选,函数共执行array.length次,每次currentValue=array[index],index从0到length-1,arr===Array,thisValue同Array.from中的一样,无论是否有return都无返回值。
var offset = standardTime[index] * 80;
$(ele).css({
'transform' : 'translateY(calc(50vh - ' + offset + 'px - 40px))'
});
// 相当于把每一列的0都居中对齐了,然后把每一列对应的时间取出来,乘以数字的高度,向下平移即得到了当前的时间,注意字符串拼接时,可以先写式子再用字符串符号分割开来,不然特容易出错。
setOpacityClass(ele, standardTime[index]);
});
}
//给1列中的数字设置不同的类名来对应透明度。
function setOpacityClass(ele, n){
Array.from(ele.children).forEach(function(ele2, index2){
// 方法1
//注意.children是document上的方法,.attr()是jquer上的方法
// if(n > index2){
// $(ele2).attr('class',opacityName[n - index2]);
// }else{
// $(ele2).attr('class',opacityName[index2 - n]);
// }
//方法2
//判断index2和n之间是否距离为index。
$(ele2).attr('class',opacityName.find(function(ele, i){
return index2-i === (+n) || index2 + i === (+n);
//注意我们的n不能直接比较,需要转换为数字类型
}));
//array.find(function(currentValue, index, arr),thisValue),对每个array数组中的值执行一遍function,返回array[index]的值,参数作用都和array.Each中的相同
});
}
_____________________________________________________________________________________________________________________
完整版(代码简洁,在原型链上编写,不带解释)
HTML代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="demo.css">
<script src="https://www.jq22.com/jquery/jquery-3.3.1.js"></script>
<title>Document</title>
</head>
<body>
<div class="wrapper">
<div class="column">
<div>0</div>
<div>1</div>
<div>2</div>
</div>
<div class="column ten" ></div>
<div class="coln">:</div>
<div class="column six"></div>
<div class="column ten"></div>
<div class="coln">:</div>
<div class="column six"></div>
<div class="column ten"></div>
</div>
<script src="demo.js"></script>
</body>
</html>
CSS代码:
*{
margin: 0;
padding: 0;
}
body{
background-color: #0e141b;
overflow: hidden;
}
.wrapper{
width: 100%;
text-align: center;
}
.wrapper .column,
.wrapper .coln{
display: inline-block;
color: rgba(224,230,235,0.89);
vertical-align: top;
font-size: 86px;
line-height: 86px;
font-weight: 300;
}
.coln{
transform: translateY(calc(50vh - 43px));
}
.column{
transition: all 300ms ease-in;
}
.visible{
opacity: 1;
}
.close{
opacity: 0.35;
}
.far{
opacity: 0.15;
}
.distance{
opacity: 0.1;
}
JS代码:
function Index(dom,use24Hours){
this.column = Array.from(dom);
this.createDom();
this.start();
this.use24Hours = use24Hours;
this.classList = ['visible','close','far','far','distance','distance'];
}
Index.prototype.start = function(){
var self = this;
setInterval(function(){
var c = self.getClock();
console.log(c);
self.column.forEach(function(ele,index){
var n = + c[index];
var offset = n * 86;
$(ele).css({
'transform':'translateY(calc(50vh - '+ offset + 'px - 43px))'
});
Array.from(ele.children).forEach(function(ele2, index2){
var className = self.getClass(n,index2);
$(ele2).attr('class',className);
})
})
},200);
};
Index.prototype.getClass = function(n, i){
var className = this.classList.find(function(ele, index){
return i-index === n || i + index === n;
});
return className || '';
};
Index.prototype.getClock = function(){
var d = new Date();
m = [this.use24Hours ? d.getHours() : d.getHours() % 12 || 12,d.getMinutes(),d.getSeconds()].reduce(function(p, n){
return p + ('0' + n).slice(-2);
});
return m.length == 6 ? m : '0'+m;
};
Index.prototype.createDom = function createDom(){
for(var i = 0; i < 6; i++){
var oDiv='<div>' + i + '</div>';
$('.six').append(oDiv);
}
for(var i = 0; i < 10; i++){
var iDiv = '<div>' + i + '</div>';
$('.ten').append(iDiv);
}
};
new Index($('.column'),true);
此博客介绍了如何使用HTML、CSS和JavaScript实现一个动态时钟,将时间显示为数字滚动效果。通过设置元素的布局、样式和透明度,使数字逐位滚动展示当前时间。涉及知识点包括DOM操作、定时器、CSS过渡效果和透明度控制。
1224





