@dolphinweex/weex-harmony 0.1.44 → 0.1.45
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/package.json
CHANGED
@@ -113,37 +113,7 @@
|
|
113
113
|
</div>
|
114
114
|
</div>
|
115
115
|
|
116
|
-
<!--
|
117
|
-
<div v-if="isDragClone" class="drag-clone" :style="dragCloneStyle">
|
118
|
-
<div
|
119
|
-
class="grid-box"
|
120
|
-
:style="applyNormalAttribute(data.list[draggingIndex].itemView)"
|
121
|
-
>
|
122
|
-
<div class="flexBox">
|
123
|
-
<img
|
124
|
-
:src="data.list[draggingIndex].iconImage.url"
|
125
|
-
:style="applyNormalAttribute(data.list[draggingIndex].iconImage)"
|
126
|
-
/>
|
127
|
-
<div @click.stop.prevent>
|
128
|
-
<img
|
129
|
-
class="isSelected"
|
130
|
-
:src="
|
131
|
-
data.list[draggingIndex].itemView.isSelected
|
132
|
-
? data.list[draggingIndex].selectIcon.selectedUrl
|
133
|
-
: data.list[draggingIndex].selectIcon.url
|
134
|
-
"
|
135
|
-
:style="applyNormalAttribute(data.list[draggingIndex].selectIcon)"
|
136
|
-
/>
|
137
|
-
</div>
|
138
|
-
</div>
|
139
|
-
<div
|
140
|
-
class="itemText"
|
141
|
-
:style="[applyNormalAttribute(data.list[draggingIndex].text)]"
|
142
|
-
>
|
143
|
-
{{ data.list[draggingIndex].text.text }}
|
144
|
-
</div>
|
145
|
-
</div>
|
146
|
-
</div>
|
116
|
+
<!-- 拖拽克隆元素将通过JavaScript动态创建并挂载到body -->
|
147
117
|
</div>
|
148
118
|
</template>
|
149
119
|
|
@@ -193,6 +163,7 @@ export default {
|
|
193
163
|
fixedItemHeight: 0,
|
194
164
|
animationFrameId: null,
|
195
165
|
isProcessingData: false,
|
166
|
+
dragCloneElement: null, // 拖拽克隆DOM元素
|
196
167
|
};
|
197
168
|
},
|
198
169
|
computed: {
|
@@ -209,33 +180,181 @@ export default {
|
|
209
180
|
marginRight: this.data.layoutConfig.marginEnd * scla,
|
210
181
|
};
|
211
182
|
},
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
183
|
+
},
|
184
|
+
methods: {
|
185
|
+
// 获取元素在页面中的绝对位置(考虑所有transform影响)
|
186
|
+
getAbsolutePosition(element) {
|
187
|
+
let x = 0;
|
188
|
+
let y = 0;
|
189
|
+
let currentElement = element;
|
190
|
+
|
191
|
+
while (currentElement) {
|
192
|
+
const rect = currentElement.getBoundingClientRect();
|
193
|
+
if (currentElement === element) {
|
194
|
+
x += rect.left;
|
195
|
+
y += rect.top;
|
196
|
+
}
|
197
|
+
currentElement = currentElement.offsetParent;
|
216
198
|
}
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
199
|
+
|
200
|
+
// 加上页面滚动偏移
|
201
|
+
x += window.pageXOffset;
|
202
|
+
y += window.pageYOffset;
|
203
|
+
|
204
|
+
return { x, y };
|
205
|
+
},
|
206
|
+
|
207
|
+
// 创建拖拽克隆元素
|
208
|
+
createDragClone(index) {
|
209
|
+
if (this.dragCloneElement) {
|
210
|
+
this.destroyDragClone();
|
221
211
|
}
|
222
212
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
213
|
+
const item = this.data.list[index];
|
214
|
+
if (!item) return;
|
215
|
+
|
216
|
+
// 创建拖拽容器
|
217
|
+
this.dragCloneElement = document.createElement('div');
|
218
|
+
this.dragCloneElement.className = 'drag-clone-dynamic';
|
219
|
+
|
220
|
+
// 设置基本样式(使用不带缩放的样式方法)
|
221
|
+
const itemViewStyle = this.applyDragCloneAttribute(item.itemView);
|
222
|
+
Object.assign(this.dragCloneElement.style, {
|
223
|
+
position: 'absolute',
|
224
|
+
zIndex: '9999',
|
225
|
+
userSelect: 'none',
|
226
|
+
boxSizing: 'border-box',
|
227
|
+
flexDirection: 'column',
|
228
|
+
pointerEvents: 'none',
|
229
|
+
transition: 'none',
|
230
|
+
willChange: 'transform',
|
231
|
+
left: '0',
|
232
|
+
top: '0',
|
233
|
+
// 覆盖itemViewStyle中可能的宽高设置,确保使用固定尺寸
|
234
|
+
...itemViewStyle,
|
235
|
+
width: `${this.fixedItemWidth }px`,
|
236
|
+
height: `${this.fixedItemHeight }px`,
|
237
|
+
display: 'flex',
|
238
|
+
justifyContent: 'space-between',
|
239
|
+
});
|
240
|
+
|
241
|
+
// 创建内容HTML(使用不带缩放的样式方法)
|
242
|
+
const iconImageStyle = this.applyDragCloneAttribute(item.iconImage);
|
243
|
+
const selectIconStyle = this.applyDragCloneAttribute(item.selectIcon);
|
244
|
+
const textStyle = this.applyDragCloneAttribute(item.text);
|
245
|
+
const actionButtonStyle = this.applyDragCloneAttribute(item.actionButton);
|
246
|
+
|
247
|
+
// 将样式对象转换为CSS字符串
|
248
|
+
const stylesToString = (styleObj) => {
|
249
|
+
return Object.entries(styleObj)
|
250
|
+
.map(([key, value]) => `${key.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${value}`)
|
251
|
+
.join('; ');
|
235
252
|
};
|
253
|
+
|
254
|
+
// 确保内部grid-box也使用固定尺寸(使用不带缩放的样式方法)
|
255
|
+
const gridBoxStyle = {
|
256
|
+
...this.applyDragCloneAttribute(item.itemView),
|
257
|
+
width: `${this.fixedItemWidth }px`,
|
258
|
+
height: `${this.fixedItemHeight }px`
|
259
|
+
};
|
260
|
+
|
261
|
+
this.dragCloneElement.innerHTML = `
|
262
|
+
<div class="grid-box" style="${stylesToString(gridBoxStyle)} ;display: flex; justify-content: space-between;flex-direction: column">
|
263
|
+
<div class="flexBox" style="display: flex; justify-content: space-between; width: 100%; position: relative; flex-direction: row;">
|
264
|
+
<img src="${item.iconImage.url}" style="${stylesToString(iconImageStyle)}" />
|
265
|
+
<div style="pointer-events: none;">
|
266
|
+
<img
|
267
|
+
class="isSelected"
|
268
|
+
src="${item.itemView.isSelected ? item.selectIcon.selectedUrl : item.selectIcon.url}"
|
269
|
+
style="${stylesToString(selectIconStyle)}"
|
270
|
+
/>
|
271
|
+
</div>
|
272
|
+
</div>
|
273
|
+
<div class="itemText" style="${stylesToString(textStyle)}; display: block; width: 80%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
274
|
+
${item.text.text}
|
275
|
+
</div>
|
276
|
+
</div>
|
277
|
+
`;
|
278
|
+
|
279
|
+
// 挂载到body
|
280
|
+
document.body.appendChild(this.dragCloneElement);
|
281
|
+
|
282
|
+
return this.dragCloneElement;
|
283
|
+
},
|
284
|
+
|
285
|
+
// 销毁拖拽克隆元素
|
286
|
+
destroyDragClone() {
|
287
|
+
if (this.dragCloneElement) {
|
288
|
+
if (this.dragCloneElement.parentNode) {
|
289
|
+
this.dragCloneElement.parentNode.removeChild(this.dragCloneElement);
|
290
|
+
}
|
291
|
+
this.dragCloneElement = null;
|
292
|
+
}
|
293
|
+
},
|
294
|
+
|
295
|
+
// 更新拖拽克隆元素位置
|
296
|
+
updateDragClonePosition() {
|
297
|
+
if (!this.dragCloneElement) return;
|
298
|
+
|
299
|
+
this.dragCloneElement.style.transform = `translate(${this.dragCloneX}px, ${this.dragCloneY}px)`;
|
300
|
+
},
|
301
|
+
|
302
|
+
// 为拖拽克隆元素应用样式(不应用缩放因子)
|
303
|
+
applyDragCloneAttribute(data = {}) {
|
304
|
+
let style = {
|
305
|
+
color: data.textColor || '#000000',
|
306
|
+
fontWeight: data.fontWeight || 'normal',
|
307
|
+
fontFamily: data.fontFamilyPath || 'inherit',
|
308
|
+
fontSize: `${data.textSize || 16}px`, // 不乘以scla
|
309
|
+
// 布局相关样式
|
310
|
+
width:
|
311
|
+
typeof data.width === 'number' && data.width > 0
|
312
|
+
? `${data.width}px` // 不乘以scla
|
313
|
+
: data.width === -1
|
314
|
+
? '%'
|
315
|
+
: data.width || '',
|
316
|
+
height:
|
317
|
+
typeof data.height === 'number'
|
318
|
+
? `${data.height}px` // 不乘以scla
|
319
|
+
: data.height || '',
|
320
|
+
backgroundColor: data.backgroundColor || 'transparent',
|
321
|
+
borderRadius: `${data.cornerRadius || 0}px`, // 不乘以scla
|
322
|
+
opacity: data.alpha || 1,
|
323
|
+
};
|
324
|
+
|
325
|
+
if (typeof data.visibility === 'number') {
|
326
|
+
if (data.visibility === 0) {
|
327
|
+
style.display = 'none';
|
328
|
+
} else {
|
329
|
+
style.display = data.display || '';
|
330
|
+
style.visibility = data.visibility === 1 ? 'visible' : 'hidden';
|
331
|
+
}
|
332
|
+
} else {
|
333
|
+
style.display = data.display || '';
|
334
|
+
}
|
335
|
+
|
336
|
+
style.borderColor = this.data.isEditing
|
337
|
+
? data.selectedBorderColor || ''
|
338
|
+
: data.normalBorderColor || '';
|
339
|
+
style.borderWidth = this.data.isEditing
|
340
|
+
? `${data.selectedBorderWidth || 0}px` // 不乘以scla
|
341
|
+
: `${data.normalBorderWidth || 0}px`; // 不乘以scla
|
342
|
+
|
343
|
+
if (data.padding) {
|
344
|
+
style.paddingTop = `${data.padding[1] || 0}px`; // 不乘以scla
|
345
|
+
style.paddingLeft = `${data.padding[0] || 0}px`; // 不乘以scla
|
346
|
+
style.paddingBottom = `${data.padding[3] || 0}px`; // 不乘以scla
|
347
|
+
style.paddingRight = `${data.padding[2] || 0}px`; // 不乘以scla
|
348
|
+
}
|
349
|
+
if (data.margin) {
|
350
|
+
style.marginTop = `${data.margin[1] || 0}px`; // 不乘以scla
|
351
|
+
style.marginLeft = `${data.margin[0] || 0}px`; // 不乘以scla
|
352
|
+
style.marginBottom = `${data.margin[3] || 0}px`; // 不乘以scla
|
353
|
+
style.marginRight = `${data.margin[2] || 0}px`; // 不乘以scla
|
354
|
+
}
|
355
|
+
|
356
|
+
return style;
|
236
357
|
},
|
237
|
-
},
|
238
|
-
methods: {
|
239
358
|
updateListItem(data) {
|
240
359
|
console.log('updateListItem收到数据:', JSON.stringify(data));
|
241
360
|
const id = data.itemView.id;
|
@@ -413,7 +532,7 @@ export default {
|
|
413
532
|
if (this.isTouchDragging || this.longPressTimer === null && this.data.isEditing) {
|
414
533
|
return;
|
415
534
|
}
|
416
|
-
|
535
|
+
|
417
536
|
if (this.data.isEditing) {
|
418
537
|
if (item.selectIcon.visibility) {
|
419
538
|
item.itemView.isSelected = !item.itemView.isSelected;
|
@@ -686,7 +805,7 @@ export default {
|
|
686
805
|
activateDragMode(index) {
|
687
806
|
console.log('长按触发,进入编辑模式');
|
688
807
|
// 进入编辑模式
|
689
|
-
|
808
|
+
|
690
809
|
if (this.data.isEditing) {
|
691
810
|
// 设置当前拖拽索引
|
692
811
|
this.draggingIndex = index;
|
@@ -701,23 +820,29 @@ export default {
|
|
701
820
|
// 获取当前元素位置用于计算偏移
|
702
821
|
const element = document.querySelectorAll('.grid-item')[index];
|
703
822
|
if (element) {
|
823
|
+
// 使用getBoundingClientRect获取视口中的位置
|
704
824
|
const rect = element.getBoundingClientRect();
|
705
|
-
const containerRect = this.$el.getBoundingClientRect();
|
706
825
|
|
707
|
-
//
|
826
|
+
// 计算触摸点相对于元素左上角的偏移
|
708
827
|
this.touchOffsetX = this.touchStartX - rect.left;
|
709
828
|
this.touchOffsetY = this.touchStartY - rect.top;
|
710
829
|
|
711
|
-
//
|
712
|
-
this.
|
713
|
-
|
830
|
+
// 创建拖拽克隆元素
|
831
|
+
this.createDragClone(index);
|
832
|
+
|
833
|
+
// 设置克隆元素的初始位置(直接使用视口坐标加滚动偏移)
|
834
|
+
this.dragCloneX = rect.left + window.pageXOffset;
|
835
|
+
this.dragCloneY = rect.top + window.pageYOffset;
|
714
836
|
this.isDragClone = true;
|
715
837
|
|
838
|
+
// 立即更新位置
|
839
|
+
this.updateDragClonePosition();
|
840
|
+
|
716
841
|
requestAnimationFrame(() => {
|
717
|
-
|
718
|
-
|
719
|
-
this.
|
720
|
-
this.
|
842
|
+
// 使用触摸点减去偏移来计算正确位置
|
843
|
+
this.dragCloneX = this.touchStartX - this.touchOffsetX + window.pageXOffset;
|
844
|
+
this.dragCloneY = this.touchStartY - this.touchOffsetY + window.pageYOffset;
|
845
|
+
this.updateDragClonePosition();
|
721
846
|
});
|
722
847
|
|
723
848
|
console.log('拖拽克隆已创建');
|
@@ -745,6 +870,7 @@ export default {
|
|
745
870
|
onTouchMove(e) {
|
746
871
|
if (!this.isTouchDragging) return;
|
747
872
|
|
873
|
+
// 确保在拖拽模式下阻止所有事件传播
|
748
874
|
if (this.isTouchDragging && this.data.isEditing) {
|
749
875
|
if (e.oriEvent) {
|
750
876
|
e.oriEvent.preventDefault();
|
@@ -754,16 +880,17 @@ export default {
|
|
754
880
|
}
|
755
881
|
|
756
882
|
const touch = e.changedTouches[0];
|
757
|
-
const containerRect = this.$el.getBoundingClientRect();
|
758
883
|
|
759
|
-
//
|
760
|
-
this.targetTouchX = touch.pageX
|
761
|
-
this.targetTouchY = touch.pageY
|
884
|
+
// 更新目标位置而非直接设置
|
885
|
+
this.targetTouchX = touch.pageX;
|
886
|
+
this.targetTouchY = touch.pageY;
|
762
887
|
|
888
|
+
// 启动平滑动画(如果尚未启动)
|
763
889
|
if (!this.animationFrameId) {
|
764
890
|
this.animationFrameId = requestAnimationFrame(this.updateDragPosition);
|
765
891
|
}
|
766
892
|
|
893
|
+
// 简化的交换逻辑
|
767
894
|
this.handleSwapLogic(touch.pageX, touch.pageY);
|
768
895
|
},
|
769
896
|
|
@@ -822,15 +949,25 @@ export default {
|
|
822
949
|
// 平滑更新拖拽位置的方法
|
823
950
|
updateDragPosition() {
|
824
951
|
const easing = 0.6;
|
825
|
-
|
826
|
-
const
|
827
|
-
|
952
|
+
// 计算目标位置(考虑页面滚动位置)
|
953
|
+
const targetX = this.targetTouchX - this.touchOffsetX + window.pageXOffset;
|
954
|
+
const targetY = this.targetTouchY - this.touchOffsetY + window.pageYOffset;
|
955
|
+
|
956
|
+
// 平滑插值
|
828
957
|
this.dragCloneX += (targetX - this.dragCloneX) * easing;
|
829
958
|
this.dragCloneY += (targetY - this.dragCloneY) * easing;
|
830
|
-
|
831
|
-
|
832
|
-
if (Math.abs(this.
|
833
|
-
|
959
|
+
|
960
|
+
// 当接近目标位置时直接设置为目标位置
|
961
|
+
if (Math.abs(this.dragCloneX - targetX) < 0.5) {
|
962
|
+
this.dragCloneX = targetX;
|
963
|
+
}
|
964
|
+
if (Math.abs(this.dragCloneY - targetY) < 0.5) {
|
965
|
+
this.dragCloneY = targetY;
|
966
|
+
}
|
967
|
+
|
968
|
+
// 更新拖拽克隆元素位置
|
969
|
+
this.updateDragClonePosition();
|
970
|
+
|
834
971
|
this.animationFrameId = requestAnimationFrame(this.updateDragPosition);
|
835
972
|
},
|
836
973
|
|
@@ -852,6 +989,9 @@ export default {
|
|
852
989
|
this.isDragClone = false;
|
853
990
|
this.hoverIndex = null;
|
854
991
|
|
992
|
+
// 销毁拖拽克隆元素
|
993
|
+
this.destroyDragClone();
|
994
|
+
|
855
995
|
// 使用延时来重置拖拽索引,避免与点击事件冲突
|
856
996
|
setTimeout(() => {
|
857
997
|
this.draggingIndex = null;
|
@@ -873,6 +1013,9 @@ export default {
|
|
873
1013
|
this.isDragClone = false;
|
874
1014
|
this.hoverIndex = null;
|
875
1015
|
|
1016
|
+
// 销毁拖拽克隆元素
|
1017
|
+
this.destroyDragClone();
|
1018
|
+
|
876
1019
|
// 立即清除拖拽索引,避免状态卡住
|
877
1020
|
this.draggingIndex = null;
|
878
1021
|
this.isAnimating = false;
|
@@ -1008,6 +1151,8 @@ export default {
|
|
1008
1151
|
cancelAnimationFrame(this.animationFrameId);
|
1009
1152
|
this.animationFrameId = null;
|
1010
1153
|
}
|
1154
|
+
// 清理拖拽克隆元素
|
1155
|
+
this.destroyDragClone();
|
1011
1156
|
},
|
1012
1157
|
created() {
|
1013
1158
|
// 初始化处理后的数据列表
|
@@ -1029,12 +1174,11 @@ button {
|
|
1029
1174
|
.outer-container {
|
1030
1175
|
width: 100%;
|
1031
1176
|
position: relative;
|
1032
|
-
|
1177
|
+
z-index: 1;
|
1033
1178
|
}
|
1034
1179
|
|
1035
1180
|
.items-container {
|
1036
1181
|
width: 100%;
|
1037
|
-
position: relative;
|
1038
1182
|
}
|
1039
1183
|
|
1040
1184
|
.grid-items-wrapper {
|
@@ -1061,6 +1205,7 @@ button {
|
|
1061
1205
|
transition: all 0.15s cubic-bezier(0.2, 0, 0.2, 1);
|
1062
1206
|
will-change: transform, opacity, box-shadow;
|
1063
1207
|
overflow: hidden;
|
1208
|
+
z-index: 1;
|
1064
1209
|
}
|
1065
1210
|
|
1066
1211
|
.grid-box {
|
@@ -1120,16 +1265,17 @@ button {
|
|
1120
1265
|
|
1121
1266
|
/* 悬停目标的样式 */
|
1122
1267
|
.hover-target {
|
1123
|
-
z-index:
|
1268
|
+
z-index: 50;
|
1124
1269
|
transform: scale(1.05);
|
1125
1270
|
transition: all 0.1s ease-out;
|
1271
|
+
position: relative;
|
1126
1272
|
}
|
1127
1273
|
|
1128
1274
|
/* 正在拖拽的元素样式 */
|
1129
1275
|
.being-dragged {
|
1130
|
-
z-index:
|
1276
|
+
z-index: 100;
|
1131
1277
|
opacity: 0.3;
|
1132
|
-
|
1278
|
+
position: relative;
|
1133
1279
|
}
|
1134
1280
|
|
1135
1281
|
/* 被拖拽时原位置隐藏 */
|
@@ -1138,21 +1284,7 @@ button {
|
|
1138
1284
|
visibility: hidden;
|
1139
1285
|
}
|
1140
1286
|
|
1141
|
-
/*
|
1142
|
-
.drag-clone {
|
1143
|
-
position: absolute;
|
1144
|
-
z-index: 100;
|
1145
|
-
user-select: none;
|
1146
|
-
box-sizing: border-box;
|
1147
|
-
display: flex;
|
1148
|
-
justify-content: space-between;
|
1149
|
-
flex-direction: column;
|
1150
|
-
pointer-events: none;
|
1151
|
-
transition: none;
|
1152
|
-
will-change: transform;
|
1153
|
-
left: 0;
|
1154
|
-
top: 0;
|
1155
|
-
}
|
1287
|
+
/* 拖拽克隆元素样式(现在通过JavaScript动态应用) */
|
1156
1288
|
|
1157
1289
|
.flexBox {
|
1158
1290
|
display: flex;
|