|
@@ -1,363 +0,0 @@
|
|
-(function (window, document, exportName, undefined) {
|
|
|
|
- "use strict";
|
|
|
|
-
|
|
|
|
- var isMultiTouch = false;
|
|
|
|
- var multiTouchStartPos;
|
|
|
|
- var eventTarget;
|
|
|
|
- var touchElements = {};
|
|
|
|
-
|
|
|
|
- // polyfills
|
|
|
|
- if (!document.createTouch) {
|
|
|
|
- document.createTouch = function (view, target, identifier, pageX, pageY, screenX, screenY, clientX, clientY) {
|
|
|
|
- // auto set
|
|
|
|
- if (clientX == undefined || clientY == undefined) {
|
|
|
|
- clientX = pageX - window.pageXOffset;
|
|
|
|
- clientY = pageY - window.pageYOffset;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return new Touch(target, identifier, {
|
|
|
|
- pageX: pageX,
|
|
|
|
- pageY: pageY,
|
|
|
|
- screenX: screenX,
|
|
|
|
- screenY: screenY,
|
|
|
|
- clientX: clientX,
|
|
|
|
- clientY: clientY
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!document.createTouchList) {
|
|
|
|
- document.createTouchList = function () {
|
|
|
|
- var touchList = new TouchList();
|
|
|
|
- for (var i = 0; i < arguments.length; i++) {
|
|
|
|
- touchList[i] = arguments[i];
|
|
|
|
- }
|
|
|
|
- touchList.length = arguments.length;
|
|
|
|
- return touchList;
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * create an touch point
|
|
|
|
- * @constructor
|
|
|
|
- * @param target
|
|
|
|
- * @param identifier
|
|
|
|
- * @param pos
|
|
|
|
- * @param deltaX
|
|
|
|
- * @param deltaY
|
|
|
|
- * @returns {Object} touchPoint
|
|
|
|
- */
|
|
|
|
- function Touch(target, identifier, pos, deltaX, deltaY) {
|
|
|
|
- deltaX = deltaX || 0;
|
|
|
|
- deltaY = deltaY || 0;
|
|
|
|
-
|
|
|
|
- this.identifier = identifier;
|
|
|
|
- this.target = target;
|
|
|
|
- this.clientX = pos.clientX + deltaX;
|
|
|
|
- this.clientY = pos.clientY + deltaY;
|
|
|
|
- this.screenX = pos.screenX + deltaX;
|
|
|
|
- this.screenY = pos.screenY + deltaY;
|
|
|
|
- this.pageX = pos.pageX + deltaX;
|
|
|
|
- this.pageY = pos.pageY + deltaY;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * create empty touchlist with the methods
|
|
|
|
- * @constructor
|
|
|
|
- * @returns touchList
|
|
|
|
- */
|
|
|
|
- function TouchList() {
|
|
|
|
- var touchList = [];
|
|
|
|
-
|
|
|
|
- touchList.item = function (index) {
|
|
|
|
- return this[index] || null;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // specified by Mozilla
|
|
|
|
- touchList.identifiedTouch = function (id) {
|
|
|
|
- return this[id + 1] || null;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- return touchList;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Simple trick to fake touch event support
|
|
|
|
- * this is enough for most libraries like Modernizr and Hammer
|
|
|
|
- */
|
|
|
|
- function fakeTouchSupport() {
|
|
|
|
- var objs = [window, document.documentElement];
|
|
|
|
- var props = ['ontouchstart', 'ontouchmove', 'ontouchcancel', 'ontouchend'];
|
|
|
|
-
|
|
|
|
- for (var o = 0; o < objs.length; o++) {
|
|
|
|
- for (var p = 0; p < props.length; p++) {
|
|
|
|
- if (objs[o] && objs[o][props[p]] == undefined) {
|
|
|
|
- objs[o][props[p]] = null;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * we don't have to emulate on a touch device
|
|
|
|
- * @returns {boolean}
|
|
|
|
- */
|
|
|
|
- function hasTouchSupport() {
|
|
|
|
- return ("ontouchstart" in window) || // touch events
|
|
|
|
- (window.Modernizr && window.Modernizr.touch) || // modernizr
|
|
|
|
- (navigator.msMaxTouchPoints || navigator.maxTouchPoints) > 2; // pointer events
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * disable mouseevents on the page
|
|
|
|
- * @param ev
|
|
|
|
- */
|
|
|
|
- function preventMouseEvents(ev) {
|
|
|
|
- // 注释启用默认事件
|
|
|
|
- // ev.preventDefault();
|
|
|
|
- // ev.stopPropagation();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * only trigger touches when the left mousebutton has been pressed
|
|
|
|
- * @param touchType
|
|
|
|
- * @returns {Function}
|
|
|
|
- */
|
|
|
|
- function onMouse(touchType) {
|
|
|
|
- return function (ev) {
|
|
|
|
- // prevent mouse events
|
|
|
|
- preventMouseEvents(ev);
|
|
|
|
-
|
|
|
|
- if (ev.which !== 1) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // The EventTarget on which the touch point started when it was first placed on the surface,
|
|
|
|
- // even if the touch point has since moved outside the interactive area of that element.
|
|
|
|
- // also, when the target doesnt exist anymore, we update it
|
|
|
|
- if (ev.type == 'mousedown' || !eventTarget || (eventTarget && !eventTarget.dispatchEvent)) {
|
|
|
|
- eventTarget = ev.target;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // shiftKey has been lost, so trigger a touchend
|
|
|
|
- if (isMultiTouch && !ev.shiftKey) {
|
|
|
|
- triggerTouch('touchend', ev);
|
|
|
|
- isMultiTouch = false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- triggerTouch(touchType, ev);
|
|
|
|
-
|
|
|
|
- // we're entering the multi-touch mode!
|
|
|
|
- if (!isMultiTouch && ev.shiftKey) {
|
|
|
|
- isMultiTouch = true;
|
|
|
|
- multiTouchStartPos = {
|
|
|
|
- pageX: ev.pageX,
|
|
|
|
- pageY: ev.pageY,
|
|
|
|
- clientX: ev.clientX,
|
|
|
|
- clientY: ev.clientY,
|
|
|
|
- screenX: ev.screenX,
|
|
|
|
- screenY: ev.screenY
|
|
|
|
- };
|
|
|
|
- triggerTouch('touchstart', ev);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // reset
|
|
|
|
- if (ev.type == 'mouseup') {
|
|
|
|
- multiTouchStartPos = null;
|
|
|
|
- isMultiTouch = false;
|
|
|
|
- eventTarget = null;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * trigger a touch event
|
|
|
|
- * @param eventName
|
|
|
|
- * @param mouseEv
|
|
|
|
- */
|
|
|
|
- function triggerTouch(eventName, mouseEv) {
|
|
|
|
- var touchEvent = document.createEvent('Event');
|
|
|
|
- touchEvent.initEvent(eventName, true, true);
|
|
|
|
-
|
|
|
|
- touchEvent.altKey = mouseEv.altKey;
|
|
|
|
- touchEvent.ctrlKey = mouseEv.ctrlKey;
|
|
|
|
- touchEvent.metaKey = mouseEv.metaKey;
|
|
|
|
- touchEvent.shiftKey = mouseEv.shiftKey;
|
|
|
|
-
|
|
|
|
- touchEvent.touches = getActiveTouches(mouseEv, eventName);
|
|
|
|
- touchEvent.targetTouches = getActiveTouches(mouseEv, eventName);
|
|
|
|
- touchEvent.changedTouches = getChangedTouches(mouseEv, eventName);
|
|
|
|
-
|
|
|
|
- eventTarget.dispatchEvent(touchEvent);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * create a touchList based on the mouse event
|
|
|
|
- * @param mouseEv
|
|
|
|
- * @returns {TouchList}
|
|
|
|
- */
|
|
|
|
- function createTouchList(mouseEv) {
|
|
|
|
- var touchList = new TouchList();
|
|
|
|
-
|
|
|
|
- if (isMultiTouch) {
|
|
|
|
- var f = TouchEmulator.multiTouchOffset;
|
|
|
|
- var deltaX = multiTouchStartPos.pageX - mouseEv.pageX;
|
|
|
|
- var deltaY = multiTouchStartPos.pageY - mouseEv.pageY;
|
|
|
|
-
|
|
|
|
- touchList.push(new Touch(eventTarget, 1, multiTouchStartPos, (deltaX * -1) - f, (deltaY * -1) + f));
|
|
|
|
- touchList.push(new Touch(eventTarget, 2, multiTouchStartPos, deltaX + f, deltaY - f));
|
|
|
|
- } else {
|
|
|
|
- touchList.push(new Touch(eventTarget, 1, mouseEv, 0, 0));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return touchList;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * receive all active touches
|
|
|
|
- * @param mouseEv
|
|
|
|
- * @returns {TouchList}
|
|
|
|
- */
|
|
|
|
- function getActiveTouches(mouseEv, eventName) {
|
|
|
|
- // empty list
|
|
|
|
- if (mouseEv.type == 'mouseup') {
|
|
|
|
- return new TouchList();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var touchList = createTouchList(mouseEv);
|
|
|
|
- if (isMultiTouch && mouseEv.type != 'mouseup' && eventName == 'touchend') {
|
|
|
|
- touchList.splice(1, 1);
|
|
|
|
- }
|
|
|
|
- return touchList;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * receive a filtered set of touches with only the changed pointers
|
|
|
|
- * @param mouseEv
|
|
|
|
- * @param eventName
|
|
|
|
- * @returns {TouchList}
|
|
|
|
- */
|
|
|
|
- function getChangedTouches(mouseEv, eventName) {
|
|
|
|
- var touchList = createTouchList(mouseEv);
|
|
|
|
-
|
|
|
|
- // we only want to return the added/removed item on multitouch
|
|
|
|
- // which is the second pointer, so remove the first pointer from the touchList
|
|
|
|
- //
|
|
|
|
- // but when the mouseEv.type is mouseup, we want to send all touches because then
|
|
|
|
- // no new input will be possible
|
|
|
|
- if (isMultiTouch && mouseEv.type != 'mouseup' &&
|
|
|
|
- (eventName == 'touchstart' || eventName == 'touchend')) {
|
|
|
|
- touchList.splice(0, 1);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return touchList;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * show the touchpoints on the screen
|
|
|
|
- */
|
|
|
|
- function showTouches(ev) {
|
|
|
|
- var touch, i, el, styles;
|
|
|
|
-
|
|
|
|
- // first all visible touches
|
|
|
|
- for (i = 0; i < ev.touches.length; i++) {
|
|
|
|
- touch = ev.touches[i];
|
|
|
|
- el = touchElements[touch.identifier];
|
|
|
|
- if (!el) {
|
|
|
|
- el = touchElements[touch.identifier] = document.createElement("div");
|
|
|
|
- document.body.appendChild(el);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- styles = TouchEmulator.template(touch);
|
|
|
|
- for (var prop in styles) {
|
|
|
|
- el.style[prop] = styles[prop];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // remove all ended touches
|
|
|
|
- if (ev.type == 'touchend' || ev.type == 'touchcancel') {
|
|
|
|
- for (i = 0; i < ev.changedTouches.length; i++) {
|
|
|
|
- touch = ev.changedTouches[i];
|
|
|
|
- el = touchElements[touch.identifier];
|
|
|
|
- if (el) {
|
|
|
|
- el.parentNode.removeChild(el);
|
|
|
|
- delete touchElements[touch.identifier];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * TouchEmulator initializer
|
|
|
|
- */
|
|
|
|
- function TouchEmulator() {
|
|
|
|
- if (hasTouchSupport()) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fakeTouchSupport();
|
|
|
|
-
|
|
|
|
- window.addEventListener("mousedown", onMouse('touchstart'), true);
|
|
|
|
- window.addEventListener("mousemove", onMouse('touchmove'), true);
|
|
|
|
- window.addEventListener("mouseup", onMouse('touchend'), true);
|
|
|
|
-
|
|
|
|
- window.addEventListener("mouseenter", preventMouseEvents, true);
|
|
|
|
- window.addEventListener("mouseleave", preventMouseEvents, true);
|
|
|
|
- window.addEventListener("mouseout", preventMouseEvents, true);
|
|
|
|
- window.addEventListener("mouseover", preventMouseEvents, true);
|
|
|
|
-
|
|
|
|
- // it uses itself!
|
|
|
|
- window.addEventListener("touchstart", showTouches, true);
|
|
|
|
- window.addEventListener("touchmove", showTouches, true);
|
|
|
|
- window.addEventListener("touchend", showTouches, true);
|
|
|
|
- window.addEventListener("touchcancel", showTouches, true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // start distance when entering the multitouch mode
|
|
|
|
- TouchEmulator.multiTouchOffset = 75;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * css template for the touch rendering
|
|
|
|
- * @param touch
|
|
|
|
- * @returns object
|
|
|
|
- */
|
|
|
|
- TouchEmulator.template = function (touch) {
|
|
|
|
- var size = 0;
|
|
|
|
- var transform = 'translate(' + (touch.clientX - (size / 2)) + 'px, ' + (touch.clientY - (size / 2)) + 'px)';
|
|
|
|
- return {
|
|
|
|
- position: 'fixed',
|
|
|
|
- left: 0,
|
|
|
|
- top: 0,
|
|
|
|
- background: '#fff',
|
|
|
|
- border: 'solid 1px #999',
|
|
|
|
- opacity: .6,
|
|
|
|
- borderRadius: '100%',
|
|
|
|
- height: size + 'px',
|
|
|
|
- width: size + 'px',
|
|
|
|
- padding: 0,
|
|
|
|
- margin: 0,
|
|
|
|
- display: 'block',
|
|
|
|
- overflow: 'hidden',
|
|
|
|
- pointerEvents: 'none',
|
|
|
|
- webkitUserSelect: 'none',
|
|
|
|
- mozUserSelect: 'none',
|
|
|
|
- userSelect: 'none',
|
|
|
|
- webkitTransform: transform,
|
|
|
|
- mozTransform: transform,
|
|
|
|
- transform: transform,
|
|
|
|
- zIndex: 100
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // export
|
|
|
|
- if (typeof define == "function" && define.amd) {
|
|
|
|
- define(function () {
|
|
|
|
- return TouchEmulator;
|
|
|
|
- });
|
|
|
|
- } else if (typeof module != "undefined" && module.exports) {
|
|
|
|
- module.exports = TouchEmulator;
|
|
|
|
- } else {
|
|
|
|
- window[exportName] = TouchEmulator;
|
|
|
|
- }
|
|
|
|
-})(window, document, "TouchEmulator");
|
|
|