fix: RouteLine 站点三修——接点从黑影外缘改回卡描边(node.right 对齐真实卡边),线层 z-10 置卡上(点不再被卡遮挡),圆心骑描边各半在卡;E2E 同步断言
This commit is contained in:
1 parent
6cb91284f0
commit
202824b093
8 files changed
+25
-16
No files matched your search
@@ -115,7 +115,7 @@ test.describe('RouteLine 规格契约', () => {
|
||||
expect(specs).toContain('4 2')
|
||||
})
|
||||
|
||||
test('站点 r6 半嵌:源骑卡右黑影外缘、目标贴左描边', async ({ page }) => {
|
||||
test('站点 r6 半嵌:源/目标圆心都骑卡描边(各半在卡上),线层在卡之上', async ({ page }) => {
|
||||
const c1 = await page.locator('a[href="#ch1"]').first().boundingBox()
|
||||
const c2 = await page.locator('a[href="#ch2"]').first().boundingBox()
|
||||
const wrap = await page.locator('main div.relative').first().boundingBox()
|
||||
@@ -126,10 +126,17 @@ test.describe('RouteLine 规格契约', () => {
|
||||
)
|
||||
expect(stations.length).toBeGreaterThanOrEqual(4)
|
||||
|
||||
const c1ShadowEdge = c1!.x - wrap!.x + c1!.width + 7 // 描边外 + 7px 黑影
|
||||
const c1Right = c1!.x - wrap!.x + c1!.width // 卡右描边(不接阴影)
|
||||
const c2Border = c2!.x - wrap!.x
|
||||
expect(stations.some((s) => Math.abs(s.cx - c1ShadowEdge) <= 3), `源站点应骑黑影外缘 x≈${c1ShadowEdge}`).toBeTruthy()
|
||||
expect(stations.some((s) => Math.abs(s.cx - c2Border) <= 3), `目标站点应贴左描边 x≈${c2Border}`).toBeTruthy()
|
||||
expect(stations.some((s) => Math.abs(s.cx - c1Right) <= 3), `源站点圆心应骑卡右描边 x≈${c1Right}`).toBeTruthy()
|
||||
expect(stations.some((s) => Math.abs(s.cx - c2Border) <= 3), `目标站点圆心应骑左描边 x≈${c2Border}`).toBeTruthy()
|
||||
|
||||
// 线层必须置于卡之上——否则半嵌的站点被卡盖住,只剩卡外一小块
|
||||
const z = await page.evaluate(() => {
|
||||
const svg = document.querySelector('main div.relative > svg') as SVGElement | null
|
||||
return svg ? getComputedStyle(svg).zIndex : 'missing'
|
||||
})
|
||||
expect(z).toBe('10')
|
||||
})
|
||||
|
||||
test('实线端点落在水平端口(M x y H 起、H x 止)', async ({ page }) => {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 177 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
@@ -1,14 +1,15 @@
|
||||
/** RouteLine —— 关系线:线形即含义(实=先后 虚=相关 点=同族)
|
||||
* 拓扑:横平竖直 + R8 直角步进;并行不合并(4px);站点 r6 半嵌卡边
|
||||
* (左贴描边、右骑硬投影外缘);同口多线自动聚合胶囊(线止于胶囊边界)。 */
|
||||
* (圆心骑左右描边,各半在卡上);线层 z-10 置于卡之上,站点不被卡遮挡;
|
||||
* 同口多线自动聚合胶囊(线止于胶囊边界)。 */
|
||||
import type { ChapterId, Edge } from '../lib/types'
|
||||
|
||||
const STATION_COLORS = ['var(--color-clash2a)', 'var(--color-clash1b)', 'var(--color-clash3a)', 'var(--color-clash1a)']
|
||||
|
||||
export interface LaneNode {
|
||||
id: ChapterId
|
||||
borderLeft: number // 左描边 x(无影侧,入口贴这里)
|
||||
right: number // 右侧黑影外缘 x(描边 + 7,出口从这里出发)
|
||||
borderLeft: number // 左描边 x(入口圆心贴这里,点半嵌)
|
||||
right: number // 右描边 x(出口圆心贴这里,点半嵌——不接阴影)
|
||||
y: number // 卡中线 y
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ export function RouteLine({
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox={`0 0 ${width} ${height}`}
|
||||
className="pointer-events-none absolute left-0 top-0"
|
||||
className="pointer-events-none absolute left-0 top-0 z-10"
|
||||
aria-hidden
|
||||
>
|
||||
{edges.map((e, i) => {
|
||||
@@ -65,7 +66,7 @@ export function RouteLine({
|
||||
if (!a || !b) return null
|
||||
const ins = insByTo.get(e.to)!
|
||||
const capsule = ins.length > 1 && firstIn.has(e.to)
|
||||
// 源站点骑出边卡黑影外缘;目标:单线=圆点贴描边,多线=胶囊(只画一次)
|
||||
// 源/目标站点:圆心骑卡描边,各半在卡上;目标:单线=圆点,多线=胶囊(只画一次)
|
||||
return (
|
||||
<g key={`st-${e.from}-${e.to}`}>
|
||||
<circle cx={a.right} cy={a.y} r={6} fill={stationColor(si++)} stroke="var(--color-ink)" strokeWidth={2} />
|
||||
|
||||
@@ -5,10 +5,11 @@ import { RouteLine } from '../../components/RouteLine'
|
||||
import { AssignBlock, Ticket } from '../../components/Ticket'
|
||||
import { EntryGuide } from '../../components/EntryGuide'
|
||||
|
||||
/* 节点=卡描边真实边缘:卡1(40,72,250) 卡2(380,0,250) 卡3(700,0,150) */
|
||||
const nodes = {
|
||||
1: { id: 1, borderLeft: 40, right: 299, y: 180 },
|
||||
2: { id: 2, borderLeft: 378, right: 639, y: 108 },
|
||||
5: { id: 5, borderLeft: 699, right: 848, y: 108 },
|
||||
1: { id: 1, borderLeft: 40, right: 290, y: 180 },
|
||||
2: { id: 2, borderLeft: 380, right: 630, y: 108 },
|
||||
5: { id: 5, borderLeft: 700, right: 850, y: 108 },
|
||||
} as const
|
||||
|
||||
export function App() {
|
||||
|
||||
@@ -9,11 +9,11 @@ import { EntryGuide } from '../../components/EntryGuide'
|
||||
import { Scatter } from '../../components/Scatter'
|
||||
import { Bar, Cross, Ring, Tremble, Tri, Wave } from '../../components/shapes'
|
||||
|
||||
/* 场景坐标(复刻已验收组合):卡1(40,110,250) 卡2(380,44,250,rot) 卡3(700,44,140) */
|
||||
/* 场景坐标(节点=卡描边真实边缘):卡1(40,110,250) 卡2(380,44,250,rot) 卡3(700,44,140) */
|
||||
const nodes = {
|
||||
1: { id: 1, borderLeft: 40, right: 299, y: 180 },
|
||||
2: { id: 2, borderLeft: 378, right: 639, y: 108 },
|
||||
5: { id: 5, borderLeft: 698, right: 848, y: 108 },
|
||||
1: { id: 1, borderLeft: 40, right: 290, y: 180 },
|
||||
2: { id: 2, borderLeft: 380, right: 630, y: 108 },
|
||||
5: { id: 5, borderLeft: 700, right: 840, y: 108 },
|
||||
} as const
|
||||
|
||||
export function App() {
|
||||
|
||||
Reference in new issue
Block a user