bindingx.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. const BindingX = uni.requireNativePlugin('bindingx');
  2. const dom = uni.requireNativePlugin('dom');
  3. const animation = uni.requireNativePlugin('animation');
  4. export default {
  5. data() {
  6. return {}
  7. },
  8. watch: {
  9. show(newVal) {
  10. if (this.autoClose) return
  11. if (this.stop) return
  12. this.stop = true
  13. if (newVal) {
  14. this.open(newVal)
  15. } else {
  16. this.close()
  17. }
  18. },
  19. leftOptions() {
  20. this.getSelectorQuery()
  21. this.init()
  22. },
  23. rightOptions(newVal) {
  24. this.init()
  25. }
  26. },
  27. created() {
  28. this.swipeaction = this.getSwipeAction()
  29. if (this.swipeaction.children !== undefined) {
  30. this.swipeaction.children.push(this)
  31. }
  32. },
  33. mounted() {
  34. this.box = this.getEl(this.$refs['selector-box--hock'])
  35. this.selector = this.getEl(this.$refs['selector-content--hock']);
  36. this.leftButton = this.getEl(this.$refs['selector-left-button--hock']);
  37. this.rightButton = this.getEl(this.$refs['selector-right-button--hock']);
  38. this.init()
  39. },
  40. // beforeDestroy() {
  41. // this.swipeaction.children.forEach((item, index) => {
  42. // if (item === this) {
  43. // this.swipeaction.children.splice(index, 1)
  44. // }
  45. // })
  46. // },
  47. methods: {
  48. init() {
  49. this.$nextTick(() => {
  50. this.x = 0
  51. this.button = {
  52. show: false
  53. }
  54. setTimeout(() => {
  55. this.getSelectorQuery()
  56. }, 200)
  57. })
  58. },
  59. onClick(index, item, position) {
  60. this.$emit('click', {
  61. content: item,
  62. index,
  63. position
  64. })
  65. },
  66. touchstart(e) {
  67. // 每次只触发一次,避免多次监听造成闪烁
  68. if (this.stop) return
  69. this.stop = true
  70. if (this.autoClose) {
  71. this.swipeaction.closeOther(this)
  72. }
  73. const leftWidth = this.button.left.width
  74. const rightWidth = this.button.right.width
  75. let expression = this.range(this.x, -rightWidth, leftWidth)
  76. let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
  77. let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)
  78. this.eventpan = BindingX.bind({
  79. anchor: this.box,
  80. eventType: 'pan',
  81. props: [{
  82. element: this.selector,
  83. property: 'transform.translateX',
  84. expression
  85. }, {
  86. element: this.leftButton,
  87. property: 'transform.translateX',
  88. expression: leftExpression
  89. }, {
  90. element: this.rightButton,
  91. property: 'transform.translateX',
  92. expression: rightExpression
  93. }, ]
  94. }, (e) => {
  95. // nope
  96. if (e.state === 'end') {
  97. this.x = e.deltaX + this.x;
  98. this.isclick = true
  99. this.bindTiming(e.deltaX)
  100. }
  101. });
  102. },
  103. touchend(e) {
  104. if (this.isopen !== 'none' && !this.isclick) {
  105. this.open('none')
  106. }
  107. },
  108. bindTiming(x) {
  109. const left = this.x
  110. const leftWidth = this.button.left.width
  111. const rightWidth = this.button.right.width
  112. const threshold = this.threshold
  113. if (!this.isopen || this.isopen === 'none') {
  114. if (left > threshold) {
  115. this.open('left')
  116. } else if (left < -threshold) {
  117. this.open('right')
  118. } else {
  119. this.open('none')
  120. }
  121. } else {
  122. if ((x > -leftWidth && x < 0) || x > rightWidth) {
  123. if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
  124. this.open('left')
  125. } else {
  126. this.open('none')
  127. }
  128. } else {
  129. if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
  130. this.open('right')
  131. } else {
  132. this.open('none')
  133. }
  134. }
  135. }
  136. },
  137. /**
  138. * 移动范围
  139. * @param {Object} num
  140. * @param {Object} mix
  141. * @param {Object} max
  142. */
  143. range(num, mix, max) {
  144. return `min(max(x+${num}, ${mix}), ${max})`
  145. },
  146. /**
  147. * 开启swipe
  148. */
  149. open(type) {
  150. this.animation(type)
  151. },
  152. /**
  153. * 关闭swipe
  154. */
  155. close() {
  156. this.animation('none')
  157. },
  158. /**
  159. * 开启关闭动画
  160. * @param {Object} type
  161. */
  162. animation(type) {
  163. const time = 300
  164. const leftWidth = this.button.left.width
  165. const rightWidth = this.button.right.width
  166. if (this.eventpan && this.eventpan.token) {
  167. BindingX.unbind({
  168. token: this.eventpan.token,
  169. eventType: 'pan'
  170. })
  171. }
  172. switch (type) {
  173. case 'left':
  174. Promise.all([
  175. this.move(this.selector, leftWidth),
  176. this.move(this.leftButton, 0),
  177. this.move(this.rightButton, rightWidth * 2)
  178. ]).then(() => {
  179. this.setEmit(leftWidth, type)
  180. })
  181. break
  182. case 'right':
  183. Promise.all([
  184. this.move(this.selector, -rightWidth),
  185. this.move(this.leftButton, -leftWidth * 2),
  186. this.move(this.rightButton, 0)
  187. ]).then(() => {
  188. this.setEmit(-rightWidth, type)
  189. })
  190. break
  191. default:
  192. Promise.all([
  193. this.move(this.selector, 0),
  194. this.move(this.leftButton, -leftWidth),
  195. this.move(this.rightButton, rightWidth)
  196. ]).then(() => {
  197. this.setEmit(0, type)
  198. })
  199. }
  200. },
  201. setEmit(x, type) {
  202. const leftWidth = this.button.left.width
  203. const rightWidth = this.button.right.width
  204. this.isopen = this.isopen || 'none'
  205. this.stop = false
  206. this.isclick = false
  207. // 只有状态不一致才会返回结果
  208. if (this.isopen !== type && this.x !== x) {
  209. if (type === 'left' && leftWidth > 0) {
  210. this.$emit('change', 'left')
  211. }
  212. if (type === 'right' && rightWidth > 0) {
  213. this.$emit('change', 'right')
  214. }
  215. if (type === 'none') {
  216. this.$emit('change', 'none')
  217. }
  218. }
  219. this.x = x
  220. this.isopen = type
  221. },
  222. move(ref, value) {
  223. return new Promise((resolve, reject) => {
  224. animation.transition(ref, {
  225. styles: {
  226. transform: `translateX(${value})`,
  227. },
  228. duration: 150, //ms
  229. timingFunction: 'linear',
  230. needLayout: false,
  231. delay: 0 //ms
  232. }, function(res) {
  233. resolve(res)
  234. })
  235. })
  236. },
  237. /**
  238. * 获取ref
  239. * @param {Object} el
  240. */
  241. getEl(el) {
  242. return el.ref
  243. },
  244. /**
  245. * 获取节点信息
  246. */
  247. getSelectorQuery() {
  248. Promise.all([
  249. this.getDom('left'),
  250. this.getDom('right'),
  251. ]).then((data) => {
  252. let show = 'none'
  253. if (this.autoClose) {
  254. show = 'none'
  255. } else {
  256. show = this.show
  257. }
  258. if (show === 'none') {
  259. // this.close()
  260. } else {
  261. this.open(show)
  262. }
  263. })
  264. },
  265. getDom(str) {
  266. return new Promise((resolve, reject) => {
  267. dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => {
  268. if (data) {
  269. this.button[str] = data.size
  270. resolve(data)
  271. } else {
  272. reject()
  273. }
  274. })
  275. })
  276. }
  277. }
  278. }