From f26f29d84e0a68831a6af14dab3eec5500496d2e Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期三, 28 五月 2025 16:48:52 +0800 Subject: [PATCH] 初始化项目 --- static/common/js/touch-emulator.js | 363 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 363 insertions(+), 0 deletions(-) diff --git a/static/common/js/touch-emulator.js b/static/common/js/touch-emulator.js new file mode 100644 index 0000000..9632413 --- /dev/null +++ b/static/common/js/touch-emulator.js @@ -0,0 +1,363 @@ +(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"); \ No newline at end of file -- Gitblit v1.9.3