项目中要用到倒计时,用Vue 实现了一个
1 <template> 2 <transition name="bkcd"> 3 <div class="bkCountDown" v-show="bkCountDownShow"> 4 <div class="kbCountDownTitle"> 5 <img src="http://static.crecgec.com/Kaipiao/countDownTitle.png"> 6 </div> 7 <div id="kbCountDownContent" class="kbCountDownContent" ref="kbCountDownContent"> 8 </div> 9 <!--倒计时结束后提示的信息--> 10 <div class="cdEndCon" v-show="cdEndConShow">{{cdEndContent}}</div> 11 </div> 12 </transition> 13 </template> 14 15 <script> 16 import $ from 'jquery' 17 18 export default { 19 props: { 20 // 控制倒计时页面显示、隐藏 21 bkCountDownShow: { 22 type: Boolean, 23 default: true 24 }, 25 // 这个参数:为了实现中途倒计时暂停功能 26 // 控制倒计时暂停/开始 27 cdStartOrEnd: { 28 type: Boolean, 29 default: true 30 }, 31 // 倒计时的时间,有父组件传递 32 countDownTime: { 33 type: String, 34 default: '2017/11/9 15:03:01' 35 }, 36 // 倒计时结束后显示的内容 37 cdEndContent: { 38 type: String, 39 default: '倒计时已经结束' 40 } 41 }, 42 data () { 43 return { 44 // 倒计时结束后显示cdEndCon 45 cdEndConShow: false, 46 timestamp: '', // 倒计时的时间戳 47 cdTimer: '', // setTimeOut值 48 timeInterval: '', // 倒计时结束时间与当前时间的之间的间隔 49 timeIntervalVal: '', // 保存时间间隔的参数 50 d: '', 51 h: '', 52 m: '', 53 s: '', 54 days: 24 * 60 * 60, 55 hours: 60 * 60, 56 minutes: 60 57 } 58 }, 59 mounted () { 60 this.countdown() 61 }, 62 watch: { 63 // 监控cdStartOrEnd值 64 cdStartOrEnd () { 65 if (this.cdStartOrEnd) { 66 this.tick() 67 } else { 68 clearTimeout(this.cdTimer) 69 } 70 } 71 }, 72 methods: { 73 countdown () { 74 this.timestamp = new Date(this.countDownTime).getTime() 75 this.init('kbCountDownContent') 76 }, 77 // 初始化 78 init (ele) { 79 $.each(['Hours', 'Minutes', 'Seconds'], function (i) { 80 $('<div class="count' + this + '">').html( 81 `<div class = "countPos">\ 82 <span class="digit static">0</span>\ 83 </div>\ 84 <div class="countPos">\ 85 <span class="digit static">0</span>\ 86 </div>` 87 ).appendTo($('#' + ele)) 88 if (this !== 'Seconds') { 89 $('#' + ele).append('<div class="countDiv countDiv' + i + '"></div>') 90 } 91 }) 92 this.tick() 93 }, 94 tick () { 95 // 每次进入这个方法,就重新计算和当前时间的间隔,然后赋值给timeInterval 96 this.timeInterval = Math.floor((this.timestamp - (new Date())) / 1000) 97 if (this.timeInterval < 0) { 98 this.timeInterval = 0 99 } 100 this.timeIntervalVal = this.timeInterval 101 // Number of days left 102 // 现在是只有时分秒,可以通过调整下面的代码,来确定显示什么 103 // this.d = Math.floor(this.timeInterval / this.days) 104 // this.updateDuo(0, 1, this.d) 105 // this.timeInterval -= this.d * this.days 106 // Number of hours left 107 this.h = Math.floor(this.timeInterval / this.hours) 108 this.updateDuo(0, 1, this.h) 109 this.timeInterval -= this.h * this.hours 110 // Number of minutes timeInterval 111 this.m = Math.floor(this.timeInterval / this.minutes) 112 this.updateDuo(2, 3, this.m) 113 this.timeInterval -= this.m * this.minutes 114 // Number of seconds timeInterval 115 this.s = this.timeInterval 116 this.updateDuo(4, 5, this.s) 117 // timeIntervalVal大于0,就执行setTimeout方法 118 if (this.timeIntervalVal > 0) { 119 this.cdTimer = setTimeout(this.tick, 1000) 120 } else { 121 // 倒计时结束 122 this.cdEndConShow = true 123 // 这块可以添加emit,给父组件传参 124 // 通过emit给父组件传参数来操作bkCountDownShow 125 // bkCountDownShow = false 126 } 127 }, 128 updateDuo (minor, major, value) { 129 this.switchDigit($('#kbCountDownContent').find('.countPos').eq(minor), Math.floor(value / 10) % 10) 130 this.switchDigit($('#kbCountDownContent').find('.countPos').eq(major), value % 10) 131 }, 132 switchDigit (position, number) { 133 let digit = position.find('.digit') 134 if (digit.is(':animated')) { 135 return false 136 } 137 if (position.data('digit') === number) { 138 return false 139 } 140 position.data('digit', number) 141 var replacement = $('<span>', { 142 'class': 'digit', 143 css: { 144 top: '-170px', 145 opacity: 0 146 }, 147 html: number 148 }) 149 digit 150 .before(replacement) 151 .removeClass('static') 152 .animate({top: '170px', opacity: 0}, 'slow', function () { 153 digit.remove() 154 }) 155 replacement 156 .delay(100) 157 .animate({top: 0, opacity: 1}, 'slow', function () { 158 replacement.addClass('static') 159 }) 160 } 161 } 162 } 163 </script> 164 165 <!-- Add "scoped" attribute to limit CSS to this component only --> 166 <style> 167 *{ 168 margin:0; 169 padding:0; 170 font-family: 'Microsoft Yahei',Tahoma,'Simsun','宋体' !important; 171 } 172 173 .bkCountDown{ 174 width: 100%; 175 height: 980px; 176 background:url('http://static.crecgec.com/Kaipiao/background.png') #b0b0b0; 177 position: absolute; 178 background-size: cover; 179 overflow: hidden; 180 } 181 .kbCountDownTitle{ 182 width: 1070px; 183 height: 120px; 184 line-height: 120px; 185 font-size: 120px; 186 margin: 190px auto 0; 187 text-align: center; 188 color: #fff; 189 } 190 .kbCountDownContent{ 191 width:1070px; 192 margin:160px auto 0; 193 text-align:center; 194 letter-spacing:-3px; 195 overflow: hidden; 196 } 197 .countPos{ 198 display: inline-block; 199 width: 150px; 200 height: 170px; 201 overflow: hidden; 202 position: relative; 203 margin-left: 15px; 204 } 205 206 .digit{ 207 position:absolute; 208 display:block; 209 width:150px; 210 height: 170px; 211 line-height: 170px; 212 text-align:center; 213 color:#fff; 214 font-size: 80px; 215 background: url('http://static.crecgec.com/Kaipiao/countDown.png') 0 0 no-repeat; 216 } 217 218 .digit.static{ 219 background: url('http://static.crecgec.com/Kaipiao/countDown.png') 0 0 no-repeat; 220 } 221 .countDays,.countHours,.countMinutes,.countSeconds{ 222 float: left; 223 font-size: 0; 224 } 225 .countDiv{ 226 display:inline-block; 227 width:10px; 228 height:50px; 229 float: left; 230 margin-top: 60px; 231 margin-left: 15px; 232 background: url('http://static.crecgec.com/Kaipiao/countDown1.png') 0 0 no-repeat; 233 } 234 .cdEndCon{ 235 width:1070px; 236 margin:20px auto 0; 237 text-align: center; 238 color: #fff; 239 font-size: 20px; 240 } 241 .bkcd-enter-active, .bkcd-leave-active{ 242 transition: opacity .5s 243 } 244 .bkcd-enter, .bkcd-leave-to{ 245 opacity: 0 246 } 247 </style>