UNPKG

deck.gl

Version:

A suite of 3D-enabled data visualization overlays, suitable for react-map-gl

1,280 lines (1,278 loc) 2.42 MB
(function webpackUniversalModuleDefinition(root, factory) { if (typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if (typeof define === 'function' && define.amd) define([], factory); else if (typeof exports === 'object') exports['deck'] = factory(); else root['deck'] = factory();})(globalThis, function () { "use strict"; var __exports__ = (() => { var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __require = /* @__PURE__ */ ((x2) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x2, { get: (a2, b) => (typeof require !== "undefined" ? require : a2)[b] }) : x2)(function(x2) { if (typeof require !== "undefined") return require.apply(this, arguments); throw new Error('Dynamic require of "' + x2 + '" is not supported'); }); var __commonJS = (cb, mod3) => function __require2() { return mod3 || (0, cb[__getOwnPropNames(cb)[0]])((mod3 = { exports: {} }).exports, mod3), mod3.exports; }; var __export = (target, all) => { for (var name10 in all) __defProp(target, name10, { get: all[name10], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod3, isNodeMode, target) => (target = mod3 != null ? __create(__getProtoOf(mod3)) : {}, __copyProps( isNodeMode || !mod3 || !mod3.__esModule ? __defProp(target, "default", { value: mod3, enumerable: true }) : target, mod3 )); var __toCommonJS = (mod3) => __copyProps(__defProp({}, "__esModule", { value: true }), mod3); var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; // (disabled):../../node_modules/@loaders.gl/worker-utils/dist/esm/lib/node/require-utils.node var require_require_utils = __commonJS({ "(disabled):../../node_modules/@loaders.gl/worker-utils/dist/esm/lib/node/require-utils.node"() { } }); // ../../node_modules/hammerjs/hammer.js var require_hammer = __commonJS({ "../../node_modules/hammerjs/hammer.js"(exports, module2) { (function(window3, document2, exportName, undefined2) { "use strict"; var VENDOR_PREFIXES = ["", "webkit", "Moz", "MS", "ms", "o"]; var TEST_ELEMENT = document2.createElement("div"); var TYPE_FUNCTION = "function"; var round2 = Math.round; var abs = Math.abs; var now = Date.now; function setTimeoutContext(fn, timeout, context) { return setTimeout(bindFn(fn, context), timeout); } function invokeArrayArg(arg, fn, context) { if (Array.isArray(arg)) { each(arg, context[fn], context); return true; } return false; } function each(obj, iterator, context) { var i3; if (!obj) { return; } if (obj.forEach) { obj.forEach(iterator, context); } else if (obj.length !== undefined2) { i3 = 0; while (i3 < obj.length) { iterator.call(context, obj[i3], i3, obj); i3++; } } else { for (i3 in obj) { obj.hasOwnProperty(i3) && iterator.call(context, obj[i3], i3, obj); } } } function deprecate(method, name10, message) { var deprecationMessage = "DEPRECATED METHOD: " + name10 + "\n" + message + " AT \n"; return function() { var e2 = new Error("get-stack-trace"); var stack2 = e2 && e2.stack ? e2.stack.replace(/^[^\(]+?[\n$]/gm, "").replace(/^\s+at\s+/gm, "").replace(/^Object.<anonymous>\s*\(/gm, "{anonymous}()@") : "Unknown Stack Trace"; var log4 = window3.console && (window3.console.warn || window3.console.log); if (log4) { log4.call(window3.console, deprecationMessage, stack2); } return method.apply(this, arguments); }; } var assign; if (typeof Object.assign !== "function") { assign = function assign2(target) { if (target === undefined2 || target === null) { throw new TypeError("Cannot convert undefined or null to object"); } var output = Object(target); for (var index = 1; index < arguments.length; index++) { var source = arguments[index]; if (source !== undefined2 && source !== null) { for (var nextKey in source) { if (source.hasOwnProperty(nextKey)) { output[nextKey] = source[nextKey]; } } } } return output; }; } else { assign = Object.assign; } var extend = deprecate(function extend2(dest, src, merge2) { var keys = Object.keys(src); var i3 = 0; while (i3 < keys.length) { if (!merge2 || merge2 && dest[keys[i3]] === undefined2) { dest[keys[i3]] = src[keys[i3]]; } i3++; } return dest; }, "extend", "Use `assign`."); var merge = deprecate(function merge2(dest, src) { return extend(dest, src, true); }, "merge", "Use `assign`."); function inherit(child, base, properties) { var baseP = base.prototype, childP; childP = child.prototype = Object.create(baseP); childP.constructor = child; childP._super = baseP; if (properties) { assign(childP, properties); } } function bindFn(fn, context) { return function boundFn() { return fn.apply(context, arguments); }; } function boolOrFn(val2, args) { if (typeof val2 == TYPE_FUNCTION) { return val2.apply(args ? args[0] || undefined2 : undefined2, args); } return val2; } function ifUndefined(val1, val2) { return val1 === undefined2 ? val2 : val1; } function addEventListeners(target, types, handler) { each(splitStr(types), function(type) { target.addEventListener(type, handler, false); }); } function removeEventListeners(target, types, handler) { each(splitStr(types), function(type) { target.removeEventListener(type, handler, false); }); } function hasParent(node2, parent) { while (node2) { if (node2 == parent) { return true; } node2 = node2.parentNode; } return false; } function inStr(str, find) { return str.indexOf(find) > -1; } function splitStr(str) { return str.trim().split(/\s+/g); } function inArray(src, find, findByKey) { if (src.indexOf && !findByKey) { return src.indexOf(find); } else { var i3 = 0; while (i3 < src.length) { if (findByKey && src[i3][findByKey] == find || !findByKey && src[i3] === find) { return i3; } i3++; } return -1; } } function toArray(obj) { return Array.prototype.slice.call(obj, 0); } function uniqueArray(src, key, sort) { var results = []; var values = []; var i3 = 0; while (i3 < src.length) { var val2 = key ? src[i3][key] : src[i3]; if (inArray(values, val2) < 0) { results.push(src[i3]); } values[i3] = val2; i3++; } if (sort) { if (!key) { results = results.sort(); } else { results = results.sort(function sortUniqueArray(a2, b) { return a2[key] > b[key]; }); } } return results; } function prefixed(obj, property) { var prefix, prop; var camelProp = property[0].toUpperCase() + property.slice(1); var i3 = 0; while (i3 < VENDOR_PREFIXES.length) { prefix = VENDOR_PREFIXES[i3]; prop = prefix ? prefix + camelProp : property; if (prop in obj) { return prop; } i3++; } return undefined2; } var _uniqueId = 1; function uniqueId() { return _uniqueId++; } function getWindowForElement(element) { var doc = element.ownerDocument || element; return doc.defaultView || doc.parentWindow || window3; } var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; var SUPPORT_TOUCH = "ontouchstart" in window3; var SUPPORT_POINTER_EVENTS = prefixed(window3, "PointerEvent") !== undefined2; var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); var INPUT_TYPE_TOUCH = "touch"; var INPUT_TYPE_PEN = "pen"; var INPUT_TYPE_MOUSE = "mouse"; var INPUT_TYPE_KINECT = "kinect"; var COMPUTE_INTERVAL = 25; var INPUT_START2 = 1; var INPUT_MOVE2 = 2; var INPUT_END2 = 4; var INPUT_CANCEL = 8; var DIRECTION_NONE = 1; var DIRECTION_LEFT = 2; var DIRECTION_RIGHT = 4; var DIRECTION_UP = 8; var DIRECTION_DOWN = 16; var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; var PROPS_XY = ["x", "y"]; var PROPS_CLIENT_XY = ["clientX", "clientY"]; function Input2(manager, callback) { var self2 = this; this.manager = manager; this.callback = callback; this.element = manager.element; this.target = manager.options.inputTarget; this.domHandler = function(ev) { if (boolOrFn(manager.options.enable, [manager])) { self2.handler(ev); } }; this.init(); } Input2.prototype = { handler: function() { }, init: function() { this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); }, destroy: function() { this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); } }; function createInputInstance(manager) { var Type2; var inputClass = manager.options.inputClass; if (inputClass) { Type2 = inputClass; } else if (SUPPORT_POINTER_EVENTS) { Type2 = PointerEventInput; } else if (SUPPORT_ONLY_TOUCH) { Type2 = TouchInput; } else if (!SUPPORT_TOUCH) { Type2 = MouseInput; } else { Type2 = TouchMouseInput; } return new Type2(manager, inputHandler); } function inputHandler(manager, eventType, input) { var pointersLen = input.pointers.length; var changedPointersLen = input.changedPointers.length; var isFirst = eventType & INPUT_START2 && pointersLen - changedPointersLen === 0; var isFinal = eventType & (INPUT_END2 | INPUT_CANCEL) && pointersLen - changedPointersLen === 0; input.isFirst = !!isFirst; input.isFinal = !!isFinal; if (isFirst) { manager.session = {}; } input.eventType = eventType; computeInputData(manager, input); manager.emit("hammer.input", input); manager.recognize(input); manager.session.prevInput = input; } function computeInputData(manager, input) { var session = manager.session; var pointers = input.pointers; var pointersLength = pointers.length; if (!session.firstInput) { session.firstInput = simpleCloneInputData(input); } if (pointersLength > 1 && !session.firstMultiple) { session.firstMultiple = simpleCloneInputData(input); } else if (pointersLength === 1) { session.firstMultiple = false; } var firstInput = session.firstInput; var firstMultiple = session.firstMultiple; var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; var center = input.center = getCenter(pointers); input.timeStamp = now(); input.deltaTime = input.timeStamp - firstInput.timeStamp; input.angle = getAngle(offsetCenter, center); input.distance = getDistance(offsetCenter, center); computeDeltaXY(session, input); input.offsetDirection = getDirection(input.deltaX, input.deltaY); var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); input.overallVelocityX = overallVelocity.x; input.overallVelocityY = overallVelocity.y; input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y; input.scale = firstMultiple ? getScale3(firstMultiple.pointers, pointers) : 1; input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers; computeIntervalInputData(session, input); var target = manager.element; if (hasParent(input.srcEvent.target, target)) { target = input.srcEvent.target; } input.target = target; } function computeDeltaXY(session, input) { var center = input.center; var offset = session.offsetDelta || {}; var prevDelta = session.prevDelta || {}; var prevInput = session.prevInput || {}; if (input.eventType === INPUT_START2 || prevInput.eventType === INPUT_END2) { prevDelta = session.prevDelta = { x: prevInput.deltaX || 0, y: prevInput.deltaY || 0 }; offset = session.offsetDelta = { x: center.x, y: center.y }; } input.deltaX = prevDelta.x + (center.x - offset.x); input.deltaY = prevDelta.y + (center.y - offset.y); } function computeIntervalInputData(session, input) { var last = session.lastInterval || input, deltaTime = input.timeStamp - last.timeStamp, velocity, velocityX, velocityY, direction; if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined2)) { var deltaX = input.deltaX - last.deltaX; var deltaY = input.deltaY - last.deltaY; var v = getVelocity(deltaTime, deltaX, deltaY); velocityX = v.x; velocityY = v.y; velocity = abs(v.x) > abs(v.y) ? v.x : v.y; direction = getDirection(deltaX, deltaY); session.lastInterval = input; } else { velocity = last.velocity; velocityX = last.velocityX; velocityY = last.velocityY; direction = last.direction; } input.velocity = velocity; input.velocityX = velocityX; input.velocityY = velocityY; input.direction = direction; } function simpleCloneInputData(input) { var pointers = []; var i3 = 0; while (i3 < input.pointers.length) { pointers[i3] = { clientX: round2(input.pointers[i3].clientX), clientY: round2(input.pointers[i3].clientY) }; i3++; } return { timeStamp: now(), pointers, center: getCenter(pointers), deltaX: input.deltaX, deltaY: input.deltaY }; } function getCenter(pointers) { var pointersLength = pointers.length; if (pointersLength === 1) { return { x: round2(pointers[0].clientX), y: round2(pointers[0].clientY) }; } var x2 = 0, y2 = 0, i3 = 0; while (i3 < pointersLength) { x2 += pointers[i3].clientX; y2 += pointers[i3].clientY; i3++; } return { x: round2(x2 / pointersLength), y: round2(y2 / pointersLength) }; } function getVelocity(deltaTime, x2, y2) { return { x: x2 / deltaTime || 0, y: y2 / deltaTime || 0 }; } function getDirection(x2, y2) { if (x2 === y2) { return DIRECTION_NONE; } if (abs(x2) >= abs(y2)) { return x2 < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; } return y2 < 0 ? DIRECTION_UP : DIRECTION_DOWN; } function getDistance(p1, p2, props) { if (!props) { props = PROPS_XY; } var x2 = p2[props[0]] - p1[props[0]], y2 = p2[props[1]] - p1[props[1]]; return Math.sqrt(x2 * x2 + y2 * y2); } function getAngle(p1, p2, props) { if (!props) { props = PROPS_XY; } var x2 = p2[props[0]] - p1[props[0]], y2 = p2[props[1]] - p1[props[1]]; return Math.atan2(y2, x2) * 180 / Math.PI; } function getRotation(start, end) { return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); } function getScale3(start, end) { return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); } var MOUSE_INPUT_MAP2 = { mousedown: INPUT_START2, mousemove: INPUT_MOVE2, mouseup: INPUT_END2 }; var MOUSE_ELEMENT_EVENTS = "mousedown"; var MOUSE_WINDOW_EVENTS = "mousemove mouseup"; function MouseInput() { this.evEl = MOUSE_ELEMENT_EVENTS; this.evWin = MOUSE_WINDOW_EVENTS; this.pressed = false; Input2.apply(this, arguments); } inherit(MouseInput, Input2, { handler: function MEhandler(ev) { var eventType = MOUSE_INPUT_MAP2[ev.type]; if (eventType & INPUT_START2 && ev.button === 0) { this.pressed = true; } if (eventType & INPUT_MOVE2 && ev.which !== 1) { eventType = INPUT_END2; } if (!this.pressed) { return; } if (eventType & INPUT_END2) { this.pressed = false; } this.callback(this.manager, eventType, { pointers: [ev], changedPointers: [ev], pointerType: INPUT_TYPE_MOUSE, srcEvent: ev }); } }); var POINTER_INPUT_MAP = { pointerdown: INPUT_START2, pointermove: INPUT_MOVE2, pointerup: INPUT_END2, pointercancel: INPUT_CANCEL, pointerout: INPUT_CANCEL }; var IE10_POINTER_TYPE_ENUM = { 2: INPUT_TYPE_TOUCH, 3: INPUT_TYPE_PEN, 4: INPUT_TYPE_MOUSE, 5: INPUT_TYPE_KINECT }; var POINTER_ELEMENT_EVENTS = "pointerdown"; var POINTER_WINDOW_EVENTS = "pointermove pointerup pointercancel"; if (window3.MSPointerEvent && !window3.PointerEvent) { POINTER_ELEMENT_EVENTS = "MSPointerDown"; POINTER_WINDOW_EVENTS = "MSPointerMove MSPointerUp MSPointerCancel"; } function PointerEventInput() { this.evEl = POINTER_ELEMENT_EVENTS; this.evWin = POINTER_WINDOW_EVENTS; Input2.apply(this, arguments); this.store = this.manager.session.pointerEvents = []; } inherit(PointerEventInput, Input2, { handler: function PEhandler(ev) { var store = this.store; var removePointer = false; var eventTypeNormalized = ev.type.toLowerCase().replace("ms", ""); var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; var isTouch = pointerType == INPUT_TYPE_TOUCH; var storeIndex = inArray(store, ev.pointerId, "pointerId"); if (eventType & INPUT_START2 && (ev.button === 0 || isTouch)) { if (storeIndex < 0) { store.push(ev); storeIndex = store.length - 1; } } else if (eventType & (INPUT_END2 | INPUT_CANCEL)) { removePointer = true; } if (storeIndex < 0) { return; } store[storeIndex] = ev; this.callback(this.manager, eventType, { pointers: store, changedPointers: [ev], pointerType, srcEvent: ev }); if (removePointer) { store.splice(storeIndex, 1); } } }); var SINGLE_TOUCH_INPUT_MAP = { touchstart: INPUT_START2, touchmove: INPUT_MOVE2, touchend: INPUT_END2, touchcancel: INPUT_CANCEL }; var SINGLE_TOUCH_TARGET_EVENTS = "touchstart"; var SINGLE_TOUCH_WINDOW_EVENTS = "touchstart touchmove touchend touchcancel"; function SingleTouchInput() { this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; this.started = false; Input2.apply(this, arguments); } inherit(SingleTouchInput, Input2, { handler: function TEhandler(ev) { var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; if (type === INPUT_START2) { this.started = true; } if (!this.started) { return; } var touches = normalizeSingleTouches.call(this, ev, type); if (type & (INPUT_END2 | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { this.started = false; } this.callback(this.manager, type, { pointers: touches[0], changedPointers: touches[1], pointerType: INPUT_TYPE_TOUCH, srcEvent: ev }); } }); function normalizeSingleTouches(ev, type) { var all = toArray(ev.touches); var changed = toArray(ev.changedTouches); if (type & (INPUT_END2 | INPUT_CANCEL)) { all = uniqueArray(all.concat(changed), "identifier", true); } return [all, changed]; } var TOUCH_INPUT_MAP = { touchstart: INPUT_START2, touchmove: INPUT_MOVE2, touchend: INPUT_END2, touchcancel: INPUT_CANCEL }; var TOUCH_TARGET_EVENTS = "touchstart touchmove touchend touchcancel"; function TouchInput() { this.evTarget = TOUCH_TARGET_EVENTS; this.targetIds = {}; Input2.apply(this, arguments); } inherit(TouchInput, Input2, { handler: function MTEhandler(ev) { var type = TOUCH_INPUT_MAP[ev.type]; var touches = getTouches.call(this, ev, type); if (!touches) { return; } this.callback(this.manager, type, { pointers: touches[0], changedPointers: touches[1], pointerType: INPUT_TYPE_TOUCH, srcEvent: ev }); } }); function getTouches(ev, type) { var allTouches = toArray(ev.touches); var targetIds = this.targetIds; if (type & (INPUT_START2 | INPUT_MOVE2) && allTouches.length === 1) { targetIds[allTouches[0].identifier] = true; return [allTouches, allTouches]; } var i3, targetTouches, changedTouches = toArray(ev.changedTouches), changedTargetTouches = [], target = this.target; targetTouches = allTouches.filter(function(touch) { return hasParent(touch.target, target); }); if (type === INPUT_START2) { i3 = 0; while (i3 < targetTouches.length) { targetIds[targetTouches[i3].identifier] = true; i3++; } } i3 = 0; while (i3 < changedTouches.length) { if (targetIds[changedTouches[i3].identifier]) { changedTargetTouches.push(changedTouches[i3]); } if (type & (INPUT_END2 | INPUT_CANCEL)) { delete targetIds[changedTouches[i3].identifier]; } i3++; } if (!changedTargetTouches.length) { return; } return [ uniqueArray(targetTouches.concat(changedTargetTouches), "identifier", true), changedTargetTouches ]; } var DEDUP_TIMEOUT = 2500; var DEDUP_DISTANCE = 25; function TouchMouseInput() { Input2.apply(this, arguments); var handler = bindFn(this.handler, this); this.touch = new TouchInput(this.manager, handler); this.mouse = new MouseInput(this.manager, handler); this.primaryTouch = null; this.lastTouches = []; } inherit(TouchMouseInput, Input2, { handler: function TMEhandler(manager, inputEvent, inputData) { var isTouch = inputData.pointerType == INPUT_TYPE_TOUCH, isMouse = inputData.pointerType == INPUT_TYPE_MOUSE; if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { return; } if (isTouch) { recordTouches.call(this, inputEvent, inputData); } else if (isMouse && isSyntheticEvent.call(this, inputData)) { return; } this.callback(manager, inputEvent, inputData); }, destroy: function destroy() { this.touch.destroy(); this.mouse.destroy(); } }); function recordTouches(eventType, eventData) { if (eventType & INPUT_START2) { this.primaryTouch = eventData.changedPointers[0].identifier; setLastTouch.call(this, eventData); } else if (eventType & (INPUT_END2 | INPUT_CANCEL)) { setLastTouch.call(this, eventData); } } function setLastTouch(eventData) { var touch = eventData.changedPointers[0]; if (touch.identifier === this.primaryTouch) { var lastTouch = { x: touch.clientX, y: touch.clientY }; this.lastTouches.push(lastTouch); var lts = this.lastTouches; var removeLastTouch = function() { var i3 = lts.indexOf(lastTouch); if (i3 > -1) { lts.splice(i3, 1); } }; setTimeout(removeLastTouch, DEDUP_TIMEOUT); } } function isSyntheticEvent(eventData) { var x2 = eventData.srcEvent.clientX, y2 = eventData.srcEvent.clientY; for (var i3 = 0; i3 < this.lastTouches.length; i3++) { var t2 = this.lastTouches[i3]; var dx = Math.abs(x2 - t2.x), dy = Math.abs(y2 - t2.y); if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { return true; } } return false; } var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, "touchAction"); var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined2; var TOUCH_ACTION_COMPUTE = "compute"; var TOUCH_ACTION_AUTO = "auto"; var TOUCH_ACTION_MANIPULATION = "manipulation"; var TOUCH_ACTION_NONE = "none"; var TOUCH_ACTION_PAN_X = "pan-x"; var TOUCH_ACTION_PAN_Y = "pan-y"; var TOUCH_ACTION_MAP = getTouchActionProps(); function TouchAction(manager, value) { this.manager = manager; this.set(value); } TouchAction.prototype = { set: function(value) { if (value == TOUCH_ACTION_COMPUTE) { value = this.compute(); } if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; } this.actions = value.toLowerCase().trim(); }, update: function() { this.set(this.manager.options.touchAction); }, compute: function() { var actions = []; each(this.manager.recognizers, function(recognizer) { if (boolOrFn(recognizer.options.enable, [recognizer])) { actions = actions.concat(recognizer.getTouchAction()); } }); return cleanTouchActions(actions.join(" ")); }, preventDefaults: function(input) { var srcEvent = input.srcEvent; var direction = input.offsetDirection; if (this.manager.session.prevented) { srcEvent.preventDefault(); return; } var actions = this.actions; var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; if (hasNone) { var isTapPointer = input.pointers.length === 1; var isTapMovement = input.distance < 2; var isTapTouchTime = input.deltaTime < 250; if (isTapPointer && isTapMovement && isTapTouchTime) { return; } } if (hasPanX && hasPanY) { return; } if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) { return this.preventSrc(srcEvent); } }, preventSrc: function(srcEvent) { this.manager.session.prevented = true; srcEvent.preventDefault(); } }; function cleanTouchActions(actions) { if (inStr(actions, TOUCH_ACTION_NONE)) { return TOUCH_ACTION_NONE; } var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); if (hasPanX && hasPanY) { return TOUCH_ACTION_NONE; } if (hasPanX || hasPanY) { return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; } if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { return TOUCH_ACTION_MANIPULATION; } return TOUCH_ACTION_AUTO; } function getTouchActionProps() { if (!NATIVE_TOUCH_ACTION) { return false; } var touchMap = {}; var cssSupports = window3.CSS && window3.CSS.supports; ["auto", "manipulation", "pan-y", "pan-x", "pan-x pan-y", "none"].forEach(function(val2) { touchMap[val2] = cssSupports ? window3.CSS.supports("touch-action", val2) : true; }); return touchMap; } var STATE_POSSIBLE = 1; var STATE_BEGAN = 2; var STATE_CHANGED = 4; var STATE_ENDED = 8; var STATE_RECOGNIZED = STATE_ENDED; var STATE_CANCELLED = 16; var STATE_FAILED = 32; function Recognizer(options) { this.options = assign({}, this.defaults, options || {}); this.id = uniqueId(); this.manager = null; this.options.enable = ifUndefined(this.options.enable, true); this.state = STATE_POSSIBLE; this.simultaneous = {}; this.requireFail = []; } Recognizer.prototype = { defaults: {}, set: function(options) { assign(this.options, options); this.manager && this.manager.touchAction.update(); return this; }, recognizeWith: function(otherRecognizer) { if (invokeArrayArg(otherRecognizer, "recognizeWith", this)) { return this; } var simultaneous = this.simultaneous; otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); if (!simultaneous[otherRecognizer.id]) { simultaneous[otherRecognizer.id] = otherRecognizer; otherRecognizer.recognizeWith(this); } return this; }, dropRecognizeWith: function(otherRecognizer) { if (invokeArrayArg(otherRecognizer, "dropRecognizeWith", this)) { return this; } otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); delete this.simultaneous[otherRecognizer.id]; return this; }, requireFailure: function(otherRecognizer) { if (invokeArrayArg(otherRecognizer, "requireFailure", this)) { return this; } var requireFail = this.requireFail; otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); if (inArray(requireFail, otherRecognizer) === -1) { requireFail.push(otherRecognizer); otherRecognizer.requireFailure(this); } return this; }, dropRequireFailure: function(otherRecognizer) { if (invokeArrayArg(otherRecognizer, "dropRequireFailure", this)) { return this; } otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); var index = inArray(this.requireFail, otherRecognizer); if (index > -1) { this.requireFail.splice(index, 1); } return this; }, hasRequireFailures: function() { return this.requireFail.length > 0; }, canRecognizeWith: function(otherRecognizer) { return !!this.simultaneous[otherRecognizer.id]; }, emit: function(input) { var self2 = this; var state = this.state; function emit(event) { self2.manager.emit(event, input); } if (state < STATE_ENDED) { emit(self2.options.event + stateStr(state)); } emit(self2.options.event); if (input.additionalEvent) { emit(input.additionalEvent); } if (state >= STATE_ENDED) { emit(self2.options.event + stateStr(state)); } }, tryEmit: function(input) { if (this.canEmit()) { return this.emit(input); } this.state = STATE_FAILED; }, canEmit: function() { var i3 = 0; while (i3 < this.requireFail.length) { if (!(this.requireFail[i3].state & (STATE_FAILED | STATE_POSSIBLE))) { return false; } i3++; } return true; }, recognize: function(inputData) { var inputDataClone = assign({}, inputData); if (!boolOrFn(this.options.enable, [this, inputDataClone])) { this.reset(); this.state = STATE_FAILED; return; } if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { this.state = STATE_POSSIBLE; } this.state = this.process(inputDataClone); if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { this.tryEmit(inputDataClone); } }, process: function(inputData) { }, getTouchAction: function() { }, reset: function() { } }; function stateStr(state) { if (state & STATE_CANCELLED) { return "cancel"; } else if (state & STATE_ENDED) { return "end"; } else if (state & STATE_CHANGED) { return "move"; } else if (state & STATE_BEGAN) { return "start"; } return ""; } function directionStr(direction) { if (direction == DIRECTION_DOWN) { return "down"; } else if (direction == DIRECTION_UP) { return "up"; } else if (direction == DIRECTION_LEFT) { return "left"; } else if (direction == DIRECTION_RIGHT) { return "right"; } return ""; } function getRecognizerByNameIfManager(otherRecognizer, recognizer) { var manager = recognizer.manager; if (manager) { return manager.get(otherRecognizer); } return otherRecognizer; } function AttrRecognizer() { Recognizer.apply(this, arguments); } inherit(AttrRecognizer, Recognizer, { defaults: { pointers: 1 }, attrTest: function(input) { var optionPointers = this.options.pointers; return optionPointers === 0 || input.pointers.length === optionPointers; }, process: function(input) { var state = this.state; var eventType = input.eventType; var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); var isValid = this.attrTest(input); if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { return state | STATE_CANCELLED; } else if (isRecognized || isValid) { if (eventType & INPUT_END2) { return state | STATE_ENDED; } else if (!(state & STATE_BEGAN)) { return STATE_BEGAN; } return state | STATE_CHANGED; } return STATE_FAILED; } }); function PanRecognizer() { AttrRecognizer.apply(this, arguments); this.pX = null; this.pY = null; } inherit(PanRecognizer, AttrRecognizer, { defaults: { event: "pan", threshold: 10, pointers: 1, direction: DIRECTION_ALL }, getTouchAction: function() { var direction = this.options.direction; var actions = []; if (direction & DIRECTION_HORIZONTAL) { actions.push(TOUCH_ACTION_PAN_Y); } if (direction & DIRECTION_VERTICAL) { actions.push(TOUCH_ACTION_PAN_X); } return actions; }, directionTest: function(input) { var options = this.options; var hasMoved = true; var distance3 = input.distance; var direction = input.direction; var x2 = input.deltaX; var y2 = input.deltaY; if (!(direction & options.direction)) { if (options.direction & DIRECTION_HORIZONTAL) { direction = x2 === 0 ? DIRECTION_NONE : x2 < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; hasMoved = x2 != this.pX; distance3 = Math.abs(input.deltaX); } else { direction = y2 === 0 ? DIRECTION_NONE : y2 < 0 ? DIRECTION_UP : DIRECTION_DOWN; hasMoved = y2 != this.pY; distance3 = Math.abs(input.deltaY); } } input.direction = direction; return hasMoved && distance3 > options.threshold && direction & options.direction; }, attrTest: function(input) { return AttrRecognizer.prototype.attrTest.call(this, input) && (this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input)); }, emit: function(input) { this.pX = input.deltaX; this.pY = input.deltaY; var direction = directionStr(input.direction); if (direction) { input.additionalEvent = this.options.event + direction; } this._super.emit.call(this, input); } }); function PinchRecognizer() { AttrRecognizer.apply(this, arguments); } inherit(PinchRecognizer, AttrRecognizer, { defaults: { event: "pinch", threshold: 0, pointers: 2 }, getTouchAction: function() { return [TOUCH_ACTION_NONE]; }, attrTest: function(input) { return this._super.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); }, emit: function(input) { if (input.scale !== 1) { var inOut = input.scale < 1 ? "in" : "out"; input.additionalEvent = this.options.event + inOut; } this._super.emit.call(this, input); } }); function PressRecognizer() { Recognizer.apply(this, arguments); this._timer = null; this._input = null; } inherit(PressRecognizer, Recognizer, { defaults: { event: "press", pointers: 1, time: 251, threshold: 9 }, getTouchAction: function() { return [TOUCH_ACTION_AUTO]; }, process: function(input) { var options = this.options; var validPointers = input.pointers.length === options.pointers; var validMovement = input.distance < options.threshold; var validTime = input.deltaTime > options.time; this._input = input; if (!validMovement || !validPointers || input.eventType & (INPUT_END2 | INPUT_CANCEL) && !validTime) { this.reset(); } else if (input.eventType & INPUT_START2) { this.reset(); this._timer = setTimeoutContext(function() { this.state = STATE_RECOGNIZED; this.tryEmit(); }, options.time, this); } else if (input.eventType & INPUT_END2) { return STATE_RECOGNIZED; } return STATE_FAILED; }, reset: function() { clearTimeout(this._timer); }, emit: function(input) { if (this.state !== STATE_RECOGNIZED) { return; } if (input && input.eventType & INPUT_END2) { this.manager.emit(this.options.event + "up", input); } else { this._input.timeStamp = now(); this.manager.emit(this.options.event, this._input); } } }); function RotateRecognizer() { AttrRecognizer.apply(this, arguments); } inherit(RotateRecognizer, AttrRecognizer, { defaults: { event: "rotate", threshold: 0, pointers: 2 }, getTouchAction: function() { return [TOUCH_ACTION_NONE]; }, attrTest: function(input) { return this._super.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); } }); function SwipeRecognizer() { AttrRecognizer.apply(this, arguments); } inherit(SwipeRecognizer, AttrRecognizer, { defaults: { event: "swipe", threshold: 10, velocity: 0.3, direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, pointers: 1 }, getTouchAction: function() { return PanRecognizer.prototype.getTouchAction.call(this); }, attrTest: function(input) { var direction = this.options.direction; var velocity; if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { velocity = input.overallVelocity; } else if (direction & DIRECTION_HORIZONTAL) { velocity = input.overallVelocityX; } else if (direction & DIRECTION_VERTICAL) { velocity = input.overallVelocityY; } return this._super.attrTest.call(this, input) && direction & input.offsetDirection && input.distance > this.options.threshold && input.maxPointers == this.options.pointers && abs(velocity) > this.options.velocity && input.eventType & INPUT_END2; }, emit: function(input) { var direction = directionStr(input.offsetDirection); if (direction) { this.manager.emit(this.options.event + direction, input); } this.manager.emit(this.options.event, input); } }); function TapRecognizer() { Recognizer.apply(this, arguments); this.pTime = false; this.pCenter = false; this._timer = null; this._input = null; this.count = 0; } inherit(TapRecognizer, Recognizer, { defaults: { event: "tap", pointers: 1, taps: 1, interval: 300, time: 250, threshold: 9, posThreshold: 10 }, getTouchAction: function() { return [TOUCH_ACTION_MANIPULATION]; }, process: function(input) { var options = this.options; var validPointers = input.pointers.length === options.pointers; var validMovement = input.distance < options.threshold; var validTouchTime = input.deltaTime < options.time; this.reset(); if (input.eventType & INPUT_START2 && this.count === 0) { return this.failTimeout(); } if (validMovement && validTouchTime && validPointers) { if (input.eventType != INPUT_END2) { return this.failTimeout(); } var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true; var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; this.pTime = input.timeStamp; this.pCenter = input.center; if (!validMultiTap || !validInterval) { this.count = 1; } else { this.count += 1; } this._input = input; var tapCount = this.count % options.taps; if (tapCount === 0) { if (!this.hasRequireFailures()) { return STATE_RECOGNIZED; } else { this._timer = setTimeoutContext(function() { this.state = STATE_RECOGNIZED; this.tryEmit(); }, options.interval, this); return STATE_BEGAN; } } } return STATE_FAILED; }, failTimeout: function() { this._timer = setTimeoutContext(function() { this.state = STATE_FAILED; }, this.options.interval, this); return STATE_FAILED; }, reset: function() { clearTimeout(this._timer); }, emit: function() { if (this.state == STATE_RECOGNIZED) { this._input.tapCount = this.count; this.manager.emit(this.options.event, this._input); } } }); function Hammer(element, options) { options = options || {}; options.recognizers = ifUndefine