0
# Momentum Control
1
2
Advanced momentum control for natural scrolling physics with customizable easing and momentum manipulation. Provides fine-grained control over scroll momentum for creating smooth, physics-based scrolling experiences.
3
4
## Capabilities
5
6
### Basic Momentum Control
7
8
Methods for directly manipulating scroll momentum during scrolling operations.
9
10
```typescript { .api }
11
/**
12
* Adds momentum to current scroll velocity
13
* @param x - Horizontal momentum to add
14
* @param y - Vertical momentum to add
15
*/
16
addMomentum(x: number, y: number): void;
17
18
/**
19
* Sets scroll momentum directly, replacing current momentum
20
* @param x - Horizontal momentum value
21
* @param y - Vertical momentum value
22
*/
23
setMomentum(x: number, y: number): void;
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
// Add momentum for smooth continuation
30
scrollbar.addMomentum(0, 200); // Add downward momentum
31
32
// Stop all momentum immediately
33
scrollbar.setMomentum(0, 0);
34
35
// Set specific momentum for custom scrolling effects
36
scrollbar.setMomentum(50, -100); // Right and up momentum
37
```
38
39
### Transformable Momentum
40
41
Advanced momentum control that allows event-based momentum transformation with callback support.
42
43
```typescript { .api }
44
/**
45
* Adds momentum that can be transformed by plugins, with callback notification
46
* @param x - Horizontal momentum to add
47
* @param y - Vertical momentum to add
48
* @param fromEvent - Source event that generated the momentum
49
* @param callback - Optional callback function called with scroll decision
50
*/
51
addTransformableMomentum(
52
x: number,
53
y: number,
54
fromEvent: Event,
55
callback?: AddTransformableMomentumCallback
56
): void;
57
```
58
59
**Usage Examples:**
60
61
```typescript
62
// Add momentum from custom gesture
63
const customGestureEvent = new CustomEvent("swipe");
64
scrollbar.addTransformableMomentum(0, 300, customGestureEvent, function(willScroll) {
65
if (willScroll) {
66
console.log("Scrolling will occur");
67
// Add visual feedback
68
this.containerEl.classList.add("scrolling");
69
} else {
70
console.log("Scroll was prevented by plugin");
71
}
72
});
73
74
// Custom momentum with mouse wheel simulation
75
const wheelEvent = new WheelEvent("wheel", { deltaY: 120 });
76
scrollbar.addTransformableMomentum(0, 120, wheelEvent, function(willScroll) {
77
// Track scroll analytics
78
analytics.track("custom_scroll", { willScroll, momentum: 120 });
79
});
80
```
81
82
### Momentum Physics Configuration
83
84
Configuration options that affect momentum behavior and physics calculations.
85
86
```typescript { .api }
87
interface ScrollbarOptions {
88
/**
89
* Momentum reduction damping factor, float between (0, 1)
90
* Lower values = more smooth scrolling (more frames)
91
* Higher values = quicker momentum decay
92
*/
93
damping: number;
94
95
/**
96
* Render every frame in integer pixel values
97
* Improves performance by avoiding sub-pixel rendering
98
*/
99
renderByPixels: boolean;
100
101
/**
102
* Allow outer scrollbars to continue scrolling when this reaches edge
103
* Affects momentum transfer to parent scrollable elements
104
*/
105
continuousScrolling: boolean;
106
}
107
```
108
109
**Usage Examples:**
110
111
```typescript
112
// Ultra-smooth momentum (more CPU intensive)
113
const smoothScrollbar = Scrollbar.init(container, {
114
damping: 0.05, // Very low damping for long momentum
115
renderByPixels: false // Sub-pixel rendering for smoothness
116
});
117
118
// Performance-optimized momentum
119
const fastScrollbar = Scrollbar.init(container, {
120
damping: 0.2, // Higher damping for quicker stops
121
renderByPixels: true, // Integer pixels for performance
122
continuousScrolling: false // Contain momentum within this scrollbar
123
});
124
```
125
126
## Advanced Momentum Patterns
127
128
### Custom Momentum Easing
129
130
Creating custom momentum behavior through easing functions and momentum manipulation.
131
132
```typescript
133
// Custom elastic momentum effect
134
function addElasticMomentum(scrollbar, targetY, elasticity = 0.8) {
135
const currentY = scrollbar.scrollTop;
136
const distance = targetY - currentY;
137
138
// Apply elastic easing
139
const momentum = distance * elasticity;
140
141
scrollbar.addTransformableMomentum(0, momentum, new Event("custom"), function(willScroll) {
142
if (willScroll && Math.abs(distance) > 1) {
143
// Continue elastic animation
144
setTimeout(() => {
145
addElasticMomentum(scrollbar, targetY, elasticity * 0.9);
146
}, 16);
147
}
148
});
149
}
150
151
// Usage
152
addElasticMomentum(scrollbar, 500);
153
```
154
155
### Momentum-Based Gestures
156
157
Implementing swipe gestures and momentum-based interactions.
158
159
```typescript
160
class SwipeGestureHandler {
161
private startY = 0;
162
private lastY = 0;
163
private velocity = 0;
164
private lastTime = 0;
165
166
constructor(private scrollbar: Scrollbar) {
167
this.setupGestureListeners();
168
}
169
170
private setupGestureListeners() {
171
const container = this.scrollbar.containerEl;
172
173
container.addEventListener("touchstart", (e) => {
174
this.startY = e.touches[0].clientY;
175
this.lastY = this.startY;
176
this.velocity = 0;
177
this.lastTime = Date.now();
178
});
179
180
container.addEventListener("touchmove", (e) => {
181
const currentY = e.touches[0].clientY;
182
const currentTime = Date.now();
183
const deltaTime = currentTime - this.lastTime;
184
185
if (deltaTime > 0) {
186
this.velocity = (currentY - this.lastY) / deltaTime;
187
}
188
189
this.lastY = currentY;
190
this.lastTime = currentTime;
191
});
192
193
container.addEventListener("touchend", (e) => {
194
// Convert velocity to momentum
195
const momentum = this.velocity * 300; // Scale factor
196
197
this.scrollbar.addTransformableMomentum(0, -momentum, e, function(willScroll) {
198
if (willScroll) {
199
// Add momentum-based visual feedback
200
this.containerEl.style.transition = "transform 0.1s ease-out";
201
this.containerEl.style.transform = `translateY(${momentum > 0 ? -2 : 2}px)`;
202
203
setTimeout(() => {
204
this.containerEl.style.transform = "";
205
this.containerEl.style.transition = "";
206
}, 100);
207
}
208
});
209
});
210
}
211
}
212
213
// Usage
214
const gestureHandler = new SwipeGestureHandler(scrollbar);
215
```
216
217
### Momentum Monitoring
218
219
Tracking and analyzing momentum for performance optimization and user experience.
220
221
```typescript
222
class MomentumMonitor {
223
private momentumHistory: Array<{time: number, momentum: Data2d}> = [];
224
225
constructor(private scrollbar: Scrollbar) {
226
this.setupMonitoring();
227
}
228
229
private setupMonitoring() {
230
// Override addMomentum to track all momentum changes
231
const originalAddMomentum = this.scrollbar.addMomentum.bind(this.scrollbar);
232
233
this.scrollbar.addMomentum = (x: number, y: number) => {
234
this.recordMomentum(x, y);
235
return originalAddMomentum(x, y);
236
};
237
}
238
239
private recordMomentum(x: number, y: number) {
240
this.momentumHistory.push({
241
time: Date.now(),
242
momentum: { x, y }
243
});
244
245
// Keep only recent history
246
if (this.momentumHistory.length > 100) {
247
this.momentumHistory.shift();
248
}
249
}
250
251
getMomentumStats() {
252
if (this.momentumHistory.length === 0) return null;
253
254
const totalMagnitude = this.momentumHistory.reduce((sum, entry) => {
255
return sum + Math.sqrt(entry.momentum.x ** 2 + entry.momentum.y ** 2);
256
}, 0);
257
258
return {
259
averageMagnitude: totalMagnitude / this.momentumHistory.length,
260
peakMomentum: this.momentumHistory.reduce((max, entry) => {
261
const magnitude = Math.sqrt(entry.momentum.x ** 2 + entry.momentum.y ** 2);
262
return Math.max(max, magnitude);
263
}, 0),
264
momentumEvents: this.momentumHistory.length
265
};
266
}
267
}
268
269
// Usage
270
const monitor = new MomentumMonitor(scrollbar);
271
272
// Later, get performance insights
273
setInterval(() => {
274
const stats = monitor.getMomentumStats();
275
console.log("Momentum stats:", stats);
276
}, 5000);
277
```
278
279
## Momentum Callback Types
280
281
```typescript { .api }
282
interface AddTransformableMomentumCallback {
283
/**
284
* Callback function called after momentum transformation
285
* @param willScroll - Whether scrolling will actually occur after transformation
286
*/
287
(this: Scrollbar, willScroll: boolean): void;
288
}
289
290
interface Data2d {
291
/** Horizontal component */
292
x: number;
293
294
/** Vertical component */
295
y: number;
296
}
297
```