hw-cus-ui 1.0.23 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DraggableBottomPopup/DraggableBottomPopup.vue +195 -0
- package/DraggableBottomPopup/index.ts +10 -0
- package/index.d.ts +3 -2
- package/index.ts +3 -2
- package/package.json +1 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="draggable-popup-mask">
|
|
3
|
+
<view
|
|
4
|
+
class="draggable-popup-container"
|
|
5
|
+
:style="{
|
|
6
|
+
top: popupTop + 'px',
|
|
7
|
+
position: isDrag ? 'fixed' : 'initial',
|
|
8
|
+
borderTopLeftRadius: isDrag ? '20rpx' : '0',
|
|
9
|
+
borderTopRightRadius: isDrag ? '20rpx' : '0'
|
|
10
|
+
}"
|
|
11
|
+
>
|
|
12
|
+
<view
|
|
13
|
+
v-if="isDrag"
|
|
14
|
+
class="draggable-popup-handle"
|
|
15
|
+
@touchstart="handleTouchStart"
|
|
16
|
+
@touchmove="handleTouchMove"
|
|
17
|
+
@touchend="handleTouchEnd"
|
|
18
|
+
@touchcancel="handleTouchEnd"
|
|
19
|
+
>
|
|
20
|
+
<view class="draggable-popup-handle-line"></view>
|
|
21
|
+
</view>
|
|
22
|
+
<view class="draggable-popup-content" :style="{ height: isDrag ? contentPopupTop + 'px' : 'auto' }">
|
|
23
|
+
<slot></slot>
|
|
24
|
+
</view>
|
|
25
|
+
</view>
|
|
26
|
+
</view>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script>
|
|
30
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
31
|
+
export default {
|
|
32
|
+
name: 'DraggableBottomPopup',
|
|
33
|
+
props: {
|
|
34
|
+
heightCalc: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: '0.4'
|
|
37
|
+
},
|
|
38
|
+
isDrag: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
default: () => true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
data() {
|
|
44
|
+
return {
|
|
45
|
+
startY: 0,
|
|
46
|
+
startTop: 0,
|
|
47
|
+
popupTop: 0,
|
|
48
|
+
windowHeight: 0,
|
|
49
|
+
contentPopupTop: 0,
|
|
50
|
+
isMoving: false,
|
|
51
|
+
containerHeight: 0, // 容器高度
|
|
52
|
+
updateContentPopupTop: null // 防抖函数
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
mounted() {
|
|
57
|
+
this.getWindowInfo();
|
|
58
|
+
this.initPopupPosition();
|
|
59
|
+
// 初始化防抖函数
|
|
60
|
+
this.updateContentPopupTop = useDebounceFn(() => {
|
|
61
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
62
|
+
}, 300);
|
|
63
|
+
},
|
|
64
|
+
methods: {
|
|
65
|
+
getWindowInfo() {
|
|
66
|
+
const systemInfo = uni.getSystemInfoSync();
|
|
67
|
+
this.windowHeight = systemInfo.windowHeight;
|
|
68
|
+
// 初始位置在屏幕外,隐藏状态
|
|
69
|
+
this.popupTop = this.windowHeight;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
initPopupPosition() {
|
|
73
|
+
this.$nextTick(() => {
|
|
74
|
+
// 获取内容高度
|
|
75
|
+
const query = uni.createSelectorQuery().in(this);
|
|
76
|
+
query
|
|
77
|
+
.select('.draggable-popup-container')
|
|
78
|
+
.boundingClientRect((data) => {
|
|
79
|
+
if (data) {
|
|
80
|
+
this.containerHeight = data.height;
|
|
81
|
+
// 默认显示屏幕高度的60%
|
|
82
|
+
this.popupTop = this.windowHeight * this.heightCalc;
|
|
83
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
84
|
+
this.changeTop();
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
.exec();
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
handleTouchStart(e) {
|
|
92
|
+
this.isMoving = true;
|
|
93
|
+
this.startY = e.touches[0].clientY;
|
|
94
|
+
this.startTop = this.popupTop;
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
handleTouchMove(e) {
|
|
98
|
+
if (!this.isMoving) return;
|
|
99
|
+
|
|
100
|
+
const moveY = e.touches[0].clientY - this.startY;
|
|
101
|
+
let newTop = this.startTop + moveY;
|
|
102
|
+
|
|
103
|
+
// 限制拖动范围,但允许拖出屏幕一定距离
|
|
104
|
+
const maxDragDistance = 100; // 最大可拖出屏幕的距离
|
|
105
|
+
|
|
106
|
+
if (newTop < -maxDragDistance) {
|
|
107
|
+
newTop = -maxDragDistance;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 保留一部分在屏幕内,方便拖回
|
|
111
|
+
if (this.containerHeight > 0) {
|
|
112
|
+
const maxTop = this.windowHeight - 50; // 至少保留50px在屏幕内
|
|
113
|
+
if (newTop > maxTop) {
|
|
114
|
+
newTop = maxTop;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.popupTop = newTop;
|
|
118
|
+
this.changeTop();
|
|
119
|
+
// 调用防抖函数而不是创建它
|
|
120
|
+
this.updateContentPopupTop();
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
handleTouchEnd(e) {
|
|
124
|
+
if (!this.isMoving) return;
|
|
125
|
+
this.isMoving = false;
|
|
126
|
+
|
|
127
|
+
// 修改:拖动结束后停留在当前位置,不自动展开或收起
|
|
128
|
+
// 只要确保popupTop在有效范围内即可
|
|
129
|
+
|
|
130
|
+
if (this.popupTop < 0) {
|
|
131
|
+
this.popupTop = 110;
|
|
132
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
133
|
+
} else if (this.popupTop > this.windowHeight) {
|
|
134
|
+
this.popupTop = this.windowHeight - 60;
|
|
135
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
136
|
+
} else if (this.popupTop < 110) {
|
|
137
|
+
this.popupTop = 110;
|
|
138
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
139
|
+
}
|
|
140
|
+
this.changeTop();
|
|
141
|
+
},
|
|
142
|
+
changeTop() {
|
|
143
|
+
this.$emit('changeTop', this.popupTop);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
</script>
|
|
148
|
+
|
|
149
|
+
<style lang="scss" scoped>
|
|
150
|
+
/* .draggable-popup-mask {
|
|
151
|
+
position: fixed;
|
|
152
|
+
top: 0;
|
|
153
|
+
left: 0;
|
|
154
|
+
right: 0;
|
|
155
|
+
bottom: 0;
|
|
156
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
157
|
+
z-index: 98;
|
|
158
|
+
} */
|
|
159
|
+
|
|
160
|
+
.draggable-popup-container {
|
|
161
|
+
position: fixed;
|
|
162
|
+
left: 0;
|
|
163
|
+
right: 0;
|
|
164
|
+
bottom: 0;
|
|
165
|
+
background-color: #ffffff;
|
|
166
|
+
border-top-left-radius: 20rpx;
|
|
167
|
+
border-top-right-radius: 20rpx;
|
|
168
|
+
transition: top 0.1s ease; /* 减少过渡时间使拖动更流畅 */
|
|
169
|
+
z-index: 99;
|
|
170
|
+
display: flex;
|
|
171
|
+
flex-direction: column;
|
|
172
|
+
overflow: auto;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.draggable-popup-handle {
|
|
176
|
+
display: flex;
|
|
177
|
+
justify-content: center;
|
|
178
|
+
align-items: center;
|
|
179
|
+
padding: 20rpx 0;
|
|
180
|
+
cursor: move;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.draggable-popup-handle-line {
|
|
184
|
+
width: 60rpx;
|
|
185
|
+
height: 8rpx;
|
|
186
|
+
border-radius: 4rpx;
|
|
187
|
+
background-color: rgba(23, 26, 29, 0.24);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.draggable-popup-content {
|
|
191
|
+
overflow: auto;
|
|
192
|
+
position: relative;
|
|
193
|
+
z-index: 100;
|
|
194
|
+
}
|
|
195
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import type { App } from 'vue';
|
|
3
|
+
import DraggableBottomPopup from './DraggableBottomPopup.vue';
|
|
4
|
+
|
|
5
|
+
// 使用install方法,在app.use挂载
|
|
6
|
+
DraggableBottomPopup.install = (app: App) => {
|
|
7
|
+
app.component(DraggableBottomPopup.__name as string, DraggableBottomPopup); //注册组件
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default DraggableBottomPopup;
|
package/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { App } from 'vue';
|
|
2
2
|
import { HwBtn } from './HwBtn';
|
|
3
|
+
import { DraggableBottomPopup } from './DraggableBottomPopup';
|
|
3
4
|
|
|
4
|
-
export { HwBtn };
|
|
5
|
+
export { HwBtn, DraggableBottomPopup };
|
|
5
6
|
|
|
6
7
|
export declare const hwCusUi: {
|
|
7
8
|
install: (app: App) => void;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
|
-
export default hwCusUi;
|
|
11
|
+
export default hwCusUi;
|
package/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// index.ts
|
|
2
2
|
import type { App } from 'vue';
|
|
3
3
|
import HwBtn from './HwBtn';
|
|
4
|
+
import DraggableBottomPopup from './DraggableBottomPopup';
|
|
4
5
|
|
|
5
6
|
// 所有组件列表
|
|
6
|
-
const components = [HwBtn];
|
|
7
|
+
const components = [HwBtn, DraggableBottomPopup];
|
|
7
8
|
|
|
8
9
|
// 定义 install 方法
|
|
9
10
|
const install = (app: App): void => {
|
|
@@ -11,7 +12,7 @@ const install = (app: App): void => {
|
|
|
11
12
|
components.forEach((component) => app.component(component.__name as string, component));
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
export { HwBtn };
|
|
15
|
+
export { HwBtn, DraggableBottomPopup };
|
|
15
16
|
|
|
16
17
|
const hwCusUi = {
|
|
17
18
|
install
|