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.children !== undefined) {
  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) return
  55. this.swipeaction.closeOther(this)
  56. },
  57. appTouchStart(e) {
  58. const {
  59. clientX
  60. } = e.changedTouches[0]
  61. this.clientX = clientX
  62. this.timestamp = new Date().getTime()
  63. },
  64. appTouchEnd(e, index, item, position) {
  65. const {
  66. clientX
  67. } = e.changedTouches[0]
  68. // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
  69. let diff = Math.abs(this.clientX - clientX)
  70. let time = (new Date().getTime()) - this.timestamp
  71. if (diff < 40 && time < 300) {
  72. this.$emit('click', {
  73. content: item,
  74. index,
  75. position
  76. })
  77. }
  78. },
  79. touchstart(e) {
  80. if (this.disabled) return
  81. this.ani = false
  82. this.x = this.left || 0
  83. this.stopTouchStart(e)
  84. this.autoClose && this.closeSwipe()
  85. },
  86. touchmove(e) {
  87. if (this.disabled) return
  88. // 是否可以滑动页面
  89. this.stopTouchMove(e);
  90. if (this.direction !== 'horizontal') {
  91. return;
  92. }
  93. this.move(this.x + this.deltaX)
  94. return false
  95. },
  96. touchend() {
  97. if (this.disabled) return
  98. this.moveDirection(this.left)
  99. },
  100. /**
  101. * 设置移动距离
  102. * @param {Object} value
  103. */
  104. move(value) {
  105. value = value || 0
  106. const leftWidth = this.leftWidth
  107. const rightWidth = this.rightWidth
  108. // 获取可滑动范围
  109. this.left = this.range(value, -rightWidth, leftWidth);
  110. },
  111. /**
  112. * 获取范围
  113. * @param {Object} num
  114. * @param {Object} min
  115. * @param {Object} max
  116. */
  117. range(num, min, max) {
  118. return Math.min(Math.max(num, min), max);
  119. },
  120. /**
  121. * 移动方向判断
  122. * @param {Object} left
  123. * @param {Object} value
  124. */
  125. moveDirection(left) {
  126. const threshold = this.threshold
  127. const isopen = this.isopen || 'none'
  128. const leftWidth = this.leftWidth
  129. const rightWidth = this.rightWidth
  130. if (this.deltaX === 0) {
  131. this.openState('none')
  132. return
  133. }
  134. if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth >
  135. 0 && rightWidth +
  136. left < threshold)) {
  137. // right
  138. this.openState('right')
  139. } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth >
  140. 0 &&
  141. leftWidth - left < threshold)) {
  142. // left
  143. this.openState('left')
  144. } else {
  145. // default
  146. this.openState('none')
  147. }
  148. },
  149. /**
  150. * 开启状态
  151. * @param {Boolean} type
  152. */
  153. openState(type) {
  154. const leftWidth = this.leftWidth
  155. const rightWidth = this.rightWidth
  156. let left = ''
  157. this.isopen = this.isopen ? this.isopen : 'none'
  158. switch (type) {
  159. case "left":
  160. left = leftWidth
  161. break
  162. case "right":
  163. left = -rightWidth
  164. break
  165. default:
  166. left = 0
  167. }
  168. if (this.isopen !== type) {
  169. this.throttle = true
  170. this.$emit('change', type)
  171. }
  172. this.isopen = type
  173. // 添加动画类
  174. this.ani = true
  175. this.$nextTick(() => {
  176. this.move(left)
  177. })
  178. // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的
  179. },
  180. close() {
  181. this.openState('none')
  182. },
  183. getDirection(x, y) {
  184. if (x > y && x > MIN_DISTANCE) {
  185. return 'horizontal';
  186. }
  187. if (y > x && y > MIN_DISTANCE) {
  188. return 'vertical';
  189. }
  190. return '';
  191. },
  192. /**
  193. * 重置滑动状态
  194. * @param {Object} event
  195. */
  196. resetTouchStatus() {
  197. this.direction = '';
  198. this.deltaX = 0;
  199. this.deltaY = 0;
  200. this.offsetX = 0;
  201. this.offsetY = 0;
  202. },
  203. /**
  204. * 设置滑动开始位置
  205. * @param {Object} event
  206. */
  207. stopTouchStart(event) {
  208. this.resetTouchStatus();
  209. const touch = event.touches[0];
  210. this.startX = touch.clientX;
  211. this.startY = touch.clientY;
  212. },
  213. /**
  214. * 滑动中,是否禁止打开
  215. * @param {Object} event
  216. */
  217. stopTouchMove(event) {
  218. const touch = event.touches[0];
  219. this.deltaX = touch.clientX - this.startX;
  220. this.deltaY = touch.clientY - this.startY;
  221. this.offsetX = Math.abs(this.deltaX);
  222. this.offsetY = Math.abs(this.deltaY);
  223. this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
  224. },
  225. getSelectorQuery() {
  226. const views = uni.createSelectorQuery().in(this)
  227. views
  228. .selectAll('.' + this.elClass)
  229. .boundingClientRect(data => {
  230. if (data.length === 0) return
  231. let show = 'none'
  232. if (this.autoClose) {
  233. show = 'none'
  234. } else {
  235. show = this.show
  236. }
  237. this.leftWidth = data[0].width || 0
  238. this.rightWidth = data[1].width || 0
  239. this.buttonShow = show
  240. })
  241. .exec()
  242. }
  243. }
  244. }
  245. // #endif
  246. export default otherMixins