diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 45d2efdf35..068dc66b2e 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -3554,3 +3554,7 @@ _qr:
scanFile: "端末の画像をスキャン"
raw: "テキスト"
mfm: "MFM"
+
+_room:
+ snapToGrid: "グリッドにスナップ"
+ gridScale: "グリッドサイズ"
diff --git a/packages/frontend/src/pages/room.vue b/packages/frontend/src/pages/room.vue
index 7482f4310c..f0e8556e3e 100644
--- a/packages/frontend/src/pages/room.vue
+++ b/packages/frontend/src/pages/room.vue
@@ -14,11 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
Install (E)
Grab (E)
- Grid Snap: {{ engine.enableGridSnapping.value ? 'on' : 'off' }}
- Snap: 1cm
- Snap: 2cm
- Snap: 4cm
- Snap: 8cm
+ Grid Snap: {{ engine.enableGridSnapping.value ? 'on' : 'off' }}
降りる (Q)
@@ -38,6 +34,7 @@ import MkButton from '@/components/MkButton.vue';
import { RoomEngine } from '@/utility/room/engine.js';
import { getObjectDef } from '@/utility/room/object-defs.js';
import MkSelect from '@/components/MkSelect.vue';
+import * as os from '@/os.js';
const canvas = useTemplateRef('canvas');
@@ -423,6 +420,35 @@ function toggleLight() {
canvas.value!.focus();
}
+function showSnappingMenu(ev: PointerEvent) {
+ if (engine.value == null) return;
+ os.popupMenu([{
+ type: 'switch',
+ text: i18n.ts._room.snapToGrid,
+ ref: engine.value.enableGridSnapping,
+ }, {
+ type: 'radioOption',
+ text: '1cm',
+ active: computed(() => engine.value!.gridSnappingScale.value === 1),
+ action: () => engine.value!.gridSnappingScale.value = 1,
+ }, {
+ type: 'radioOption',
+ text: '2cm',
+ active: computed(() => engine.value!.gridSnappingScale.value === 2),
+ action: () => engine.value!.gridSnappingScale.value = 2,
+ }, {
+ type: 'radioOption',
+ text: '4cm',
+ active: computed(() => engine.value!.gridSnappingScale.value === 4),
+ action: () => engine.value!.gridSnappingScale.value = 4,
+ }, {
+ type: 'radioOption',
+ text: '8cm',
+ active: computed(() => engine.value!.gridSnappingScale.value === 8),
+ action: () => engine.value!.gridSnappingScale.value = 8,
+ }], ev.currentTarget ?? ev.target);
+}
+
function toggleGridSnapping() {
engine.value.enableGridSnapping.value = !engine.value.enableGridSnapping.value;
canvas.value!.focus();
diff --git a/packages/i18n/src/autogen/locale.ts b/packages/i18n/src/autogen/locale.ts
index f814f3ecc2..2703ea436e 100644
--- a/packages/i18n/src/autogen/locale.ts
+++ b/packages/i18n/src/autogen/locale.ts
@@ -13266,4 +13266,14 @@ export interface Locale extends ILocale {
*/
"mfm": string;
};
+ "_room": {
+ /**
+ * グリッドにスナップ
+ */
+ "snapToGrid": string;
+ /**
+ * グリッドサイズ
+ */
+ "gridScale": string;
+ };
}