完成靶子放大编辑
This commit is contained in:
@@ -26,19 +26,40 @@ const arrow = ref(null);
|
|||||||
const isDragging = ref(false);
|
const isDragging = ref(false);
|
||||||
const dragStartPos = ref({ x: 0, y: 0 });
|
const dragStartPos = ref({ x: 0, y: 0 });
|
||||||
const capsuleHeight = ref(0);
|
const capsuleHeight = ref(0);
|
||||||
|
const scale = ref(1);
|
||||||
|
const zoomPos = ref({ x: 0, y: 0 });
|
||||||
|
const targetPos = ref({ x: 0, y: 0 });
|
||||||
|
let lastMoveTime = 0;
|
||||||
|
|
||||||
// 点击靶纸创建新的点
|
// 点击靶纸创建新的点
|
||||||
const onClick = async (e) => {
|
const onClick = async (e) => {
|
||||||
if (arrow.value !== null || !props.onChange) return;
|
if (
|
||||||
|
arrow.value !== null ||
|
||||||
|
!props.onChange ||
|
||||||
|
Date.now() - lastMoveTime < 300
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const newArrow = {
|
const newArrow = {
|
||||||
x: e.detail.x,
|
x: e.detail.x - zoomPos.value.x - 6 / scale.value,
|
||||||
y: e.detail.y - rect.value.top - capsuleHeight.value,
|
y:
|
||||||
|
e.detail.y -
|
||||||
|
rect.value.top -
|
||||||
|
capsuleHeight.value -
|
||||||
|
zoomPos.value.y -
|
||||||
|
6 / scale.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
targetPos.value = {
|
||||||
|
x: zoomPos.value.x,
|
||||||
|
y: zoomPos.value.y,
|
||||||
};
|
};
|
||||||
const side = rect.value.width;
|
const side = rect.value.width;
|
||||||
newArrow.ring = calcRing(
|
newArrow.ring = calcRing(
|
||||||
props.id,
|
props.id,
|
||||||
newArrow.x - rect.value.width * 0.05,
|
newArrow.x / scale.value - rect.value.width * 0.05,
|
||||||
newArrow.y - 10,
|
newArrow.y / scale.value - rect.value.width * 0.05,
|
||||||
rect.value.width * 0.9,
|
rect.value.width * 0.9,
|
||||||
rect.value.width * 0.9
|
rect.value.width * 0.9
|
||||||
);
|
);
|
||||||
@@ -51,18 +72,27 @@ const onClick = async (e) => {
|
|||||||
|
|
||||||
// 确认添加箭矢
|
// 确认添加箭矢
|
||||||
const confirmAdd = () => {
|
const confirmAdd = () => {
|
||||||
if (props.onChange)
|
if (props.onChange) {
|
||||||
props.onChange({ ...arrow.value, ring: arrow.value.ring || "M" });
|
props.onChange({
|
||||||
|
x: arrow.value.x / scale.value,
|
||||||
|
y: arrow.value.y / scale.value,
|
||||||
|
ring: arrow.value.ring || "M",
|
||||||
|
});
|
||||||
|
}
|
||||||
arrow.value = null;
|
arrow.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 删除箭矢
|
// 删除箭矢
|
||||||
const deleteArrow = () => {
|
const deleteArrow = () => {
|
||||||
arrow.value = null;
|
arrow.value = null;
|
||||||
|
targetPos.value = {
|
||||||
|
x: zoomPos.value.x,
|
||||||
|
y: zoomPos.value.y,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 开始拖拽 - 同样修复坐标获取
|
// 开始拖拽 - 同样修复坐标获取
|
||||||
const startDrag = async (e, index) => {
|
const startDrag = async (e) => {
|
||||||
if (!e.touches[0]) return;
|
if (!e.touches[0]) return;
|
||||||
isDragging.value = true;
|
isDragging.value = true;
|
||||||
dragStartPos.value = {
|
dragStartPos.value = {
|
||||||
@@ -73,27 +103,34 @@ const startDrag = async (e, index) => {
|
|||||||
|
|
||||||
// 拖拽移动 - 同样修复坐标获取
|
// 拖拽移动 - 同样修复坐标获取
|
||||||
const onDrag = async (e) => {
|
const onDrag = async (e) => {
|
||||||
|
lastMoveTime = Date.now();
|
||||||
if (!isDragging.value || !e.touches[0] || !arrow.value) return;
|
if (!isDragging.value || !e.touches[0] || !arrow.value) return;
|
||||||
|
|
||||||
let clientX = e.touches[0].clientX;
|
let clientX = e.touches[0].clientX;
|
||||||
let clientY = e.touches[0].clientY;
|
let clientY = e.touches[0].clientY;
|
||||||
|
|
||||||
// 计算移动距离
|
// 计算移动距离
|
||||||
const deltaX = clientX - dragStartPos.value.x;
|
const deltaX = clientX - dragStartPos.value.x;
|
||||||
const deltaY = clientY - dragStartPos.value.y;
|
const deltaY = clientY - dragStartPos.value.y;
|
||||||
|
|
||||||
const side = rect.value.width;
|
const side = rect.value.width;
|
||||||
|
|
||||||
// 更新坐标
|
// 更新坐标
|
||||||
arrow.value.x = Math.max(0, Math.min(side, arrow.value.x * side + deltaX));
|
arrow.value.x = Math.max(
|
||||||
arrow.value.y = Math.max(0, Math.min(side, arrow.value.y * side + deltaY));
|
0,
|
||||||
|
Math.min(side * scale.value, arrow.value.x * side + deltaX)
|
||||||
|
);
|
||||||
|
arrow.value.y = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(side * scale.value, arrow.value.y * side + deltaY)
|
||||||
|
);
|
||||||
|
|
||||||
arrow.value.ring = calcRing(
|
arrow.value.ring = calcRing(
|
||||||
props.id,
|
props.id,
|
||||||
arrow.value.x - rect.value.width * 0.05,
|
arrow.value.x / scale.value - rect.value.width * 0.05,
|
||||||
arrow.value.y - 10,
|
arrow.value.y / scale.value - rect.value.width * 0.05,
|
||||||
rect.value.width * 0.9,
|
rect.value.width * 0.9,
|
||||||
rect.value.width * 0.9
|
rect.value.width * 0.9
|
||||||
);
|
);
|
||||||
|
|
||||||
arrow.value.x = arrow.value.x / side;
|
arrow.value.x = arrow.value.x / side;
|
||||||
arrow.value.y = arrow.value.y / side;
|
arrow.value.y = arrow.value.y / side;
|
||||||
|
|
||||||
@@ -102,17 +139,24 @@ const onDrag = async (e) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 结束拖拽
|
// 结束拖拽
|
||||||
const endDrag = () => {
|
const endDrag = (e) => {
|
||||||
isDragging.value = false;
|
isDragging.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const scale = ref(1);
|
|
||||||
const onScale = (e) => {
|
const onScale = (e) => {
|
||||||
scale.value = e.detail.scale; // 返回 1 ~ 2
|
lastMoveTime = Date.now();
|
||||||
|
const lastScale = scale.value;
|
||||||
|
scale.value = e.detail.scale;
|
||||||
|
zoomPos.value = { x: e.detail.x, y: e.detail.y };
|
||||||
|
if (arrow.value) {
|
||||||
|
arrow.value.x = arrow.value.x * (scale.value / lastScale);
|
||||||
|
arrow.value.y = arrow.value.y * (scale.value / lastScale);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMove = (e) => {
|
const onMove = (e) => {
|
||||||
console.log(e);
|
if (e.detail.source) {
|
||||||
|
zoomPos.value = { x: e.detail.x, y: e.detail.y };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
@@ -126,7 +170,7 @@ onMounted(async () => {
|
|||||||
<template>
|
<template>
|
||||||
<view
|
<view
|
||||||
class="container"
|
class="container"
|
||||||
@click="onClick"
|
@tap="onClick"
|
||||||
@touchmove="onDrag"
|
@touchmove="onDrag"
|
||||||
@touchend="endDrag"
|
@touchend="endDrag"
|
||||||
>
|
>
|
||||||
@@ -135,6 +179,8 @@ onMounted(async () => {
|
|||||||
class="move-view"
|
class="move-view"
|
||||||
direction="all"
|
direction="all"
|
||||||
scale
|
scale
|
||||||
|
:x="targetPos.x"
|
||||||
|
:y="targetPos.y"
|
||||||
:scale-min="1"
|
:scale-min="1"
|
||||||
:scale-max="3"
|
:scale-max="3"
|
||||||
:scale-value="scale"
|
:scale-value="scale"
|
||||||
@@ -144,61 +190,68 @@ onMounted(async () => {
|
|||||||
:out-of-bounds="true"
|
:out-of-bounds="true"
|
||||||
>
|
>
|
||||||
<image :src="src" mode="widthFix" />
|
<image :src="src" mode="widthFix" />
|
||||||
</movable-view>
|
|
||||||
<view
|
|
||||||
v-for="(arrow, index) in arrows"
|
|
||||||
:key="index"
|
|
||||||
class="arrow-point"
|
|
||||||
:style="{
|
|
||||||
left: (arrow.x !== undefined ? arrow.x : 0) * 100 + '%',
|
|
||||||
top: (arrow.y !== undefined ? arrow.y : 0) * 100 + '%',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<view
|
<view
|
||||||
v-if="arrow.x !== undefined && arrow.y !== undefined"
|
v-for="(arrow, index) in arrows"
|
||||||
class="point"
|
:key="index"
|
||||||
><text>{{ index + 1 }}</text></view
|
class="arrow-point"
|
||||||
|
:style="{
|
||||||
|
left: (arrow.x !== undefined ? arrow.x : 0) * 100 + '%',
|
||||||
|
top: (arrow.y !== undefined ? arrow.y : 0) * 100 + '%',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
</view>
|
|
||||||
<movable-view
|
|
||||||
v-if="arrow"
|
|
||||||
class="arrow-point"
|
|
||||||
direction="all"
|
|
||||||
:animation="false"
|
|
||||||
:x="rect.width * arrow.x"
|
|
||||||
:y="rect.width * arrow.y"
|
|
||||||
>
|
|
||||||
<!-- 箭矢点 -->
|
|
||||||
<view class="point"> </view>
|
|
||||||
<!-- 编辑按钮组(只在编辑状态下显示) -->
|
|
||||||
<view class="edit-buttons" @click.stop>
|
|
||||||
<view class="edit-btn-text">
|
|
||||||
<text v-if="arrow.ring === 0" :style="{ width: '100%' }"
|
|
||||||
>未上靶</text
|
|
||||||
>
|
|
||||||
<text v-if="arrow.ring !== 0">{{ arrow.ring }}</text>
|
|
||||||
<text
|
|
||||||
v-if="arrow.ring > 0"
|
|
||||||
:style="{
|
|
||||||
fontSize: '16px',
|
|
||||||
marginLeft: '2px',
|
|
||||||
}"
|
|
||||||
>环</text
|
|
||||||
>
|
|
||||||
</view>
|
|
||||||
<view class="edit-btn confirm-btn" @click.stop="confirmAdd(index)">
|
|
||||||
<image src="../static/arrow-edit-save.png" mode="widthFix" />
|
|
||||||
</view>
|
|
||||||
<view class="edit-btn delete-btn" @click.stop="deleteArrow(index)">
|
|
||||||
<image src="../static/arrow-edit-delete.png" mode="widthFix" />
|
|
||||||
</view>
|
|
||||||
<view
|
<view
|
||||||
class="edit-btn drag-btn"
|
v-if="arrow.x !== undefined && arrow.y !== undefined"
|
||||||
@touchstart.stop="startDrag($event, index)"
|
class="point"
|
||||||
|
:style="{ transform: `scale(${1 / scale})` }"
|
||||||
>
|
>
|
||||||
<image src="../static/arrow-edit-move.png" mode="widthFix" />
|
<text>{{ index + 1 }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<movable-view
|
||||||
|
v-if="arrow"
|
||||||
|
class="arrow-point"
|
||||||
|
direction="all"
|
||||||
|
:animation="false"
|
||||||
|
:out-of-bounds="true"
|
||||||
|
:x="arrow ? (rect.width * arrow.x) / scale : 0"
|
||||||
|
:y="arrow ? (rect.width * arrow.y) / scale : 0"
|
||||||
|
>
|
||||||
|
<view class="point" :style="{ transform: `scale(${1 / scale})` }">
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="arrow"
|
||||||
|
class="edit-buttons"
|
||||||
|
@touchstart.stop
|
||||||
|
:style="{ transform: `scale(${1 / scale})` }"
|
||||||
|
>
|
||||||
|
<view class="edit-btn-text">
|
||||||
|
<text v-if="arrow.ring === 0" :style="{ width: '100%' }"
|
||||||
|
>未上靶</text
|
||||||
|
>
|
||||||
|
<text v-if="arrow.ring !== 0">{{ arrow.ring }}</text>
|
||||||
|
<text
|
||||||
|
v-if="arrow.ring > 0"
|
||||||
|
:style="{
|
||||||
|
fontSize: '16px',
|
||||||
|
marginLeft: '2px',
|
||||||
|
}"
|
||||||
|
>环</text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
<view class="edit-btn confirm-btn" @touchstart.stop="confirmAdd">
|
||||||
|
<image src="../static/arrow-edit-save.png" mode="widthFix" />
|
||||||
|
</view>
|
||||||
|
<view class="edit-btn delete-btn" @touchstart.stop="deleteArrow">
|
||||||
|
<image src="../static/arrow-edit-delete.png" mode="widthFix" />
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="edit-btn drag-btn"
|
||||||
|
@touchstart.stop="startDrag($event)"
|
||||||
|
>
|
||||||
|
<image src="../static/arrow-edit-move.png" mode="widthFix" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</movable-view>
|
||||||
</movable-view>
|
</movable-view>
|
||||||
</movable-area>
|
</movable-area>
|
||||||
</view>
|
</view>
|
||||||
@@ -209,6 +262,7 @@ onMounted(async () => {
|
|||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vw;
|
height: 100vw;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
transform: translateY(-10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.move-area {
|
.move-area {
|
||||||
@@ -220,7 +274,7 @@ onMounted(async () => {
|
|||||||
.move-view {
|
.move-view {
|
||||||
width: 90vw;
|
width: 90vw;
|
||||||
height: 90vw;
|
height: 90vw;
|
||||||
margin: 10px 5vw;
|
padding: 5vw;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,12 +284,14 @@ onMounted(async () => {
|
|||||||
|
|
||||||
.arrow-point {
|
.arrow-point {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point {
|
.point {
|
||||||
transform: translate(-50%, -50%);
|
min-width: 12px;
|
||||||
width: 12px;
|
min-height: 12px;
|
||||||
height: 12px;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -245,6 +301,7 @@ onMounted(async () => {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background-color: #ff4444;
|
background-color: #ff4444;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
transition: all 0.1s linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point > text {
|
.point > text {
|
||||||
@@ -255,13 +312,14 @@ onMounted(async () => {
|
|||||||
|
|
||||||
.edit-buttons {
|
.edit-buttons {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(50% - 50px);
|
top: calc(50% - 44px);
|
||||||
left: calc(50% - 50px);
|
left: calc(50% - 44px);
|
||||||
background: #18ff6899;
|
background: #18ff6899;
|
||||||
width: 88px;
|
width: 88px;
|
||||||
height: 88px;
|
height: 88px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
transition: all 0.1s linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-btn-text {
|
.edit-btn-text {
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ onMounted(async () => {
|
|||||||
bowType.value = pointBook.bowType;
|
bowType.value = pointBook.bowType;
|
||||||
distance.value = pointBook.distance;
|
distance.value = pointBook.distance;
|
||||||
bowtargetType.value = pointBook.bowtargetType;
|
bowtargetType.value = pointBook.bowtargetType;
|
||||||
|
expandIndex.value = 3;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -183,6 +184,6 @@ onMounted(async () => {
|
|||||||
font-size: 27px;
|
font-size: 27px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
color: #FFF4C9;
|
color: #fff4c9;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user