js-Extensions-touchJS

js-Extensions-touchJS是一个非常简单的原生js touch扩展,用于适配移动端的常用touch操作(点击tab、双击dbTab、长按longPress、长按终止longPressCancel、滑动swipe以及具体滑动方向left right up down)

Tính đến 30-11-2022. Xem phiên bản mới nhất.

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greasyfork.org/scripts/455704/1123115/js-Extensions-touchJS.js

// ==UserScript==
// @name         js-Extensions-touchJS
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  js-Extensions-touchJS是一个非常简单的原生js touch扩展,用于适配移动端的常用touch操作(点击tab、双击dbTab、长按longPress、长按终止longPressCancel、滑动swipe以及具体滑动方向left right up down)
// @author       tutu辣么可爱(greasyfork)/IcedWatermelonJuice(github)
// @grant        none
// ==/UserScript==
(function() {
	var touchJS = {}

	function jsonExtend(json1 = {}, json2 = {}, json3 = {}) {
		return Object.assign(json1, json2, json3)
	}

	function getFnName(fn) {
		if (fn.name) {
			return fn.name
		} else {
			var fnstr = fn.toString().match(/function\s*([^(]*)\(/);
			return fnstr ? fnstr[1] : null
		}
	}
	touchJS.bind = function(target, evt, fn, fnName = null) {
		if (!target || typeof target !== "object") {
			console.error("touchJS.bind(target, evt, fn, fnName)参数错误,对象(target)不存在");
			return false;
		}
		// 预处理
		var that = target;
		that.jsTouchFnMap = that.jsTouchFnMap ? that.jsTouchFnMap : {};
		var fnMap = jsonExtend({}, that.jsTouchFnMap),
			fnKeyArray = ["swipe", "left", "right", "up", "down", "tap", "dbTap", "longPress",
				"longPressCancel"
			]; //可用的事件名

		function addFn(e, f, n) {
			if (fnKeyArray.indexOf(e) < 0) {
				let msg = "touchJS.bind(target, evt, fn, fnName)参数错误,指定事件(evt)不支持。支持的事件列表:";
				console.error(msg + fnKeyArray.toString());
				return false;
			}
			fnMap[e] = fnMap[e] ? fnMap[e] : {};
			if (!n) { //无方法名,获取并使用默认数字id
				defAry = Object.keys(fnMap[e]).filter((v) => {
					/^\d{1,}$/.test(v)
				});
				//获取可用数字id
				if (!fnMap[e][defAry.length]) { //假设id连续,长度就是新id
					n = defAry.length
				} else { //说明id不连续(手动删过事件方法),寻找中间缺少的id
					defAry.sort((a, b) => {
						return a - b
					});
					for (let i = 0; i < defAry.length; i++) {
						if (defAry[i] !== i) {
							n = i;
							break;
						}
					}
				}
			}
			fnMap[e][n] = f
			return true
		}
		if (typeof evt === "string" && typeof fn === "function") {
			if (!addFn(evt, fn, fnName ? fnName : getFnName(fn))) {
				return false
			}
		} else if (typeof evt === "object" && !fn) {
			for (let e in evt) {
				if (!addFn(e, evt[e], getFnName(evt[e]))) {
					return false
				}
			}
		}
		that.jsTouchFnMap = jsonExtend({}, that.jsTouchFnMap, fnMap);
		//添加事件
		if (!that.jsTouchFnMap.eventLoaded) {
			that.jsTouchFnMap.eventLoaded = true;
			var execFn = function(evt) { //执行方法
				if (!evt) {
					return false
				}
				if (/left|right|up|down/.test(evt)) {
					evt = [evt, "swipe"];
				} else {
					evt = [evt];
				}
				evt.forEach((e) => {
					e = that.jsTouchFnMap[e] ? that.jsTouchFnMap[e] : {};
					for (let i in e) {
						if (typeof e[i] === "function") {
							e[i]();
						}
					}
				})
			}
			var lp_timer = -1,
				tap_timer = -1,
				lp_flag = false,
				swipe_flag = false,
				tap_sum = 0,
				pos = {
					x: 0,
					y: 0
				};
			that.addEventListener('touchstart', ts, false);
			that.addEventListener('touchmove', tm, false);
			that.addEventListener('touchend', te, false);
			//具体实现
			function dir(past, now) { //判方向
				if (Math.abs(past.x - now.x) > Math.abs(past.y - now.y)) {
					if (now.x > past.x) {
						return "right"
					} else {
						return "left"
					}
				} else {
					if (now.y > past.y) {
						return "down"
					} else {
						return "up"
					}
				}
				return null
			}

			function ts(e) { //touchstart
				e = e || window.event
				lp_timer !== -1 && clearTimeout(lp_timer);
				lp_timer = -1;
				lp_flag = false;
				swipe_flag = false;
				pos = {
					x: e.changedTouches[0].clientX,
					y: e.changedTouches[0].clientY
				}
				lp_timer = setTimeout(function() {
					if (!swipe_flag) {
						lp_timer = -1;
						lp_flag = true;
						execFn("longPress")
					}
				}, 600)
			}

			function tm(e) { //touchmove
				var e = e || window.event;
				let temp = {
					x: e.changedTouches[0].clientX,
					y: e.changedTouches[0].clientY
				}
				if (!lp_flag && (Math.abs(pos.x - temp.x) > 10 || Math.abs(pos.y - temp.y) > 10)) {
					swipe_flag = true;
					lp_timer !== -1 && clearTimeout(lp_timer);
					lp_timer = -1;
					execFn(dir(pos, temp));
				}
			}

			function te(e) { //touchend
				var e = e || window.event;
				lp_timer !== -1 && clearTimeout(lp_timer);
				tap_timer !== -1 && clearTimeout(tap_timer);
				lp_timer = -1;
				tap_timer = -1;
				if (lp_flag) {
					execFn("longPressCancel");
				} else if (!swipe_flag) {
					tap_sum += 1;
					if (tap_sum >= 2) {
						tap_sum = 0;
						execFn("dbTap");
					} else {
						tap_timer = setTimeout(() => {
							tap_sum = 0;
							execFn("tap");
						}, 200)
					}
				}
			}
		}
		return that
	}
	touchJS.unbind = function(target, evt, fnName = null) {
		if (!target || typeof target !== "object") {
			console.error("touchJS.unbind(target, evt, fnName)参数错误,对象(target)不存在");
			return false;
		}
		var that = target;
		if (typeof evt === "string") {
			that.jsTouchFnMap = that.jsTouchFnMap ? that.jsTouchFnMap : {};
			if (that.jsTouchFnMap[evt]) {
				if (fnName) {
					fnName = typeof fnName === "function" ? getFnName(fnName) : fnName;
					delete that.jsTouchFnMap[evt][fnName];
				} else {
					delete that.jsTouchFnMap[evt]
				}
			}
		}
		return that
	}
	window.touchJS=touchJS;
})();