bab-Touchbox.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <template>
  2. <view>
  3. <view :class="isend?'fixedbox2' :'fixedbox'"
  4. :style="{'height':windowHeight + 'px','width':windowWidth + 'px','top':fixboxtop +'px','border-top-left-radius':radius,'border-top-right-radius':radius,'z-index':zIndex}"
  5. @touchmove="getstart" @tap="tap" @touchend="getend" ref="fixbox">
  6. <view class="content" :style="{'height':windowHeight + 'px'}">
  7. <view class="tapBoxTouchLine" v-if="showLine">
  8. <view class="line" :style="{'transform': `scaleY(${lineScale})`,'width':`${lineWidth}rpx`}"></view>
  9. </view>
  10. <slot />
  11. </view>
  12. </view>
  13. </view>
  14. </template>
  15. <script>
  16. /**
  17. * tapBox 触摸上拉组件
  18. * @description 触摸上拉组件,类似于高德美团上拉组件
  19. * @property {String} radius 左上右上圆角
  20. * @property {Number} minHeight 最低高度 占总屏幕高度占比
  21. * @property {Number} minHeight 最高高度 占总屏幕高度占比
  22. * @property {Number} touchHeight 允许滑动区域高度默认顶部横线高度 0为任意区域可滑动,单位rpx
  23. * @property {Boolean} showLine 上否显示顶部滑动线
  24. * @event {Function} tap 点击事件
  25. * @event {Function} getstart 开始滑动时触发事件
  26. * @event {Function} getend 滑动结束事件
  27. */
  28. export default {
  29. name: 'tapBox',
  30. data() {
  31. return {
  32. windowHeight: 0, // 屏幕高度
  33. windowWidth: 0, // 屏幕宽度
  34. firsttop: 0, // 默认高度
  35. fixboxtop: 0, // 实际高度
  36. phonetop: 200, // 默认滑动分界线 - 后面计算为最低与最高的一半
  37. phoneMinTop: 100, // 默认滑动分界线 - 后面计算为最低与最高的一半
  38. isend: false, // 触摸结束
  39. isfirst: true, // 手指第一次触摸
  40. tapboxtop: 0, // 手指距离顶部距离
  41. };
  42. },
  43. props: {
  44. // width: 120rpx;
  45. // transform: scaleY(0.5);
  46. lineScale: {
  47. type: Number,
  48. default: 1,
  49. },
  50. lineWidth: {
  51. type: Number,
  52. default: 220,
  53. },
  54. zIndex: {
  55. type: Number,
  56. default: 99,
  57. },
  58. radius: {
  59. type: String,
  60. default: '50rpx',
  61. },
  62. minHeight: {
  63. type: Number,
  64. default: 0.2,
  65. },
  66. smallHeight: {
  67. type: Number,
  68. default: 0.35,
  69. },
  70. maxHeight: {
  71. type: Number,
  72. default: 0.5,
  73. },
  74. touchHeight: {
  75. type: Number,
  76. default: 0,
  77. },
  78. showLine: {
  79. type: Boolean,
  80. default: true,
  81. },
  82. },
  83. mounted() {
  84. this.$nextTick(function() {
  85. this.windowWidth = uni.getSystemInfoSync().windowWidth;
  86. this.windowHeight = uni.getSystemInfoSync().windowHeight;
  87. var defaultHeight = this.windowHeight * (1 - this.minHeight);
  88. this.firsttop = defaultHeight;
  89. this.phonetop =
  90. (this.windowHeight * this.maxHeight - this.windowHeight * this.minHeight) / 2;
  91. this.phoneMinTop =
  92. (this.windowHeight * this.minHeight - this.windowHeight * this.smallHeight) / 2;
  93. this.fixboxtop = defaultHeight;
  94. this.$emit('currentHeight', this.windowHeight - this.fixboxtop);
  95. this.$emit('maxtHeight', this.windowHeight * this.maxHeight);
  96. });
  97. },
  98. onReady() {},
  99. computed: {},
  100. methods: {
  101. // 隐藏
  102. concealList(){
  103. const H_ = uni.getSystemInfoSync().windowHeight;
  104. this.fixboxtop = H_ - uni.upx2px(200)
  105. },
  106. tap(e) {
  107. // console.log(e)
  108. },
  109. getstart(e) {
  110. e.preventDefault();
  111. const {clientY , screenY } = e.touches[0];
  112. let Y = clientY || screenY;
  113. // //#ifdef MP-WEIXIN
  114. // Y = e.touches[0].clientY;
  115. // //#endif
  116. // //#ifndef MP-WEIXIN
  117. // Y = e.touches[0].screenY;
  118. // //#endif
  119. // console.log(Y)
  120. // 这里特殊处理 解决:在滑动框内如果存在滚动元素,则会出现滑动时滑动框和内部滚动同时滑的问题
  121. if (this.touchHeight !== 0) {
  122. if (Y - this.fixboxtop > this.touchHeight) {
  123. return false;
  124. }
  125. }
  126. this.isend = false;
  127. if (this.isfirst) {
  128. this.isfirst = false;
  129. this.tapboxtop = Y - this.fixboxtop;
  130. }
  131. this.fixboxtop = Y - this.tapboxtop;
  132. console.log('this.fixboxtop > this.firsttop = ' ,Y , this.tapboxtop)
  133. if (this.fixboxtop > this.firsttop) {
  134. if (this.fixboxtop >= this.windowHeight * (1 - this.smallHeight)) {
  135. this.fixboxtop = this.windowHeight * (1 - this.smallHeight);
  136. }
  137. } else {
  138. // 往上滑
  139. if (this.fixboxtop <= this.windowHeight * (1 - this.maxHeight)) {
  140. this.fixboxtop = this.windowHeight * (1 - this.maxHeight);
  141. }
  142. }
  143. this.$emit('currentHeight', this.windowHeight - this.fixboxtop);
  144. },
  145. getend() {
  146. this.isend = true;
  147. this.isfirst = true;
  148. //中间高度以下
  149. if (this.fixboxtop > this.firsttop) {
  150. //当超过平衡值
  151. if (this.fixboxtop - this.firsttop >= this.phoneMinTop) {
  152. this.fixboxtop = this.windowHeight * (1 - this.smallHeight);
  153. } else {
  154. this.fixboxtop = this.windowHeight * (1 - this.minHeight);
  155. }
  156. }
  157. //中间高度以上
  158. else {
  159. //滑动距离小于平衡值
  160. if (this.firsttop - this.fixboxtop <= this.phonetop) {
  161. this.fixboxtop = this.firsttop;
  162. } else {
  163. this.fixboxtop = this.windowHeight * (1 - this.maxHeight);
  164. }
  165. }
  166. this.$emit('currentHeight', this.windowHeight - this.fixboxtop);
  167. },
  168. },
  169. };
  170. </script>
  171. <style lang="scss" scoped>
  172. .tapBoxTouchLine {
  173. display: flex;
  174. align-items: center;
  175. justify-content: center;
  176. padding: 20rpx 0 30rpx;
  177. }
  178. .line {
  179. margin: 0px;
  180. vertical-align: middle;
  181. // border-bottom: 8rpx solid rgb(214, 215, 217);
  182. height: 8rpx;
  183. background-color: rgb(214, 215, 217);
  184. border-radius: 4rpx;
  185. // border: 4rpx;
  186. // border-top-color: rgb(214, 215, 217);
  187. // border-right-color: rgb(214, 215, 217);
  188. // border-left-color: rgb(214, 215, 217);
  189. }
  190. .fixedbox {
  191. position: fixed;
  192. left: 0;
  193. background-color: #ffffff;
  194. padding: 0 12px;
  195. }
  196. .fixedbox2 {
  197. position: fixed;
  198. left: 0;
  199. background-color: #ffffff;
  200. padding: 0 12px;
  201. transition-property: top;
  202. transition-duration: 0.8s;
  203. }
  204. </style>