useScrollTo.ts 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { ref, unref } from 'vue'
  2. export interface ScrollToParams {
  3. el: HTMLElement
  4. to: number
  5. position: string
  6. duration?: number
  7. callback?: () => void
  8. }
  9. const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
  10. t /= d / 2
  11. if (t < 1) {
  12. return (c / 2) * t * t + b
  13. }
  14. t--
  15. return (-c / 2) * (t * (t - 2) - 1) + b
  16. }
  17. const move = (el: HTMLElement, position: string, amount: number) => {
  18. el[position] = amount
  19. }
  20. export function useScrollTo({
  21. el,
  22. position = 'scrollLeft',
  23. to,
  24. duration = 500,
  25. callback
  26. }: ScrollToParams) {
  27. const isActiveRef = ref(false)
  28. const start = el[position]
  29. const change = to - start
  30. const increment = 20
  31. let currentTime = 0
  32. function animateScroll() {
  33. if (!unref(isActiveRef)) {
  34. return
  35. }
  36. currentTime += increment
  37. const val = easeInOutQuad(currentTime, start, change, duration)
  38. move(el, position, val)
  39. if (currentTime < duration && unref(isActiveRef)) {
  40. requestAnimationFrame(animateScroll)
  41. } else {
  42. if (callback) {
  43. callback()
  44. }
  45. }
  46. }
  47. function run() {
  48. isActiveRef.value = true
  49. animateScroll()
  50. }
  51. function stop() {
  52. isActiveRef.value = false
  53. }
  54. return { start: run, stop }
  55. }