feat: thêm tính năng nút la bàn để xoay map theo hướng Bắc hoặc theo hướng người dùng di chuyển
This commit is contained in:
@@ -29,6 +29,7 @@ import {
|
|||||||
Search,
|
Search,
|
||||||
LocateFixed,
|
LocateFixed,
|
||||||
Loader2,
|
Loader2,
|
||||||
|
Compass,
|
||||||
Car,
|
Car,
|
||||||
Bike,
|
Bike,
|
||||||
Navigation,
|
Navigation,
|
||||||
@@ -98,6 +99,17 @@ const RecenterUser = ({ position, trigger }: { position: [number, number] | null
|
|||||||
}, [trigger, position, map]);
|
}, [trigger, position, map]);
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
// Component Helper để xử lý xoay bản đồ theo hướng di chuyển hoặc hướng Bắc
|
||||||
|
const MapRotationHandler = ({ rotation }: { rotation: number }) => {
|
||||||
|
const map = useMap();
|
||||||
|
useEffect(() => {
|
||||||
|
const container = map.getContainer();
|
||||||
|
// Xoay container bản đồ và scale nhẹ để tránh lộ khoảng trắng ở các góc khi xoay
|
||||||
|
container.style.transform = `rotate(${rotation}deg) scale(${rotation === 0 ? 1 : 1.2})`;
|
||||||
|
container.style.transition = 'transform 0.5s cubic-bezier(0.4, 0, 0.2, 1)';
|
||||||
|
}, [rotation, map]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
// Menu ngữ cảnh cho bản đồ
|
// Menu ngữ cảnh cho bản đồ
|
||||||
const MapContextMenu = ({ onAction }: { onAction: (action: string, latlng: L.LatLng) => void }) => {
|
const MapContextMenu = ({ onAction }: { onAction: (action: string, latlng: L.LatLng) => void }) => {
|
||||||
const [menuPos, setMenuPos] = useState<{ x: number, y: number, latlng: L.LatLng } | null>(null);
|
const [menuPos, setMenuPos] = useState<{ x: number, y: number, latlng: L.LatLng } | null>(null);
|
||||||
@@ -309,6 +321,8 @@ export const TourDetailPage = ({
|
|||||||
const [searchResults, setSearchResults] = useState<any[]>([]);
|
const [searchResults, setSearchResults] = useState<any[]>([]);
|
||||||
const [isSearching, setIsSearching] = useState(false);
|
const [isSearching, setIsSearching] = useState(false);
|
||||||
const [locateTrigger, setLocateTrigger] = useState(0);
|
const [locateTrigger, setLocateTrigger] = useState(0);
|
||||||
|
const [isHeadingMode, setIsHeadingMode] = useState(false);
|
||||||
|
const [mapRotation, setMapRotation] = useState(0);
|
||||||
const [isRoutingLoading, setIsRoutingLoading] = useState(false);
|
const [isRoutingLoading, setIsRoutingLoading] = useState(false);
|
||||||
const [travelMode, setTravelMode] = useState<'driving' | 'bike' | 'foot'>('driving');
|
const [travelMode, setTravelMode] = useState<'driving' | 'bike' | 'foot'>('driving');
|
||||||
const [routes, setRoutes] = useState<any[]>([]);
|
const [routes, setRoutes] = useState<any[]>([]);
|
||||||
@@ -1217,6 +1231,9 @@ export const TourDetailPage = ({
|
|||||||
{/* Xử lý di chuyển tâm bản đồ về phía người dùng */}
|
{/* Xử lý di chuyển tâm bản đồ về phía người dùng */}
|
||||||
<RecenterUser position={userLocation} trigger={locateTrigger} />
|
<RecenterUser position={userLocation} trigger={locateTrigger} />
|
||||||
|
|
||||||
|
{/* Xử lý xoay bản đồ */}
|
||||||
|
<MapRotationHandler rotation={mapRotation} />
|
||||||
|
|
||||||
{/* Hiển thị vị trí hiện tại của người dùng */}
|
{/* Hiển thị vị trí hiện tại của người dùng */}
|
||||||
{userLocation && (
|
{userLocation && (
|
||||||
<Marker position={userLocation} icon={mapIcons.user} zIndexOffset={1000}>
|
<Marker position={userLocation} icon={mapIcons.user} zIndexOffset={1000}>
|
||||||
@@ -1402,6 +1419,22 @@ export const TourDetailPage = ({
|
|||||||
<Footprints className="w-4 h-4" />
|
<Footprints className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Nút La bàn / Xoay bản đồ */}
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
if (mapRotation !== 0) {
|
||||||
|
setMapRotation(0);
|
||||||
|
setIsHeadingMode(false);
|
||||||
|
} else {
|
||||||
|
setIsHeadingMode(!isHeadingMode);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={`p-2.5 rounded-xl transition-all border-t border-gray-100 mt-1 ${isHeadingMode ? 'bg-blue-600 text-white shadow-md' : 'text-gray-500 hover:bg-gray-100'}`}
|
||||||
|
title={isHeadingMode ? "Dừng xoay (Khóa hướng Bắc)" : "Tự động xoay theo hướng di chuyển"}
|
||||||
|
>
|
||||||
|
<Compass className="w-4 h-4 transition-transform duration-500" style={{ transform: `rotate(${mapRotation}deg)` }} />
|
||||||
|
</button>
|
||||||
|
|
||||||
{/* Nút Tìm tôi */}
|
{/* Nút Tìm tôi */}
|
||||||
<button
|
<button
|
||||||
onClick={() => setLocateTrigger(prev => prev + 1)}
|
onClick={() => setLocateTrigger(prev => prev + 1)}
|
||||||
|
|||||||
Reference in New Issue
Block a user