UNPKG

3.81 kBJavaScriptView Raw
1const raf = require('./utils/raf');
2const getWindow = require('./utils/window').getWindow;
3const is = require('./utils/is');
4const domUtils = require('./utils/domUtils');
5const Interaction = require('./Interaction');
6const defaultOptions = require('./defaultOptions');
7
8const autoScroll = {
9 defaults: {
10 enabled : false,
11 container: null, // the item that is scrolled (Window or HTMLElement)
12 margin : 60,
13 speed : 300, // the scroll speed in pixels per second
14 },
15
16 interaction: null,
17 i: null, // the handle returned by window.setInterval
18 x: 0, y: 0, // Direction each pulse is to scroll in
19
20 isScrolling: false,
21 prevTime: 0,
22
23 start: function (interaction) {
24 autoScroll.isScrolling = true;
25 raf.cancel(autoScroll.i);
26
27 autoScroll.interaction = interaction;
28 autoScroll.prevTime = new Date().getTime();
29 autoScroll.i = raf.request(autoScroll.scroll);
30 },
31
32 stop: function () {
33 autoScroll.isScrolling = false;
34 raf.cancel(autoScroll.i);
35 },
36
37 // scroll the window by the values in scroll.x/y
38 scroll: function () {
39 const options = autoScroll.interaction.target.options[autoScroll.interaction.prepared.name].autoScroll;
40 const container = options.container || getWindow(autoScroll.interaction.element);
41 const now = new Date().getTime();
42 // change in time in seconds
43 const dt = (now - autoScroll.prevTime) / 1000;
44 // displacement
45 const s = options.speed * dt;
46
47 if (s >= 1) {
48 if (is.window(container)) {
49 container.scrollBy(autoScroll.x * s, autoScroll.y * s);
50 }
51 else if (container) {
52 container.scrollLeft += autoScroll.x * s;
53 container.scrollTop += autoScroll.y * s;
54 }
55
56 autoScroll.prevTime = now;
57 }
58
59 if (autoScroll.isScrolling) {
60 raf.cancel(autoScroll.i);
61 autoScroll.i = raf.request(autoScroll.scroll);
62 }
63 },
64 check: function (interactable, actionName) {
65 const options = interactable.options;
66
67 return options[actionName].autoScroll && options[actionName].autoScroll.enabled;
68 },
69 onInteractionMove: function ({ interaction, pointer }) {
70 if (!(interaction.interacting()
71 && autoScroll.check(interaction.target, interaction.prepared.name))) {
72 return;
73 }
74
75 if (interaction.simulation) {
76 autoScroll.x = autoScroll.y = 0;
77 return;
78 }
79
80 let top;
81 let right;
82 let bottom;
83 let left;
84
85 const options = interaction.target.options[interaction.prepared.name].autoScroll;
86 const container = options.container || getWindow(interaction.element);
87
88 if (is.window(container)) {
89 left = pointer.clientX < autoScroll.margin;
90 top = pointer.clientY < autoScroll.margin;
91 right = pointer.clientX > container.innerWidth - autoScroll.margin;
92 bottom = pointer.clientY > container.innerHeight - autoScroll.margin;
93 }
94 else {
95 const rect = domUtils.getElementClientRect(container);
96
97 left = pointer.clientX < rect.left + autoScroll.margin;
98 top = pointer.clientY < rect.top + autoScroll.margin;
99 right = pointer.clientX > rect.right - autoScroll.margin;
100 bottom = pointer.clientY > rect.bottom - autoScroll.margin;
101 }
102
103 autoScroll.x = (right ? 1: left? -1: 0);
104 autoScroll.y = (bottom? 1: top? -1: 0);
105
106 if (!autoScroll.isScrolling) {
107 // set the autoScroll properties to those of the target
108 autoScroll.margin = options.margin;
109 autoScroll.speed = options.speed;
110
111 autoScroll.start(interaction);
112 }
113 },
114};
115
116Interaction.signals.on('stop-active', function () {
117 autoScroll.stop();
118});
119
120Interaction.signals.on('action-move', autoScroll.onInteractionMove);
121
122defaultOptions.perAction.autoScroll = autoScroll.defaults;
123
124module.exports = autoScroll;