fix: marker layout, badge position, and clipping
This commit is contained in:
parent
3f0babcb97
commit
e6d6fbd278
1 changed files with 116 additions and 78 deletions
|
|
@ -13,67 +13,59 @@
|
|||
|
||||
.custom-marker-wrapper {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 62px; /* Increased to accommodate pointer shape */
|
||||
width: var(--marker-size, 48px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-marker-position-circle {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
z-index: 1;
|
||||
justify-content: flex-start;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.custom-marker-profile-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 48px;
|
||||
height: 54px;
|
||||
position: relative;
|
||||
width: var(--marker-size, 48px);
|
||||
height: var(--marker-size, 48px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: visible;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.custom-marker-image-container {
|
||||
width: 48px;
|
||||
height: 54px;
|
||||
width: var(--marker-size, 48px);
|
||||
height: var(--marker-size, 48px);
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.custom-marker-image-container::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
bottom: -6px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-top: 8px solid var(--border-color, #757575);
|
||||
z-index: 1;
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: var(--border-color, #757575);
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.custom-marker-image {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: var(--marker-size, 48px);
|
||||
height: var(--marker-size, 48px);
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
border-radius: var(--marker-radius, 50%);
|
||||
}
|
||||
|
||||
.custom-marker-badge {
|
||||
position: absolute;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
right: -4px;
|
||||
bottom: -4px;
|
||||
width: var(--badge-size, 20px);
|
||||
height: var(--badge-size, 20px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -83,6 +75,17 @@
|
|||
z-index: 3;
|
||||
}
|
||||
|
||||
.custom-marker-position-circle {
|
||||
position: relative;
|
||||
margin-top: 10px;
|
||||
width: var(--position-circle-size, 16px);
|
||||
height: var(--position-circle-size, 16px);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
z-index: 1;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
#refresh-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
|
|
@ -247,33 +250,40 @@ const MARKER_SIZES = {
|
|||
};
|
||||
|
||||
// Get selected marker size with fallback to medium
|
||||
let selectedMarkerSize = MARKER_SIZES[MARKER_SIZE_PARAM] || MARKER_SIZES.medium;
|
||||
let selectedMarkerSize = { ...(MARKER_SIZES[MARKER_SIZE_PARAM] || MARKER_SIZES.medium) };
|
||||
|
||||
// Apply CSS custom properties for dynamic sizing
|
||||
document.documentElement.style.setProperty('--marker-size', `${selectedMarkerSize.marker}px`);
|
||||
document.documentElement.style.setProperty('--badge-size', `${selectedMarkerSize.badge}px`);
|
||||
document.documentElement.style.setProperty('--popup-offset', `${selectedMarkerSize.popupOffset}px`);
|
||||
document.documentElement.style.setProperty('--marker-height', `${selectedMarkerSize.marker + 14}px`); // +14 for pointer
|
||||
applyMarkerSizeVariables(selectedMarkerSize);
|
||||
|
||||
// Apply CSS variables for border radius and sizing
|
||||
const styleSheet = document.getElementById('dynamic-styles');
|
||||
|
||||
// Set CSS variables on document root
|
||||
// Apply CSS variables for border radius
|
||||
document.documentElement.style.setProperty('--marker-radius', MARKER_BORDER_RADIUS);
|
||||
document.documentElement.style.setProperty('--badge-radius', BADGE_BORDER_RADIUS);
|
||||
document.documentElement.style.setProperty('--marker-size', `${selectedMarkerSize.marker}px`);
|
||||
document.documentElement.style.setProperty('--badge-size', `${selectedMarkerSize.badge}px`);
|
||||
document.documentElement.style.setProperty('--popup-offset', `${selectedMarkerSize.popupOffset}px`);
|
||||
document.documentElement.style.setProperty('--marker-height', `${selectedMarkerSize.marker + 14}px`);
|
||||
|
||||
const POSITION_CIRCLE_SIZE = 16;
|
||||
const MARKER_LAYOUT_FALLBACK_OFFSET = 24;
|
||||
let markerDimensions = {
|
||||
size: selectedMarkerSize.marker,
|
||||
totalHeight: selectedMarkerSize.marker + MARKER_LAYOUT_FALLBACK_OFFSET
|
||||
};
|
||||
|
||||
const styleSheet = document.getElementById('dynamic-styles');
|
||||
|
||||
// Add static CSS rules that use CSS variables (only if stylesheet is available)
|
||||
if (styleSheet && styleSheet.sheet) {
|
||||
// Add static sizing and radius rules that use CSS variables
|
||||
styleSheet.sheet.insertRule(`.custom-marker-wrapper { width: var(--marker-size); height: calc(var(--marker-size) + 14px); }`, styleSheet.sheet.cssRules.length);
|
||||
styleSheet.sheet.insertRule(`.custom-marker-profile-wrapper { width: var(--marker-size); height: var(--marker-height); }`, styleSheet.sheet.cssRules.length);
|
||||
styleSheet.sheet.insertRule(`.custom-marker-image-container { width: var(--marker-size); height: var(--marker-height); }`, styleSheet.sheet.cssRules.length);
|
||||
styleSheet.sheet.insertRule(`.custom-marker-image { width: var(--marker-size); height: var(--marker-size); border-radius: var(--marker-radius); }`, styleSheet.sheet.cssRules.length);
|
||||
styleSheet.sheet.insertRule(`.custom-marker-badge { width: var(--badge-size); height: var(--badge-size); border-radius: var(--badge-radius); font-size: calc(var(--badge-size) * 0.6); }`, styleSheet.sheet.cssRules.length);
|
||||
const rules = [
|
||||
`.custom-marker-wrapper { width: var(--marker-size); }`,
|
||||
`.custom-marker-profile-wrapper { width: var(--marker-size); height: var(--marker-size); }`,
|
||||
`.custom-marker-image-container { width: var(--marker-size); height: var(--marker-size); }`,
|
||||
`.custom-marker-image { width: var(--marker-size); height: var(--marker-size); border-radius: var(--marker-radius); }`,
|
||||
`.custom-marker-badge { width: var(--badge-size); height: var(--badge-size); border-radius: var(--badge-radius); font-size: calc(var(--badge-size) * 0.6); }`
|
||||
];
|
||||
rules.forEach(rule => styleSheet.sheet.insertRule(rule, styleSheet.sheet.cssRules.length));
|
||||
}
|
||||
|
||||
function applyMarkerSizeVariables(sizeConfig) {
|
||||
document.documentElement.style.setProperty('--marker-size', `${sizeConfig.marker}px`);
|
||||
document.documentElement.style.setProperty('--badge-size', `${sizeConfig.badge}px`);
|
||||
document.documentElement.style.setProperty('--popup-offset', `${sizeConfig.popupOffset}px`);
|
||||
}
|
||||
|
||||
// Parse entities configuration
|
||||
|
|
@ -456,10 +466,40 @@ function createMarkerHTML(personState, activityState, pictureUrl) {
|
|||
</div>
|
||||
<div class="custom-marker-position-circle" style="background: #76D4C3; border: 2px solid ${zoneConfig.color};"></div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
// Measure the rendered marker stack so anchors match pointer and circle placement
|
||||
function recalculateMarkerDimensions() {
|
||||
markerDimensions.size = selectedMarkerSize.marker;
|
||||
const measuredHeight = measureMarkerHeight();
|
||||
markerDimensions.totalHeight = measuredHeight || (selectedMarkerSize.marker + MARKER_LAYOUT_FALLBACK_OFFSET);
|
||||
}
|
||||
|
||||
function createPopupHTML(friendlyName, personState, pictureUrl, zoneColor, speedData, activityState) {
|
||||
function measureMarkerHeight() {
|
||||
if (!document.body) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tempContainer = document.createElement('div');
|
||||
tempContainer.style.position = 'absolute';
|
||||
tempContainer.style.visibility = 'hidden';
|
||||
tempContainer.style.pointerEvents = 'none';
|
||||
tempContainer.innerHTML = createMarkerHTML('not_home', 'unknown', '');
|
||||
|
||||
document.body.appendChild(tempContainer);
|
||||
const markerElement = tempContainer.querySelector('.custom-marker-wrapper');
|
||||
const measuredHeight = markerElement ? Math.ceil(markerElement.getBoundingClientRect().height) : null;
|
||||
tempContainer.remove();
|
||||
|
||||
return measuredHeight;
|
||||
}
|
||||
|
||||
recalculateMarkerDimensions();
|
||||
|
||||
|
||||
function createPopupHTML(friendlyName, personState, pictureUrl, zoneColor, speedData, activityState) {
|
||||
|
||||
const stateLabel = personState.charAt(0).toUpperCase() + personState.slice(1).replace(/_/g, ' ');
|
||||
|
||||
// Get activity display info from ACTIVITIES config
|
||||
|
|
@ -533,10 +573,11 @@ function updateMarkerOSM(entityId, data, lat, lon, personState, activityState, p
|
|||
const speedData = data.speed || null;
|
||||
|
||||
// Get dynamic marker dimensions
|
||||
const markerSize = selectedMarkerSize.marker;
|
||||
const markerHeight = markerSize + 14;
|
||||
const markerAnchor = Math.floor(markerSize / 2);
|
||||
const markerSize = markerDimensions.size;
|
||||
const markerTotalHeight = markerDimensions.totalHeight;
|
||||
const popupOffset = selectedMarkerSize.popupOffset;
|
||||
const markerAnchorX = Math.floor(markerSize / 2);
|
||||
const markerAnchorY = markerTotalHeight - Math.floor(POSITION_CIRCLE_SIZE / 2);
|
||||
|
||||
let marker = markers[entityId];
|
||||
const wasPopupOpen = marker && marker.isPopupOpen();
|
||||
|
|
@ -554,8 +595,8 @@ function updateMarkerOSM(entityId, data, lat, lon, personState, activityState, p
|
|||
marker.setIcon(L.divIcon({
|
||||
className: 'custom-leaflet-marker',
|
||||
html: iconHtml,
|
||||
iconSize: [markerSize, markerHeight],
|
||||
iconAnchor: [markerAnchor, markerHeight],
|
||||
iconSize: [markerSize, markerTotalHeight],
|
||||
iconAnchor: [markerAnchorX, markerAnchorY],
|
||||
popupAnchor: [0, popupOffset]
|
||||
}));
|
||||
|
||||
|
|
@ -566,8 +607,8 @@ function updateMarkerOSM(entityId, data, lat, lon, personState, activityState, p
|
|||
const icon = L.divIcon({
|
||||
className: 'custom-leaflet-marker',
|
||||
html: iconHtml,
|
||||
iconSize: [markerSize, markerHeight],
|
||||
iconAnchor: [markerAnchor, markerHeight],
|
||||
iconSize: [markerSize, markerTotalHeight],
|
||||
iconAnchor: [markerAnchorX, markerAnchorY],
|
||||
popupAnchor: [0, popupOffset]
|
||||
});
|
||||
|
||||
|
|
@ -582,7 +623,7 @@ function updateMarkerOSM(entityId, data, lat, lon, personState, activityState, p
|
|||
currentPopup.closePopup();
|
||||
}
|
||||
currentPopup = marker;
|
||||
map.setView(marker.getLatLng(), 17, { animate: true });
|
||||
map.setView(marker.getLatLng(), Math.max(map.getZoom(), 17), { animate: true });
|
||||
});
|
||||
|
||||
markers[entityId] = marker;
|
||||
|
|
@ -615,6 +656,9 @@ function updateMarkerGoogle(entityId, data, lat, lon, personState, activityState
|
|||
if (marker.infoWindow) {
|
||||
marker.infoWindow.setContent(createPopupHTML(friendlyName, personState, pictureUrl, zoneConfig.color, speedData, activityState));
|
||||
marker.infoWindow.setPosition(position);
|
||||
marker.infoWindow.setOptions({
|
||||
pixelOffset: new google.maps.Size(0, selectedMarkerSize.popupOffset)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Create custom HTML overlay
|
||||
|
|
@ -644,7 +688,7 @@ function updateMarkerGoogle(entityId, data, lat, lon, personState, activityState
|
|||
|
||||
if (this.infoWindow) {
|
||||
map.setCenter(this.position);
|
||||
map.setZoom(17);
|
||||
map.setZoom(Math.max(map.getZoom(), 17));
|
||||
this.infoWindow.open(this.getMap());
|
||||
currentPopup = this.infoWindow;
|
||||
}
|
||||
|
|
@ -662,12 +706,13 @@ function updateMarkerGoogle(entityId, data, lat, lon, personState, activityState
|
|||
);
|
||||
|
||||
const div = this.div;
|
||||
const markerSize = selectedMarkerSize.marker;
|
||||
const markerHeight = markerSize + 14;
|
||||
const markerSize = markerDimensions.size;
|
||||
const markerTotalHeight = markerDimensions.totalHeight;
|
||||
const markerAnchor = Math.floor(markerSize / 2);
|
||||
const verticalAnchor = markerTotalHeight - Math.floor(POSITION_CIRCLE_SIZE / 2);
|
||||
|
||||
div.style.left = (pos.x - markerAnchor) + 'px'; // Center horizontally
|
||||
div.style.top = (pos.y - markerHeight) + 'px'; // Position above point
|
||||
div.style.top = (pos.y - verticalAnchor) + 'px'; // Position above point
|
||||
}
|
||||
|
||||
onRemove() {
|
||||
|
|
@ -849,16 +894,9 @@ window.addEventListener('message', (event) => {
|
|||
|
||||
if (event.data.marker_size && MARKER_SIZES[event.data.marker_size]) {
|
||||
// Update marker size dynamically
|
||||
const newSize = MARKER_SIZES[event.data.marker_size];
|
||||
selectedMarkerSize.marker = newSize.marker;
|
||||
selectedMarkerSize.badge = newSize.badge;
|
||||
selectedMarkerSize.popupOffset = newSize.popupOffset;
|
||||
|
||||
// Update CSS custom properties
|
||||
document.documentElement.style.setProperty('--marker-size', `${newSize.marker}px`);
|
||||
document.documentElement.style.setProperty('--badge-size', `${newSize.badge}px`);
|
||||
document.documentElement.style.setProperty('--popup-offset', `${newSize.popupOffset}px`);
|
||||
document.documentElement.style.setProperty('--marker-height', `${newSize.marker + 14}px`);
|
||||
selectedMarkerSize = { ...MARKER_SIZES[event.data.marker_size] };
|
||||
applyMarkerSizeVariables(selectedMarkerSize);
|
||||
recalculateMarkerDimensions();
|
||||
|
||||
console.log('Marker size updated to:', event.data.marker_size);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue