feat(web-platform): release V0.9.3 全模块界面重构
This commit is contained in:
@@ -1,88 +1,25 @@
|
||||
import { CirclePause, CirclePlay, Mouse, MousePointer2 } from 'lucide-react';
|
||||
import type { InteractionMode, ViewerSelection } from '../../viewer/MuJoCoViewer';
|
||||
import { Badge, Kbd } from '../../components/ui';
|
||||
const labels: Record<InteractionMode, string> = {
|
||||
select: '选择',
|
||||
joint: '关节拖动',
|
||||
force: '外力施加',
|
||||
};
|
||||
const primaryGestures: Record<InteractionMode, string> = {
|
||||
select: '左键旋转',
|
||||
joint: '左键拖动关节',
|
||||
force: '左键拖动施力',
|
||||
};
|
||||
export function ViewportHUD({
|
||||
paused,
|
||||
mode,
|
||||
selection,
|
||||
ready,
|
||||
mapEditing = false,
|
||||
}: {
|
||||
paused: boolean;
|
||||
mode: InteractionMode;
|
||||
selection: ViewerSelection | null;
|
||||
ready: boolean;
|
||||
mapEditing?: boolean;
|
||||
}) {
|
||||
if (!ready) return null;
|
||||
import { CirclePause, CirclePlay } from 'lucide-react';
|
||||
import { useAppStore } from '../../stores/useAppStore';
|
||||
import { Badge } from '../../components/ui';
|
||||
import { StoreStatusBar } from './StatusBar';
|
||||
|
||||
export function ViewportHUD() {
|
||||
const paused = useAppStore((state) => state.paused);
|
||||
const ready = useAppStore((state) => Boolean(state.snapshot));
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
aria-label="视口状态"
|
||||
className="pointer-events-none absolute left-3 top-3 z-10 flex max-w-[70%] flex-wrap items-center gap-1.5"
|
||||
>
|
||||
<Badge tone={paused ? 'neutral' : 'success'}>
|
||||
{paused ? <CirclePause className="h-3 w-3" /> : <CirclePlay className="h-3 w-3" />}
|
||||
{paused ? '已暂停' : '仿真中'}
|
||||
</Badge>
|
||||
<Badge tone="accent">
|
||||
<MousePointer2 className="h-3 w-3" />
|
||||
{labels[mode]}
|
||||
</Badge>
|
||||
{selection && (
|
||||
<Badge title={`body ${selection.bodyId} · geom ${selection.geomId}`}>
|
||||
{selection.bodyName}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
aria-label="视口操作提示"
|
||||
className="pointer-events-none absolute bottom-14 left-1/2 z-10 hidden -translate-x-1/2 items-center gap-2 whitespace-nowrap rounded-full border border-border-strong bg-panel/85 px-3 py-1.5 text-[10px] text-text-secondary shadow-xl backdrop-blur lg:flex"
|
||||
>
|
||||
<Mouse aria-hidden="true" className="h-3 w-3 text-text-secondary" />
|
||||
<span>{primaryGestures[mode]}</span>
|
||||
<span aria-hidden="true" className="text-border-strong">
|
||||
·
|
||||
</span>
|
||||
<span>右键平移</span>
|
||||
<span aria-hidden="true" className="text-border-strong">
|
||||
·
|
||||
</span>
|
||||
<span>滚轮缩放</span>
|
||||
{mapEditing && mode === 'select' ? (
|
||||
<>
|
||||
<span aria-hidden="true" className="text-border-strong">
|
||||
·
|
||||
</span>
|
||||
<Kbd>W</Kbd>
|
||||
<Kbd>E</Kbd>
|
||||
<Kbd>R</Kbd>
|
||||
<span>变换</span>
|
||||
<Kbd>F</Kbd>
|
||||
<span>聚焦</span>
|
||||
</>
|
||||
<div
|
||||
aria-label="视口状态"
|
||||
className="flex flex-wrap items-center gap-2 rounded-lg border border-border bg-panel/90 px-2 py-1 text-xs shadow-sm"
|
||||
>
|
||||
<Badge tone={!ready || paused ? 'neutral' : 'success'}>
|
||||
{!ready || paused ? (
|
||||
<CirclePause className="h-3.5 w-3.5" />
|
||||
) : (
|
||||
mode !== 'select' && (
|
||||
<>
|
||||
<span aria-hidden="true" className="text-border-strong">
|
||||
·
|
||||
</span>
|
||||
<Kbd>1</Kbd>
|
||||
<span>旋转视角</span>
|
||||
</>
|
||||
)
|
||||
<CirclePlay className="h-3.5 w-3.5" />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
{!ready ? '待导入' : paused ? '已暂停' : '仿真中'}
|
||||
</Badge>
|
||||
<StoreStatusBar />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user