numberDraw.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <template>
  2. <div class="count" :class="[changeState, arrow]">
  3. <span class="current top">{{ nextTime }}</span>
  4. <span class="next top">{{ time }}</span>
  5. <span class="current bottom">{{ nextTime }}</span>
  6. <span class="next bottom">{{ time }}</span>
  7. </div>
  8. </template>
  9. <script setup lang="ts">
  10. import { computed, ref, watch, toRefs } from 'vue'
  11. const props = defineProps({
  12. chartConfig: {
  13. type: Object,
  14. required: true
  15. },
  16. value: {
  17. type: Number,
  18. required: false
  19. }
  20. })
  21. //动态宽高
  22. const { w, h } = toRefs(props.chartConfig.attr)
  23. let changeState = ref('')
  24. let time: any = ref(0) //当前数字
  25. let nextTime = ref(0) //下一个数字
  26. let duration = 1000 //延迟时间
  27. let arrow = 'up' //方向
  28. watch(
  29. () => props.value,
  30. (n: any) => {
  31. if (typeof n == 'number') selfAdaption(n)
  32. },
  33. { deep: true, immediate: true }
  34. )
  35. //自适应改变数字
  36. function selfAdaption(n: any) {
  37. changeState.value = ''
  38. setTimeout(() => {
  39. changeState.value = 'changing'
  40. }, 20)
  41. setTimeout(() => {
  42. changeState.value = 'changed'
  43. }, duration * 0.9)
  44. time.value = n
  45. nextTime.value = n - 1 < 0 ? 0 : n - 1
  46. }
  47. // // 倒计时改变
  48. // function Interval() {
  49. // setTimeout(() => {
  50. // changeState.value = ''
  51. // setTimeout(() => {
  52. // changeState.value = 'changing'
  53. // }, 20)
  54. // setTimeout(() => {
  55. // changeState.value = 'changed'
  56. // }, duration * 0.9)
  57. // if (time.value == 0) arrow = 'up'
  58. // if (time.value == 9) arrow = 'down'
  59. // let delta = -1
  60. // if (arrow == 'up') delta = 1
  61. // if (arrow == 'down') {
  62. // if (time.value == 0) {
  63. // setTimeout(() => {
  64. // time.value = 9
  65. // }, 20)
  66. // }
  67. // }
  68. // if (arrow == 'up') {
  69. // if (time.value == 9) {
  70. // setTimeout(() => {
  71. // time.value = 0
  72. // }, 20)
  73. // }
  74. // }
  75. // time.value += delta
  76. // nextTime.value = time.value - delta
  77. // Interval()
  78. // }, duration)
  79. // }
  80. // if (!(typeof props.value == 'number')) {
  81. // Interval()
  82. // }
  83. </script>
  84. <style lang="less" scoped>
  85. .count {
  86. box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.2);
  87. -moz-perspective: 500px;
  88. -webkit-perspective: 500px;
  89. perspective: 500px;
  90. text-align: center;
  91. -moz-transform: translateZ(0);
  92. -webkit-transform: translateZ(0);
  93. transform: translateZ(0);
  94. width: v-bind('w + "px"');
  95. height: v-bind('h + "px"');
  96. line-height: v-bind('h + "px"');
  97. padding: 15px;
  98. box-sizing: border-box;
  99. }
  100. .count span {
  101. background: #202020;
  102. color: #f8f8f8;
  103. display: block;
  104. font-size: 50px;
  105. left: 0;
  106. position: absolute;
  107. top: 0;
  108. text-shadow: 0 1px 0 #282828, 0 2px 0 #1e1e1e, 0 3px 0 #141414, 0 4px 0 #0a0a0a, 0 5px 0 #000,
  109. 0 0 10px rgba(0, 0, 0, 0.8);
  110. -moz-transform-origin: 0 v-bind('h / 2 + "px"') 0;
  111. -webkit-transform-origin: 0 v-bind('h / 2 + "px"') 0;
  112. transform-origin: 0 v-bind('h / 2 + "px"') 0;
  113. width: 100%;
  114. }
  115. .count span:before {
  116. border-bottom: 2px solid #000;
  117. content: '';
  118. left: 0;
  119. position: absolute;
  120. width: 100%;
  121. }
  122. .count span:after {
  123. box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.35);
  124. content: '';
  125. height: 100%;
  126. left: 0;
  127. position: absolute;
  128. top: 0;
  129. width: 100%;
  130. }
  131. .count .small {
  132. font-size: 175px;
  133. }
  134. .count .top {
  135. border-top-left-radius: 11px;
  136. border-top-right-radius: 11px;
  137. box-shadow: inset 0 2px rgba(0, 0, 0, 0.9), inset 0 3px 0 rgba(255, 255, 255, 0.4);
  138. height: 50%;
  139. overflow: hidden;
  140. }
  141. .count .top:before {
  142. bottom: 0;
  143. }
  144. .count .top:after {
  145. background: -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
  146. background: -webkit-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
  147. background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
  148. border-top-left-radius: 11px;
  149. border-top-right-radius: 11px;
  150. }
  151. .count .bottom {
  152. border-radius: 10px;
  153. height: 100%;
  154. }
  155. .count .bottom:before {
  156. top: 50%;
  157. }
  158. .count .bottom:after {
  159. border-radius: 10px;
  160. background: -moz-linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0));
  161. background: -webkit-linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0));
  162. background: linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0));
  163. }
  164. .count.down .top {
  165. border-top-left-radius: 11px;
  166. border-top-right-radius: 11px;
  167. height: 50%;
  168. }
  169. .count.down .top.current {
  170. -moz-transform-style: flat;
  171. -webkit-transform-style: flat;
  172. transform-style: flat;
  173. z-index: 3;
  174. }
  175. .count.down .top.next {
  176. -moz-transform: rotate3d(1, 0, 0, -90deg);
  177. -ms-transform: rotate3d(1, 0, 0, -90deg);
  178. -webkit-transform: rotate3d(1, 0, 0, -90deg);
  179. transform: rotate3d(1, 0, 0, -90deg);
  180. z-index: 4;
  181. }
  182. .count.down .bottom {
  183. border-radius: 10px;
  184. }
  185. .count.down .bottom.current {
  186. z-index: 2;
  187. }
  188. .count.down .bottom.next {
  189. z-index: 1;
  190. }
  191. .count.down.changing .bottom.current {
  192. box-shadow: 0 75px 5px -20px rgba(0, 0, 0, 0.3);
  193. -moz-transform: rotate3d(1, 0, 0, 90deg);
  194. -ms-transform: rotate3d(1, 0, 0, 90deg);
  195. -webkit-transform: rotate3d(1, 0, 0, 90deg);
  196. transform: rotate3d(1, 0, 0, 90deg);
  197. -moz-transition: -moz-transform 0.35s ease-in, box-shadow 0.35s ease-in;
  198. -o-transition: -o-transform 0.35s ease-in, box-shadow 0.35s ease-in;
  199. -webkit-transition: -webkit-transform 0.35s ease-in, box-shadow 0.35s ease-in;
  200. transition: transform 0.35s ease-in, box-shadow 0.35s ease-in;
  201. }
  202. .count.down.changing .top.next,
  203. .count.down.changed .top.next {
  204. -moz-transition: -moz-transform 0.35s ease-out 0.35s;
  205. -o-transition: -o-transform 0.35s ease-out 0.35s;
  206. -webkit-transition: -webkit-transform 0.35s ease-out;
  207. -webkit-transition-delay: 0.35s;
  208. transition: transform 0.35s ease-out 0.35s;
  209. -moz-transform: none;
  210. -ms-transform: none;
  211. -webkit-transform: none;
  212. transform: none;
  213. }
  214. .count.up .top {
  215. height: 50%;
  216. }
  217. .count.up .top.current {
  218. z-index: 4;
  219. }
  220. .count.up .top.next {
  221. z-index: 3;
  222. }
  223. .count.up .bottom.current {
  224. z-index: 1;
  225. }
  226. .count.up .bottom.next {
  227. box-shadow: 0 75px 5px -20px rgba(0, 0, 0, 0.3);
  228. -moz-transform: rotate3d(1, 0, 0, 90deg);
  229. -ms-transform: rotate3d(1, 0, 0, 90deg);
  230. -webkit-transform: rotate3d(1, 0, 0, 90deg);
  231. transform: rotate3d(1, 0, 0, 90deg);
  232. z-index: 2;
  233. }
  234. .count.up.changing .top.current {
  235. -moz-transform: rotate3d(1, 0, 0, -90deg);
  236. -ms-transform: rotate3d(1, 0, 0, -90deg);
  237. -webkit-transform: rotate3d(1, 0, 0, -90deg);
  238. transform: rotate3d(1, 0, 0, -90deg);
  239. -moz-transition: -moz-transform 0.2625s ease-in, box-shadow 0.2625s ease-in;
  240. -o-transition: -o-transform 0.2625s ease-in, box-shadow 0.2625s ease-in;
  241. -webkit-transition: -webkit-transform 0.2625s ease-in, box-shadow 0.2625s ease-in;
  242. transition: transform 0.2625s ease-in, box-shadow 0.2625s ease-in;
  243. }
  244. .count.up.changing .bottom.next,
  245. .count.up.changed .bottom.next {
  246. box-shadow: 0 0 0 0 transparent;
  247. -moz-transition: box-shadow 0.175s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s,
  248. -moz-transform 0.35s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s;
  249. -o-transition: box-shadow 0.175s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s,
  250. -o-transform 0.35s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s;
  251. -webkit-transition: box-shadow 0.175s cubic-bezier(0.375, 1.495, 0.61, 0.78),
  252. -webkit-transform 0.35s cubic-bezier(0.375, 1.495, 0.61, 0.78);
  253. -webkit-transition-delay: 0.35s, 0.35s;
  254. transition: box-shadow 0.175s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s,
  255. transform 0.35s cubic-bezier(0.375, 1.495, 0.61, 0.78) 0.35s;
  256. -moz-transform: rotate3d(1, 0, 0, 0);
  257. -ms-transform: rotate3d(1, 0, 0, 0);
  258. -webkit-transform: rotate3d(1, 0, 0, 0);
  259. transform: rotate3d(1, 0, 0, 0);
  260. }
  261. .count.changed .top.current,
  262. .count.changed .bottom.current {
  263. display: none;
  264. }
  265. html,
  266. body {
  267. height: 100%;
  268. width: 100%;
  269. }
  270. body {
  271. background: #202020;
  272. background-origin: 50% 50%;
  273. -moz-background-size: cover;
  274. -o-background-size: cover;
  275. -webkit-background-size: cover;
  276. background-size: cover;
  277. font-family: 'Oswald';
  278. }
  279. </style>