Skip to content

Commit

Permalink
[FE][Fix] 머지 과정에서 발생한 오류 해결
Browse files Browse the repository at this point in the history
- hostview에서 socket으로 guest들의 실시간 위치 정보만 받아오기
- guestview에서는 socket으로 본인의 위치를 보내는 역할
  • Loading branch information
happyhyep committed Nov 29, 2024
2 parents 5224733 + bbce5dd commit 469604e
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ZoomSlider } from '@/component/zoomslider/ZoomSlider';
export const MapCanvasForView = ({
lat,
lng,
alpha,
otherLocations,
guests,
width,
Expand Down Expand Up @@ -70,6 +71,7 @@ export const MapCanvasForView = ({
guests,
lat,
lng,
alpha,
});

const {
Expand Down Expand Up @@ -101,7 +103,7 @@ export const MapCanvasForView = ({

useEffect(() => {
redrawCanvas();
}, [guests, otherLocations, lat, lng, map]);
}, [guests, otherLocations, lat, lng, alpha, map]);

return (
<div
Expand Down
71 changes: 47 additions & 24 deletions frontend/src/hooks/getUserLocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
interface IGetUserLocation {
lat: number | null;
lng: number | null;
alpha: number | null;
error: string | null;
}

Expand Down Expand Up @@ -32,36 +33,58 @@ export const getUserLocation = (): IGetUserLocation => {
const [location, setLocation] = useState<IGetUserLocation>({
lat: null,
lng: null,
alpha: null,
error: null,
});

useEffect(() => {
if (navigator.geolocation) {
const watchId = navigator.geolocation.watchPosition(
position => {
setLocation({
lat: position.coords.latitude,
lng: position.coords.longitude,
error: null,
});
},
error => {
setLocation({
lat: 37.3595704,
lng: 127.105399,
error: error.message,
});
},
{ enableHighAccuracy: true, maximumAge: 5000, timeout: 10000 },
);
let watchId: number;

const handlePosition = (position: GeolocationPosition) => {
setLocation(prev => ({
...prev,
lat: position.coords.latitude,
lng: position.coords.longitude,
error: null,
}));
};

return () => navigator.geolocation.clearWatch(watchId);
const handleError = (error: GeolocationPositionError) => {
setLocation({
lat: 37.3595704,
lng: 127.105399,
alpha: 0,
error: error.message,
});
};

if (navigator.geolocation) {
watchId = navigator.geolocation.watchPosition(handlePosition, handleError, {
enableHighAccuracy: true,
maximumAge: 5000,
timeout: 10000,
});
} else {
setLocation({
lat: 37.3595704,
lng: 127.105399,
alpha: 0,
error: '현재 위치를 불러오지 못했습니다',
});
}
setLocation({
lat: 37.3595704,
lng: 127.105399,
error: '현재 위치를 불러오지 못했습니다',
});

const handleOrientation = (event: DeviceOrientationEvent) => {
if (event.alpha !== null) {
setLocation(prev => ({ ...prev, alpha: event.alpha }));
}
};

window.addEventListener('deviceorientation', handleOrientation);

return () => {
if (watchId) navigator.geolocation.clearWatch(watchId);
window.removeEventListener('deviceorientation', handleOrientation);
};
}, []);

return location;
Expand Down
131 changes: 104 additions & 27 deletions frontend/src/hooks/useRedraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,32 @@ import { LINE_WIDTH, STROKE_STYLE } from '@/lib/constants/canvasConstants.ts';

import startmarker from '@/assets/startmarker.svg';
import endmarker from '@/assets/endmarker.svg';
import mylocation from '@/assets/mylocation.svg';
import character1 from '@/assets/character1.png';
import character2 from '@/assets/character2.png';
import { IMarkerStyle } from '@/lib/types/canvasInterface.ts';

interface ILatLng {
lat: number;
lng: number;
}

interface ILatLngAlpha {
lat: number;
lng: number;
alpha: number;
}

interface IOtherLocation {
location: ILatLng;
token: string;
location: ILatLngAlpha;
color: string;
}

interface IGuest {
startPoint: ILatLng;
endPoint: ILatLng;
paths: ILatLng[];
markerStyle: IMarkerStyle;
}

interface IUseRedrawCanvasProps {
Expand All @@ -35,6 +44,7 @@ interface IUseRedrawCanvasProps {
guests?: IGuest[] | null;
lat?: number;
lng?: number;
alpha?: number | null;
}

export const useRedrawCanvas = ({
Expand All @@ -48,9 +58,11 @@ export const useRedrawCanvas = ({
guests = [],
lat,
lng,
alpha = 0,
}: IUseRedrawCanvasProps) => {
const startImageRef = useRef<HTMLImageElement | null>(null);
const endImageRef = useRef<HTMLImageElement | null>(null);
const mylocationRef = useRef<HTMLImageElement | null>(null);
const character1Ref = useRef<HTMLImageElement | null>(null);
const character2Ref = useRef<HTMLImageElement | null>(null);

Expand All @@ -61,6 +73,9 @@ export const useRedrawCanvas = ({
endImageRef.current = new Image();
endImageRef.current.src = endmarker;

mylocationRef.current = new Image();
mylocationRef.current.src = mylocation;

character1Ref.current = new Image();
character1Ref.current.src = character1;

Expand All @@ -72,11 +87,72 @@ export const useRedrawCanvas = ({
ctx: CanvasRenderingContext2D,
point: { x: number; y: number } | null,
image: HTMLImageElement | null,
zoom: number,
rotate: number,
) => {
if (point && image) {
const markerSize = 32;
ctx.drawImage(image, point.x - markerSize / 2, point.y - markerSize, markerSize, markerSize);
const markerSize = zoom * 5;
ctx.save();
ctx.translate(point.x, point.y);
ctx.rotate(rotate);
ctx.drawImage(image, -markerSize / 2, -markerSize / 2, markerSize, markerSize);
ctx.restore();
}
};

// eslint-disable-next-line no-shadow
const hexToRgba = (hex: string, alpha: number) => {
// eslint-disable-next-line no-param-reassign
hex = hex.replace(/^#/, '');

if (hex.length === 3) {
// eslint-disable-next-line no-param-reassign
hex = hex
.split('')
.map(char => char + char)
.join('');
}

const bigint = parseInt(hex, 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;

return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};

const drawNeonCircleAndDirection = (
ctx: CanvasRenderingContext2D,
point: { x: number; y: number } | null,
zoom: number,
color: string,
) => {
if (!point) return;

const radius = zoom * 3;
const gradient = ctx.createRadialGradient(
point.x,
point.y + zoom,
0,
point.x,
point.y + zoom,
radius,
);

const alphaStart = 0.75;
const alphaEnd = 0;

gradient.addColorStop(0, hexToRgba(color || '#3498db', alphaStart));
gradient.addColorStop(1, hexToRgba(color || '#3498db', alphaEnd));

ctx.beginPath();
ctx.arc(point.x, point.y + zoom + 1, radius, 0, 2 * Math.PI);
ctx.fillStyle = gradient;
ctx.fill();

ctx.save();

ctx.restore();
};

const drawPath = (ctx: CanvasRenderingContext2D, points: ILatLng[]) => {
Expand All @@ -96,20 +172,6 @@ export const useRedrawCanvas = ({
}
};

// const getMarkerColor = (token: string): string => {
// // 문자열 해싱을 통해 고유 숫자 생성
// let hash = 0;
// for (let i = 0; i < token.length; i++) {
// hash = token.charCodeAt(i) + ((hash << 5) - hash);
// }
// // 해시 값을 기반으로 RGB 값 생성
// const r = (hash >> 16) & 0xff;
// const g = (hash >> 8) & 0xff;
// const b = hash & 0xff;
// // RGB를 HEX 코드로 변환
// return `rgb(${r}, ${g}, ${b})`;
// };

const redrawCanvas = () => {
if (!canvasRef.current || !map) return;

Expand All @@ -123,14 +185,15 @@ export const useRedrawCanvas = ({
ctx.lineCap = 'round';
ctx.lineJoin = 'round';

const zoom = map.getZoom();
if (startMarker) {
const startPoint = latLngToCanvasPoint(startMarker);
drawMarker(ctx, startPoint, startImageRef.current);
drawMarker(ctx, startPoint, startImageRef.current, zoom, 0);
}

if (endMarker) {
const endPoint = latLngToCanvasPoint(endMarker);
drawMarker(ctx, endPoint, endImageRef.current);
drawMarker(ctx, endPoint, endImageRef.current, zoom, 0);
}

if (pathPoints) {
Expand All @@ -139,24 +202,38 @@ export const useRedrawCanvas = ({

if (lat && lng) {
const currentLocation = latLngToCanvasPoint({ lat, lng });
drawMarker(ctx, currentLocation, character1Ref.current);
if (alpha) {
drawMarker(ctx, currentLocation, character1Ref.current, zoom, (alpha * Math.PI) / 180);
} else {
drawMarker(ctx, currentLocation, character1Ref.current, zoom, 0);
}
}

if (otherLocations) {
otherLocations.forEach(({ location }) => {
// const markerColor = getMarkerColor(token);
const locationPoint = latLngToCanvasPoint(location);
drawMarker(ctx, locationPoint, character2Ref.current);
otherLocations.forEach(({ location, color }) => {
const locationPoint = latLngToCanvasPoint({
lat: location.lat ? location.lat : 0,
lng: location.lng ? location.lng : 0,
});

drawNeonCircleAndDirection(ctx, locationPoint, zoom, color);
drawMarker(
ctx,
locationPoint,
character2Ref.current,
zoom,
(location.alpha * Math.PI) / 180,
);
});
}

if (guests) {
guests.forEach(({ startPoint, endPoint, paths }) => {
const startLocation = latLngToCanvasPoint(startPoint);
drawMarker(ctx, startLocation, startImageRef.current);
drawMarker(ctx, startLocation, startImageRef.current, zoom, 0);

const endLocation = latLngToCanvasPoint(endPoint);
drawMarker(ctx, endLocation, endImageRef.current);
drawMarker(ctx, endLocation, endImageRef.current, zoom, 0);

drawPath(ctx, paths);
});
Expand Down
33 changes: 33 additions & 0 deletions frontend/src/hooks/useSocket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useState, useEffect } from 'react';

export const useSocket = (url: string) => {
const [ws, setWs] = useState<WebSocket | null>(null);

useEffect(() => {
const socket = new WebSocket(url);
setWs(socket);

socket.onopen = () => {
console.log('Socket connected');
};

socket.onmessage = event => {
const data = JSON.parse(event.data);
console.log(data);
};

socket.onclose = () => {
console.log('Socket closed');
};

socket.onerror = err => {
console.error('Socket error:', err);
};

return () => {
socket.close();
};
}, [url]);

return ws;
};
Loading

0 comments on commit 469604e

Please sign in to comment.