bindingx.js 6.3 KB

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