fix: announce 3d camera orientation
This commit is contained in:
@@ -85,8 +85,7 @@ const beamPatternSurfaceView = createReceiveBeamPatternSurfaceView(
|
|||||||
elements["beam-pattern-surface"],
|
elements["beam-pattern-surface"],
|
||||||
{
|
{
|
||||||
onViewDirectionChange(direction) {
|
onViewDirectionChange(direction) {
|
||||||
elements["beam-pattern-axis-view"].value = direction;
|
syncBeamViewDirection(direction);
|
||||||
document.documentElement.dataset.beamPatternViewAxis = direction;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -372,8 +371,29 @@ const VIEW_DIRECTION_LABELS = Object.freeze({
|
|||||||
custom: "자유 회전",
|
custom: "자유 회전",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function resolvedViewDirection(direction) {
|
||||||
|
return Object.hasOwn(VIEW_DIRECTION_LABELS, direction) ? direction : "iso";
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewDirectionDescription(direction) {
|
||||||
|
const resolved = resolvedViewDirection(direction);
|
||||||
|
return resolved === "custom"
|
||||||
|
? VIEW_DIRECTION_LABELS.custom
|
||||||
|
: VIEW_DIRECTION_LABELS[resolved] + " 원점 보기";
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncBeamViewDirection(direction) {
|
||||||
|
const resolved = resolvedViewDirection(direction);
|
||||||
|
elements["beam-pattern-axis-view"].value = resolved;
|
||||||
|
document.documentElement.dataset.beamPatternViewAxis = resolved;
|
||||||
|
elements["beam-pattern-surface"].setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
"3D 수신 빔 패턴 표면 · " + viewDirectionDescription(resolved),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function syncArrayViewDirection(direction) {
|
function syncArrayViewDirection(direction) {
|
||||||
const resolved = Object.hasOwn(VIEW_DIRECTION_LABELS, direction) ? direction : "iso";
|
const resolved = resolvedViewDirection(direction);
|
||||||
elements["array-axis-view"].value = resolved;
|
elements["array-axis-view"].value = resolved;
|
||||||
elements["array-canvas"].dataset.viewAxis = resolved;
|
elements["array-canvas"].dataset.viewAxis = resolved;
|
||||||
document.documentElement.dataset.arrayViewAxis = resolved;
|
document.documentElement.dataset.arrayViewAxis = resolved;
|
||||||
@@ -381,6 +401,10 @@ function syncArrayViewDirection(direction) {
|
|||||||
elements["canvas-front-badge"].textContent = resolved === "custom"
|
elements["canvas-front-badge"].textContent = resolved === "custom"
|
||||||
? "+Z FRONT · 자유 회전"
|
? "+Z FRONT · 자유 회전"
|
||||||
: "시점 " + VIEW_DIRECTION_LABELS[resolved] + " 원점 보기 · +Z FRONT";
|
: "시점 " + VIEW_DIRECTION_LABELS[resolved] + " 원점 보기 · +Z FRONT";
|
||||||
|
elements["array-canvas"].setAttribute(
|
||||||
|
"aria-label",
|
||||||
|
"마이크 어레이 3D 검사 canvas · " + viewDirectionDescription(resolved),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +458,6 @@ function setArrayViewMode(mode, options = {}) {
|
|||||||
elements["canvas-front-badge"].textContent = resolved === "3d"
|
elements["canvas-front-badge"].textContent = resolved === "3d"
|
||||||
? "+Z FRONT · 초록 축"
|
? "+Z FRONT · 초록 축"
|
||||||
: "+Z FRONT · 화면 바깥쪽";
|
: "+Z FRONT · 화면 바깥쪽";
|
||||||
if (resolved === "3d") syncArrayViewDirection(elements["array-axis-view"].value);
|
|
||||||
elements["array-canvas"].setAttribute(
|
elements["array-canvas"].setAttribute(
|
||||||
"aria-label",
|
"aria-label",
|
||||||
resolved === "3d"
|
resolved === "3d"
|
||||||
@@ -447,6 +470,7 @@ function setArrayViewMode(mode, options = {}) {
|
|||||||
? "ArrowLeft ArrowRight ArrowUp ArrowDown F R Escape"
|
? "ArrowLeft ArrowRight ArrowUp ArrowDown F R Escape"
|
||||||
: "V A F Escape Delete ArrowLeft ArrowRight ArrowUp ArrowDown",
|
: "V A F Escape Delete ArrowLeft ArrowRight ArrowUp ArrowDown",
|
||||||
);
|
);
|
||||||
|
if (resolved === "3d") syncArrayViewDirection(elements["array-axis-view"].value);
|
||||||
setTool(state.tool);
|
setTool(state.tool);
|
||||||
canvasView.render(canvasState());
|
canvasView.render(canvasState());
|
||||||
if (options.focus) canvasView.focus();
|
if (options.focus) canvasView.focus();
|
||||||
@@ -1409,7 +1433,7 @@ elements["array-view-3d-button"].addEventListener("click", () =>
|
|||||||
elements["array-axis-view"].addEventListener("change", () => {
|
elements["array-axis-view"].addEventListener("change", () => {
|
||||||
const direction = elements["array-axis-view"].value;
|
const direction = elements["array-axis-view"].value;
|
||||||
canvasView.setViewDirection(direction);
|
canvasView.setViewDirection(direction);
|
||||||
announceSelection("3D 시점 · " + VIEW_DIRECTION_LABELS[direction] + " 원점 보기");
|
announceSelection("3D 시점 · " + viewDirectionDescription(direction));
|
||||||
});
|
});
|
||||||
elements["fit-view-button"].addEventListener("click", () => canvasView.fit());
|
elements["fit-view-button"].addEventListener("click", () => canvasView.fit());
|
||||||
elements["zoom-in-button"].addEventListener("click", () => canvasView.zoomBy(1.25));
|
elements["zoom-in-button"].addEventListener("click", () => canvasView.zoomBy(1.25));
|
||||||
@@ -1659,8 +1683,7 @@ window.addEventListener("unload", () => {
|
|||||||
elements["snap-enabled"].checked = state.snapEnabled;
|
elements["snap-enabled"].checked = state.snapEnabled;
|
||||||
setNumber(elements["snap-step"], state.snapStepM * 1000);
|
setNumber(elements["snap-step"], state.snapStepM * 1000);
|
||||||
syncArrayViewDirection("iso");
|
syncArrayViewDirection("iso");
|
||||||
elements["beam-pattern-axis-view"].value = "iso";
|
syncBeamViewDirection("iso");
|
||||||
document.documentElement.dataset.beamPatternViewAxis = "iso";
|
|
||||||
setArrayViewMode("2d", { announce: false });
|
setArrayViewMode("2d", { announce: false });
|
||||||
setBeamPatternViewMode("cuts", { render: false });
|
setBeamPatternViewMode("cuts", { render: false });
|
||||||
syncBeamPatternFrequency();
|
syncBeamPatternFrequency();
|
||||||
|
|||||||
@@ -282,6 +282,10 @@ test("Array Builder가 preset·직접 편집·검증·표준 JSON round trip을
|
|||||||
const beamAxisView = documentObject.querySelector("#beam-pattern-axis-view");
|
const beamAxisView = documentObject.querySelector("#beam-pattern-axis-view");
|
||||||
assertEqual(beamAxisView.value, "iso", "3D beam surface starts in isometric view");
|
assertEqual(beamAxisView.value, "iso", "3D beam surface starts in isometric view");
|
||||||
assertEqual(beamSurface.dataset.viewAxis, "iso", "beam canvas exposes isometric provenance");
|
assertEqual(beamSurface.dataset.viewAxis, "iso", "beam canvas exposes isometric provenance");
|
||||||
|
assert(
|
||||||
|
beamSurface.getAttribute("aria-label").includes("등각 원점 보기"),
|
||||||
|
"beam canvas accessible name exposes its current view",
|
||||||
|
);
|
||||||
const beamComputeBeforeAxisView =
|
const beamComputeBeforeAxisView =
|
||||||
documentObject.documentElement.dataset.beamPatternComputeMs;
|
documentObject.documentElement.dataset.beamPatternComputeMs;
|
||||||
const beamFrequencyBeforeAxisView = beamSurface.dataset.frequencyHz;
|
const beamFrequencyBeforeAxisView = beamSurface.dataset.frequencyHz;
|
||||||
@@ -357,6 +361,10 @@ test("Array Builder가 preset·직접 편집·검증·표준 JSON round trip을
|
|||||||
);
|
);
|
||||||
assertEqual(beamSurface.dataset.viewAxis, "custom", "beam drag enters free-orbit mode");
|
assertEqual(beamSurface.dataset.viewAxis, "custom", "beam drag enters free-orbit mode");
|
||||||
assertEqual(beamAxisView.value, "custom", "beam view selector reflects free orbit");
|
assertEqual(beamAxisView.value, "custom", "beam view selector reflects free orbit");
|
||||||
|
assert(
|
||||||
|
beamSurface.getAttribute("aria-label").includes("자유 회전"),
|
||||||
|
"beam canvas accessible name follows free orbit",
|
||||||
|
);
|
||||||
beamSurface.dispatchEvent(new windowObject.KeyboardEvent("keydown", {
|
beamSurface.dispatchEvent(new windowObject.KeyboardEvent("keydown", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
cancelable: true,
|
cancelable: true,
|
||||||
@@ -365,6 +373,10 @@ test("Array Builder가 preset·직접 편집·검증·표준 JSON round trip을
|
|||||||
await nextPaint(windowObject);
|
await nextPaint(windowObject);
|
||||||
assertEqual(beamSurface.dataset.viewAxis, "iso", "beam R shortcut restores isometric view");
|
assertEqual(beamSurface.dataset.viewAxis, "iso", "beam R shortcut restores isometric view");
|
||||||
assertEqual(beamAxisView.value, "iso", "beam selector follows the R shortcut");
|
assertEqual(beamAxisView.value, "iso", "beam selector follows the R shortcut");
|
||||||
|
assert(
|
||||||
|
beamSurface.getAttribute("aria-label").includes("등각 원점 보기"),
|
||||||
|
"beam accessible name follows the R shortcut",
|
||||||
|
);
|
||||||
assertEqual(
|
assertEqual(
|
||||||
documentObject.documentElement.dataset.beamPatternComputeMs,
|
documentObject.documentElement.dataset.beamPatternComputeMs,
|
||||||
beamComputeBeforeAxisView,
|
beamComputeBeforeAxisView,
|
||||||
@@ -446,6 +458,10 @@ test("Array Builder가 preset·직접 편집·검증·표준 JSON round trip을
|
|||||||
const arrayAxisView = documentObject.querySelector("#array-axis-view");
|
const arrayAxisView = documentObject.querySelector("#array-axis-view");
|
||||||
assert(!arrayAxisControl.hidden, "array axis selector appears only for 3D inspection");
|
assert(!arrayAxisControl.hidden, "array axis selector appears only for 3D inspection");
|
||||||
assertEqual(arrayAxisView.value, "iso", "array 3D starts in isometric view");
|
assertEqual(arrayAxisView.value, "iso", "array 3D starts in isometric view");
|
||||||
|
assert(
|
||||||
|
canvas.getAttribute("aria-label").includes("등각 원점 보기"),
|
||||||
|
"array canvas accessible name exposes its current view",
|
||||||
|
);
|
||||||
const arraySaveStateBeforeAxisView =
|
const arraySaveStateBeforeAxisView =
|
||||||
documentObject.querySelector("#save-state").textContent;
|
documentObject.querySelector("#save-state").textContent;
|
||||||
const array3dBeforeAxisView = canvas.toDataURL();
|
const array3dBeforeAxisView = canvas.toDataURL();
|
||||||
@@ -517,6 +533,10 @@ test("Array Builder가 preset·직접 편집·검증·표준 JSON round trip을
|
|||||||
);
|
);
|
||||||
assertEqual(canvas.dataset.viewAxis, "custom", "array drag enters free-orbit mode");
|
assertEqual(canvas.dataset.viewAxis, "custom", "array drag enters free-orbit mode");
|
||||||
assertEqual(arrayAxisView.value, "custom", "array view selector reflects free orbit");
|
assertEqual(arrayAxisView.value, "custom", "array view selector reflects free orbit");
|
||||||
|
assert(
|
||||||
|
canvas.getAttribute("aria-label").includes("자유 회전"),
|
||||||
|
"array canvas accessible name follows free orbit",
|
||||||
|
);
|
||||||
assertEqual(
|
assertEqual(
|
||||||
documentObject.querySelector('#microphone-list [aria-selected="true"]')
|
documentObject.querySelector('#microphone-list [aria-selected="true"]')
|
||||||
?.dataset.microphoneId,
|
?.dataset.microphoneId,
|
||||||
@@ -531,6 +551,10 @@ test("Array Builder가 preset·직접 편집·검증·표준 JSON round trip을
|
|||||||
await nextPaint(windowObject);
|
await nextPaint(windowObject);
|
||||||
assertEqual(canvas.dataset.viewAxis, "iso", "array R shortcut restores isometric view");
|
assertEqual(canvas.dataset.viewAxis, "iso", "array R shortcut restores isometric view");
|
||||||
assertEqual(arrayAxisView.value, "iso", "array selector follows the R shortcut");
|
assertEqual(arrayAxisView.value, "iso", "array selector follows the R shortcut");
|
||||||
|
assert(
|
||||||
|
canvas.getAttribute("aria-label").includes("등각 원점 보기"),
|
||||||
|
"array accessible name follows the R shortcut",
|
||||||
|
);
|
||||||
assertEqual(
|
assertEqual(
|
||||||
documentObject.querySelector("#save-state").textContent,
|
documentObject.querySelector("#save-state").textContent,
|
||||||
arraySaveStateBeforeAxisView,
|
arraySaveStateBeforeAxisView,
|
||||||
|
|||||||
Reference in New Issue
Block a user