stellar-ui-plus 1.23.13 → 1.23.15
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.
|
@@ -5,11 +5,11 @@ export default class TouchScaleing {
|
|
|
5
5
|
|
|
6
6
|
startParam: {
|
|
7
7
|
id1: number | null
|
|
8
|
-
x1
|
|
9
|
-
y1
|
|
8
|
+
x1?: number | null
|
|
9
|
+
y1?: number | null
|
|
10
10
|
id2: number | null
|
|
11
|
-
x2
|
|
12
|
-
y2
|
|
11
|
+
x2?: number | null
|
|
12
|
+
y2?: number | null
|
|
13
13
|
} = {
|
|
14
14
|
id1: null,
|
|
15
15
|
x1: null,
|
|
@@ -19,12 +19,17 @@ export default class TouchScaleing {
|
|
|
19
19
|
y2: null,
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
isScale = false
|
|
22
23
|
scale = 1
|
|
24
|
+
baseScale = 1
|
|
23
25
|
|
|
24
26
|
rotate = 0
|
|
27
|
+
baseRotate = 0
|
|
25
28
|
|
|
26
29
|
translateX = 0
|
|
27
30
|
translateY = 0
|
|
31
|
+
baseTranslateX = 0
|
|
32
|
+
baseTranslateY = 0
|
|
28
33
|
|
|
29
34
|
private _setData(changedTouches: UniTouchList) {
|
|
30
35
|
for (let i = 0; i < changedTouches.length; i++) {
|
|
@@ -77,23 +82,41 @@ export default class TouchScaleing {
|
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
touchMove(changedTouches: UniTouchList) {
|
|
80
|
-
if (changedTouches.length < 2)
|
|
81
|
-
return false
|
|
82
85
|
this._setData(changedTouches)
|
|
83
86
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
// 单指拖拽处理
|
|
88
|
+
if (this.isScale && changedTouches.length === 1) {
|
|
89
|
+
const param = this.startParam
|
|
90
|
+
const [x1, y1] = this._getTouchPosition() as number[]
|
|
91
|
+
|
|
92
|
+
// 如果之前有记录第一个触摸点,则计算移动距离
|
|
93
|
+
if (param.x1 && param.y1) {
|
|
94
|
+
this.translateX = this.baseTranslateX + (x1 - param.x1)
|
|
95
|
+
this.translateY = this.baseTranslateY + (y1 - param.y1)
|
|
96
|
+
}
|
|
97
|
+
return true
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 双指缩放处理
|
|
101
|
+
if (changedTouches.length >= 2) {
|
|
102
|
+
const param = this.startParam
|
|
103
|
+
const [startX1, startY1, startX2, startY2] = [param.x1, param.y1, param.x2, param.y2] as number[]
|
|
104
|
+
const [x1, y1, x2, y2] = this._getTouchPosition() as number[]
|
|
105
|
+
|
|
106
|
+
this.scale = this.baseScale *
|
|
107
|
+
(Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
|
|
108
|
+
/ Math.sqrt((startX2 - startX1) ** 2 + (startY2 - startY1) ** 2))
|
|
109
|
+
|
|
110
|
+
this.rotate = this.baseRotate +
|
|
111
|
+
((Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI
|
|
112
|
+
- (Math.atan2(startY2 - startY1, startX2 - startX1) * 180) / Math.PI)
|
|
113
|
+
|
|
114
|
+
this.translateX = this.baseTranslateX + ((x1 + x2) / 2 - (startX1 + startX2) / 2)
|
|
115
|
+
this.translateY = this.baseTranslateY + ((y1 + y2) / 2 - (startY1 + startY2) / 2)
|
|
116
|
+
return true
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return false
|
|
97
120
|
}
|
|
98
121
|
|
|
99
122
|
touchEnd(changedTouches: UniTouchList) {
|
|
@@ -112,6 +135,26 @@ export default class TouchScaleing {
|
|
|
112
135
|
this.startParam.x2 = null
|
|
113
136
|
this.startParam.y2 = null
|
|
114
137
|
}
|
|
138
|
+
|
|
139
|
+
// 保存当前状态作为基础值,以便下次操作基于此状态继续
|
|
140
|
+
this.baseScale = this.scale
|
|
141
|
+
this.baseRotate = this.rotate
|
|
142
|
+
this.baseTranslateX = this.translateX
|
|
143
|
+
this.baseTranslateY = this.translateY
|
|
144
|
+
this.isScale = this.scale > 1
|
|
115
145
|
return !this.identifiers.length
|
|
116
146
|
}
|
|
117
|
-
|
|
147
|
+
|
|
148
|
+
// 重置所有变换状态
|
|
149
|
+
reset() {
|
|
150
|
+
this.isScale = false
|
|
151
|
+
this.scale = 1
|
|
152
|
+
this.baseScale = 1
|
|
153
|
+
this.rotate = 0
|
|
154
|
+
this.baseRotate = 0
|
|
155
|
+
this.translateX = 0
|
|
156
|
+
this.translateY = 0
|
|
157
|
+
this.baseTranslateX = 0
|
|
158
|
+
this.baseTranslateY = 0
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { onMounted, watch, computed } from 'vue';
|
|
2
|
+
import { onMounted, watch, computed, ref } from 'vue';
|
|
3
3
|
import utils from '../../utils/utils';
|
|
4
4
|
import propsData from './props';
|
|
5
5
|
import useData from './useData';
|
|
@@ -18,7 +18,7 @@ const emits = defineEmits<{
|
|
|
18
18
|
|
|
19
19
|
const { dataIndex, setDataIndex, dataShow, setDataShow, touch, setTouch, scaling, setScaling, translate, setTranslate, rotate, setRotate, transition, setTransition, dataShowmenu, setDataShowmenu } =
|
|
20
20
|
useData();
|
|
21
|
-
|
|
21
|
+
const isScale = ref(false); // 是否缩放了
|
|
22
22
|
const props = defineProps(propsData);
|
|
23
23
|
|
|
24
24
|
const cmpUrls = computed<{ url: string; type: string | number; path?: string }[]>(() => {
|
|
@@ -43,11 +43,27 @@ watch(
|
|
|
43
43
|
setDataIndex(props.index);
|
|
44
44
|
}
|
|
45
45
|
setDataShow(v);
|
|
46
|
+
// 当切换显示状态时,重置缩放和拖拽状态
|
|
47
|
+
if (!v && touch.value) {
|
|
48
|
+
touch.value.reset();
|
|
49
|
+
setScaling(1);
|
|
50
|
+
setTranslate('0');
|
|
51
|
+
setRotate(0);
|
|
52
|
+
}
|
|
46
53
|
},
|
|
47
54
|
{ immediate: true }
|
|
48
55
|
);
|
|
49
56
|
watch(() => props.showmenu, setDataShowmenu, { immediate: true });
|
|
50
57
|
|
|
58
|
+
const resetScal = () => {
|
|
59
|
+
if (touch.value) {
|
|
60
|
+
touch.value.reset();
|
|
61
|
+
isScale.value = false;
|
|
62
|
+
setScaling(1);
|
|
63
|
+
setTranslate('0');
|
|
64
|
+
setRotate(0);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
51
67
|
const onClose = async () => {
|
|
52
68
|
let next = true;
|
|
53
69
|
const stop = new Promise((resolve, reject) => {
|
|
@@ -64,10 +80,12 @@ const onClose = async () => {
|
|
|
64
80
|
setDataShow(false);
|
|
65
81
|
emits('update:show', false);
|
|
66
82
|
emits('close');
|
|
83
|
+
// 关闭时重置缩放和拖拽状态
|
|
84
|
+
resetScal();
|
|
67
85
|
};
|
|
68
86
|
|
|
69
87
|
const onTouchstart = (e: UniTouchEvent) => {
|
|
70
|
-
if (props.scale) return;
|
|
88
|
+
if (!props.scale) return;
|
|
71
89
|
const [x1, y1, x2, y2] = touch.value?.touchStart(e.changedTouches) || [];
|
|
72
90
|
if (x1 && y1 && x2 && y2) {
|
|
73
91
|
if (dataShowmenu) setDataShowmenu(false);
|
|
@@ -75,7 +93,7 @@ const onTouchstart = (e: UniTouchEvent) => {
|
|
|
75
93
|
};
|
|
76
94
|
|
|
77
95
|
const onTouchmove = (e: UniTouchEvent) => {
|
|
78
|
-
if (props.scale) return;
|
|
96
|
+
if (!props.scale) return;
|
|
79
97
|
const bool = touch.value?.touchMove(e.changedTouches);
|
|
80
98
|
if (!bool) return;
|
|
81
99
|
if (dataShowmenu) setDataShowmenu(false);
|
|
@@ -85,59 +103,91 @@ const onTouchmove = (e: UniTouchEvent) => {
|
|
|
85
103
|
};
|
|
86
104
|
|
|
87
105
|
const onTouchend = (e: UniTouchEvent) => {
|
|
88
|
-
if (props.scale) return;
|
|
106
|
+
if (!props.scale) return;
|
|
89
107
|
if (dataShowmenu.value !== props.showmenu) setDataShowmenu(props.showmenu);
|
|
90
108
|
const bool = touch.value?.touchEnd(e.changedTouches);
|
|
91
109
|
if (!bool) return;
|
|
92
|
-
|
|
93
|
-
setTimeout(() => {
|
|
94
|
-
setScaling(1);
|
|
95
|
-
setTranslate('0');
|
|
96
|
-
setRotate(0);
|
|
97
|
-
setTimeout(() => {
|
|
98
|
-
setTransition('0');
|
|
99
|
-
}, 100);
|
|
100
|
-
}, 50);
|
|
110
|
+
isScale.value = touch.value?.isScale || false;
|
|
101
111
|
};
|
|
102
112
|
|
|
103
113
|
const onChange = (e: SwiperOnChangeEvent) => {
|
|
104
114
|
setDataIndex(e.detail.current);
|
|
105
115
|
emits('update:index', e.detail.current);
|
|
106
116
|
emits('change', e.detail.current);
|
|
117
|
+
// 切换图片时重置缩放和拖拽状态
|
|
118
|
+
resetScal();
|
|
107
119
|
};
|
|
108
120
|
|
|
109
121
|
const onLongpress = () => {
|
|
110
122
|
emits('longpress', dataIndex.value);
|
|
111
123
|
};
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
const currentItem = computed(() => {
|
|
125
|
+
return cmpUrls.value[dataIndex.value];
|
|
126
|
+
});
|
|
127
|
+
let clickNum = 0;
|
|
128
|
+
let clickTimer: any = 0;
|
|
129
|
+
const onClick = () => {
|
|
130
|
+
clearTimeout(clickTimer);
|
|
131
|
+
clickNum++;
|
|
132
|
+
if (clickNum > 1) {
|
|
133
|
+
clickNum = 0;
|
|
134
|
+
resetScal();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
clickTimer = setTimeout(() => {
|
|
138
|
+
clickNum = 0;
|
|
139
|
+
}, 300);
|
|
140
|
+
};
|
|
114
141
|
</script>
|
|
115
142
|
<template>
|
|
116
143
|
<view class="ste-media-preview-root" data-test="media-preview" v-if="dataShow">
|
|
117
144
|
<view class="media-preview-content">
|
|
118
|
-
<
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
<template v-if="isScale">
|
|
146
|
+
<view
|
|
147
|
+
class="preview-item"
|
|
148
|
+
data-test="media-preview-item"
|
|
149
|
+
@click.stop="onClick"
|
|
150
|
+
@touchstart="onTouchstart"
|
|
151
|
+
@touchmove="onTouchmove"
|
|
152
|
+
@touchend="onTouchend"
|
|
153
|
+
@longpress="onLongpress"
|
|
154
|
+
:style="[cmpTransform]"
|
|
155
|
+
>
|
|
156
|
+
<!-- #ifndef APP -->
|
|
157
|
+
<video class="video" object-fit="contain" v-if="currentItem.type === 'video'" :src="currentItem.url || currentItem.path" @click.stop="1" />
|
|
158
|
+
<image v-else class="image" :show-menu-by-longpress="dataShowmenu" :src="currentItem.url || currentItem.path" mode="aspectFit" />
|
|
159
|
+
<!-- #endif -->
|
|
160
|
+
<!-- #ifdef APP -->
|
|
161
|
+
<video class="video" object-fit="contain" v-if="currentItem.type === 'video' && cmpUrls.length <= 1" :src="currentItem.url || currentItem.path" @click.stop="1" />
|
|
162
|
+
<image v-else class="image" :show-menu-by-longpress="dataShowmenu" :src="currentItem.url || currentItem.path" mode="aspectFit" />
|
|
163
|
+
<!-- #endif -->
|
|
164
|
+
</view>
|
|
165
|
+
</template>
|
|
166
|
+
<template v-else>
|
|
167
|
+
<swiper style="width: 100%; height: 100%" :autoplay="props.autoplay > 0" :interval="props.autoplay" :circular="props.loop" :current="dataIndex" @change="onChange">
|
|
168
|
+
<swiper-item v-for="(item, index) in cmpUrls" :key="index">
|
|
169
|
+
<view
|
|
170
|
+
class="preview-item"
|
|
171
|
+
data-test="media-preview-item"
|
|
172
|
+
@click.stop="onClick"
|
|
173
|
+
@touchstart="onTouchstart"
|
|
174
|
+
@touchmove="onTouchmove"
|
|
175
|
+
@touchend="onTouchend"
|
|
176
|
+
@longpress="onLongpress"
|
|
177
|
+
:style="[dataIndex === index ? cmpTransform : {}]"
|
|
178
|
+
>
|
|
179
|
+
<!-- #ifndef APP -->
|
|
180
|
+
<video class="video" object-fit="contain" v-if="item.type === 'video'" :src="item.url || item.path" @click.stop="1" />
|
|
181
|
+
<ste-image v-else class="image" :showMenuByLongpress="dataShowmenu" :src="item.url || item.path" mode="aspectFit" />
|
|
182
|
+
<!-- #endif -->
|
|
183
|
+
<!-- #ifdef APP -->
|
|
184
|
+
<video class="video" object-fit="contain" v-if="item.type === 'video' && cmpUrls.length <= 1" :src="item.url || item.path" @click.stop="1" />
|
|
185
|
+
<ste-image v-else class="image" :showMenuByLongpress="dataShowmenu" :src="item.url || item.path" mode="aspectFit" />
|
|
186
|
+
<!-- #endif -->
|
|
187
|
+
</view>
|
|
188
|
+
</swiper-item>
|
|
189
|
+
</swiper>
|
|
190
|
+
</template>
|
|
141
191
|
</view>
|
|
142
192
|
<view class="media-preview-footer">
|
|
143
193
|
<view class="footer-index">
|