tui-countdown.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. clearInterval(this.countdown);
  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.doLoop();
  167. },
  168. beforeDestroy() {
  169. clearInterval(this.countdown);
  170. this.countdown = null;
  171. },
  172. methods: {
  173. getWidth: function(num, width) {
  174. return num > 99 ? (width / 2) * num.toString().length : width;
  175. },
  176. endOfTime() {
  177. clearInterval(this.countdown);
  178. this.countdown = null;
  179. this.$emit('end', {});
  180. },
  181. doLoop: function() {
  182. let seconds = this.time || 0;
  183. this.countDown(seconds);
  184. this.countdown = setInterval(() => {
  185. seconds--;
  186. if (seconds < 0) {
  187. this.endOfTime();
  188. return;
  189. }
  190. this.countDown(seconds);
  191. }, 1000);
  192. },
  193. countDown(seconds) {
  194. let [day, hour, minute, second] = [0, 0, 0, 0];
  195. if (seconds > 0) {
  196. day = this.days ? Math.floor(seconds / (60 * 60 * 24)) : 0;
  197. hour = this.hours ? Math.floor(seconds / (60 * 60)) - day * 24 : 0;
  198. minute = this.minutes ? Math.floor(seconds / 60) - hour * 60 - day * 24 * 60 : 0;
  199. second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
  200. } else {
  201. this.endOfTime();
  202. }
  203. hour = hour < 10 ? '0' + hour : hour;
  204. minute = minute < 10 ? '0' + minute : minute;
  205. second = second < 10 ? '0' + second : second;
  206. this.d = day;
  207. this.h = hour;
  208. this.i = minute;
  209. this.s = second;
  210. }
  211. }
  212. };
  213. </script>
  214. <style scoped>
  215. .tui-countdown-box {
  216. display: flex;
  217. align-items: center;
  218. }
  219. .tui-countdown-box {
  220. display: flex;
  221. align-items: center;
  222. }
  223. .tui-countdown-item {
  224. border: 1rpx solid;
  225. display: flex;
  226. align-items: center;
  227. justify-content: center;
  228. padding: 2rpx;
  229. border-radius: 6rpx;
  230. white-space: nowrap;
  231. transform: translateZ(0);
  232. }
  233. .tui-countdown-time {
  234. margin: 0;
  235. padding: 0;
  236. }
  237. .tui-countdown-colon {
  238. display: flex;
  239. justify-content: center;
  240. padding: 0 5rpx;
  241. }
  242. .tui-colon-pad {
  243. padding: 0 !important;
  244. }
  245. .tui-countdown-scale {
  246. transform: scale(0.9);
  247. transform-origin: center center;
  248. }
  249. </style>