hy-app 0.6.6 → 0.6.8

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.
@@ -188,9 +188,10 @@ onMounted(() => {
188
188
 
189
189
  // 始终绑定 page scroll 回退(能兼容大多数场景)
190
190
  // 注意:如果页面使用 scroll-view(而非页面滚动),你应传入 scrollSelector 以使用 relativeTo(container)
191
- onPageScroll && onPageScroll(onPageScrollListener)
191
+ // onPageScroll && onPageScroll(onPageScrollListener)
192
192
  })
193
193
  })
194
+ onPageScroll && onPageScroll(onPageScrollListener)
194
195
 
195
196
  onUnmounted(() => {
196
197
  observer?.disconnect()
@@ -1,224 +1,230 @@
1
- <template>
2
- <view
3
- class="hy-swiper"
4
- :style="{
5
- backgroundColor: bgColor,
6
- height: addUnit(height),
7
- borderRadius: addUnit(radius)
8
- }"
9
- >
10
- <view class="hy-swiper__loading" v-if="loading">
11
- <hy-loading mode="circle"></hy-loading>
12
- </view>
13
- <swiper
14
- v-else
15
- class="hy-swiper__wrapper"
16
- :style="{
17
- flex: '1',
18
- height: addUnit(height)
19
- }"
20
- @change="change"
21
- :circular="circular"
22
- :interval="interval"
23
- :duration="duration"
24
- :autoplay="autoplay"
25
- :current="current"
26
- :currentItemId="currentItemId"
27
- :previousMargin="addUnit(previousMargin)"
28
- :nextMargin="addUnit(nextMargin)"
29
- :acceleration="acceleration"
30
- :displayMultipleItems="list.length > 0 ? displayMultipleItems : 0"
31
- :easingFunction="easingFunction"
32
- >
33
- <swiper-item
34
- class="hy-swiper__wrapper--item"
35
- v-for="(item, index) in list"
36
- :key="index"
37
- >
38
- <slot :record="item" :index="index">
39
- <view class="hy-swiper__wrapper--item__wrapper" :style="[itemStyle(index)]">
40
- <!-- 在nvue中,image图片的宽度默认为屏幕宽度,需要通过flex:1撑开,另外必须设置高度才能显示图片 -->
41
- <image
42
- class="hy-swiper__wrapper--item__wrapper--image"
43
- v-if="getItemType(item) === 'image'"
44
- :src="getSource(item)"
45
- :mode="imgMode"
46
- @tap="clickHandler(index)"
47
- :style="{
48
- height: addUnit(height),
49
- borderRadius: addUnit(radius)
50
- }"
51
- ></image>
52
- <video
53
- class="hy-swiper__wrapper--item__wrapper--video"
54
- v-if="getItemType(item) === 'video'"
55
- :id="`video-${index}`"
56
- :enable-progress-gesture="false"
57
- :src="getSource(item)"
58
- :poster="getPoster(item)"
59
- :title="showTitle && hasTitle(item)"
60
- :style="{
61
- height: addUnit(height)
62
- }"
63
- controls
64
- @tap="clickHandler(index)"
65
- ></video>
66
- <view
67
- v-if="showTitle && hasTitle(item)"
68
- class="hy-swiper__wrapper--item__wrapper--title"
69
- >
70
- <text class="hy-line-1">{{ hasTitle(item) }}</text>
71
- </view>
72
- </view>
73
- </slot>
74
- </swiper-item>
75
- </swiper>
76
- <view class="hy-swiper__indicator" :style="[indicatorStyle]">
77
- <slot name="indicator" :current="currentIndex" :length="list.length">
78
- <hy-swiper-indicator
79
- v-if="!loading && indicator && !showTitle"
80
- :indicatorActiveColor="indicatorActiveColor"
81
- :indicatorInactiveColor="indicatorInactiveColor"
82
- :length="list.length"
83
- :current="currentIndex"
84
- :indicatorMode="indicatorMode"
85
- ></hy-swiper-indicator>
86
- </slot>
87
- </view>
88
- </view>
89
- </template>
90
-
91
- <script lang="ts">
92
- export default {
93
- name: 'hy-swiper',
94
- options: {
95
- addGlobalClass: true,
96
- virtualHost: true,
97
- styleIsolation: 'shared'
98
- }
99
- }
100
- </script>
101
-
102
- <script setup lang="ts">
103
- import { computed, ref, watch, getCurrentInstance } from 'vue'
104
- import type { CSSProperties } from 'vue'
105
- import { addUnit, isVideo } from '../../libs'
106
- import type { ISwiperEmits, SwiperList, SwiperVo } from './typing'
107
- import swiperProps from './props'
108
- // 组件
109
- import HyLoading from '../hy-loading/hy-loading.vue'
110
- import HySwiperIndicator from './hy-swiper-indicator.vue'
111
-
112
- /**
113
- * 一般用于导航轮播,广告展示等场景,可开箱即用
114
- * @displayName hy-swiper
115
- */
116
- defineOptions({})
117
-
118
- const props = defineProps(swiperProps)
119
- const emit = defineEmits<ISwiperEmits>()
120
-
121
- const instance = getCurrentInstance()
122
- const currentIndex = ref<string | number>(0)
123
-
124
- watch(
125
- () => props.current,
126
- (newVal) => {
127
- currentIndex.value = newVal
128
- }
129
- )
130
-
131
- const hasTitle = computed(() => {
132
- return (item: string | Record<string, any>) => {
133
- if (typeof item === 'object') {
134
- return item.title || ''
135
- } else {
136
- return ''
137
- }
138
- }
139
- })
140
-
141
- /**
142
- * @description 轮播图3D效果
143
- * */
144
- const itemStyle = computed(() => {
145
- return (index: number): CSSProperties => {
146
- const style: CSSProperties = {}
147
- // #ifndef APP-NVUE || MP-TOUTIAO
148
- // 左右流出空间的写法不支持nvue和头条
149
- // 只有配置了此二值,才加上对应的圆角,以及缩放
150
- if (props.nextMargin && props.previousMargin) {
151
- style.borderRadius = addUnit(props.radius)
152
- if (index !== currentIndex.value) style.transform = 'scale(0.92)'
153
- }
154
- // #endif
155
- return style
156
- }
157
- })
158
-
159
- /**
160
- * @description 获取目标路径,可能数组中为字符串,对象的形式,额外可指定对象的目标属性名keyName
161
- * */
162
- const getSource = (item: string | Record<string, any>): string => {
163
- if (typeof item === 'string') return item
164
- if (typeof item === 'object' && props.keyName) return item[props.keyName]
165
- return ''
166
- }
167
-
168
- /**
169
- * @description 轮播切换事件
170
- */
171
- const change = (e: SwiperVo) => {
172
- // 当前的激活索引
173
- const { current } = e.detail
174
- pauseVideo(currentIndex.value)
175
- currentIndex.value = current
176
- emit('update:current', currentIndex.value)
177
- emit('change', e.detail)
178
- }
179
-
180
- /**
181
- * @description 切换轮播时,暂停视频播放
182
- * */
183
- const pauseVideo = (index: number | string) => {
184
- const lastItem = getSource(props.list[Number(index)])
185
- if (isVideo(lastItem)) {
186
- // 当视频隐藏时,暂停播放
187
- const video = uni.createVideoContext(`video-${index}`, instance)
188
- video.pause()
189
- }
190
- }
191
-
192
- /**
193
- * @description 当一个轮播item为视频时,获取它的视频海报
194
- * */
195
- const getPoster = (item: string | SwiperList): string => {
196
- return typeof item === 'object' && item.poster ? item.poster : ''
197
- }
198
-
199
- /**
200
- * @description 点击某个item
201
- * */
202
- const clickHandler = (index: number) => {
203
- emit('click', index)
204
- }
205
-
206
- /**
207
- * @description 判断链接是视频还是图片
208
- * */
209
- const getItemType = computed(() => {
210
- return (item: string | Record<string, unknown>) => {
211
- if (typeof item === 'string') return isVideo(item) ? 'video' : 'image'
212
- if (typeof item === 'object' && props.keyName) {
213
- if (!item.type) return isVideo(item[props.keyName] as string) ? 'video' : 'image'
214
- if (item.type === 'image') return 'image'
215
- if (item.type === 'video') return 'video'
216
- return 'image'
217
- }
218
- }
219
- })
220
- </script>
221
-
222
- <style lang="scss" scoped>
223
- @import './index.scss';
224
- </style>
1
+ <template>
2
+ <view
3
+ class="hy-swiper"
4
+ :style="{
5
+ backgroundColor: bgColor,
6
+ height: addUnit(height),
7
+ borderRadius: addUnit(radius)
8
+ }"
9
+ >
10
+ <view class="hy-swiper__loading" v-if="loading">
11
+ <hy-loading mode="circle"></hy-loading>
12
+ </view>
13
+ <swiper
14
+ v-else
15
+ class="hy-swiper__wrapper"
16
+ :style="{
17
+ flex: '1',
18
+ height: addUnit(height)
19
+ }"
20
+ @change="change"
21
+ :circular="circular"
22
+ :interval="interval"
23
+ :duration="duration"
24
+ :autoplay="autoplay"
25
+ :current="current"
26
+ :currentItemId="currentItemId"
27
+ :previousMargin="addUnit(previousMargin)"
28
+ :nextMargin="addUnit(nextMargin)"
29
+ :acceleration="acceleration"
30
+ :displayMultipleItems="list.length > 0 ? displayMultipleItems : 0"
31
+ :easingFunction="easingFunction"
32
+ >
33
+ <swiper-item
34
+ class="hy-swiper__wrapper--item"
35
+ v-for="(item, index) in list"
36
+ :key="index"
37
+ >
38
+ <slot v-if="$slots.default" :record="item" :index="index"> </slot>
39
+ <view v-else class="hy-swiper__wrapper--item__wrapper" :style="[itemStyle(index)]">
40
+ <!-- 在nvue中,image图片的宽度默认为屏幕宽度,需要通过flex:1撑开,另外必须设置高度才能显示图片 -->
41
+ <image
42
+ class="hy-swiper__wrapper--item__wrapper--image"
43
+ v-if="getItemType(item) === 'image'"
44
+ :src="getSource(item)"
45
+ :mode="imgMode"
46
+ @tap="clickHandler(index)"
47
+ :style="{
48
+ height: addUnit(height),
49
+ borderRadius: addUnit(radius)
50
+ }"
51
+ ></image>
52
+ <video
53
+ class="hy-swiper__wrapper--item__wrapper--video"
54
+ v-if="getItemType(item) === 'video'"
55
+ :id="`video-${index}`"
56
+ :enable-progress-gesture="false"
57
+ :src="getSource(item)"
58
+ :poster="getPoster(item)"
59
+ :title="showTitle && hasTitle(item)"
60
+ :style="{
61
+ height: addUnit(height)
62
+ }"
63
+ controls
64
+ @tap="clickHandler(index)"
65
+ ></video>
66
+ <view
67
+ v-if="showTitle && hasTitle(item)"
68
+ class="hy-swiper__wrapper--item__wrapper--title"
69
+ >
70
+ <text class="hy-line-1">{{ hasTitle(item) }}</text>
71
+ </view>
72
+ </view>
73
+ </swiper-item>
74
+ </swiper>
75
+ <view class="hy-swiper__indicator" :style="[indicatorStyle]">
76
+ <slot
77
+ v-if="$slots.indicator"
78
+ name="indicator"
79
+ :current="currentIndex"
80
+ :length="list.length"
81
+ >
82
+ </slot>
83
+ <hy-swiper-indicator
84
+ v-else-if="!loading && indicator && !showTitle"
85
+ :indicatorActiveColor="indicatorActiveColor"
86
+ :indicatorInactiveColor="indicatorInactiveColor"
87
+ :length="list.length"
88
+ :current="currentIndex"
89
+ :indicatorMode="indicatorMode"
90
+ ></hy-swiper-indicator>
91
+ </view>
92
+ </view>
93
+ </template>
94
+
95
+ <script lang="ts">
96
+ export default {
97
+ name: 'hy-swiper',
98
+ options: {
99
+ addGlobalClass: true,
100
+ virtualHost: true,
101
+ styleIsolation: 'shared'
102
+ }
103
+ }
104
+ </script>
105
+
106
+ <script setup lang="ts">
107
+ import { computed, ref, watch, getCurrentInstance } from 'vue'
108
+ import type { CSSProperties } from 'vue'
109
+ import { addUnit, isVideo } from '../../libs'
110
+ import type { ISwiperEmits, SwiperList, SwiperVo } from './typing'
111
+ import swiperProps from './props'
112
+ // 组件
113
+ import HyLoading from '../hy-loading/hy-loading.vue'
114
+ import HySwiperIndicator from './hy-swiper-indicator.vue'
115
+
116
+ /**
117
+ * 一般用于导航轮播,广告展示等场景,可开箱即用
118
+ * @displayName hy-swiper
119
+ */
120
+ defineOptions({})
121
+
122
+ const props = defineProps(swiperProps)
123
+ const emit = defineEmits<ISwiperEmits>()
124
+
125
+ const instance = getCurrentInstance()
126
+ const currentIndex = ref<string | number>(0)
127
+
128
+ watch(
129
+ () => props.current,
130
+ (newVal) => {
131
+ currentIndex.value = newVal
132
+ }
133
+ )
134
+
135
+ const hasTitle = computed(() => {
136
+ return (item: string | Record<string, any>) => {
137
+ if (typeof item === 'object') {
138
+ return item.title || ''
139
+ } else {
140
+ return ''
141
+ }
142
+ }
143
+ })
144
+
145
+ /**
146
+ * 轮播图3D效果
147
+ * */
148
+ const itemStyle = computed(() => {
149
+ return (index: number): CSSProperties => {
150
+ const style: CSSProperties = {}
151
+ // #ifndef APP-NVUE || MP-TOUTIAO
152
+ // 左右流出空间的写法不支持nvue和头条
153
+ // 只有配置了此二值,才加上对应的圆角,以及缩放
154
+ if (props.nextMargin && props.previousMargin) {
155
+ style.borderRadius = addUnit(props.radius)
156
+ if (index !== currentIndex.value) style.transform = 'scale(0.92)'
157
+ }
158
+ // #endif
159
+ return style
160
+ }
161
+ })
162
+
163
+ /**
164
+ * 获取目标路径,可能数组中为字符串,对象的形式,额外可指定对象的目标属性名keyName
165
+ * */
166
+ const getSource = (item: string | Record<string, any>): string => {
167
+ if (typeof item === 'string') return item
168
+ if (typeof item === 'object' && props.keyName) return item[props.keyName]
169
+ return ''
170
+ }
171
+
172
+ /**
173
+ * 轮播切换事件
174
+ */
175
+ const change = (e: SwiperVo) => {
176
+ // 当前的激活索引
177
+ const { current } = e.detail
178
+ pauseVideo(currentIndex.value)
179
+ currentIndex.value = current
180
+ emit('update:current', currentIndex.value)
181
+ emit('change', e.detail)
182
+ }
183
+
184
+ /**
185
+ * 切换轮播时,暂停视频播放
186
+ * */
187
+ const pauseVideo = (index: number | string) => {
188
+ const lastItem = getSource(props.list[Number(index)])
189
+ if (isVideo(lastItem)) {
190
+ // 当视频隐藏时,暂停播放
191
+ // #ifdef MP-WEIXIN
192
+ const video = uni.createVideoContext(`video-${index}`, instance)
193
+ video.pause()
194
+ // #endif
195
+ }
196
+ }
197
+
198
+ /**
199
+ * 当一个轮播item为视频时,获取它的视频海报
200
+ * */
201
+ const getPoster = (item: string | SwiperList): string => {
202
+ return typeof item === 'object' && item.poster ? item.poster : ''
203
+ }
204
+
205
+ /**
206
+ * 点击某个item
207
+ * */
208
+ const clickHandler = (index: number) => {
209
+ emit('click', index)
210
+ }
211
+
212
+ /**
213
+ * 判断链接是视频还是图片
214
+ * */
215
+ const getItemType = computed(() => {
216
+ return (item: string | Record<string, unknown>) => {
217
+ if (typeof item === 'string') return isVideo(item) ? 'video' : 'image'
218
+ if (typeof item === 'object' && props.keyName) {
219
+ if (!item.type) return isVideo(item[props.keyName] as string) ? 'video' : 'image'
220
+ if (item.type === 'image') return 'image'
221
+ if (item.type === 'video') return 'video'
222
+ return 'image'
223
+ }
224
+ }
225
+ })
226
+ </script>
227
+
228
+ <style lang="scss" scoped>
229
+ @import './index.scss';
230
+ </style>
@@ -99,7 +99,7 @@ const swiperProps = {
99
99
  },
100
100
  /** 组件高度 */
101
101
  height: {
102
- type: Number,
102
+ type: [String, Number],
103
103
  default: 130
104
104
  },
105
105
  /** 背景颜色 */
@@ -1,64 +1,64 @@
1
- /**
2
- * 摇一摇传感器hooks
3
- * */
4
- import { ref } from "vue";
5
- import type { Ref } from "vue";
6
- import { debounce } from "../../libs";
7
-
8
- interface Acceleration {
9
- x: number;
10
- y: number;
11
- z: number;
12
- }
13
-
14
- export function useShakeService(shakeThreshold: number = 30) {
15
- const lastAcceleration: Ref<Acceleration> = ref({ x: 0, y: 0, z: 0 });
16
- const lastTime: Ref<number> = ref(Date.now());
17
- const shakeCallback: Ref<null | (() => void)> = ref(null);
18
-
19
- const startShakeListener = (callback: () => void): void => {
20
- shakeCallback.value = callback;
21
- uni.startAccelerometer({
22
- success: () => {
23
- uni.onAccelerometerChange(handleShake);
24
- },
25
- fail: (err: any) => {
26
- console.error("加速度传感器启动失败", err.errMsg);
27
- },
28
- });
29
- };
30
-
31
- const stopShakeListener = (): void => {
32
- uni.stopAccelerometer().then(
33
- (res) => {
34
- uni.offAccelerometerChange(handleShake);
35
- },
36
- (err) => console.error("加速度传感器关闭失败", err.errMsg),
37
- );
38
- };
39
-
40
- const handleShake = (res: Acceleration): void => {
41
- const acceleration = res;
42
- const currentTime = Date.now();
43
- const timeDiff = (currentTime - lastTime.value) / 1000; // 转换为秒
44
-
45
- // 计算加速度的欧几里得距离
46
- const deltaX = acceleration.x - lastAcceleration.value.x;
47
- const deltaY = acceleration.y - lastAcceleration.value.y;
48
- const deltaZ = acceleration.z - lastAcceleration.value.z;
49
- const speed =
50
- Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / timeDiff;
51
-
52
- if (speed > shakeThreshold && shakeCallback.value) {
53
- debounce(shakeCallback.value, 500);
54
- }
55
-
56
- lastAcceleration.value = acceleration;
57
- lastTime.value = currentTime;
58
- };
59
-
60
- return {
61
- startShakeListener,
62
- stopShakeListener,
63
- };
64
- }
1
+ /**
2
+ * 摇一摇传感器hooks
3
+ * */
4
+ import { ref } from "vue";
5
+ import type { Ref } from "vue";
6
+ import { debounce } from "../../libs";
7
+
8
+ interface Acceleration {
9
+ x: number;
10
+ y: number;
11
+ z: number;
12
+ }
13
+
14
+ export function useShakeService(shakeThreshold: number = 30) {
15
+ const lastAcceleration: Ref<Acceleration> = ref({ x: 0, y: 0, z: 0 });
16
+ const lastTime: Ref<number> = ref(Date.now());
17
+ const shakeCallback: Ref<null | (() => void)> = ref(null);
18
+
19
+ const startShakeListener = (callback: () => void): void => {
20
+ shakeCallback.value = callback;
21
+ uni.startAccelerometer({
22
+ success: () => {
23
+ uni.onAccelerometerChange(handleShake);
24
+ },
25
+ fail: (err: any) => {
26
+ console.error("加速度传感器启动失败", err.errMsg);
27
+ },
28
+ });
29
+ };
30
+
31
+ const stopShakeListener = (): void => {
32
+ uni.stopAccelerometer().then(
33
+ (res) => {
34
+ uni.offAccelerometerChange(handleShake);
35
+ },
36
+ (err) => console.error("加速度传感器关闭失败", err.errMsg),
37
+ );
38
+ };
39
+
40
+ const handleShake = (res: Acceleration): void => {
41
+ const acceleration = res;
42
+ const currentTime = Date.now();
43
+ const timeDiff = (currentTime - lastTime.value) / 1000; // 转换为秒
44
+
45
+ // 计算加速度的欧几里得距离
46
+ const deltaX = acceleration.x - lastAcceleration.value.x;
47
+ const deltaY = acceleration.y - lastAcceleration.value.y;
48
+ const deltaZ = acceleration.z - lastAcceleration.value.z;
49
+ const speed =
50
+ Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / timeDiff;
51
+
52
+ if (speed > shakeThreshold && shakeCallback.value) {
53
+ debounce(shakeCallback.value, 500);
54
+ }
55
+
56
+ lastAcceleration.value = acceleration;
57
+ lastTime.value = currentTime;
58
+ };
59
+
60
+ return {
61
+ startShakeListener,
62
+ stopShakeListener,
63
+ };
64
+ }
@@ -433,6 +433,7 @@ const getRect = <T extends boolean>(
433
433
  } else if (!all && rect) {
434
434
  resolve(rect as HyUtils.RectResultType<T>)
435
435
  } else {
436
+ console.log(rect)
436
437
  error(`调用getRect方法,没有找到${selector}对应的元素内容`)
437
438
  reject(new Error('No nodes found'))
438
439
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hy-app",
3
- "version": "0.6.6",
3
+ "version": "0.6.8",
4
4
  "description": "📱一个基于vue3+ts构建的uni-app组件库,拥有八十多个精美组件,适配多端,支持自定义主题",
5
5
  "main": "./index.ts",
6
6
  "private": false,