|
| 1 | +export default class AutoScroller { |
| 2 | + constructor(container, onScrollCallback) { |
| 3 | + this.container = container; |
| 4 | + this.onScrollCallback = onScrollCallback; |
| 5 | + } |
| 6 | + |
| 7 | + clear() { |
| 8 | + if (this.interval == null) { |
| 9 | + return; |
| 10 | + } |
| 11 | + |
| 12 | + clearInterval(this.interval); |
| 13 | + this.interval = null; |
| 14 | + } |
| 15 | + |
| 16 | + update({translate, minTranslate, maxTranslate, width, height}) { |
| 17 | + const direction = { |
| 18 | + x: 0, |
| 19 | + y: 0, |
| 20 | + }; |
| 21 | + const speed = { |
| 22 | + x: 1, |
| 23 | + y: 1, |
| 24 | + }; |
| 25 | + const acceleration = { |
| 26 | + x: 10, |
| 27 | + y: 10, |
| 28 | + }; |
| 29 | + |
| 30 | + const { |
| 31 | + scrollTop, |
| 32 | + scrollLeft, |
| 33 | + scrollHeight, |
| 34 | + scrollWidth, |
| 35 | + clientHeight, |
| 36 | + clientWidth, |
| 37 | + } = this.container; |
| 38 | + |
| 39 | + const isTop = scrollTop === 0; |
| 40 | + const isBottom = scrollHeight - scrollTop - clientHeight === 0; |
| 41 | + const isLeft = scrollLeft === 0; |
| 42 | + const isRight = scrollWidth - scrollLeft - clientWidth === 0; |
| 43 | + |
| 44 | + if (translate.y >= maxTranslate.y - height / 2 && !isBottom) { |
| 45 | + // Scroll Down |
| 46 | + direction.y = 1; |
| 47 | + speed.y = |
| 48 | + acceleration.y * |
| 49 | + Math.abs((maxTranslate.y - height / 2 - translate.y) / height); |
| 50 | + } else if (translate.x >= maxTranslate.x - width / 2 && !isRight) { |
| 51 | + // Scroll Right |
| 52 | + direction.x = 1; |
| 53 | + speed.x = |
| 54 | + acceleration.x * |
| 55 | + Math.abs((maxTranslate.x - width / 2 - translate.x) / width); |
| 56 | + } else if (translate.y <= minTranslate.y + height / 2 && !isTop) { |
| 57 | + // Scroll Up |
| 58 | + direction.y = -1; |
| 59 | + speed.y = |
| 60 | + acceleration.y * |
| 61 | + Math.abs((translate.y - height / 2 - minTranslate.y) / height); |
| 62 | + } else if (translate.x <= minTranslate.x + width / 2 && !isLeft) { |
| 63 | + // Scroll Left |
| 64 | + direction.x = -1; |
| 65 | + speed.x = |
| 66 | + acceleration.x * |
| 67 | + Math.abs((translate.x - width / 2 - minTranslate.x) / width); |
| 68 | + } |
| 69 | + |
| 70 | + if (this.interval) { |
| 71 | + this.clear(); |
| 72 | + this.isAutoScrolling = false; |
| 73 | + } |
| 74 | + |
| 75 | + if (direction.x !== 0 || direction.y !== 0) { |
| 76 | + this.interval = setInterval(() => { |
| 77 | + this.isAutoScrolling = true; |
| 78 | + const offset = { |
| 79 | + left: speed.x * direction.x, |
| 80 | + top: speed.y * direction.y, |
| 81 | + }; |
| 82 | + this.container.scrollTop += offset.top; |
| 83 | + this.container.scrollLeft += offset.left; |
| 84 | + |
| 85 | + this.onScrollCallback(offset); |
| 86 | + }, 5); |
| 87 | + } |
| 88 | + } |
| 89 | +} |
0 commit comments