index.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. import styleToCssString from '../helpers/libs/styleToCssString'
  4. import { nearest } from '../helpers/shared/nearest'
  5. import { getTouchPoints, getPointsNumber } from '../helpers/shared/gestures'
  6. import { getSystemInfoSync } from '../helpers/hooks/useNativeAPI'
  7. import { rubberbandIfOutOfBounds } from '../helpers/shared/rubberband'
  8. baseComponent({
  9. useExport: true,
  10. properties: {
  11. prefixCls: {
  12. type: String,
  13. value: 'wux-floating-panel',
  14. },
  15. defaultAnchors: {
  16. type: Array,
  17. value: [],
  18. },
  19. },
  20. data: {
  21. wrapStyle: '',
  22. possibles: [],
  23. moving: false,
  24. },
  25. computed: {
  26. classes: ['prefixCls', function(prefixCls) {
  27. const wrap = classNames(prefixCls)
  28. const hd = `${prefixCls}__hd`
  29. const bd = `${prefixCls}__bd`
  30. const bar = `${prefixCls}__bar`
  31. const mask = `${prefixCls}__mask`
  32. return {
  33. wrap,
  34. hd,
  35. bd,
  36. bar,
  37. mask,
  38. }
  39. }],
  40. },
  41. methods: {
  42. /**
  43. * 手指触摸动作开始
  44. */
  45. onTouchStart(e) {
  46. if (this.data.moving || getPointsNumber(e) > 1) return
  47. this.startY = getTouchPoints(e).y
  48. this.moveY = 0
  49. this.endY = 0
  50. this.setData({ moving: true })
  51. },
  52. /**
  53. * 手指触摸后移动
  54. */
  55. onTouchMove(e) {
  56. if (!this.data.moving || getPointsNumber(e) > 1) return
  57. this.moveY = getTouchPoints(e).y
  58. const deltaY = this.moveY - this.startY
  59. const offsetY = rubberbandIfOutOfBounds(
  60. Math.abs(this.lastY + deltaY),
  61. -this.bounds.bottom,
  62. -this.bounds.top,
  63. )
  64. this.setTransform(-Math.round(offsetY))
  65. },
  66. /**
  67. * 手指触摸动作结束
  68. */
  69. onTouchEnd(e) {
  70. if (!this.data.moving || getPointsNumber(e) > 1) return
  71. this.endY = getTouchPoints(e).y
  72. const deltaY = this.endY - this.startY
  73. const offsetY = this.lastY + deltaY
  74. this.lastY = nearest(this.data.possibles, offsetY)
  75. this.setTransform(Math.round(this.lastY), .3)
  76. setTimeout(() => this.setData({ moving: false }), 300)
  77. },
  78. /**
  79. * 设置滚动样式
  80. */
  81. setTransform(y, time) {
  82. const wrapStyle = styleToCssString({
  83. height: `${-this.bounds.top}px`,
  84. transform: `translate3d(0, calc(100% + ${y}px), 0)`,
  85. transition: time ? `cubic-bezier(0, 0, 0.2, 1.15) ${time}s` : 'none',
  86. })
  87. if (this.data.wrapStyle !== wrapStyle) {
  88. this.setData({ wrapStyle }, () => {
  89. if (!!time) {
  90. setTimeout(() => this.setTransform(y), time * 1000)
  91. }
  92. })
  93. this.triggerEvent('heightChange', {
  94. height: -y,
  95. minHeight: -this.bounds.bottom,
  96. maxHeight: -this.bounds.top,
  97. animating: !!time,
  98. })
  99. }
  100. },
  101. ['export']() {
  102. const setHeight = (height, options = { immediate: false }) => {
  103. this.setTransform(-height, options.immediate ? .3 : 0)
  104. this.lastY = -height
  105. }
  106. return {
  107. setHeight,
  108. }
  109. },
  110. },
  111. created() {
  112. this.moveY = 0
  113. this.endY = 0
  114. this.startY = 0
  115. this.lastY = 0
  116. },
  117. attached() {
  118. const defaultAnchors = this.data.defaultAnchors.filter(x => typeof x === 'number').filter(x => x > 0)
  119. const possibles = defaultAnchors.length === 0 ? [-getSystemInfoSync(['window']).windowHeight] : defaultAnchors.map(x => -x)
  120. const bounds = {
  121. top: Math.round(possibles[possibles.length - 1]),
  122. bottom: Math.round(possibles[0]),
  123. }
  124. this.bounds = bounds
  125. this.lastY = bounds.bottom
  126. this.setData({
  127. possibles,
  128. })
  129. this.setTransform(bounds.bottom)
  130. },
  131. })