mpother.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 > 0 && rightWidth +
  135. left < threshold)) {
  136. // right
  137. this.openState('right')
  138. } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 &&
  139. leftWidth - left < threshold)) {
  140. // left
  141. this.openState('left')
  142. } else {
  143. // default
  144. this.openState('none')
  145. }
  146. },
  147. /**
  148. * 开启状态
  149. * @param {Boolean} type
  150. */
  151. openState(type) {
  152. const leftWidth = this.leftWidth
  153. const rightWidth = this.rightWidth
  154. let left = ''
  155. this.isopen = this.isopen ? this.isopen : 'none'
  156. switch (type) {
  157. case "left":
  158. left = leftWidth
  159. break
  160. case "right":
  161. left = -rightWidth
  162. break
  163. default:
  164. left = 0
  165. }
  166. if (this.isopen !== type) {
  167. this.throttle = true
  168. this.$emit('change', type)
  169. }
  170. this.isopen = type
  171. // 添加动画类
  172. this.ani = true
  173. this.$nextTick(() => {
  174. this.move(left)
  175. })
  176. // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的
  177. },
  178. close() {
  179. this.openState('none')
  180. },
  181. getDirection(x, y) {
  182. if (x > y && x > MIN_DISTANCE) {
  183. return 'horizontal';
  184. }
  185. if (y > x && y > MIN_DISTANCE) {
  186. return 'vertical';
  187. }
  188. return '';
  189. },
  190. /**
  191. * 重置滑动状态
  192. * @param {Object} event
  193. */
  194. resetTouchStatus() {
  195. this.direction = '';
  196. this.deltaX = 0;
  197. this.deltaY = 0;
  198. this.offsetX = 0;
  199. this.offsetY = 0;
  200. },
  201. /**
  202. * 设置滑动开始位置
  203. * @param {Object} event
  204. */
  205. stopTouchStart(event) {
  206. this.resetTouchStatus();
  207. const touch = event.touches[0];
  208. this.startX = touch.clientX;
  209. this.startY = touch.clientY;
  210. },
  211. /**
  212. * 滑动中,是否禁止打开
  213. * @param {Object} event
  214. */
  215. stopTouchMove(event) {
  216. const touch = event.touches[0];
  217. this.deltaX = touch.clientX - this.startX;
  218. this.deltaY = touch.clientY - this.startY;
  219. this.offsetX = Math.abs(this.deltaX);
  220. this.offsetY = Math.abs(this.deltaY);
  221. this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
  222. },
  223. getSelectorQuery() {
  224. const views = uni.createSelectorQuery().in(this)
  225. views
  226. .selectAll('.'+this.elClass)
  227. .boundingClientRect(data => {
  228. if(data.length === 0) return
  229. let show = 'none'
  230. if (this.autoClose) {
  231. show = 'none'
  232. } else {
  233. show = this.show
  234. }
  235. this.leftWidth = data[0].width || 0
  236. this.rightWidth = data[1].width || 0
  237. this.buttonShow = show
  238. })
  239. .exec()
  240. }
  241. }
  242. }
  243. // #endif
  244. export default otherMixins