js-Extensions-touchJS

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

当前为 2022-12-04 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/455704/1124837/js-Extensions-touchJS.js

  1. // ==UserScript==
  2. // @name js-Extensions-touchJS
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.6
  5. // @description js-Extensions-touchJS是一个非常简单的原生js touch扩展,用于适配移动端的常用touch操作(点击tab、双击dbTab、长按longPress、长按终止longPressCancel、滑动swipe以及具体滑动方向left right up down),并兼容鼠标手势操作
  6. // @author tutu辣么可爱(greasyfork)/IcedWatermelonJuice(github)
  7. // @grant none
  8. // ==/UserScript==
  9. (function() {
  10. var touchJS = {}
  11.  
  12. function jsonExtend(json1 = {}, json2 = {}, json3 = {}) {
  13. return Object.assign(json1, json2, json3)
  14. }
  15.  
  16. function getFnName(fn) {
  17. if (fn.name) {
  18. return fn.name
  19. } else {
  20. var fnstr = fn.toString().match(/function\s*([^(]*)\(/);
  21. return fnstr ? fnstr[1] : null
  22. }
  23. }
  24. touchJS.bind = function(target, evt, fn, fnName = null) {
  25. if (!target || typeof target !== "object") {
  26. console.error("touchJS.bind(target, evt, fn, fnName)参数错误,对象(target)不存在");
  27. return false;
  28. }
  29. // 预处理
  30. var that = target;
  31. that.libForTouchJsExt = that.libForTouchJsExt ? that.libForTouchJsExt : {};
  32. var fnMap = jsonExtend({}, that.libForTouchJsExt),
  33. fnKeyArray = ["swipe", "left", "right", "up", "down", "tap", "dbTap", "longPress",
  34. "longPressCancel"
  35. ]; //可用的事件名
  36.  
  37. function addFn(e, f, n) {
  38. if (fnKeyArray.indexOf(e) < 0) {
  39. let msg = "touchJS.bind(target, evt, fn, fnName)参数错误,指定事件(evt)不支持。支持的事件列表:";
  40. console.error(msg + fnKeyArray.toString());
  41. return false;
  42. }
  43. fnMap[e] = fnMap[e] ? fnMap[e] : {};
  44. if (!n) { //无方法名,获取并使用默认数字id
  45. defAry = Object.keys(fnMap[e]).filter((v) => {
  46. /^\d{1,}$/.test(v)
  47. });
  48. //获取可用数字id
  49. if (!fnMap[e][defAry.length]) { //假设id连续,长度就是新id
  50. n = defAry.length
  51. } else { //说明id不连续(手动删过事件方法),寻找中间缺少的id
  52. defAry.sort((a, b) => {
  53. return a - b
  54. });
  55. for (let i = 0; i < defAry.length; i++) {
  56. if (defAry[i] !== i) {
  57. n = i;
  58. break;
  59. }
  60. }
  61. }
  62. }
  63. fnMap[e][n] = f
  64. return true
  65. }
  66. if (typeof evt === "string" && typeof fn === "function") {
  67. if (!addFn(evt, fn, fnName ? fnName : getFnName(fn))) {
  68. return false
  69. }
  70. } else if (typeof evt === "object" && !fn) {
  71. for (let e in evt) {
  72. if (!addFn(e, evt[e], getFnName(evt[e]))) {
  73. return false
  74. }
  75. }
  76. }
  77. that.libForTouchJsExt = jsonExtend({}, that.libForTouchJsExt, fnMap);
  78. //添加事件
  79. if (!that.libForTouchJsExt.eventLoaded) {
  80. that.libForTouchJsExt.eventLoaded = true;
  81. var execFn = function(evt, params = {}) { //执行方法
  82. if (!evt || that.hasAttribute("touchJS-disabled")) {
  83. return false
  84. }
  85. if (/left|right|up|down/.test(evt)) {
  86. evt = [evt, "swipe"];
  87. } else {
  88. evt = [evt];
  89. }
  90. params.target = that;
  91. evt.forEach((e) => {
  92. e = that.libForTouchJsExt[e] ? that.libForTouchJsExt[e] : {};
  93. for (let i in e) {
  94. if (typeof e[i] === "function") {
  95. e[i](params);
  96. }
  97. }
  98. })
  99. }
  100. var touch_timer = -1,
  101. lp_timer = -1,
  102. tap_timer = -1,
  103. touch_flag = false,
  104. lp_flag = false,
  105. swipe_flag = false,
  106. mouseDown_flag = false,
  107. tap_sum = 0,
  108. pos = {
  109. x: 0,
  110. y: 0
  111. };
  112.  
  113. function initTouch() {
  114. touch_flag = true;
  115. touch_timer !== -1 && clearTimeout(touch_timer);
  116. touch_timer = setTimeout(() => {
  117. touch_flag = false;
  118. }, 100)
  119. }
  120. that.addEventListener('touchstart', (e) => {
  121. initTouch();
  122. e = e || window.event;
  123. ts(e);
  124. }, false);
  125. that.addEventListener('touchmove', (e) => {
  126. initTouch();
  127. e = e || window.event;
  128. tm(e);
  129. }, false);
  130. that.addEventListener('touchend', (e) => {
  131. initTouch();
  132. e = e || window.event;
  133. te(e);
  134. }, false);
  135. that.addEventListener('mousedown', (e) => {
  136. mouseDown_flag = true;
  137. e = e || window.event;
  138. !touch_flag && ts(e);
  139. }, false);
  140. that.addEventListener('mousemove', (e) => {
  141. if (!mouseDown_flag) {
  142. return false
  143. }
  144. e = e || window.event;
  145. !touch_flag && tm(e);
  146. }, false);
  147. that.addEventListener('mouseup', (e) => {
  148. mouseDown_flag = false;
  149. e = e || window.event;
  150. !touch_flag && te(e);
  151. }, false);
  152. //具体实现
  153. function dir(past, now) { //判方向
  154. if (Math.abs(past.x - now.x) > Math.abs(past.y - now.y)) {
  155. if (now.x > past.x) {
  156. return "right"
  157. } else {
  158. return "left"
  159. }
  160. } else {
  161. if (now.y > past.y) {
  162. return "down"
  163. } else {
  164. return "up"
  165. }
  166. }
  167. return null
  168. }
  169.  
  170. function ts(e) { //touchstart
  171. lp_timer !== -1 && clearTimeout(lp_timer);
  172. lp_timer = -1;
  173. lp_flag = false;
  174. swipe_flag = false;
  175. pos = {
  176. x: e.clientX || e.changedTouches[0].clientX,
  177. y: e.clientY || e.changedTouches[0].clientY
  178. }
  179. lp_timer = setTimeout(function() {
  180. if (!swipe_flag) {
  181. lp_timer = -1;
  182. lp_flag = true;
  183. execFn("longPress", {
  184. 0: pos
  185. });
  186. }
  187. }, 600)
  188. }
  189.  
  190. function tm(e) { //touchmove
  191. let temp = {
  192. x: e.clientX || e.changedTouches[0].clientX,
  193. y: e.clientY || e.changedTouches[0].clientY
  194. }
  195. if (!lp_flag && (Math.abs(pos.x - temp.x) > 10 || Math.abs(pos.y - temp.y) > 10)) {
  196. swipe_flag = true;
  197. lp_timer !== -1 && clearTimeout(lp_timer);
  198. lp_timer = -1;
  199. execFn(dir(pos, temp), {
  200. 0: pos,
  201. 1: temp
  202. });
  203. pos = temp;
  204. }
  205. }
  206.  
  207. function te(e) { //touchend
  208. lp_timer !== -1 && clearTimeout(lp_timer);
  209. tap_timer !== -1 && clearTimeout(tap_timer);
  210. lp_timer = -1;
  211. tap_timer = -1;
  212. if (lp_flag) {
  213. execFn("longPressCancel", {
  214. 0: pos
  215. });
  216. } else if (!swipe_flag) {
  217. tap_sum += 1;
  218. if (tap_sum >= 2) {
  219. tap_sum = 0;
  220. execFn("dbTap", {
  221. 0: pos
  222. });
  223. } else {
  224. tap_timer = setTimeout(() => {
  225. tap_sum = 0;
  226. execFn("tap", {
  227. 0: pos
  228. });
  229. }, 200)
  230. }
  231. }
  232. }
  233. }
  234. return that
  235. }
  236. touchJS.unbind = function(target, evt, fnName = null) {
  237. if (!target || typeof target !== "object") {
  238. console.error("touchJS.unbind(target, evt, fnName)参数错误,对象(target)不存在");
  239. return false;
  240. }
  241. var that = target;
  242. if (typeof evt === "string") {
  243. that.libForTouchJsExt = that.libForTouchJsExt ? that.libForTouchJsExt : {};
  244. if (that.libForTouchJsExt[evt]) {
  245. if (fnName) {
  246. fnName = typeof fnName === "function" ? getFnName(fnName) : fnName;
  247. delete that.libForTouchJsExt[evt][fnName];
  248. } else {
  249. delete that.libForTouchJsExt[evt]
  250. }
  251. }
  252. }
  253. return that
  254. }
  255. window.touchJS = touchJS;
  256. })();