clock.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <view class="clock-box">
  3. <view class="clock" :style="{ '--ds': ds, '--dm': dm, '--dh': dh }">
  4. <view class="clock-pane">
  5. <text class="clock-num" :style="{ '--i': n }" v-for="n in 12" :key="n">{{ n }}</text>
  6. </view>
  7. <view class="clock-hour"></view>
  8. <view class="clock-min"></view>
  9. <view class="clock-sec"></view>
  10. </view>
  11. </view>
  12. </template>
  13. <script lang="ts" setup>
  14. const d = new Date()
  15. const h = d.getHours()
  16. const m = d.getMinutes()
  17. const s = d.getSeconds()
  18. const ds = ref(s)
  19. const dm = ref(m + s / 60)
  20. const dh = ref(h + m / 60 + s / 3600)
  21. </script>
  22. <style lang="scss">
  23. .clock {
  24. position: relative;
  25. display: flex;
  26. align-items: center;
  27. justify-content: center;
  28. width: 380px;
  29. height: 380px;
  30. font-size: 24px;
  31. border-radius: 20px;
  32. box-shadow: 2px 2px 20px #0000001a;
  33. --step: 60s;
  34. }
  35. .clock::before {
  36. position: absolute;
  37. width: 300px;
  38. height: 300px;
  39. content: '';
  40. background: repeating-conic-gradient(from -0.5deg, #333 0 1deg, transparent 0deg 30deg),
  41. repeating-conic-gradient(from -0.5deg, #ccc 0 1deg, transparent 0deg 6deg);
  42. border-radius: 50%;
  43. mask: radial-gradient(transparent 145px, red 0);
  44. }
  45. .clock-pane {
  46. position: absolute;
  47. width: 250px;
  48. height: 250px;
  49. }
  50. .clock-num {
  51. position: absolute;
  52. offset-path: path(
  53. 'M250 125c0 69.036-55.964 125-125 125S0 194.036 0 125 55.964 0 125 0s125 55.964 125 125z'
  54. );
  55. offset-distance: calc(var(--i) * 10% / 1.2 - 25%);
  56. offset-rotate: 0deg;
  57. }
  58. .clock-hour {
  59. position: absolute;
  60. width: 4px;
  61. height: 60px;
  62. background: #333;
  63. transform: translateY(-50%) rotate(0);
  64. transform-origin: center bottom;
  65. animation: clock calc(var(--step) * 60 * 12) infinite linear;
  66. animation-delay: calc(-1 * var(--step) * var(--dh) * 60);
  67. }
  68. .clock-min {
  69. position: absolute;
  70. width: 4px;
  71. height: 90px;
  72. background: #333;
  73. transform: translateY(-50%) rotate(0);
  74. transform-origin: center bottom;
  75. animation: clock calc(var(--step) * 60) infinite linear;
  76. animation-delay: calc(-1 * var(--step) * var(--dm));
  77. }
  78. .clock-sec {
  79. position: absolute;
  80. width: 2px;
  81. height: 120px;
  82. background: red;
  83. transform: translateY(-50%) rotate(0);
  84. transform-origin: center bottom;
  85. animation: clock var(--step) infinite steps(60);
  86. animation-delay: calc(-1 * var(--step) * var(--ds) / 60);
  87. }
  88. .clock-sec::after {
  89. position: absolute;
  90. bottom: 0;
  91. left: 50%;
  92. width: 10px;
  93. height: 10px;
  94. content: '';
  95. background: #fff;
  96. border: 4px solid #333;
  97. border-radius: 50%;
  98. transform: translate(-50%, 50%);
  99. }
  100. @keyframes clock {
  101. to {
  102. transform: translateY(-50%) rotate(360deg);
  103. }
  104. }
  105. a {
  106. width: 8px;
  107. height: 9px;
  108. }
  109. </style>