11<script setup lang="ts">
2- import { computed , onBeforeUnmount , onMounted , provide , ref } from ' vue'
2+ import { computed , inject , onBeforeUnmount , onMounted , ref , type Ref } from ' vue'
33
44const svg = ref <SVGElement >()
55const zoom = ref (1.0 )
@@ -9,16 +9,18 @@ const mouseDownPoint = ref<{
99 x: number
1010 y: number
1111} | null >(null )
12+ const lastMousePosition = ref <{
13+ clientX: number
14+ clientY: number
15+ target: EventTarget | null
16+ } | null >(null )
1217
13- // 選択状態の管理
14- const selectedObject = ref <{
18+ // 親から提供されるselectedObjectをinject
19+ const selectedObject = inject < Ref <{
1520 type: ' robot' | ' ball'
1621 id? : number
1722 team? : ' YELLOW' | ' BLUE'
18- } | null >(null )
19-
20- // 選択状態をprovide
21- provide (' selectedObject' , selectedObject )
23+ } | null >> (' selectedObject' )!
2224
2325// 移動イベントの定義
2426const emit = defineEmits <{
@@ -44,6 +46,13 @@ function onScroll(event: WheelEvent) {
4446}
4547
4648function onMouseMove(event : MouseEvent ) {
49+ // マウス位置を記録(エンターキーでの移動に使用)
50+ lastMousePosition .value = {
51+ clientX: event .clientX ,
52+ clientY: event .clientY ,
53+ target: event .target ,
54+ }
55+
4756 if (mouseDownPoint .value !== null ) {
4857 activeTranslation .value = {
4958 x: event .clientX - mouseDownPoint .value .x ,
@@ -67,6 +76,34 @@ function onMouseUp() {
6776 }
6877}
6978
79+ function moveSelectedObject(clientX : number , clientY : number , target ? : EventTarget | null ) {
80+ if (selectedObject .value !== null ) {
81+ // SVG座標を取得(イベントターゲットからownerSVGElementを取得)
82+ let svgElement: SVGSVGElement | null = null
83+
84+ if (target && target instanceof SVGElement ) {
85+ svgElement = target .ownerSVGElement
86+ }
87+
88+ // フォールバック:svg.value を使用
89+ if (! svgElement ) {
90+ svgElement = svg .value as SVGSVGElement | null
91+ }
92+
93+ if (svgElement ) {
94+ const pt = svgElement .createSVGPoint ()
95+ pt .x = clientX
96+ pt .y = clientY
97+ const ctm = svgElement .getScreenCTM ()
98+ if (ctm ) {
99+ const svgPt = pt .matrixTransform (ctm .inverse ())
100+ // Y座標を反転してemit
101+ emit (' moveObject' , svgPt .x , - svgPt .y )
102+ }
103+ }
104+ }
105+ }
106+
70107function onKeyDown(event : KeyboardEvent ) {
71108 if (event .key === ' ' ) {
72109 zoom .value = 1
@@ -75,23 +112,19 @@ function onKeyDown(event: KeyboardEvent) {
75112 if (event .key === ' Escape' ) {
76113 selectedObject .value = null
77114 }
115+ if (event .key === ' Enter' && lastMousePosition .value ) {
116+ moveSelectedObject (
117+ lastMousePosition .value .clientX ,
118+ lastMousePosition .value .clientY ,
119+ lastMousePosition .value .target
120+ )
121+ event .preventDefault ()
122+ }
78123}
79124
80125function onDoubleClick(event : MouseEvent ) {
81- if (selectedObject .value !== null ) {
82- // SVG座標を取得
83- const svgElement = svg .value
84- if (svgElement ) {
85- const pt = svgElement .createSVGPoint ()
86- pt .x = event .clientX
87- pt .y = event .clientY
88- const svgPt = pt .matrixTransform (svgElement .getScreenCTM ()?.inverse ())
89-
90- // Y座標を反転してemit
91- emit (' moveObject' , svgPt .x , - svgPt .y )
92- }
93- event .preventDefault ()
94- }
126+ moveSelectedObject (event .clientX , event .clientY , event .target )
127+ event .preventDefault ()
95128}
96129
97130const transform = computed (() => {
0 commit comments