UNPKG

vimo-dt

Version:

A Vue2.x UI Project For Mobile & HyBrid

368 lines (294 loc) 10.3 kB
'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;