export const TouchEmulator = (() => { /** * 模拟移动端 touch 事件 */ var eventTarget // polyfills if (!document.createTouch) { document.createTouch = function ( view, target, identifier, pageX, pageY, screenX, screenY ) { // auto set return new Touch( target, identifier, { pageX: pageX, pageY: pageY, screenX: screenX, screenY: screenY, clientX: pageX - window.pageXOffset, clientY: pageY - window.pageYOffset, }, 0, 0 ) } } if (!document.createTouchList) { document.createTouchList = function () { var touchList = 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 */ var Touch = 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 } } } } /** * only trigger touches when the left mousebutton has been pressed * @param touchType * @returns {Function} */ function onMouse(touchType) { return function (ev) { // prevent mouse events 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 } triggerTouch(touchType, ev) // reset if (ev.type === 'mouseup') { 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) touchEvent.targetTouches = getActiveTouches(mouseEv) touchEvent.changedTouches = createTouchList(mouseEv) eventTarget.dispatchEvent(touchEvent) } /** * create a touchList based on the mouse event * @param mouseEv * @returns {TouchList} */ function createTouchList(mouseEv) { var touchList = TouchList() touchList.push(new Touch(eventTarget, 1, mouseEv, 0, 0)) return touchList } /** * receive all active touches * @param mouseEv * @returns {TouchList} */ function getActiveTouches(mouseEv) { // empty list if (mouseEv.type === 'mouseup') { return TouchList() } return createTouchList(mouseEv) } /** * TouchEmulator initializer */ function TouchEmulator(target) { fakeTouchSupport() target.addEventListener('mousedown', onMouse('touchstart'), true) target.addEventListener('mousemove', onMouse('touchmove'), true) target.addEventListener('mouseup', onMouse('touchend'), true) } // start distance when entering the multitouch mode TouchEmulator['multiTouchOffset'] = 75 return TouchEmulator })()