mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
114 lines
2.3 KiB
TypeScript
114 lines
2.3 KiB
TypeScript
import {raf} from '../util/dom';
|
|
|
|
|
|
export class ScrollTo {
|
|
|
|
constructor(ele, x, y, duration) {
|
|
if (typeof ele === 'string') {
|
|
// string query selector
|
|
ele = document.querySelector(ele);
|
|
}
|
|
|
|
if (ele) {
|
|
if (ele.nativeElement) {
|
|
// angular ElementRef
|
|
ele = ele.nativeElement;
|
|
}
|
|
|
|
if (ele.nodeType === 1) {
|
|
this._el = ele;
|
|
}
|
|
}
|
|
}
|
|
|
|
start(x, y, duration, tolerance) {
|
|
// scroll animation loop w/ easing
|
|
// credit https://gist.github.com/dezinezync/5487119
|
|
let self = this;
|
|
|
|
if (!self._el) {
|
|
// invalid element
|
|
return Promise.resolve();
|
|
}
|
|
|
|
x = x || 0;
|
|
y = y || 0;
|
|
tolerance = tolerance || 0;
|
|
|
|
let fromY = self._el.scrollTop;
|
|
let fromX = self._el.scrollLeft;
|
|
|
|
let xDistance = Math.abs(x - fromX);
|
|
let yDistance = Math.abs(y - fromY);
|
|
|
|
if (yDistance <= tolerance && xDistance <= tolerance) {
|
|
// prevent scrolling if already close to there
|
|
self._el = null;
|
|
return Promise.resolve();
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
let start;
|
|
|
|
// start scroll loop
|
|
self.isPlaying = true;
|
|
|
|
// chill out for a frame first
|
|
raf(() => {
|
|
start = Date.now();
|
|
raf(step);
|
|
});
|
|
|
|
// scroll loop
|
|
function step() {
|
|
if (!self._el) {
|
|
return resolve();
|
|
}
|
|
|
|
let time = Math.min(1, ((Date.now() - start) / duration));
|
|
|
|
// where .5 would be 50% of time on a linear scale easedT gives a
|
|
// fraction based on the easing method
|
|
let easedT = easeOutCubic(time);
|
|
|
|
if (fromY != y) {
|
|
self._el.scrollTop = parseInt((easedT * (y - fromY)) + fromY, 10);
|
|
}
|
|
if (fromX != x) {
|
|
self._el.scrollLeft = parseInt((easedT * (x - fromX)) + fromX, 10);
|
|
}
|
|
|
|
if (time < 1 && self.isPlaying) {
|
|
raf(step);
|
|
|
|
} else if (!self.isPlaying) {
|
|
// stopped
|
|
self._el = null;
|
|
reject();
|
|
|
|
} else {
|
|
// done
|
|
self._el = null;
|
|
resolve();
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
stop() {
|
|
this.isPlaying = false;
|
|
}
|
|
|
|
dispose() {
|
|
this.stop();
|
|
this._el = null;
|
|
}
|
|
|
|
}
|
|
|
|
// decelerating to zero velocity
|
|
function easeOutCubic(t) {
|
|
return (--t) * t * t + 1;
|
|
}
|