mock: 選択枠を太くし、最前面の描画層に移す(T-30 単位1)

選択枠と長押し候補の枠を NodeSvg の再帰から外し、ノードの描画より後に描く
PhySelectionLayer に移した。枠はワールド変換とローカル矩形から純粋関数
selectionFrames で求め、画面上3.5pxで描く。部品の選択表示は形状上に残す。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TDkA8qMQ3Uf1eY3Ar19vjy
This commit is contained in:
2026-10-21 08:42:14 +09:00
co-authored by Claude Opus 5.5
parent d110320cb8
commit e92708dc12
6 changed files with 202 additions and 53 deletions
+3 -46
View File
@@ -10,7 +10,6 @@ const props = defineProps<{
dim: boolean;
zoom: number;
angle: number;
longCandidate?: string | null;
}>();
const emit = defineEmits<{
down: [e: PointerEvent, n: Node, el: SVGGElement];
@@ -57,18 +56,9 @@ function badgeBox(n: Node) {
:height="n.size.h"
rx=".06"
class="key-face"
:class="{ chosen: selected.includes(n.id), ghost: n.ghost, decal: n.decal }" /><text
class="key-label"
x=".08"
y=".24"
>{{ n.labels?.find(Boolean) }}</text
><rect
v-if="selected.includes(n.id)"
:width="n.size.w"
:height="n.size.h"
class="sel"
:class="{ candidate: longCandidate === n.id }"
/></g>
:class="{ chosen: selected.includes(n.id), ghost: n.ghost, decal: n.decal }"
/><text class="key-label" x=".08" y=".24">{{ n.labels?.find(Boolean) }}</text></g
>
<g
v-else-if="n.type === 'component'"
class="node"
@@ -117,18 +107,9 @@ function badgeBox(n: Node) {
:dim="dim"
:zoom="zoom"
:angle="angle + n.transform.rotation"
:long-candidate="longCandidate"
@down="(e, c, el) => emit('down', e, c, el)"
@badge="(g, e) => emit('badge', g, e)"
@focus="(id) => emit('focus', id)"
/><rect
v-if="selected.includes(n.id) || longCandidate === n.id"
:x="bounds(n).x"
:y="bounds(n).y"
:width="bounds(n).width"
:height="bounds(n).height"
class="group-sel"
:class="{ candidate: longCandidate === n.id }"
/><text x="0" y="-.12" class="group-label">{{ n.name }}</text></g
>
<g v-else class="group"
@@ -142,18 +123,9 @@ function badgeBox(n: Node) {
:dim="dim"
:zoom="zoom"
:angle="angle + n.transform.rotation"
:long-candidate="longCandidate"
@down="(e, c, el) => emit('down', e, c, el)"
@badge="(g, e) => emit('badge', g, e)"
@focus="(id) => emit('focus', id)"
/><rect
v-if="selected.includes(n.id) || longCandidate === n.id"
:x="bounds(n).x"
:y="bounds(n).y"
:width="bounds(n).width"
:height="bounds(n).height"
class="group-sel"
:class="{ candidate: longCandidate === n.id }"
/><g
:transform="`rotate(${badgeBox(n).angle} ${badgeBox(n).x} ${badgeBox(n).y})`"
class="badge"
@@ -216,21 +188,6 @@ function badgeBox(n: Node) {
stroke: #315d7a;
stroke-width: 0.03;
}
.sel,
.group-sel {
fill: none;
stroke: #1769d2;
stroke-width: 2px;
vector-effect: non-scaling-stroke;
pointer-events: none;
}
.group-sel {
stroke-dasharray: 5 3;
}
.candidate {
stroke: #e87912;
stroke-width: 2.5px;
}
.group {
cursor: default;
}