bindingx.js 6.3 KB

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