UNPKG

easyscroller

Version:

Mobile-friendly accelerated panning and zooming for DOM and Canvas based on Zynga Scroller.

179 lines (178 loc) 8 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); var Scroller_1 = require("./Scroller"); var EasyScroller = /** @class */ (function () { function EasyScroller(content, options) { var _this = this; this.options = {}; this.browserHasPerspectiveProperty = false; this.browserHasTransformProperty = true; this.eventHandlers = []; if (!content) { throw new Error('No Content Element specified!'); } this.content = content; this.container = content.parentNode; if (!this.container) { throw new Error('No Parent Container for Content! Please wrap Content Element in a Container.'); } this.options = __assign({}, this.options, options); this.scroller = new Scroller_1.Scroller(function (left, top, zoom) { _this.render(left, top, zoom); }, options); var helperElem = document.createElement('div'); var vendorPrefix = this.getVendorPrefix(); // the content element needs a correct transform origin for zooming this.content.style[vendorPrefix + "TransformOrigin"] = 'left top'; this.transformProperty = vendorPrefix + "Transform"; this.browserHasTransformProperty = helperElem.style[this.transformProperty] !== undefined; var perspectiveProperty = vendorPrefix + "Perspective"; this.browserHasPerspectiveProperty = helperElem.style[perspectiveProperty] !== undefined; this.bindEvents(); // reflow for the first time this.reflow(); } EasyScroller.prototype.getVendorPrefix = function () { var docStyle = document.documentElement.style; var engine; if (window.opera && Object.prototype.toString.call(window.opera) === '[object Opera]') { engine = 'presto'; } else if ('MozAppearance' in docStyle) { engine = 'gecko'; } else if ('WebkitAppearance' in docStyle) { engine = 'webkit'; } else if (typeof navigator.cpuClass === 'string') { engine = 'trident'; } var vendorMap = { trident: 'ms', gecko: 'Moz', webkit: 'Webkit', presto: 'O', }; return vendorMap[engine]; }; EasyScroller.prototype.render = function (left, top, zoom) { if (this.browserHasPerspectiveProperty) { this.content.style[this.transformProperty] = 'translate3d(' + -left + 'px,' + -top + 'px,0) scale(' + zoom + ')'; } else if (this.browserHasTransformProperty) { this.content.style[this.transformProperty] = 'translate(' + -left + 'px,' + -top + 'px) scale(' + zoom + ')'; } else { this.content.style.marginLeft = left ? -left / zoom + 'px' : ''; this.content.style.marginTop = top ? -top / zoom + 'px' : ''; this.content.style.zoom = zoom || ''; } }; EasyScroller.prototype.reflow = function () { // set the right scroller dimensions this.scroller.setDimensions(this.container.clientWidth, this.container.clientHeight, this.content.offsetWidth, this.content.offsetHeight); // refresh the position for zooming purposes var rect = this.container.getBoundingClientRect(); this.scroller.setPosition(rect.left + this.container.clientLeft, rect.top + this.container.clientTop); }; EasyScroller.prototype.bindEvents = function () { var _this = this; var resizeHandler = function () { return _this.reflow(); }; // reflow handling this.eventHandlers.push({ event: 'resize', handler: resizeHandler, forElem: window }); // touch devices bind touch events if ('ontouchstart' in window) { var touchstartHandler = function (e) { // Don't react if initial down happens on a form element if (e.touches[0] && e.touches[0].target && e.touches[0].target.tagName.match(/input|textarea|select/i)) { return; } // reflow since the container may have changed _this.reflow(); _this.scroller.doTouchStart(e.touches, e.timeStamp); }; var touchmoveHandler = function (e) { e.preventDefault(); _this.scroller.doTouchMove(e.touches, e.timeStamp, e.scale); }; var touchendHandler = function (e) { return _this.scroller.doTouchEnd(e.timeStamp); }; var touchcancelHandler = function (e) { return _this.scroller.doTouchEnd(e.timeStamp); }; this.eventHandlers.push({ event: 'touchstart', handler: touchstartHandler, forElem: this.container }, { event: 'touchmove', handler: touchmoveHandler, forElem: this.container }, { event: 'touchend', handler: touchendHandler, forElem: this.container }, { event: 'touchcancel', handler: touchcancelHandler, forElem: this.container }); } else { // non-touch bind mouse events var mousedown = false; var mousedownHandler = function (e) { if (e.target.tagName.match(/input|textarea|select/i)) { return; } _this.scroller.doTouchStart([ { pageX: e.pageX, pageY: e.pageY, }, ], e.timeStamp); mousedown = true; // reflow since the container may have changed _this.reflow(); e.preventDefault(); }; var mousemoveHandler = function (e) { if (!mousedown) { return; } _this.scroller.doTouchMove([ { pageX: e.pageX, pageY: e.pageY, }, ], e.timeStamp); mousedown = true; }; var mouseupHandler = function (e) { if (!mousedown) { return; } _this.scroller.doTouchEnd(e.timeStamp); mousedown = false; }; var mousewheelHandler = function (e) { if (_this.options.zooming) { _this.scroller.doMouseZoom(e.wheelDelta, e.timeStamp, e.pageX, e.pageY); e.preventDefault(); } }; this.eventHandlers.push({ event: 'mousedown', handler: mousedownHandler, forElem: this.container }, { event: 'mousemove', handler: mousemoveHandler, forElem: document }, { event: 'mouseup', handler: mouseupHandler, forElem: document }, { event: 'mousewheel', handler: mousewheelHandler, forElem: this.container }); } return this.eventHandlers.forEach(function (eventHandler) { eventHandler.forElem.addEventListener(eventHandler.event, eventHandler.handler, false); }); }; /** * Retrieves Scroller instance. */ EasyScroller.prototype.getScroller = function () { return this.scroller; }; /** * Call on disposal of EasyScroller to clean up Event Handlers. */ EasyScroller.prototype.destroy = function () { return this.eventHandlers.forEach(function (eventHandler) { eventHandler.forElem.removeEventListener(eventHandler.event, eventHandler.handler, false); }); }; return EasyScroller; }()); exports.EasyScroller = EasyScroller;