vimo-dt
Version:
A Vue2.x UI Project For Mobile & HyBrid
368 lines (294 loc) • 10.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _registerListener = require('.//register-listener');
var _registerListener2 = _interopRequireDefault(_registerListener);
var _type = require('./type');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var SCROLL_END_DEBOUNCE_MS = 80;
var FRAME_MS = 1000 / 60;
var EVENT_OPTS = { passive: true };
var ScrollView = function () {
function ScrollView() {
_classCallCheck(this, ScrollView);
this.isScrolling = false;
this.initialized = false;
this.scrollStart = function (ev) {};
this.scroll = function (ev) {};
this.scrollEnd = function (ev) {};
this.transform = window.VM && window.VM.platform && window.VM.platform.css.transform;
this._el = null;
this._evel = null;
this._lsn = null;
this._endTmr = null;
this.ev = {
timeStamp: 0,
scrollLeft: 0,
scrollTop: 0,
scrollHeight: 0,
scrollWidth: 0,
contentHeight: 0,
contentWidth: 0,
contentTop: 0,
startY: 0,
startX: 0,
deltaY: 0,
deltaX: 0,
velocityY: 0,
velocityX: 0,
directionY: 'down',
directionX: null,
contentElement: null,
fixedElement: null,
scrollElement: null,
headerElement: null,
footerElement: null };
}
_createClass(ScrollView, [{
key: 'init',
value: function init(element) {
var eventElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : element;
if (!this.initialized) {
this.initialized = true;
this._el = element;
this._evel = eventElement;
this.ev.scrollHeight = this._el.scrollHeight;
this.ev.scrollWidth = this._el.scrollWidth;
this.enableNativeScrolling();
}
}
}, {
key: 'enableNativeScrolling',
value: function enableNativeScrolling() {
var self = this;
var ev = self.ev;
var positions = [];
function scrollCallback(scrollEvent) {
ev.timeStamp = scrollEvent.timeStamp;
ev.scrollTop = self.getTop();
ev.scrollLeft = self.getLeft();
ev.scrollHeight = self.getHeight();
ev.scrollWidth = self.getWidth();
if (!self.isScrolling) {
self.isScrolling = true;
ev.startY = ev.scrollTop;
ev.startX = ev.scrollLeft;
ev.velocityY = ev.velocityX = 0;
ev.deltaY = ev.deltaX = 0;
positions.length = 0;
self.scrollStart(ev);
}
positions.push(ev.scrollTop, ev.scrollLeft, ev.timeStamp);
if (positions.length > 3) {
ev.deltaY = ev.scrollTop - ev.startY;
ev.deltaX = ev.scrollLeft - ev.startX;
var endPos = positions.length - 1;
var startPos = endPos;
var timeRange = ev.timeStamp - 100;
for (var i = endPos; i > 0 && positions[i] > timeRange; i -= 3) {
startPos = i;
}
if (startPos !== endPos) {
var timeOffset = positions[endPos] - positions[startPos];
var movedTop = positions[startPos - 2] - positions[endPos - 2];
var movedLeft = positions[startPos - 1] - positions[endPos - 1];
ev.velocityY = movedTop / timeOffset * FRAME_MS;
ev.velocityX = movedLeft / timeOffset * FRAME_MS;
ev.directionY = movedTop > 0 ? 'up' : 'down';
ev.directionX = movedLeft > 0 ? 'left' : 'right';
}
}
function scrollEnd() {
self.isScrolling = false;
ev.velocityY = ev.velocityX = 0;
self.scrollEnd(ev);
self._endTmr = null;
}
self.scroll(ev);
window.clearTimeout(self._endTmr);
self._endTmr = window.setTimeout(scrollEnd, SCROLL_END_DEBOUNCE_MS);
}
self._lsn && self._lsn();
self._lsn = (0, _registerListener2.default)(this._evel, 'scroll', scrollCallback, EVENT_OPTS);
}
}, {
key: 'getHeight',
value: function getHeight() {
return this._el.scrollHeight;
}
}, {
key: 'getWidth',
value: function getWidth() {
return this._el.scrollWidth;
}
}, {
key: 'getTop',
value: function getTop() {
if (this._evel === window) {
return window.scrollY;
} else {
return this._el.scrollTop;
}
}
}, {
key: 'getLeft',
value: function getLeft() {
return this._el.scrollLeft;
}
}, {
key: 'setTop',
value: function setTop(top) {
if (this._evel === window) {
return window.scrollTo(0, top);
} else {
this._el.scrollTop = top;
}
}
}, {
key: 'setLeft',
value: function setLeft(left) {
this._el.scrollLeft = left;
}
}, {
key: 'stop',
value: function stop() {
this.isScrolling = false;
}
}, {
key: 'destroy',
value: function destroy() {
this.stop();
this.initialized = false;
this._endTmr && window.clearTimeout(this._endTmr);
this._lsn && this._lsn();
this._lsn = null;
var ev = this.ev;
ev.contentElement = ev.fixedElement = ev.scrollElement = ev.headerElement = {};
this._el = this.ev = ev = null;
this.scrollStart && (this.scrollStart = function (ev) {});
this.scroll && (this.scrollStart = function (ev) {});
this.scrollEnd && (this.scrollStart = function (ev) {});
}
}, {
key: 'scrollTo',
value: function scrollTo() {
var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var _this = this;
var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 300;
var done = arguments[3];
var el = this._el;
var promise = void 0;
if (done === undefined) {
promise = new Promise(function (resolve) {
done = resolve;
});
}
if (duration < 32) {
this.setTop(y);
this.setLeft(x);
done();
return promise;
}
var fromY = this.getTop();
var fromX = this.getLeft();
var maxAttempts = duration / 16 + 100;
var transform = this.transform;
var startTime = void 0;
var timeStamp = void 0;
var attempts = 0;
var stopScroll = false;
var step = function step() {
attempts++;
if (stopScroll || attempts > maxAttempts) {
_this.isScrolling = false;
el.style[transform] = '';
done();
return;
}
timeStamp = new Date().getTime();
var time = Math.min(1, (timeStamp - startTime) / duration);
var easedT = --time * time * time + 1;
if (fromY !== y) {
_this.setTop(easedT * (y - fromY) + fromY);
}
if (fromX !== x) {
_this.setLeft(Math.floor(easedT * (x - fromX) + fromX));
}
if (easedT < 1) {
window.requestAnimationFrame(step);
} else {
stopScroll = true;
_this.isScrolling = false;
done();
}
};
this.isScrolling = true;
startTime = new Date().getTime();
window.requestAnimationFrame(step);
return promise;
}
}, {
key: 'scrollToTop',
value: function scrollToTop() {
var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300;
return this.scrollTo(0, 0, duration);
}
}, {
key: 'scrollToBottom',
value: function scrollToBottom() {
var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300;
var y = this.getHeight() - this._el.clientHeight;
return this.scrollTo(0, y, duration);
}
}, {
key: 'scrollBy',
value: function scrollBy() {
var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 300;
var done = arguments[3];
y += this.getTop();
x += this.getLeft();
return this.scrollTo(x, y, duration, done);
}
}, {
key: 'scrollToElement',
value: function scrollToElement(el) {
var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
var offsetX = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var offsetY = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
var done = arguments[4];
if (!el) {
console.assert(el, 'The method scrollToElement() need element!');
return new Promise(function (resolve) {
resolve();
});
}
var x = 0;
var y = el.offsetTop;
if ((0, _type.isPresent)(offsetX)) {
if ((0, _type.isNumber)(offsetX) && offsetX !== 0) {
x = el.offsetLeft + offsetX;
}
if ((0, _type.isBoolean)(offsetX) && offsetX) {
x = el.offsetLeft + (this.ev.contentWidth - el.offsetWidth) / 2;
}
}
if ((0, _type.isPresent)(offsetY)) {
if ((0, _type.isNumber)(offsetY)) {
y -= offsetY;
}
if ((0, _type.isBoolean)(offsetY) && offsetY) {
y -= (window.innerHeight - el.offsetHeight) / 2;
}
}
return this.scrollTo(x, y, duration, done);
}
}]);
return ScrollView;
}();
exports.default = ScrollView;