numberScroll.vue 979 B

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. <template>
  2. <span ref="numberEl">{{ displayValue }}</span>
  3. </template>
  4. <script setup>
  5. import { ref, watch, onMounted } from "vue";
  6. const props = defineProps({
  7. value: { type: Number, default: 0 },
  8. duration: { type: Number, default: 1500 },
  9. easing: { type: Function, default: (t) => t * (2 - t) },
  10. });
  11. const displayValue = ref(0);
  12. const numberEl = ref(null);
  13. function animate(start, end) {
  14. const startTime = performance.now();
  15. const frame = (currentTime) => {
  16. const elapsed = currentTime - startTime;
  17. const progress = Math.min(elapsed / props.duration, 1);
  18. displayValue.value = Math.floor(start + (end - start) * props.easing(progress));
  19. displayValue.value = displayValue.value.toLocaleString();
  20. if (progress < 1) {
  21. requestAnimationFrame(frame);
  22. }
  23. };
  24. requestAnimationFrame(frame);
  25. }
  26. watch(
  27. () => props.value,
  28. (newVal, oldVal) => {
  29. animate(oldVal, newVal);
  30. }
  31. );
  32. onMounted(() => {
  33. animate(0, props.value);
  34. });
  35. </script>