diff --git a/src/components/BowTarget.vue b/src/components/BowTarget.vue
index 79ee41d..1a26f5a 100644
--- a/src/components/BowTarget.vue
+++ b/src/components/BowTarget.vue
@@ -57,6 +57,8 @@ const timer = ref(null);
const dirTimer = ref(null);
const angle = ref(null);
const circleColor = ref("");
+const ROUND_TIP_OFFSET_Y = -32;
+const EXPERIENCE_TIP_OFFSET_Y = -68;
watch(
() => props.scores,
@@ -133,14 +135,14 @@ function formatTargetPosition(percent, offset) {
return pxOffset ? `calc(${percent}%${pxOffset})` : `${percent}%`;
}
-function getTargetPositionStyle(point, offsetPx = 0) {
+function getTargetPositionStyle(point, offsetPx = 0, extraOffset = {}) {
if (!point) return { display: "none" };
const radius = safeTargetRadius.value;
const diameter = radius * 2;
const direction = getPointDirection(point);
- const xOffset = direction ? direction.x * offsetPx : 0;
- const yOffset = direction ? -direction.y * offsetPx : 0;
+ const xOffset = (direction ? direction.x * offsetPx : 0) + (extraOffset.x || 0);
+ const yOffset = (direction ? -direction.y * offsetPx : 0) + (extraOffset.y || 0);
const leftPercent = ((point.x + radius) / diameter) * 100;
const topPercent = ((radius - point.y) / diameter) * 100;
@@ -162,9 +164,22 @@ function getHitStyle(shot) {
};
}
-function getTipStyle(shot) {
+function getRoundTipStyle(shot) {
const point = getShotPoint(shot, true);
- return getTargetPositionStyle(point, shot?.ring ? currentHitRadiusPx.value : 0);
+ return getTargetPositionStyle(
+ point,
+ shot?.ring ? currentHitRadiusPx.value : 0,
+ { y: ROUND_TIP_OFFSET_Y }
+ );
+}
+
+function getExperienceTipStyle(shot) {
+ const point = getShotPoint(shot, true);
+ return getTargetPositionStyle(
+ point,
+ shot?.ring ? currentHitRadiusPx.value : 0,
+ { y: EXPERIENCE_TIP_OFFSET_Y }
+ );
}
const simulShoot = async () => {
if (device.value.deviceId) await simulShootAPI(device.value.deviceId);
@@ -247,14 +262,14 @@ onBeforeUnmount(() => {
经验 +1
{{ latestOne.ringX ? "X" : latestOne.ring || "未上靶"
}}环
@@ -265,14 +280,14 @@ onBeforeUnmount(() => {
user.id === bluelatestOne.playerId
"
class="e-value fade-in-out"
- :style="getTipStyle(bluelatestOne)"
+ :style="getExperienceTipStyle(bluelatestOne)"
>
经验 +1
{{ bluelatestOne.ringX ? "X" : bluelatestOne.ring || "未上靶"
}}环
@@ -356,6 +371,31 @@ onBeforeUnmount(() => {
font-size: 24px;
margin-left: 5px;
}
+@keyframes target-tip-fade-in-out {
+ 0% {
+ transform: translate(-50%, -50%) translateY(20px);
+ opacity: 0;
+ }
+
+ 30% {
+ transform: translate(-50%, -50%);
+ opacity: 1;
+ }
+
+ 80% {
+ transform: translate(-50%, -50%);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: translate(-50%, -50%);
+ opacity: 0;
+ }
+}
+.round-tip.fade-in-out,
+.e-value.fade-in-out {
+ animation: target-tip-fade-in-out 1.2s ease forwards;
+}
.target > image:last-child {
width: 100%;
height: 100%;
diff --git a/src/pages/team-battle/components/BowTarget.vue b/src/pages/team-battle/components/BowTarget.vue
index c855fea..4555309 100644
--- a/src/pages/team-battle/components/BowTarget.vue
+++ b/src/pages/team-battle/components/BowTarget.vue
@@ -59,6 +59,8 @@ const timer = ref(null);
const dirTimer = ref(null);
const angle = ref(null);
const circleColor = ref("");
+const ROUND_TIP_OFFSET_Y = -32;
+const EXPERIENCE_TIP_OFFSET_Y = -68;
function showShotFlash(flash) {
const shootData = flash?.shootData;
@@ -128,14 +130,14 @@ function formatTargetPosition(percent, offset) {
return pxOffset ? `calc(${percent}%${pxOffset})` : `${percent}%`;
}
-function getTargetPositionStyle(point, offsetPx = 0) {
+function getTargetPositionStyle(point, offsetPx = 0, extraOffset = {}) {
if (!point) return { display: "none" };
const radius = safeTargetRadius.value;
const diameter = radius * 2;
const direction = getPointDirection(point);
- const xOffset = direction ? direction.x * offsetPx : 0;
- const yOffset = direction ? -direction.y * offsetPx : 0;
+ const xOffset = (direction ? direction.x * offsetPx : 0) + (extraOffset.x || 0);
+ const yOffset = (direction ? -direction.y * offsetPx : 0) + (extraOffset.y || 0);
const leftPercent = ((point.x + radius) / diameter) * 100;
const topPercent = ((radius - point.y) / diameter) * 100;
@@ -157,9 +159,22 @@ function getHitStyle(shot) {
};
}
-function getTipStyle(shot) {
+function getRoundTipStyle(shot) {
const point = getShotPoint(shot, true);
- return getTargetPositionStyle(point, shot?.ring ? currentHitRadiusPx.value : 0);
+ return getTargetPositionStyle(
+ point,
+ shot?.ring ? currentHitRadiusPx.value : 0,
+ { y: ROUND_TIP_OFFSET_Y }
+ );
+}
+
+function getExperienceTipStyle(shot) {
+ const point = getShotPoint(shot, true);
+ return getTargetPositionStyle(
+ point,
+ shot?.ring ? currentHitRadiusPx.value : 0,
+ { y: EXPERIENCE_TIP_OFFSET_Y }
+ );
}
const simulShoot = async () => {
if (device.value.deviceId) await simulShootAPI(device.value.deviceId);
@@ -242,14 +257,14 @@ onBeforeUnmount(() => {
经验 +1
{{ latestOne.ringX ? "X" : latestOne.ring || "未上靶"
}}环
@@ -260,14 +275,14 @@ onBeforeUnmount(() => {
user.id === bluelatestOne.playerId
"
class="e-value fade-in-out"
- :style="getTipStyle(bluelatestOne)"
+ :style="getExperienceTipStyle(bluelatestOne)"
>
经验 +1
{{ bluelatestOne.ringX ? "X" : bluelatestOne.ring || "未上靶"
}}环
@@ -351,6 +366,31 @@ onBeforeUnmount(() => {
font-size: 24px;
margin-left: 5px;
}
+@keyframes target-tip-fade-in-out {
+ 0% {
+ transform: translate(-50%, -50%) translateY(20px);
+ opacity: 0;
+ }
+
+ 30% {
+ transform: translate(-50%, -50%);
+ opacity: 1;
+ }
+
+ 80% {
+ transform: translate(-50%, -50%);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: translate(-50%, -50%);
+ opacity: 0;
+ }
+}
+.round-tip.fade-in-out,
+.e-value.fade-in-out {
+ animation: target-tip-fade-in-out 1.2s ease forwards;
+}
.target > image:last-child {
width: 100%;
height: 100%;