添加靶子缩放功能

This commit is contained in:
kron
2025-08-07 18:13:14 +08:00
parent 125719f294
commit d20e84f66c
3 changed files with 82 additions and 38 deletions

View File

@@ -25,16 +25,23 @@ const rect = ref({});
const arrow = ref(null); 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 onClick = async (e) => { const onClick = async (e) => {
if (arrow.value !== null || !props.onChange) return; if (arrow.value !== null || !props.onChange) return;
const newArrow = { const newArrow = {
x: e.detail.x - (rect.value.width * 0.1) / 2, x: e.detail.x,
y: e.detail.y - rect.value.top - 10, y: e.detail.y - rect.value.top - capsuleHeight.value,
}; };
const side = rect.value.width * 0.9; const side = rect.value.width;
newArrow.ring = calcRing(props.id, newArrow.x, newArrow.y, side, side); newArrow.ring = calcRing(
props.id,
newArrow.x - rect.value.width * 0.05,
newArrow.y - 10,
rect.value.width * 0.9,
rect.value.width * 0.9
);
arrow.value = { arrow.value = {
...newArrow, ...newArrow,
x: newArrow.x / side, x: newArrow.x / side,
@@ -75,17 +82,17 @@ const onDrag = async (e) => {
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 * 0.9; const side = rect.value.width;
// 更新坐标 // 更新坐标
arrow.value.x = Math.max(0, Math.min(side, arrow.value.x * side + deltaX)); arrow.value.x = Math.max(0, Math.min(side, arrow.value.x * side + deltaX));
arrow.value.y = Math.max(0, Math.min(side, arrow.value.y * side + deltaY)); arrow.value.y = Math.max(0, Math.min(side, arrow.value.y * side + deltaY));
arrow.value.ring = calcRing( arrow.value.ring = calcRing(
props.id, props.id,
arrow.value.x, arrow.value.x - rect.value.width * 0.05,
arrow.value.y, arrow.value.y - 10,
side, rect.value.width * 0.9,
side 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;
@@ -99,21 +106,45 @@ const endDrag = () => {
isDragging.value = false; isDragging.value = false;
}; };
const scale = ref(1);
const onScale = (e) => {
scale.value = e.detail.scale; // 返回 1 ~ 2
};
const onMove = (e) => {
console.log(e);
};
onMounted(async () => { onMounted(async () => {
const result = await getElementRect(); const menuBtnInfo = uni.getMenuButtonBoundingClientRect();
capsuleHeight.value = menuBtnInfo.top - 9;
const result = await getElementRect(".container");
rect.value = result; rect.value = result;
}); });
</script> </script>
<template> <template>
<movable-area class="move-container">
<view <view
class="container" class="container"
@click="onClick" @click="onClick"
@touchmove="onDrag" @touchmove="onDrag"
@touchend="endDrag" @touchend="endDrag"
>
<movable-area class="move-area" scale-area>
<movable-view
class="move-view"
direction="all"
scale
:scale-min="1"
:scale-max="3"
:scale-value="scale"
:animation="false"
@scale="onScale"
@change="onMove"
:out-of-bounds="true"
> >
<image :src="src" mode="widthFix" /> <image :src="src" mode="widthFix" />
</movable-view>
<view <view
v-for="(arrow, index) in arrows" v-for="(arrow, index) in arrows"
:key="index" :key="index"
@@ -134,8 +165,8 @@ onMounted(async () => {
class="arrow-point" class="arrow-point"
direction="all" direction="all"
:animation="false" :animation="false"
:x="rect.width * 0.9 * arrow.x" :x="rect.width * arrow.x"
:y="rect.width * 0.9 * arrow.y" :y="rect.width * arrow.y"
> >
<!-- 箭矢点 --> <!-- 箭矢点 -->
<view class="point"> </view> <view class="point"> </view>
@@ -169,25 +200,32 @@ onMounted(async () => {
</view> </view>
</view> </view>
</movable-view> </movable-view>
</view>
</movable-area> </movable-area>
</view>
</template> </template>
<style scoped> <style scoped>
.move-container {
width: 90vw;
height: 90vw;
margin: 10px auto;
}
.container { .container {
width: 100%; width: 100vw;
position: relative; height: 100vw;
user-select: none; overflow: hidden;
} }
.container > image { .move-area {
width: 100%;
height: 100%;
position: relative;
}
.move-view {
width: 90vw;
height: 90vw;
margin: 10px 5vw;
position: relative;
}
.move-view > image {
width: 100%; width: 100%;
display: block;
} }
.arrow-point { .arrow-point {
@@ -200,7 +238,6 @@ onMounted(async () => {
height: 12px; height: 12px;
border-radius: 50%; border-radius: 50%;
border: 1px solid #fff; border: 1px solid #fff;
z-index: 1;
color: #fff; color: #fff;
font-size: 8px; font-size: 8px;
text-align: center; text-align: center;
@@ -218,8 +255,8 @@ onMounted(async () => {
.edit-buttons { .edit-buttons {
position: absolute; position: absolute;
top: calc(50% - 44px); top: calc(50% - 50px);
left: calc(50% - 44px); left: calc(50% - 50px);
background: #18ff6899; background: #18ff6899;
width: 88px; width: 88px;
height: 88px; height: 88px;

View File

@@ -195,6 +195,7 @@ onMounted(() => {
display: grid; display: grid;
column-gap: 1vw; column-gap: 1vw;
grid-template-columns: repeat(6, 1fr); grid-template-columns: repeat(6, 1fr);
position: relative;
} }
.bow-arrows > view, .bow-arrows > view,
.bow-rings > view { .bow-rings > view {
@@ -252,6 +253,7 @@ onMounted(() => {
justify-content: space-between; justify-content: space-between;
font-size: 13px; font-size: 13px;
margin: 0 15px; margin: 0 15px;
position: relative;
} }
.title-bar > view:first-child { .title-bar > view:first-child {
display: flex; display: flex;

View File

@@ -288,11 +288,11 @@ export const isGameEnded = async (battleId) => {
}; };
// 获取元素尺寸和位置信息 // 获取元素尺寸和位置信息
export const getElementRect = () => { export const getElementRect = (classname) => {
return new Promise((resolve) => { return new Promise((resolve) => {
const query = uni.createSelectorQuery(); const query = uni.createSelectorQuery();
query query
.select(".container") .select(classname)
.boundingClientRect((rect) => { .boundingClientRect((rect) => {
resolve(rect); resolve(rect);
}) })
@@ -409,7 +409,12 @@ export const calcPinBowTarget = (
y / targetWidth >= 0.032 && y / targetWidth >= 0.032 &&
y / targetHeight <= 0.51 y / targetHeight <= 0.51
) { ) {
return calcHalfBowTarget(x - targetWidth * 0.26, y - targetHeight * 0.032, side, noX); return calcHalfBowTarget(
x - targetWidth * 0.26,
y - targetHeight * 0.032,
side,
noX
);
} else if (x / targetHeight <= 0.48 && y / targetHeight >= 0.482) { } else if (x / targetHeight <= 0.48 && y / targetHeight >= 0.482) {
return calcHalfBowTarget(x, y - targetHeight * 0.482, side, noX); return calcHalfBowTarget(x, y - targetHeight * 0.482, side, noX);
} else if (x / targetHeight >= 0.52 && y / targetHeight >= 0.482) { } else if (x / targetHeight >= 0.52 && y / targetHeight >= 0.482) {