SlyCountDown.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <view class="Body" :style="{padding:styles.outPad+'px'}">
  3. <view>{{attrs.front}}</view>
  4. <view class="u-count-down__view" v-html="formattedTime"></view>
  5. </view>
  6. </template>
  7. <script>
  8. import {
  9. isSameSecond,
  10. parseFormat,
  11. parseTimeData
  12. } from './utils';
  13. import Mixin from "../Mixin";
  14. import { forEach } from 'mathjs';
  15. export default {
  16. data() {
  17. return {
  18. timer: null,
  19. // 各单位(天,时,分等)剩余时间
  20. timeData: parseTimeData(0),
  21. // 格式化后的时间,如"03:23:21"
  22. formattedTime: '0',
  23. // 倒计时是否正在进行中
  24. runing: false,
  25. endTime: 0, // 结束的毫秒时间戳
  26. remainTime: 0, // 剩余的毫秒时间
  27. }
  28. },
  29. mixins: [Mixin],
  30. props: {
  31. // 倒计时时长,单位ms
  32. time: {
  33. type: [String, Number],
  34. default: 1800000
  35. },
  36. // 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒
  37. // format: {
  38. // type: String,
  39. // default: 'HH:mm:ss'
  40. // },
  41. // 是否自动开始倒计时
  42. // autoStart: {
  43. // type: Boolean,
  44. // default: false
  45. // },
  46. // 是否展示毫秒倒计时
  47. millisecond: {
  48. type: Boolean,
  49. default: false
  50. },
  51. // 是否显示样式
  52. styleBool:{
  53. type:Boolean,
  54. default:true
  55. },
  56. },
  57. watch: {
  58. dataVal(n) {
  59. this.reset()
  60. }
  61. },
  62. mounted() {
  63. this.init()
  64. },
  65. methods: {
  66. init() {
  67. this.reset()
  68. },
  69. // 开始倒计时
  70. start() {
  71. if (this.runing) return
  72. // 标识为进行中
  73. this.runing = true
  74. // 结束时间戳 = 此刻时间戳 + 剩余的时间
  75. this.endTime = Date.now() + this.remainTime
  76. this.toTick()
  77. },
  78. // 根据是否展示毫秒,执行不同操作函数
  79. toTick() {
  80. if (this.millisecond) {
  81. this.microTick()
  82. } else {
  83. this.macroTick()
  84. }
  85. },
  86. macroTick() {
  87. this.clearTimeout()
  88. // 每隔一定时间,更新一遍定时器的值
  89. // 同时此定时器的作用也能带来毫秒级的更新
  90. this.timer = setTimeout(() => {
  91. // 获取剩余时间
  92. const remain = this.getRemainTime()
  93. // 重设剩余时间
  94. if (!isSameSecond(remain, this.remainTime) || remain === 0) {
  95. this.setRemainTime(remain)
  96. }
  97. // 如果剩余时间不为0,则继续检查更新倒计时
  98. if (this.remainTime !== 0) {
  99. this.macroTick()
  100. }
  101. }, 30)
  102. },
  103. microTick() {
  104. this.clearTimeout()
  105. this.timer = setTimeout(() => {
  106. this.setRemainTime(this.getRemainTime())
  107. if (this.remainTime !== 0) {
  108. this.microTick()
  109. }
  110. }, 50)
  111. },
  112. // 获取剩余的时间
  113. getRemainTime() {
  114. // 取最大值,防止出现小于0的剩余时间值
  115. return Math.max(this.endTime - Date.now(), 0)
  116. },
  117. // 设置剩余的时间
  118. setRemainTime(remain) {
  119. this.remainTime = remain
  120. // 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象
  121. const timeData = parseTimeData(remain)
  122. this.$emit('change', timeData)
  123. // 得出格式化后的时间
  124. if(this.styleBool){
  125. this.formattedTime=this.dealStyle(parseFormat(this.attrs.format, timeData))
  126. }else{
  127. this.formattedTime= parseFormat(this.attrs.format, timeData)
  128. }
  129. // 如果时间已到,停止倒计时
  130. if (remain <= 0) {
  131. this.pause()
  132. this.$emit('finish')
  133. }
  134. },
  135. dealStyle(time){
  136. let arr=time.split(':');
  137. let html=""
  138. let style={
  139. // width: '30px !important',
  140. // height: this.height+'px !important',
  141. // background: '#3c9cff',
  142. background:this.styles.backgroundColor,
  143. 'font-size':'12px !important',
  144. margin:'0 5px,',
  145. color:'#fff',
  146. display:"inline-block",
  147. padding:'5px',
  148. }
  149. Object.assign(style)
  150. let styleCopy=JSON.stringify(style).replace(/"/g,'').replace(/,/g,';');
  151. let styleStr=styleCopy.slice(1,styleCopy.length-1);
  152. console.log(styleStr)
  153. arr.forEach((v,i)=>{
  154. if(i<arr.length-1){
  155. html+=`<view style="${styleStr}">${v}</view>:`
  156. }else{
  157. html+=`<view style="${styleStr}">${v}</view>`
  158. }
  159. })
  160. return html
  161. console.log('--------------',html)
  162. },
  163. // 重置倒计时
  164. reset() {
  165. this.pause()
  166. this.remainTime = this.dataVal.timer
  167. this.setRemainTime(this.remainTime)
  168. if (this.attrs.autoStart) {
  169. this.start()
  170. }
  171. },
  172. // 暂停倒计时
  173. pause() {
  174. this.runing = false;
  175. this.clearTimeout()
  176. },
  177. // 清空定时器
  178. clearTimeout() {
  179. clearTimeout(this.timer)
  180. this.timer = null
  181. }
  182. },
  183. beforeDestroy() {
  184. this.clearTimeout()
  185. }
  186. }
  187. </script>
  188. <style lang="scss" scoped>
  189. // .u-count-down__view{
  190. // text{
  191. // width: 44rpx !important;
  192. // height: 44rpx;
  193. // background: #3c9cff;
  194. // }
  195. // }
  196. .Body{
  197. display: flex;
  198. align-items: center;
  199. }
  200. </style>