bindingx.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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 && Array.isArray(this.swipeaction.children)) {
  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. // fix by mehaotian 禁止滑动
  70. if (this.disabled) return
  71. // 每次只触发一次,避免多次监听造成闪烁
  72. if (this.stop) return
  73. this.stop = true
  74. if (this.autoClose && this.swipeaction) {
  75. this.swipeaction.closeOther(this)
  76. }
  77. const leftWidth = this.button.left.width
  78. const rightWidth = this.button.right.width
  79. let expression = this.range(this.x, -rightWidth, leftWidth)
  80. let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
  81. let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)
  82. this.eventpan = BindingX.bind({
  83. anchor: this.box,
  84. eventType: 'pan',
  85. props: [{
  86. element: this.selector,
  87. property: 'transform.translateX',
  88. expression
  89. }, {
  90. element: this.leftButton,
  91. property: 'transform.translateX',
  92. expression: leftExpression
  93. }, {
  94. element: this.rightButton,
  95. property: 'transform.translateX',
  96. expression: rightExpression
  97. }, ]
  98. }, (e) => {
  99. // nope
  100. if (e.state === 'end') {
  101. this.x = e.deltaX + this.x;
  102. this.isclick = true
  103. this.bindTiming(e.deltaX)
  104. }
  105. });
  106. },
  107. touchend(e) {
  108. if (this.isopen !== 'none' && !this.isclick) {
  109. this.open('none')
  110. }
  111. },
  112. bindTiming(x) {
  113. const left = this.x
  114. const leftWidth = this.button.left.width
  115. const rightWidth = this.button.right.width
  116. const threshold = this.threshold
  117. if (!this.isopen || this.isopen === 'none') {
  118. if (left > threshold) {
  119. this.open('left')
  120. } else if (left < -threshold) {
  121. this.open('right')
  122. } else {
  123. this.open('none')
  124. }
  125. } else {
  126. if ((x > -leftWidth && x < 0) || x > rightWidth) {
  127. if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
  128. this.open('left')
  129. } else {
  130. this.open('none')
  131. }
  132. } else {
  133. if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
  134. this.open('right')
  135. } else {
  136. this.open('none')
  137. }
  138. }
  139. }
  140. },
  141. /**
  142. * 移动范围
  143. * @param {Object} num
  144. * @param {Object} mix
  145. * @param {Object} max
  146. */
  147. range(num, mix, max) {
  148. return `min(max(x+${num}, ${mix}), ${max})`
  149. },
  150. /**
  151. * 开启swipe
  152. */
  153. open(type) {
  154. this.animation(type)
  155. },
  156. /**
  157. * 关闭swipe
  158. */
  159. close() {
  160. this.animation('none')
  161. },
  162. /**
  163. * 开启关闭动画
  164. * @param {Object} type
  165. */
  166. animation(type) {
  167. const time = 300
  168. const leftWidth = this.button.left.width
  169. const rightWidth = this.button.right.width
  170. if (this.eventpan && this.eventpan.token) {
  171. BindingX.unbind({
  172. token: this.eventpan.token,
  173. eventType: 'pan'
  174. })
  175. }
  176. switch (type) {
  177. case 'left':
  178. Promise.all([
  179. this.move(this.selector, leftWidth),
  180. this.move(this.leftButton, 0),
  181. this.move(this.rightButton, rightWidth * 2)
  182. ]).then(() => {
  183. this.setEmit(leftWidth, type)
  184. })
  185. break
  186. case 'right':
  187. Promise.all([
  188. this.move(this.selector, -rightWidth),
  189. this.move(this.leftButton, -leftWidth * 2),
  190. this.move(this.rightButton, 0)
  191. ]).then(() => {
  192. this.setEmit(-rightWidth, type)
  193. })
  194. break
  195. default:
  196. Promise.all([
  197. this.move(this.selector, 0),
  198. this.move(this.leftButton, -leftWidth),
  199. this.move(this.rightButton, rightWidth)
  200. ]).then(() => {
  201. this.setEmit(0, type)
  202. })
  203. }
  204. },
  205. setEmit(x, type) {
  206. const leftWidth = this.button.left.width
  207. const rightWidth = this.button.right.width
  208. this.isopen = this.isopen || 'none'
  209. this.stop = false
  210. this.isclick = false
  211. // 只有状态不一致才会返回结果
  212. if (this.isopen !== type && this.x !== x) {
  213. if (type === 'left' && leftWidth > 0) {
  214. this.$emit('change', 'left')
  215. }
  216. if (type === 'right' && rightWidth > 0) {
  217. this.$emit('change', 'right')
  218. }
  219. if (type === 'none') {
  220. this.$emit('change', 'none')
  221. }
  222. }
  223. this.x = x
  224. this.isopen = type
  225. },
  226. move(ref, value) {
  227. return new Promise((resolve, reject) => {
  228. animation.transition(ref, {
  229. styles: {
  230. transform: `translateX(${value})`,
  231. },
  232. duration: 150, //ms
  233. timingFunction: 'linear',
  234. needLayout: false,
  235. delay: 0 //ms
  236. }, function(res) {
  237. resolve(res)
  238. })
  239. })
  240. },
  241. /**
  242. * 获取ref
  243. * @param {Object} el
  244. */
  245. getEl(el) {
  246. return el.ref
  247. },
  248. /**
  249. * 获取节点信息
  250. */
  251. getSelectorQuery() {
  252. Promise.all([
  253. this.getDom('left'),
  254. this.getDom('right'),
  255. ]).then((data) => {
  256. let show = 'none'
  257. if (this.autoClose) {
  258. show = 'none'
  259. } else {
  260. show = this.show
  261. }
  262. if (show === 'none') {
  263. // this.close()
  264. } else {
  265. this.open(show)
  266. }
  267. })
  268. },
  269. getDom(str) {
  270. return new Promise((resolve, reject) => {
  271. dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => {
  272. if (data) {
  273. this.button[str] = data.size
  274. resolve(data)
  275. } else {
  276. reject()
  277. }
  278. })
  279. })
  280. }
  281. }
  282. }
  283. // #endif
  284. export default bindIngXMixins