mpother.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. let otherMixins = {}
  2. // #ifndef APP-PLUS|| MP-WEIXIN || H5
  3. const MIN_DISTANCE = 10;
  4. otherMixins = {
  5. data() {
  6. // TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug
  7. const elClass = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
  8. return {
  9. uniShow: false,
  10. left: 0,
  11. buttonShow: 'none',
  12. ani: false,
  13. moveLeft: '',
  14. elClass
  15. }
  16. },
  17. watch: {
  18. show(newVal) {
  19. if (this.autoClose) return
  20. this.openState(newVal)
  21. },
  22. left() {
  23. this.moveLeft = `translateX(${this.left}px)`
  24. },
  25. buttonShow(newVal) {
  26. if (this.autoClose) return
  27. this.openState(newVal)
  28. },
  29. leftOptions() {
  30. this.init()
  31. },
  32. rightOptions() {
  33. this.init()
  34. }
  35. },
  36. mounted() {
  37. this.swipeaction = this.getSwipeAction()
  38. if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
  39. this.swipeaction.children.push(this)
  40. }
  41. this.init()
  42. },
  43. methods: {
  44. init() {
  45. clearTimeout(this.timer)
  46. this.timer = setTimeout(() => {
  47. this.getSelectorQuery()
  48. }, 100)
  49. // 移动距离
  50. this.left = 0
  51. this.x = 0
  52. },
  53. closeSwipe(e) {
  54. if (this.autoClose && this.swipeaction) {
  55. this.swipeaction.closeOther(this)
  56. }
  57. },
  58. appTouchStart(e) {
  59. const {
  60. clientX
  61. } = e.changedTouches[0]
  62. this.clientX = clientX
  63. this.timestamp = new Date().getTime()
  64. },
  65. appTouchEnd(e, index, item, position) {
  66. const {
  67. clientX
  68. } = e.changedTouches[0]
  69. // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
  70. let diff = Math.abs(this.clientX - clientX)
  71. let time = (new Date().getTime()) - this.timestamp
  72. if (diff < 40 && time < 300) {
  73. this.$emit('click', {
  74. content: item,
  75. index,
  76. position
  77. })
  78. }
  79. },
  80. touchstart(e) {
  81. if (this.disabled) return
  82. this.ani = false
  83. this.x = this.left || 0
  84. this.stopTouchStart(e)
  85. this.autoClose && this.closeSwipe()
  86. },
  87. touchmove(e) {
  88. if (this.disabled) return
  89. // 是否可以滑动页面
  90. this.stopTouchMove(e);
  91. if (this.direction !== 'horizontal') {
  92. return;
  93. }
  94. this.move(this.x + this.deltaX)
  95. return false
  96. },
  97. touchend() {
  98. if (this.disabled) return
  99. this.moveDirection(this.left)
  100. },
  101. /**
  102. * 设置移动距离
  103. * @param {Object} value
  104. */
  105. move(value) {
  106. value = value || 0
  107. const leftWidth = this.leftWidth
  108. const rightWidth = this.rightWidth
  109. // 获取可滑动范围
  110. this.left = this.range(value, -rightWidth, leftWidth);
  111. },
  112. /**
  113. * 获取范围
  114. * @param {Object} num
  115. * @param {Object} min
  116. * @param {Object} max
  117. */
  118. range(num, min, max) {
  119. return Math.min(Math.max(num, min), max);
  120. },
  121. /**
  122. * 移动方向判断
  123. * @param {Object} left
  124. * @param {Object} value
  125. */
  126. moveDirection(left) {
  127. const threshold = this.threshold
  128. const isopen = this.isopen || 'none'
  129. const leftWidth = this.leftWidth
  130. const rightWidth = this.rightWidth
  131. if (this.deltaX === 0) {
  132. this.openState('none')
  133. return
  134. }
  135. if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth >
  136. 0 && rightWidth +
  137. left < threshold)) {
  138. // right
  139. this.openState('right')
  140. } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth >
  141. 0 &&
  142. leftWidth - left < threshold)) {
  143. // left
  144. this.openState('left')
  145. } else {
  146. // default
  147. this.openState('none')
  148. }
  149. },
  150. /**
  151. * 开启状态
  152. * @param {Boolean} type
  153. */
  154. openState(type) {
  155. const leftWidth = this.leftWidth
  156. const rightWidth = this.rightWidth
  157. let left = ''
  158. this.isopen = this.isopen ? this.isopen : 'none'
  159. switch (type) {
  160. case "left":
  161. left = leftWidth
  162. break
  163. case "right":
  164. left = -rightWidth
  165. break
  166. default:
  167. left = 0
  168. }
  169. if (this.isopen !== type) {
  170. this.throttle = true
  171. this.$emit('change', type)
  172. }
  173. this.isopen = type
  174. // 添加动画类
  175. this.ani = true
  176. this.$nextTick(() => {
  177. this.move(left)
  178. })
  179. // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的
  180. },
  181. close() {
  182. this.openState('none')
  183. },
  184. getDirection(x, y) {
  185. if (x > y && x > MIN_DISTANCE) {
  186. return 'horizontal';
  187. }
  188. if (y > x && y > MIN_DISTANCE) {
  189. return 'vertical';
  190. }
  191. return '';
  192. },
  193. /**
  194. * 重置滑动状态
  195. * @param {Object} event
  196. */
  197. resetTouchStatus() {
  198. this.direction = '';
  199. this.deltaX = 0;
  200. this.deltaY = 0;
  201. this.offsetX = 0;
  202. this.offsetY = 0;
  203. },
  204. /**
  205. * 设置滑动开始位置
  206. * @param {Object} event
  207. */
  208. stopTouchStart(event) {
  209. this.resetTouchStatus();
  210. const touch = event.touches[0];
  211. this.startX = touch.clientX;
  212. this.startY = touch.clientY;
  213. },
  214. /**
  215. * 滑动中,是否禁止打开
  216. * @param {Object} event
  217. */
  218. stopTouchMove(event) {
  219. const touch = event.touches[0];
  220. this.deltaX = touch.clientX - this.startX;
  221. this.deltaY = touch.clientY - this.startY;
  222. this.offsetX = Math.abs(this.deltaX);
  223. this.offsetY = Math.abs(this.deltaY);
  224. this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
  225. },
  226. getSelectorQuery() {
  227. const views = uni.createSelectorQuery().in(this)
  228. views
  229. .selectAll('.' + this.elClass)
  230. .boundingClientRect(data => {
  231. if (data.length === 0) return
  232. let show = 'none'
  233. if (this.autoClose) {
  234. show = 'none'
  235. } else {
  236. show = this.show
  237. }
  238. this.leftWidth = data[0].width || 0
  239. this.rightWidth = data[1].width || 0
  240. this.buttonShow = show
  241. })
  242. .exec()
  243. }
  244. }
  245. }
  246. // #endif
  247. export default otherMixins