update gps
This commit is contained in:
@@ -250,6 +250,7 @@ export function Ebike({ position }: EbikeProps): React.JSX.Element {
|
|||||||
minZ: -142,
|
minZ: -142,
|
||||||
maxZ: 138,
|
maxZ: 138,
|
||||||
}}
|
}}
|
||||||
|
zoom={4}
|
||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
@@ -42,6 +42,21 @@ export interface EbikeGPSMapProps {
|
|||||||
* Optional world position for the GPS screen (defaults to origin)
|
* Optional world position for the GPS screen (defaults to origin)
|
||||||
*/
|
*/
|
||||||
position?: [number, number, number];
|
position?: [number, number, number];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolution of the offscreen canvas used for the map texture.
|
||||||
|
* Higher values yield sharper rendering at the cost of GPU memory.
|
||||||
|
* Default: 1024 (1024×1024 px)
|
||||||
|
*/
|
||||||
|
canvasSize?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zoom level applied to the map view.
|
||||||
|
* 1 = full world bounds, 2 = 2× zoom-in centred on the player, etc.
|
||||||
|
* Values < 1 zoom out beyond the calculated world bounds.
|
||||||
|
* Default: 1
|
||||||
|
*/
|
||||||
|
zoom?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,6 +73,8 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
|
|||||||
width = 1,
|
width = 1,
|
||||||
height = 1,
|
height = 1,
|
||||||
position = [0, 0, 0],
|
position = [0, 0, 0],
|
||||||
|
canvasSize = 1024,
|
||||||
|
zoom = 1,
|
||||||
}) => {
|
}) => {
|
||||||
const [waypoints, setWaypoints] = useState<Waypoint[]>([]);
|
const [waypoints, setWaypoints] = useState<Waypoint[]>([]);
|
||||||
const [mapImage, setMapImage] = useState<HTMLImageElement | HTMLCanvasElement | null>(null);
|
const [mapImage, setMapImage] = useState<HTMLImageElement | HTMLCanvasElement | null>(null);
|
||||||
@@ -65,11 +82,20 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
|
|||||||
// Offscreen high-res canvas for crystal clear rendering
|
// Offscreen high-res canvas for crystal clear rendering
|
||||||
const [offscreenCanvas] = useState(() => {
|
const [offscreenCanvas] = useState(() => {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = 1024;
|
canvas.width = canvasSize;
|
||||||
canvas.height = 1024;
|
canvas.height = canvasSize;
|
||||||
return canvas;
|
return canvas;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Resize the canvas whenever canvasSize changes
|
||||||
|
useEffect(() => {
|
||||||
|
offscreenCanvas.width = canvasSize;
|
||||||
|
offscreenCanvas.height = canvasSize;
|
||||||
|
if (textureRef.current) {
|
||||||
|
textureRef.current.needsUpdate = true;
|
||||||
|
}
|
||||||
|
}, [canvasSize, offscreenCanvas]);
|
||||||
|
|
||||||
const textureRef = useRef<THREE.CanvasTexture | null>(null);
|
const textureRef = useRef<THREE.CanvasTexture | null>(null);
|
||||||
const animTimeRef = useRef<number>(0);
|
const animTimeRef = useRef<number>(0);
|
||||||
|
|
||||||
@@ -123,8 +149,8 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
|
|||||||
img.src = mapImageUrl;
|
img.src = mapImageUrl;
|
||||||
}, [mapImageUrl]);
|
}, [mapImageUrl]);
|
||||||
|
|
||||||
// Determine grid boundaries
|
// Determine grid boundaries (before zoom)
|
||||||
const bounds = useMemo(() => {
|
const baseBounds = useMemo(() => {
|
||||||
if (worldBounds) return worldBounds;
|
if (worldBounds) return worldBounds;
|
||||||
|
|
||||||
if (waypoints.length === 0) {
|
if (waypoints.length === 0) {
|
||||||
@@ -150,6 +176,24 @@ export const EbikeGPSMap: React.FC<EbikeGPSMapProps> = ({
|
|||||||
};
|
};
|
||||||
}, [waypoints, worldBounds]);
|
}, [waypoints, worldBounds]);
|
||||||
|
|
||||||
|
// Apply zoom: shrink the view window around the player position
|
||||||
|
const bounds = useMemo(() => {
|
||||||
|
const clampedZoom = Math.max(0.1, zoom);
|
||||||
|
if (clampedZoom === 1) return baseBounds;
|
||||||
|
|
||||||
|
const centerX = startPos.x;
|
||||||
|
const centerZ = startPos.z;
|
||||||
|
const halfW = (baseBounds.maxX - baseBounds.minX) / 2 / clampedZoom;
|
||||||
|
const halfH = (baseBounds.maxZ - baseBounds.minZ) / 2 / clampedZoom;
|
||||||
|
|
||||||
|
return {
|
||||||
|
minX: centerX - halfW,
|
||||||
|
maxX: centerX + halfW,
|
||||||
|
minZ: centerZ - halfH,
|
||||||
|
maxZ: centerZ + halfH,
|
||||||
|
};
|
||||||
|
}, [baseBounds, zoom, startPos]);
|
||||||
|
|
||||||
// Snapped positions
|
// Snapped positions
|
||||||
const startPosSnapped = useMemo(() => {
|
const startPosSnapped = useMemo(() => {
|
||||||
if (waypoints.length === 0) return null;
|
if (waypoints.length === 0) return null;
|
||||||
|
|||||||
@@ -266,6 +266,8 @@ export function TestMap({ onOctreeReady }: TestMapProps): React.JSX.Element {
|
|||||||
"minZ": -142,
|
"minZ": -142,
|
||||||
"maxZ": 138
|
"maxZ": 138
|
||||||
}}
|
}}
|
||||||
|
zoom={1}
|
||||||
|
canvasSize={900}
|
||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
Reference in New Issue
Block a user