라이브 체류중 누적 배지 표시

This commit is contained in:
seo
2026-07-12 14:54:45 +09:00
parent 57f47c43ab
commit 42b8fb097e
2 changed files with 110 additions and 1 deletions
+109
View File
@@ -433,6 +433,9 @@ const deviceLang = (navigator.language || navigator.userLanguage || "en").starts
trackLines: [],
smallMarkers: [],
stayMarkers: [],
currentStayMarker: null,
currentStayTimer: null,
currentStayState: null,
historyStartMarker: null,
historyEndMarker: null,
playbackMarker: null,
@@ -2233,6 +2236,103 @@ function createFaceMarkerIcon(size = 60) {
};
}
function createCurrentStayIcon(text) {
return {
content: `<div class="current-stay-badge-wrap"><div class="current-stay-badge">${text}</div></div>`,
anchor: new naver.maps.Point(0, 0)
};
}
function currentStayText(seconds) {
const duration = formatDuration(Math.round(seconds));
return langCode === 'ko' ? `누적 ${duration} 체류중` : `${duration} staying`;
}
function stopCurrentStayBadge() {
if (mapState.currentStayTimer) {
clearInterval(mapState.currentStayTimer);
mapState.currentStayTimer = null;
}
if (mapState.currentStayMarker) {
mapState.currentStayMarker.setMap(null);
}
mapState.currentStayState = null;
}
function currentStaySegmentStart(stay, currentPoint) {
const points = mapState.historyPoints || [];
let startTime = currentPoint.time || new Date().toISOString();
for (let i = points.length - 1; i >= 0; i--) {
const point = points[i];
if (distanceMeters(stay, point) > STAY_GROUP_RADIUS_M) {
break;
}
startTime = point.time || startTime;
}
return startTime;
}
function currentStayStateFor(point) {
if (!mapState.map || !hasValidCoords(point.lat, point.lng) || !mapState.stayPoints?.length) return null;
const stay = mapState.stayPoints.find(item => distanceMeters(item, point) <= STAY_GROUP_RADIUS_M);
if (!stay) return null;
const visits = Array.isArray(stay.visits) ? stay.visits : [];
const segmentStart = currentStaySegmentStart(stay, point);
const segmentStartTs = toTimestamp(segmentStart) || toTimestamp(point.time) || Date.now();
const pointTs = toTimestamp(point.time) || Date.now();
const lastVisit = visits.at(-1);
const latestVisitIsCurrent = lastVisit
&& Math.abs((toTimestamp(lastVisit.endTime) || 0) - pointTs) <= 60000
&& distanceMeters(stay, point) <= STAY_GROUP_RADIUS_M;
const baseDuration = Math.max(0, Number(stay.duration) || 0) - (latestVisitIsCurrent ? Math.max(0, Number(lastVisit.duration) || 0) : 0);
return {
latlng: point.latlng || new naver.maps.LatLng(point.lat, point.lng),
baseDuration,
startedAt: segmentStartTs,
};
}
function renderCurrentStayBadge() {
const state = mapState.currentStayState;
if (!state || !mapState.currentStayMarker) return;
const elapsed = Math.max(0, (Date.now() - state.startedAt) / 1000);
const text = currentStayText(state.baseDuration + elapsed);
mapState.currentStayMarker.setIcon(createCurrentStayIcon(text));
}
function updateCurrentStayBadge(point) {
if (mapState.playbackTimer || _overrideRange) {
stopCurrentStayBadge();
return;
}
const state = currentStayStateFor(point);
if (!state) {
stopCurrentStayBadge();
return;
}
mapState.currentStayState = state;
if (!mapState.currentStayMarker) {
mapState.currentStayMarker = new naver.maps.Marker({
position: state.latlng,
map: mapState.map,
zIndex: 130,
icon: createCurrentStayIcon(currentStayText(state.baseDuration))
});
} else {
mapState.currentStayMarker.setMap(mapState.map);
mapState.currentStayMarker.setPosition(state.latlng);
}
renderCurrentStayBadge();
if (!mapState.currentStayTimer) {
mapState.currentStayTimer = setInterval(renderCurrentStayBadge, 1000);
}
}
function createMainMarker(latlng) {
mapState.marker = new naver.maps.Marker({
position: latlng,
@@ -2266,6 +2366,7 @@ function setCurrentLocationVisible(visible) {
const map = visible ? mapState.map : null;
mapState.marker?.setMap?.(map);
mapState.circle?.setMap?.(map);
if (!visible) stopCurrentStayBadge();
}
function applyMarkerEffects(marker) {
@@ -2321,6 +2422,7 @@ function bounceMarker(marker) {
function resetHistoryLayer() {
stopHistoryPlayback();
stopCurrentStayBadge();
clearTrackLines();
if (mapState.smallMarkers?.length) {
mapState.smallMarkers.forEach(m => m.setMap?.(null));
@@ -2479,6 +2581,7 @@ function updateDOMWithData(data) {
}
updateConfiguredHome(data) || updateHomeCenter(data.latitude, data.longitude);
setCurrentLocationVisible(false);
stopCurrentStayBadge();
clearCurrentRangeCircles();
// 히스토리 궤적/포인트 업데이트
@@ -2530,6 +2633,12 @@ function updateDOMWithData(data) {
lastLat = data.latitude;
lastLng = data.longitude;
lastUpdateISOTime = data.updated;
updateCurrentStayBadge({
lat: data.latitude,
lng: data.longitude,
latlng,
time: data.updated || new Date().toISOString(),
});
}
function animateCircleRadius(targetRadius) {