完成创建靶点

This commit is contained in:
kron
2025-07-31 14:32:14 +08:00
parent 0ebe34cc1e
commit af888c68be
8 changed files with 269 additions and 12 deletions

View File

@@ -249,6 +249,7 @@ const simulShoot2 = async () => {
text-align: center; text-align: center;
line-height: 10px; line-height: 10px;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
} }
.hit > text { .hit > text {
transform: scaleX(0.7); transform: scaleX(0.7);

View File

@@ -1,8 +1,143 @@
<script setup></script> <script setup>
import { ref, onMounted } from "vue";
import { getElementRect, calcRing } from "@/util";
const props = defineProps({
arrows: {
type: Array,
default: () => [],
},
onChange: {
type: Function,
default: (arrow) => {},
},
});
const rect = ref({});
const arrow = ref(null);
const isDragging = ref(false);
const dragStartPos = ref({ x: 0, y: 0 });
// 点击靶纸创建新的点
const onClick = async (e) => {
if (arrow.value !== null) return;
const newArrow = {
x: e.detail.x - (rect.value.width * 0.1) / 2,
y: e.detail.y - rect.value.top - 10,
};
newArrow.ring = calcRing(newArrow.x, newArrow.y);
arrow.value = newArrow;
};
// 确认添加箭矢
const confirmAdd = () => {
props.onChange(arrow.value);
arrow.value = null;
};
// 删除箭矢
const deleteArrow = () => {
arrow.value = null;
};
// 开始拖拽 - 同样修复坐标获取
const startDrag = async (e, index) => {
if (!e.touches[0]) return;
isDragging.value = true;
dragStartPos.value = {
x: e.touches[0].clientX,
y: e.touches[0].clientY,
};
};
// 拖拽移动 - 同样修复坐标获取
const onDrag = async (e) => {
if (!isDragging.value || !e.touches[0] || !arrow.value) return;
let clientX = e.touches[0].clientX;
let clientY = e.touches[0].clientY;
// 计算移动距离
const deltaX = clientX - dragStartPos.value.x;
const deltaY = clientY - dragStartPos.value.y;
const length = rect.value.width * 0.9;
// 更新坐标
arrow.value.x = Math.max(0, Math.min(length, arrow.value.x + deltaX));
arrow.value.y = Math.max(0, Math.min(length, arrow.value.y + deltaY));
arrow.value.ring = calcRing(arrow.value.x, arrow.value.y);
// 更新拖拽起始位置
dragStartPos.value = { x: clientX, y: clientY };
};
// 结束拖拽
const endDrag = () => {
isDragging.value = false;
};
onMounted(async () => {
const result = await getElementRect();
rect.value = result;
});
</script>
<template> <template>
<view class="container"> <view
class="container"
@click="onClick"
@touchmove="onDrag"
@touchend="endDrag"
>
<image src="../static/bow-target.png" mode="widthFix" /> <image src="../static/bow-target.png" mode="widthFix" />
<view
v-for="(arrow, index) in arrows"
:key="index"
class="arrow-point"
:style="{
left: (arrow.x !== undefined ? arrow.x : 0) + 'px',
top: (arrow.y !== undefined ? arrow.y : 0) + 'px',
}"
>
<view v-if="arrow.x !== undefined && arrow.y !== undefined" class="point"
><text>{{ index + 1 }}</text></view
>
</view>
<!-- 渲染所有箭矢点 -->
<view
v-if="arrow"
class="arrow-point"
:style="{
left: arrow.x + 'px',
top: arrow.y + 'px',
}"
>
<!-- 箭矢点 -->
<view class="point"> </view>
<!-- 编辑按钮组只在编辑状态下显示 -->
<view class="edit-buttons" @click.stop>
<text
><text :style="{ fontSize: '24px', marginRight: '5px' }">{{
arrow.ring
}}</text
>{{ arrow.ring ? "环" : "" }}</text
>
<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
class="edit-btn drag-btn"
@touchstart.stop="startDrag($event, index)"
>
<image src="../static/arrow-edit-move.png" mode="widthFix" />
</view>
</view>
</view>
</view> </view>
</template> </template>
@@ -10,8 +145,91 @@
.container { .container {
width: 90%; width: 90%;
margin: 10px auto; margin: 10px auto;
position: relative;
user-select: none;
} }
.container > image { .container > image {
width: 100%; width: 100%;
display: block;
}
.arrow-point {
position: absolute;
transform: translate(-50%, -50%);
z-index: 10;
}
.point {
width: 12px;
height: 12px;
border-radius: 50%;
border: 1px solid #fff;
z-index: 1;
color: #fff;
font-size: 8px;
text-align: center;
line-height: 10px;
box-sizing: border-box;
background-color: #ff4444;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
.point > text {
transform: scaleX(0.7);
display: block;
font-weight: bold;
}
.edit-buttons {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
background: #18ff6899;
width: 88px;
height: 88px;
display: flex;
align-items: flex-end;
}
.edit-buttons > text {
width: 100%;
display: block;
line-height: 50px;
text-align: center;
font-size: 20px;
font-weight: bold;
color: #fff;
}
.edit-btn {
transform: translateX(-50%) translateY(-50%);
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
}
.edit-btn > image {
width: 24px;
height: 24px;
}
.confirm-btn {
left: 50%;
bottom: -24px;
}
.delete-btn {
right: -24px;
bottom: -24px;
}
.drag-btn {
left: 50%;
top: 0;
} }
</style> </style>

View File

@@ -236,7 +236,9 @@ watch(
<text></text> <text></text>
</view> </view>
</view> </view>
<view>选择每组的箭数</view> <view :style="{ marginTop: '5px', marginBottom: '10px' }"
>选择每组的箭数</view
>
<view class="amount-items"> <view class="amount-items">
<view <view
v-for="(item, index) in groupArrows" v-for="(item, index) in groupArrows"

View File

@@ -24,6 +24,10 @@ const ringColors = [
"#9B9B9B", "#9B9B9B",
]; ];
const onEdit = (arrows) => {
arrowGroups.value[currentGroup.value][currentArrow.value] = { ring };
};
const onBack = () => { const onBack = () => {
uni.navigateBack(); uni.navigateBack();
}; };
@@ -38,17 +42,22 @@ const onSubmit = () => {
}; };
const onClickRing = (ring) => { const onClickRing = (ring) => {
if (arrowGroups.value[currentGroup.value]) { if (arrowGroups.value[currentGroup.value]) {
arrowGroups.value[currentGroup.value][currentArrow.value] = ring; arrowGroups.value[currentGroup.value][currentArrow.value] = { ring };
clickable.value = arrowGroups.value[currentGroup.value].every( clickable.value = arrowGroups.value[currentGroup.value].every(
(item) => !!item (item) => !!item.ring
); );
if (currentArrow.value < amount.value - 1) { if (currentArrow.value < amount.value - 1) currentArrow.value++;
currentArrow.value++;
}
} }
}; };
const deleteArrow = () => { const deleteArrow = () => {
arrowGroups.value[currentGroup.value][currentArrow.value] = ""; arrowGroups.value[currentGroup.value][currentArrow.value] = {};
};
const onEditDone = (arrow) => {
arrowGroups.value[currentGroup.value][currentArrow.value] = {
...arrow,
ring: 10,
};
if (currentArrow.value < amount.value - 1) currentArrow.value++;
}; };
onMounted(() => { onMounted(() => {
@@ -57,7 +66,7 @@ onMounted(() => {
groups.value = Number(pointBook.amountGroup.split("/")[0]); groups.value = Number(pointBook.amountGroup.split("/")[0]);
amount.value = Number(pointBook.amountGroup.split("/")[1]); amount.value = Number(pointBook.amountGroup.split("/")[1]);
for (let i = 1; i <= groups.value; i++) { for (let i = 1; i <= groups.value; i++) {
arrowGroups.value[i] = new Array(amount.value).fill(""); arrowGroups.value[i] = new Array(amount.value).fill({});
} }
} }
}); });
@@ -71,7 +80,10 @@ onMounted(() => {
:onBack="() => (showTip = true)" :onBack="() => (showTip = true)"
> >
<view class="container"> <view class="container">
<BowTargetEdit /> <BowTargetEdit
:onChange="onEditDone"
:arrows="arrowGroups[currentGroup]"
/>
<view class="title-bar"> <view class="title-bar">
<view> <view>
<view /> <view />
@@ -92,7 +104,13 @@ onMounted(() => {
borderColor: currentArrow === index ? '#FED847' : '#eeeeee', borderColor: currentArrow === index ? '#FED847' : '#eeeeee',
borderWidth: currentArrow === index ? '2px' : '1px', borderWidth: currentArrow === index ? '2px' : '1px',
}" }"
>{{ isNaN(arrow) ? arrow : arrow ? arrow + " 环" : "" }}</view >{{
isNaN(arrow.ring)
? arrow.ring
: arrow.ring
? arrow.ring + " 环"
: ""
}}</view
> >
</view> </view>
<text>输入分值的情况下系统不提供落点稳定性分</text> <text>输入分值的情况下系统不提供落点稳定性分</text>

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -282,3 +282,21 @@ export const isGameEnded = async (battleId) => {
} }
return !isGaming; return !isGaming;
}; };
// 获取元素尺寸和位置信息
export const getElementRect = () => {
return new Promise((resolve) => {
const query = uni.createSelectorQuery();
query
.select(".container")
.boundingClientRect((rect) => {
resolve(rect);
})
.exec();
});
};
export const calcRing = (x, y) => {
console.log(1111, x, y);
return 8;
};