废话开篇:JS 通过操控标签的隐藏与显示来实现倒计时展示小工具
一、实现效果
1、默认展示数字
2、数字倒计时
3、数字倒计时展示虚位
4、数字倒计时不展示虚位
5、小数
6、负数
7、小数倒计时
每一个单独数字都是由一个独立的标签进行的绘制,再通过数字的处理将独立数字组合成一个完整的数字展示。
二、代码
1、HTML
<div class="numer_wsl_contain"><div id="number1"></div><div id="number2"></div><div id="number3"></div><div id="number4"></div>
</div>
<script> let wholeNumberManage1 = new WholeNumberManage(21921,document.getElementById('number1'),1000)let wholeNumberManage2 = new WholeNumberManage(21921,document.getElementById('number2'),1000)wholeNumberManage2.isCountDown = truelet wholeNumberManage3 = new WholeNumberManage(1021,document.getElementById('number3'),50)wholeNumberManage3.isCountDown = truelet wholeNumberManage4 = new WholeNumberManage(1021,document.getElementById('number4'),50)wholeNumberManage4.isCountDown = truewholeNumberManage4.isShowVirtualNum = false </script>
大部分的布局操作全部放到 JS 里,简化 html 内容。
2、CSS
.numer_wsl_contain{width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;
}
.number_wsl {margin-top: 50px;width: 100%;position: relative;display: flex;flex-direction: row;justify-content: center;align-items: center;
}
.num_wsl {position: relative;width: 23px;height: 30px;
}
/* 绘制横杠 */
.num_wsl_cross {position: absolute;left: 0px;width: 100%;height: 10%;background:linear-gradient(135deg,transparent 0, transparent 50%,black 50%,black 100%),linear-gradient(45deg,transparent 0, transparent 50%,black 50%,black 100%),linear-gradient(-135deg,transparent 0, transparent 50%,black 50%,black 100%),linear-gradient(-45deg,transparent 0, transparent 50%,black 50%,black 100%);background-repeat: no-repeat;background-position:0% 0%,0% 100%,100% 0%,100% 100%;background-size:50% 50%,50% 50%,50% 50%,50% 50%;
}
/* 3个横杠位置区分 */
.num_wsl_cross_one {top: 0px;
}
.num_wsl_cross_two {top: 45%;
}
.num_wsl_cross_three {top: 90%;
}
/* 绘制竖杠 */
.num_wsl_vertical {position: absolute;top: -5%;width: 12%;height: 65%;background:linear-gradient(135deg,transparent 0, transparent 50%,black 50%,black 100%),linear-gradient(45deg,transparent 0, transparent 50%,black 50%,black 100%),linear-gradient(-135deg,transparent 0, transparent 50%,black 50%,black 100%),linear-gradient(-45deg,transparent 0, transparent 50%,black 50%,black 100%);background-repeat: no-repeat;background-position:0% 0%,0% 100%,100% 0%,100% 100%;background-size:50% 50%,50% 50%,50% 50%,50% 50%;
}
/* 6个绘制竖杠位置区分 */
.num_wsl_vertical_one {left: 16.2%;
}
.num_wsl_vertical_two {left: 72.8%;
}
.num_wsl_vertical_three {top: 40.8%;left: 16.2%;
}
.num_wsl_vertical_four {top: 40.8%;left: 72.8%;
}
/* 小数点 */
.num_wsl_point {position: absolute;left: 35%;top: calc(90% - 7.5% * (23 / 30));width: 15%;height: calc(15% * (23 / 30));background-color: black;
}
3、数字管理类
NumberSingleManage 单数字展示类
// 单数字操作
class NumberSingleManage {// 操作dom对象el = nullmap = {}// 当前数字_num = 0constructor(num,el){if(el){this.el = el} else {// 没有dom传入对象,进行创建this.el = this.createElement(['num_wsl'])}// 创建单数字节点(3横,4竖)this.createSingleNumNode()this.getSingleMapRelationship()this.overwriteSetMethod()this.num = num}// 重写set方法overwriteSetMethod(){Object.defineProperty(this, 'num', {get: function () {return this._num},set: function (newValue) {this._num = newValuethis.changeNum(this._num)}})}// 创建单数字节点createSingleNumNode(){//样式集合let classes = [['num_wsl_cross','num_wsl_cross_one'],['num_wsl_cross','num_wsl_cross_two'],['num_wsl_cross','num_wsl_cross_three'],['num_wsl_vertical','num_wsl_vertical_one'],['num_wsl_vertical','num_wsl_vertical_two'],['num_wsl_vertical','num_wsl_vertical_three'],['num_wsl_vertical','num_wsl_vertical_four'],['num_wsl_point']]//添加节点classes.forEach(classNames => {this.el.appendChild(this.createElement(classNames))});}// 创建el并赋予样式createElement(classNames){let div = document.createElement('div')classNames.forEach((className)=>{div.classList.add(className)})return div}// 建立映射关系(数字对应数字节点的隐藏与显示)getSingleMapRelationship(){let num_cross_one = this.el.getElementsByClassName('num_wsl_cross_one')[0]let num_cross_two = this.el.getElementsByClassName('num_wsl_cross_two')[0]let num_cross_three = this.el.getElementsByClassName('num_wsl_cross_three')[0]let num_vertical_one = this.el.getElementsByClassName('num_wsl_vertical_one')[0]let num_vertical_two = this.el.getElementsByClassName('num_wsl_vertical_two')[0]let num_vertical_three = this.el.getElementsByClassName('num_wsl_vertical_three')[0]let num_vertical_four = this.el.getElementsByClassName('num_wsl_vertical_four')[0]this.map = {reset:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elShow(num_cross_two)this.elShow(num_cross_three)this.elShow(num_vertical_one)this.elShow(num_vertical_two)this.elShow(num_vertical_three)this.elShow(num_vertical_four)},allHide:()=>{this.elHide(num_wsl_point)this.elHide(num_cross_one)this.elHide(num_cross_two)this.elHide(num_cross_three)this.elHide(num_vertical_one)this.elHide(num_vertical_two)this.elHide(num_vertical_three)this.elHide(num_vertical_four)},'-':()=>{this.elHide(num_wsl_point)this.elHide(num_cross_one)this.elShow(num_cross_two)this.elHide(num_cross_three)this.elHide(num_vertical_one)this.elHide(num_vertical_two)this.elHide(num_vertical_three)this.elHide(num_vertical_four)},'.':()=>{this.elShow(num_wsl_point)this.elHide(num_cross_one)this.elHide(num_cross_two)this.elHide(num_cross_three)this.elHide(num_vertical_one)this.elHide(num_vertical_two)this.elHide(num_vertical_three)this.elHide(num_vertical_four)},0:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elHide(num_cross_two)this.elShow(num_cross_three)this.elShow(num_vertical_one)this.elShow(num_vertical_two)this.elShow(num_vertical_three)this.elShow(num_vertical_four)},1:()=>{this.elHide(num_wsl_point)this.elHide(num_cross_one)this.elHide(num_cross_two)this.elHide(num_cross_three)this.elHide(num_vertical_one)this.elShow(num_vertical_two)this.elHide(num_vertical_three)this.elShow(num_vertical_four)},2:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elShow(num_cross_two)this.elShow(num_cross_three)this.elHide(num_vertical_one)this.elShow(num_vertical_two)this.elShow(num_vertical_three)this.elHide(num_vertical_four)},3:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elShow(num_cross_two)this.elShow(num_cross_three)this.elHide(num_vertical_one)this.elShow(num_vertical_two)this.elHide(num_vertical_three)this.elShow(num_vertical_four)},4:()=>{this.elHide(num_wsl_point)this.elHide(num_cross_one)this.elShow(num_cross_two)this.elHide(num_cross_three)this.elShow(num_vertical_one)this.elShow(num_vertical_two)this.elHide(num_vertical_three)this.elShow(num_vertical_four)},5:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elShow(num_cross_two)this.elShow(num_cross_three)this.elShow(num_vertical_one)this.elHide(num_vertical_two)this.elHide(num_vertical_three)this.elShow(num_vertical_four)},6:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elShow(num_cross_two)this.elShow(num_cross_three)this.elShow(num_vertical_one)this.elHide(num_vertical_two)this.elShow(num_vertical_three)this.elShow(num_vertical_four)},7:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elHide(num_cross_two)this.elHide(num_cross_three)this.elHide(num_vertical_one)this.elShow(num_vertical_two)this.elHide(num_vertical_three)this.elShow(num_vertical_four)},8:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elShow(num_cross_two)this.elShow(num_cross_three)this.elShow(num_vertical_one)this.elShow(num_vertical_two)this.elShow(num_vertical_three)this.elShow(num_vertical_four)},9:()=>{this.elHide(num_wsl_point)this.elShow(num_cross_one)this.elShow(num_cross_two)this.elShow(num_cross_three)this.elShow(num_vertical_one)this.elShow(num_vertical_two)this.elHide(num_vertical_three)this.elShow(num_vertical_four)}}}//显示全部节点showAllNode(){this.map['reset']()}//隐藏全部节点hideAllNodel(){this.map['allHide']()}//变更数字changeNum(num){this.map[num] && this.map[num]()}//显示elShow(el){el.style.visibility="visible"}//隐藏elHide(el){el.style.visibility="hidden"}
}
WholeNumberManage 完整数字展示与操作类
// 整串数字操作
class WholeNumberManage {//单数字存储 numberSingleManages = [] //完整数字 wholeNum = null //展示的dom对象 mountedEl = null//定时器 timer = null //是否显示虚位isShowVirtualNum = true//是否开始倒计时 _isCountDown = null //倒计时时间间隔 _countDownInterval = 1000//初始整数位数_integerNumberLength = nullconstructor(wholeNum,el,countDownInterval){this.mountedEl = elthis.mountedEl.classList.add("number_wsl")this.wholeNum = wholeNumthis._countDownInterval = countDownIntervalthis.createWholeNumShowEl(this.parseWholeNum(wholeNum))this.overwriteSetMethod()}// 重写set方法overwriteSetMethod(){// 是否进行倒计时Object.defineProperty(this, 'isCountDown', {get: function () {return this._isCountDown},set: function (newValue) {if(newValue){this._isCountDown = newValuethis.startCountDown()} else {clearInterval(this.timer)}}})}// 倒计时startCountDown(){if(!this.wholeNum || this.wholeNum <= 0){return}if(this.timer){clearInterval(this.timer)}this.timer = setInterval(()=>{if(this.wholeNum < 0){clearInterval(this.timer)}this.wholeNum = math.subtract(math.bignumber(this.wholeNum),math.bignumber(1)).toString()this.countDownRefreshNum(this.parseWholeNum(this.wholeNum))},this._countDownInterval)}// 解析数字parseWholeNum(wholeNum){//获取整数部分长度this.setInitialIntegerNumberLength(wholeNum)//解析数字if(String(wholeNum).indexOf('.') == -1){return this.parseWholeIntegerlNum(wholeNum)} else {return this.parseWholeFloatNum(wholeNum)}}//设置初始整数位数setInitialIntegerNumberLength(wholeNum){if(!this._integerNumberLength){this._integerNumberLength = this.getIntegerLength(wholeNum)}}//获取整数位数getIntegerLength(wholeNum){return String(Math.abs(wholeNum)).split('.')[0].length}// 浮点型数字解析parseWholeFloatNum(wholeNum){let nums = []let numsByPoint = String(wholeNum).split('.')numsByPoint.forEach((num,index)=>{nums = nums.concat([...String(num)])if(index==0 && this.isShowVirtualNum){nums = this.complementInteger(nums,this._integerNumberLength - num.length)}nums.push('.')})nums.splice(-1)return nums}// 补位complementInteger(nums,complementLength){if(complementLength > 0){let zeroArr = new Array(complementLength)zeroArr.fill(0,complementLength,0)nums = [...zeroArr,...nums]}return nums}// 整型数字解析parseWholeIntegerlNum(wholeNum){let nums = [...String(wholeNum)]if(this.isShowVirtualNum){let currentIntegerNumberLength = this.getIntegerLength(wholeNum)let integerNumberLengthDifference = (this._integerNumberLength - currentIntegerNumberLength)nums = this.complementInteger(nums,integerNumberLengthDifference)}return nums}// 创建数字展示区createWholeNumShowEl(nums){nums.forEach((num)=>{this.numberSingleManages.push(new NumberSingleManage(num))if(this.mountedEl){this.mountedEl.appendChild(this.numberSingleManages.slice(-1)[0].el)}})}// 刷新数字countDownRefreshNum(nums){//删除多余的domlet virtualNum = (this.numberSingleManages.length - nums.length)if(virtualNum){let needMoveNumberSingleManages = this.numberSingleManages.splice(0,virtualNum)needMoveNumberSingleManages.forEach((numberSingleManages)=>{numberSingleManages.el.remove()}) }//重置所有数据位0this.numberSingleManages.forEach((numberSingleManage)=>{numberSingleManage.num = 0})//进行数据填充nums.forEach((num,index)=>{if(index < this.numberSingleManages.length){let numberSingleManage = this.numberSingleManages[index]numberSingleManage.num = num} else {this.numberSingleManages.push(new NumberSingleManage(num))this.mountedEl.appendChild(this.numberSingleManages.slice(-1)[0].el)}})}
}
三、总结与思考
其实就是单纯的dom操作,没有特别难理解的内容。代码拙劣,大神勿笑[抱拳][抱拳][抱拳]
最后
整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享
部分文档展示:




文章篇幅有限,后面的内容就不一一展示了
有需要的小伙伴,可以点下方卡片免费领取
本文介绍了如何使用JavaScript、HTML和CSS实现一个倒计时展示小工具,包括默认展示数字、倒计时、倒计时虚位处理、小数和负数的显示以及倒计时与小数的结合。内容主要涉及DOM操作,提供了NumberSingleManage和WholeNumberManage两个类的介绍。
5288

被折叠的 条评论
为什么被折叠?



