bindingx.js 6.1 KB

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