168 lines
5.6 KiB
TypeScript
168 lines
5.6 KiB
TypeScript
import React, { useState } from 'react';
|
|
import Image from 'next/image';
|
|
import useNavigationStore from '@/app/store/navigationStore';
|
|
import type { Zone } from '@/app/types';
|
|
|
|
interface ToolbarButton {
|
|
icon: string;
|
|
label: string;
|
|
onClick: () => void;
|
|
onMouseDown?: () => void;
|
|
onMouseUp?: () => void;
|
|
active?: boolean;
|
|
children?: ToolbarButton[];
|
|
}
|
|
|
|
interface SceneToolbarProps {
|
|
onZoomIn?: () => void;
|
|
onZoomOut?: () => void;
|
|
onTopView?: () => void;
|
|
onPan?: () => void;
|
|
onSelectModel?: (modelPath: string) => void;
|
|
panActive?: boolean;
|
|
navMenuActive?: boolean;
|
|
onToggleSensorHighlights?: () => void;
|
|
sensorHighlightsActive?: boolean;
|
|
}
|
|
|
|
const SceneToolbar: React.FC<SceneToolbarProps> = ({
|
|
onZoomIn,
|
|
onZoomOut,
|
|
onTopView,
|
|
onPan,
|
|
onSelectModel,
|
|
panActive = false,
|
|
navMenuActive = false,
|
|
onToggleSensorHighlights,
|
|
sensorHighlightsActive = true,
|
|
}) => {
|
|
const [isZoomOpen, setIsZoomOpen] = useState(false);
|
|
const { showMonitoring, openMonitoring, closeMonitoring, currentZones, loadZones, currentObject } = useNavigationStore();
|
|
|
|
const handleToggleNavMenu = () => {
|
|
if (showMonitoring) {
|
|
closeMonitoring();
|
|
} else {
|
|
openMonitoring();
|
|
}
|
|
};
|
|
|
|
const defaultButtons: ToolbarButton[] = [
|
|
{
|
|
icon: '/icons/Zoom.png',
|
|
label: 'Масштаб',
|
|
onClick: () => setIsZoomOpen(!isZoomOpen),
|
|
active: isZoomOpen,
|
|
children: [
|
|
{
|
|
icon: '/icons/plus.svg',
|
|
label: 'Приблизить',
|
|
onClick: onZoomIn || (() => {}),
|
|
},
|
|
{
|
|
icon: '/icons/minus.svg',
|
|
label: 'Отдалить',
|
|
onClick: onZoomOut || (() => {}),
|
|
},
|
|
]
|
|
},
|
|
{
|
|
icon: '/icons/Video.png',
|
|
label: 'Вид сверху',
|
|
onClick: onTopView || (() => console.log('Top View')),
|
|
},
|
|
{
|
|
icon: '/icons/Pointer.png',
|
|
label: 'Панорамирование',
|
|
onClick: onPan || (() => console.log('Pan')),
|
|
active: panActive,
|
|
},
|
|
{
|
|
icon: '/icons/Eye.png',
|
|
label: 'Подсветка датчиков',
|
|
onClick: onToggleSensorHighlights || (() => console.log('Toggle Sensor Highlights')),
|
|
active: sensorHighlightsActive,
|
|
},
|
|
{
|
|
icon: '/icons/Layers.png',
|
|
label: 'Общий вид',
|
|
onClick: handleToggleNavMenu,
|
|
active: navMenuActive,
|
|
},
|
|
];
|
|
|
|
|
|
return (
|
|
<div className="fixed right-5 top-1/2 transform -translate-y-1/2 z-50">
|
|
<div className="flex flex-col gap-0">
|
|
<div
|
|
className="flex flex-col items-center gap-2 py-4 bg-[#161824] rounded-[15px] border border-white/10 shadow-[0_8px_32px_rgba(0,0,0,0.3)]"
|
|
style={{ minHeight: '320px' }}
|
|
>
|
|
{defaultButtons.map((button, index) => (
|
|
<div key={index} className="flex flex-col items-center gap-2">
|
|
<button
|
|
onClick={button.onClick}
|
|
className={`
|
|
relative group flex items-center justify-center w-16 h-12 rounded-lg transition-all duration-200
|
|
hover:bg-blue-600/20 hover:scale-110 hover:shadow-lg
|
|
focus:outline-none focus:ring-2 focus:ring-blue-500/50
|
|
${button.active
|
|
? 'bg-blue-600/30 text-blue-400 shadow-md'
|
|
: 'bg-transparent text-gray-300 hover:text-blue-400'
|
|
}
|
|
`}
|
|
title={button.label}
|
|
>
|
|
<Image
|
|
src={button.icon}
|
|
alt={button.label}
|
|
width={20}
|
|
height={20}
|
|
className="w-5 h-5 transition-transform duration-200 group-hover:scale-110"
|
|
/>
|
|
<div className="absolute right-full mr-3 top-1/2 transform -translate-y-1/2
|
|
opacity-0 group-hover:opacity-100 transition-opacity duration-200
|
|
pointer-events-none z-60">
|
|
<div className="bg-gray-900 text-white text-xs px-2 py-1 rounded
|
|
whitespace-nowrap shadow-lg border border-gray-700">
|
|
{button.label}
|
|
</div>
|
|
<div className="absolute left-full top-1/2 transform -translate-y-1/2
|
|
w-0 h-0 border-t-4 border-t-transparent
|
|
border-b-4 border-b-transparent
|
|
border-l-4 border-l-gray-900">
|
|
</div>
|
|
</div>
|
|
</button>
|
|
{button.active && button.children && (
|
|
<div className="flex flex-col gap-2 mt-2">
|
|
{button.children.map((childButton, childIndex) => (
|
|
<button
|
|
key={childIndex}
|
|
onClick={childButton.onClick}
|
|
onMouseDown={childButton.onMouseDown}
|
|
onMouseUp={childButton.onMouseUp}
|
|
className="relative group flex items-center justify-center w-12 h-10 bg-gray-800/50 rounded-md transition-all duration-200 hover:bg-blue-600/30"
|
|
title={childButton.label}
|
|
>
|
|
<Image
|
|
src={childButton.icon}
|
|
alt={childButton.label}
|
|
width={16}
|
|
height={16}
|
|
className="w-4 h-4"
|
|
/>
|
|
</button>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SceneToolbar; |