mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 13:32:54 +08:00
chore(scrollTo): add scroll completed callback as option
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import { CSS, pointerCoord, nativeRaf, cancelRaf } from '../util/dom';
|
import { CSS, pointerCoord, nativeRaf, rafFrames, cancelRaf } from '../util/dom';
|
||||||
|
|
||||||
|
|
||||||
export class ScrollView {
|
export class ScrollView {
|
||||||
@ -35,71 +35,82 @@ export class ScrollView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollTo(x: number, y: number, duration: number): Promise<any> {
|
scrollTo(x: number, y: number, duration: number, done?: Function): Promise<any> {
|
||||||
// scroll animation loop w/ easing
|
// scroll animation loop w/ easing
|
||||||
// credit https://gist.github.com/dezinezync/5487119
|
// credit https://gist.github.com/dezinezync/5487119
|
||||||
let self = this;
|
|
||||||
|
|
||||||
|
let promise: Promise<any>;
|
||||||
|
if (done === undefined) {
|
||||||
|
// only create a promise if a done callback wasn't provided
|
||||||
|
// done can be a null, which avoids any functions
|
||||||
|
promise = new Promise((res, rej) => {
|
||||||
|
done = res;
|
||||||
|
done = rej;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const self = this;
|
||||||
if (!self._el) {
|
if (!self._el) {
|
||||||
// invalid element
|
// invalid element
|
||||||
return Promise.resolve();
|
done();
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = x || 0;
|
x = x || 0;
|
||||||
y = y || 0;
|
y = y || 0;
|
||||||
|
|
||||||
let fromY = self._el.scrollTop;
|
const fromY = self._el.scrollTop;
|
||||||
let fromX = self._el.scrollLeft;
|
const fromX = self._el.scrollLeft;
|
||||||
|
|
||||||
let maxAttempts = (duration / 16) + 100;
|
const maxAttempts = (duration / 16) + 100;
|
||||||
|
|
||||||
return new Promise(resolve => {
|
let startTime: number;
|
||||||
let startTime: number;
|
let attempts = 0;
|
||||||
let attempts = 0;
|
|
||||||
|
|
||||||
// scroll loop
|
// scroll loop
|
||||||
function step() {
|
function step() {
|
||||||
attempts++;
|
attempts++;
|
||||||
|
|
||||||
if (!self._el || !self.isPlaying || attempts > maxAttempts) {
|
if (!self._el || !self.isPlaying || attempts > maxAttempts) {
|
||||||
self.isPlaying = false;
|
self.isPlaying = false;
|
||||||
resolve();
|
self._el.style.transform = ``;
|
||||||
return;
|
done();
|
||||||
}
|
return;
|
||||||
|
|
||||||
let time = Math.min(1, ((Date.now() - startTime) / duration));
|
|
||||||
|
|
||||||
// where .5 would be 50% of time on a linear scale easedT gives a
|
|
||||||
// fraction based on the easing method
|
|
||||||
let easedT = (--time) * time * time + 1;
|
|
||||||
|
|
||||||
if (fromY !== y) {
|
|
||||||
self.setTop((easedT * (y - fromY)) + fromY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fromX !== x) {
|
|
||||||
self._el.scrollLeft = Math.floor((easedT * (x - fromX)) + fromX);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (easedT < 1) {
|
|
||||||
nativeRaf(step);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// done
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// start scroll loop
|
let time = Math.min(1, ((Date.now() - startTime) / duration));
|
||||||
self.isPlaying = true;
|
|
||||||
|
|
||||||
// chill out for a frame first
|
// where .5 would be 50% of time on a linear scale easedT gives a
|
||||||
nativeRaf(() => {
|
// fraction based on the easing method
|
||||||
startTime = Date.now();
|
let easedT = (--time) * time * time + 1;
|
||||||
|
|
||||||
|
if (fromY !== y) {
|
||||||
|
self.setTop((easedT * (y - fromY)) + fromY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromX !== x) {
|
||||||
|
self._el.scrollLeft = Math.floor((easedT * (x - fromX)) + fromX);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (easedT < 1) {
|
||||||
nativeRaf(step);
|
nativeRaf(step);
|
||||||
});
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
self._el.style.transform = ``;
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start scroll loop
|
||||||
|
self.isPlaying = true;
|
||||||
|
|
||||||
|
// chill out for a frame first
|
||||||
|
rafFrames(2, () => {
|
||||||
|
startTime = Date.now();
|
||||||
|
step();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollToTop(duration: number): Promise<any> {
|
scrollToTop(duration: number): Promise<any> {
|
||||||
|
Reference in New Issue
Block a user