mpother.js 5.5 KB

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