tui-countdown.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <view class="tui-countdown-box">
  3. <view class="tui-countdown-item" :style="{ background: backgroundColor, borderColor: borderColor, width: getWidth(d, width) + 'rpx', height: height + 'rpx' }" v-if="days">
  4. <view class="tui-countdown-time" :class="[scale ? 'tui-countdown-scale' : '']" :style="{ fontSize: size + 'rpx', color: color, lineHeight: size + 'rpx' }">
  5. {{ d }}
  6. </view>
  7. </view>
  8. <view
  9. class="tui-countdown-colon"
  10. :class="{ 'tui-colon-pad': borderColor == 'transparent' }"
  11. :style="{ lineHeight: colonSize + 'rpx', fontSize: colonSize + 'rpx', color: colonColor }"
  12. v-if="days"
  13. >
  14. {{ isColon ? ':' : '天' }}
  15. </view>
  16. <view class="tui-countdown-item" :style="{ background: backgroundColor, borderColor: borderColor, width: getWidth(h, width) + 'rpx', height: height + 'rpx' }" v-if="hours">
  17. <view class="tui-countdown-time" :class="[scale ? 'tui-countdown-scale' : '']" :style="{ fontSize: size + 'rpx', color: color, lineHeight: size + 'rpx' }">
  18. {{ h }}
  19. </view>
  20. </view>
  21. <view
  22. class="tui-countdown-colon"
  23. :class="{ 'tui-colon-pad': borderColor == 'transparent' }"
  24. :style="{ lineHeight: colonSize + 'rpx', fontSize: colonSize + 'rpx', color: colonColor }"
  25. v-if="hours"
  26. >
  27. {{ isColon ? ':' : '时' }}
  28. </view>
  29. <view
  30. class="tui-countdown-item"
  31. :style="{ background: backgroundColor, borderColor: borderColor, width: getWidth(i, width) + 'rpx', height: height + 'rpx' }"
  32. v-if="minutes"
  33. >
  34. <view class="tui-countdown-time" :class="[scale ? 'tui-countdown-scale' : '']" :style="{ fontSize: size + 'rpx', color: color, lineHeight: size + 'rpx' }">
  35. {{ i }}
  36. </view>
  37. </view>
  38. <view
  39. class="tui-countdown-colon"
  40. :class="{ 'tui-colon-pad': borderColor == 'transparent' }"
  41. :style="{ lineHeight: colonSize + 'rpx', fontSize: colonSize + 'rpx', color: colonColor }"
  42. v-if="minutes"
  43. >
  44. {{ isColon ? ':' : '分' }}
  45. </view>
  46. <view
  47. class="tui-countdown-item"
  48. :style="{ background: backgroundColor, borderColor: borderColor, width: getWidth(s, width) + 'rpx', height: height + 'rpx' }"
  49. v-if="seconds"
  50. >
  51. <view class="tui-countdown-time" :class="[scale ? 'tui-countdown-scale' : '']" :style="{ fontSize: size + 'rpx', color: color, lineHeight: size + 'rpx' }">
  52. {{ s }}
  53. </view>
  54. </view>
  55. <view
  56. class="tui-countdown-colon"
  57. :class="{ 'tui-colon-pad': borderColor == 'transparent' }"
  58. :style="{ lineHeight: colonSize + 'rpx', fontSize: colonSize + 'rpx', color: colonColor }"
  59. v-if="seconds && !isColon"
  60. >
  61. {{ unitEn ? 's' : '秒' }}
  62. </view>
  63. </view>
  64. </template>
  65. <script>
  66. export default {
  67. name: 'tuiCountdown',
  68. props: {
  69. //数字框宽度
  70. width: {
  71. type: Number,
  72. default: 25
  73. },
  74. //数字框高度
  75. height: {
  76. type: Number,
  77. default: 25
  78. },
  79. //数字框border颜色
  80. borderColor: {
  81. type: String,
  82. default: '#333'
  83. },
  84. //数字框背景颜色
  85. backgroundColor: {
  86. type: String,
  87. default: '#fff'
  88. },
  89. //数字框字体大小
  90. size: {
  91. type: Number,
  92. default: 24
  93. },
  94. //数字框字体颜色
  95. color: {
  96. type: String,
  97. default: '#333'
  98. },
  99. //是否缩放 0.9
  100. scale: {
  101. type: Boolean,
  102. default: false
  103. },
  104. //冒号大小
  105. colonSize: {
  106. type: Number,
  107. default: 28
  108. },
  109. //冒号颜色
  110. colonColor: {
  111. type: String,
  112. default: '#333'
  113. },
  114. //剩余时间 (单位:秒)
  115. time: {
  116. type: Number,
  117. default: 0
  118. },
  119. //是否包含天
  120. days: {
  121. type: Boolean,
  122. default: false
  123. },
  124. //是否包含小时
  125. hours: {
  126. type: Boolean,
  127. default: true
  128. },
  129. //是否包含分钟
  130. minutes: {
  131. type: Boolean,
  132. default: true
  133. },
  134. //是否包含秒
  135. seconds: {
  136. type: Boolean,
  137. default: true
  138. },
  139. //单位用英文缩写表示 仅seconds秒数有效
  140. unitEn: {
  141. type: Boolean,
  142. default: false
  143. },
  144. //是否展示为冒号,false为文字
  145. isColon: {
  146. type: Boolean,
  147. default: true
  148. }
  149. },
  150. watch: {
  151. time(val) {
  152. this.clearTimer();
  153. this.doLoop();
  154. }
  155. },
  156. data() {
  157. return {
  158. countdown: null,
  159. d: '0',
  160. h: '00',
  161. i: '00',
  162. s: '00'
  163. };
  164. },
  165. created() {
  166. this.clearTimer();
  167. this.doLoop();
  168. },
  169. beforeDestroy() {
  170. this.clearTimer();
  171. },
  172. methods: {
  173. getWidth: function(num, width) {
  174. return num > 99 ? (width / 2) * num.toString().length : width;
  175. },
  176. clearTimer(){
  177. clearInterval(this.countdown);
  178. this.countdown = null;
  179. },
  180. endOfTime() {
  181. this.clearTimer();
  182. this.$emit('end', {});
  183. },
  184. doLoop: function() {
  185. let seconds = this.time || 0;
  186. this.countDown(seconds);
  187. this.countdown = setInterval(() => {
  188. seconds--;
  189. if (seconds < 0) {
  190. this.endOfTime();
  191. return;
  192. }
  193. this.countDown(seconds);
  194. }, 1000);
  195. },
  196. countDown(seconds) {
  197. let [day, hour, minute, second] = [0, 0, 0, 0];
  198. if (seconds > 0) {
  199. day = this.days ? Math.floor(seconds / (60 * 60 * 24)) : 0;
  200. hour = this.hours ? Math.floor(seconds / (60 * 60)) - day * 24 : 0;
  201. minute = this.minutes ? Math.floor(seconds / 60) - hour * 60 - day * 24 * 60 : 0;
  202. second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
  203. } else {
  204. this.endOfTime();
  205. }
  206. hour = hour < 10 ? '0' + hour : hour;
  207. minute = minute < 10 ? '0' + minute : minute;
  208. second = second < 10 ? '0' + second : second;
  209. this.d = day;
  210. this.h = hour;
  211. this.i = minute;
  212. this.s = second;
  213. }
  214. }
  215. };
  216. </script>
  217. <style scoped>
  218. .tui-countdown-box {
  219. display: flex;
  220. align-items: center;
  221. }
  222. .tui-countdown-box {
  223. display: flex;
  224. align-items: center;
  225. }
  226. .tui-countdown-item {
  227. border: 1rpx solid;
  228. display: flex;
  229. align-items: center;
  230. justify-content: center;
  231. padding: 2rpx;
  232. border-radius: 6rpx;
  233. white-space: nowrap;
  234. transform: translateZ(0);
  235. }
  236. .tui-countdown-time {
  237. margin: 0;
  238. padding: 0;
  239. }
  240. .tui-countdown-colon {
  241. display: flex;
  242. justify-content: center;
  243. padding: 0 5rpx;
  244. }
  245. .tui-colon-pad {
  246. padding: 0 !important;
  247. }
  248. .tui-countdown-scale {
  249. transform: scale(0.9);
  250. transform-origin: center center;
  251. }
  252. </style>