지도 도시 포인터 대상을 아이콘으로 한정
This commit is contained in:
@@ -1732,7 +1732,7 @@ test('enters general and nation command arguments and sends exact values', async
|
|||||||
expect(castle.renderedWidth / castle.naturalWidth).toBeCloseTo(castle.renderedHeight / castle.naturalHeight, 2);
|
expect(castle.renderedWidth / castle.naturalWidth).toBeCloseTo(castle.renderedHeight / castle.naturalHeight, 2);
|
||||||
}
|
}
|
||||||
const layerStyles = await commandMap.evaluate((element) => ({
|
const layerStyles = await commandMap.evaluate((element) => ({
|
||||||
background: getComputedStyle(element.querySelector<HTMLElement>('.map-bglayer1')!).backgroundImage,
|
background: element.querySelector<HTMLImageElement>('.map-bglayer1 .map-background-image')?.src ?? '',
|
||||||
road: getComputedStyle(element.querySelector<HTMLElement>('.map-bgroad')!).backgroundImage,
|
road: getComputedStyle(element.querySelector<HTMLElement>('.map-bgroad')!).backgroundImage,
|
||||||
}));
|
}));
|
||||||
expect(layerStyles.background).toContain('/game/map/che/bg_spring.jpg');
|
expect(layerStyles.background).toContain('/game/map/che/bg_spring.jpg');
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ const city = {
|
|||||||
};
|
};
|
||||||
const castleFixtures = [
|
const castleFixtures = [
|
||||||
{ id: 1, level: 8, layoutLevel: 1, x: 100, y: 100, width: 32, height: 24 },
|
{ id: 1, level: 8, layoutLevel: 1, x: 100, y: 100, width: 32, height: 24 },
|
||||||
{ id: 2, level: 1, layoutLevel: 8, x: 200, y: 100, width: 16, height: 15 },
|
{ id: 2, name: '진류', level: 6, layoutLevel: 6, x: 365, y: 185, width: 26, height: 18 },
|
||||||
{ id: 3, level: 2, layoutLevel: 8, x: 300, y: 100, width: 20, height: 14 },
|
{ id: 3, name: '관도', level: 2, layoutLevel: 2, x: 340, y: 165, width: 20, height: 14 },
|
||||||
{ id: 4, level: 3, layoutLevel: 8, x: 400, y: 100, width: 14, height: 14 },
|
{ id: 4, name: '정도', level: 2, layoutLevel: 2, x: 400, y: 210, width: 20, height: 14 },
|
||||||
{ id: 5, name: '남만', level: 4, layoutLevel: 8, x: 80, y: 455, width: 20, height: 15 },
|
{ id: 5, name: '남만', level: 4, layoutLevel: 8, x: 80, y: 455, width: 20, height: 15 },
|
||||||
{ id: 6, name: '교지', level: 5, layoutLevel: 8, x: 130, y: 480, width: 24, height: 16 },
|
{ id: 6, name: '교지', level: 5, layoutLevel: 8, x: 130, y: 480, width: 24, height: 16 },
|
||||||
{ id: 7, name: '남해', level: 6, layoutLevel: 8, x: 245, y: 480, width: 26, height: 18 },
|
{ id: 7, name: '남해', level: 6, layoutLevel: 8, x: 245, y: 480, width: 26, height: 18 },
|
||||||
@@ -551,6 +551,63 @@ test('map keeps desktop hover navigation and lets touch users choose one-tap or
|
|||||||
await desktopCity.hover();
|
await desktopCity.hover();
|
||||||
await expect(page.locator('.map-tooltip .tooltip-title')).toHaveText('【하북|특】업');
|
await expect(page.locator('.map-tooltip .tooltip-title')).toHaveText('【하북|특】업');
|
||||||
|
|
||||||
|
const cityHitTargets = await page.locator('.map-area .city-base').evaluateAll((cities) =>
|
||||||
|
cities.map((city) => {
|
||||||
|
const icon = city.querySelector<HTMLElement>('.city-icon');
|
||||||
|
const background = city.querySelector<HTMLElement>('.city-bg');
|
||||||
|
if (!icon || !background) throw new Error('Missing city icon or background');
|
||||||
|
const cityRect = city.getBoundingClientRect();
|
||||||
|
const iconRect = icon.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
city: { left: cityRect.left, top: cityRect.top, width: cityRect.width, height: cityRect.height },
|
||||||
|
icon: { left: iconRect.left, top: iconRect.top, width: iconRect.width, height: iconRect.height },
|
||||||
|
backgroundPointerEvents: getComputedStyle(background).pointerEvents,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
for (const target of cityHitTargets) {
|
||||||
|
expect(target.city).toEqual(target.icon);
|
||||||
|
expect(target.backgroundPointerEvents).toBe('none');
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstCityBackgroundOnlyPoint = await desktopCity.evaluate((city) => {
|
||||||
|
const iconRect = city.querySelector<HTMLElement>('.city-icon')!.getBoundingClientRect();
|
||||||
|
const backgroundRect = city.querySelector<HTMLElement>('.city-bg')!.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
x: backgroundRect.left + 2,
|
||||||
|
y: backgroundRect.top + 2,
|
||||||
|
icon: { left: iconRect.left, top: iconRect.top, right: iconRect.right, bottom: iconRect.bottom },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
expect(firstCityBackgroundOnlyPoint.x).toBeLessThan(firstCityBackgroundOnlyPoint.icon.left);
|
||||||
|
expect(firstCityBackgroundOnlyPoint.y).toBeLessThan(firstCityBackgroundOnlyPoint.icon.top);
|
||||||
|
await page.mouse.move(firstCityBackgroundOnlyPoint.x, firstCityBackgroundOnlyPoint.y);
|
||||||
|
await expect(page.locator('.map-tooltip')).toHaveCount(0);
|
||||||
|
await page.mouse.click(firstCityBackgroundOnlyPoint.x, firstCityBackgroundOnlyPoint.y);
|
||||||
|
await expect(page).toHaveURL(/\/global-info$/u);
|
||||||
|
|
||||||
|
const mapRect = await page.locator('.map-area').evaluate((element) => {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
return { left: rect.left, top: rect.top };
|
||||||
|
});
|
||||||
|
for (const gap of [
|
||||||
|
{ x: 351, y: 174, between: '관도-진류' },
|
||||||
|
{ x: 383, y: 198, between: '진류-정도' },
|
||||||
|
]) {
|
||||||
|
await page.mouse.move(mapRect.left + gap.x, mapRect.top + gap.y);
|
||||||
|
await expect(page.locator('.map-tooltip'), `${gap.between} 아이콘 사이 hover`).toHaveCount(0);
|
||||||
|
await page.mouse.click(mapRect.left + gap.x, mapRect.top + gap.y);
|
||||||
|
await expect(page, `${gap.between} 아이콘 사이 click`).toHaveURL(/\/global-info$/u);
|
||||||
|
}
|
||||||
|
|
||||||
|
const jinliu = page.getByRole('link', { name: '진류', exact: true });
|
||||||
|
await jinliu.hover();
|
||||||
|
await expect(page.locator('.map-tooltip .tooltip-title')).toHaveText('【하북|중】진류');
|
||||||
|
await jinliu.click();
|
||||||
|
await expect(page).toHaveURL(/\/current-city\?cityId=2$/u);
|
||||||
|
await page.goBack();
|
||||||
|
await expect(page).toHaveURL(/\/global-info$/u);
|
||||||
|
|
||||||
for (const cityName of ['남만', '교지', '남해', '대']) {
|
for (const cityName of ['남만', '교지', '남해', '대']) {
|
||||||
await page.getByRole('link', { name: cityName, exact: true }).hover();
|
await page.getByRole('link', { name: cityName, exact: true }).hover();
|
||||||
await expect(page.locator('.map-tooltip')).toBeVisible();
|
await expect(page.locator('.map-tooltip')).toBeVisible();
|
||||||
@@ -698,7 +755,7 @@ test('map keeps desktop hover navigation and lets touch users choose one-tap or
|
|||||||
|
|
||||||
await mobileCities.nth(1).tap();
|
await mobileCities.nth(1).tap();
|
||||||
await expect(mobilePage).toHaveURL(/\/global-info$/u);
|
await expect(mobilePage).toHaveURL(/\/global-info$/u);
|
||||||
await expect(mobilePage.locator('.map-tooltip .tooltip-title')).toHaveText('【하북|수】성2');
|
await expect(mobilePage.locator('.map-tooltip .tooltip-title')).toHaveText('【하북|중】진류');
|
||||||
await mobilePage.screenshot({ path: testInfo.outputPath('mobile-map-first-tap-tooltip.png'), fullPage: true });
|
await mobilePage.screenshot({ path: testInfo.outputPath('mobile-map-first-tap-tooltip.png'), fullPage: true });
|
||||||
|
|
||||||
await mobileCities.nth(1).tap();
|
await mobileCities.nth(1).tap();
|
||||||
|
|||||||
@@ -78,7 +78,12 @@ const touchend = (event: TouchEvent) => {
|
|||||||
readonly: props.readonly,
|
readonly: props.readonly,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
:style="{ left: `${props.city.x}px`, top: `${props.city.y}px` }"
|
:style="{
|
||||||
|
left: `${props.city.x}px`,
|
||||||
|
top: `${props.city.y}px`,
|
||||||
|
width: `${size}px`,
|
||||||
|
height: `${size}px`,
|
||||||
|
}"
|
||||||
@mouseenter="emit('hover', props.city.id)"
|
@mouseenter="emit('hover', props.city.id)"
|
||||||
@mouseleave="emit('leave')"
|
@mouseleave="emit('leave')"
|
||||||
@touchstart="touchstart"
|
@touchstart="touchstart"
|
||||||
@@ -107,10 +112,7 @@ const touchend = (event: TouchEvent) => {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.map-city {
|
.map-city {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex;
|
box-sizing: border-box;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 2px;
|
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
color: rgba(232, 221, 196, 0.8);
|
color: rgba(232, 221, 196, 0.8);
|
||||||
@@ -126,7 +128,8 @@ const touchend = (event: TouchEvent) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.city-dot {
|
.city-dot {
|
||||||
position: relative;
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
border: 1px solid rgba(232, 221, 196, 0.6);
|
border: 1px solid rgba(232, 221, 196, 0.6);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -179,6 +182,7 @@ const touchend = (event: TouchEvent) => {
|
|||||||
.city-state {
|
.city-state {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: rgba(232, 221, 196, 0.8);
|
background: rgba(232, 221, 196, 0.8);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.city-state.state-war {
|
.city-state.state-war {
|
||||||
@@ -194,6 +198,11 @@ const touchend = (event: TouchEvent) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.city-name {
|
.city-name {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 2px);
|
||||||
|
left: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateX(-50%);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -85,16 +85,11 @@ const cityBackgroundSize = computed(() => {
|
|||||||
return detailSize.value;
|
return detailSize.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
const baseSize = computed(() => ({
|
|
||||||
width: 40 * props.mapScale,
|
|
||||||
height: 30 * props.mapScale,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const cityBaseStyle = computed(() => ({
|
const cityBaseStyle = computed(() => ({
|
||||||
left: `${props.city.x}px`,
|
left: `${props.city.x}px`,
|
||||||
top: `${props.city.y}px`,
|
top: `${props.city.y}px`,
|
||||||
width: `${baseSize.value.width}px`,
|
width: `${detailSize.value.iconWidth}px`,
|
||||||
height: `${baseSize.value.height}px`,
|
height: `${detailSize.value.iconHeight}px`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const cityBgStyle = computed(() => {
|
const cityBgStyle = computed(() => {
|
||||||
@@ -251,12 +246,14 @@ const cityStateStyle = computed(() => ({
|
|||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.city-img {
|
.city-img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
pointer-events: none;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,5 +314,6 @@ const cityStateStyle = computed(() => ({
|
|||||||
.city-state {
|
.city-state {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user