Compare commits
2 commits
925e98aea7
...
75d3b557fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75d3b557fe | ||
|
|
b19635f324 |
7 changed files with 131 additions and 28 deletions
|
|
@ -55,3 +55,24 @@ tabs:
|
||||||
type: map-editor
|
type: map-editor
|
||||||
mode: single
|
mode: single
|
||||||
help: Déplacez le marqueur
|
help: Déplacez le marqueur
|
||||||
|
markerIcon:
|
||||||
|
label: Icône personnalisée
|
||||||
|
type: files
|
||||||
|
multiple: false
|
||||||
|
accept:
|
||||||
|
- image/jpeg
|
||||||
|
- image/png
|
||||||
|
- image/svg+xml
|
||||||
|
width: 1/2
|
||||||
|
help: Image à utiliser comme marqueur (JPG, PNG ou SVG). Laissez vide pour utiliser le marqueur par défaut.
|
||||||
|
|
||||||
|
markerIconSize:
|
||||||
|
label: Taille de l'icône
|
||||||
|
type: range
|
||||||
|
min: 20
|
||||||
|
max: 500
|
||||||
|
step: 5
|
||||||
|
default: 40
|
||||||
|
after: px
|
||||||
|
width: 1/2
|
||||||
|
help: Taille de l'icône en pixels
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -28,6 +28,23 @@ Kirby::plugin('geoproject/map-editor', [
|
||||||
},
|
},
|
||||||
'longitude' => function ($longitude = null) {
|
'longitude' => function ($longitude = null) {
|
||||||
return $longitude;
|
return $longitude;
|
||||||
|
},
|
||||||
|
'markerIconUrl' => function ($markerIconUrl = null) {
|
||||||
|
// Auto-detect marker icon from page files
|
||||||
|
if ($markerIconUrl === null && $this->model()) {
|
||||||
|
$iconFile = $this->model()->markerIcon()->toFile();
|
||||||
|
if ($iconFile) {
|
||||||
|
return $iconFile->url();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $markerIconUrl;
|
||||||
|
},
|
||||||
|
'markerIconSize' => function ($markerIconSize = 40) {
|
||||||
|
// Auto-detect marker icon size from page
|
||||||
|
if ($this->model() && $this->model()->markerIconSize()->isNotEmpty()) {
|
||||||
|
return (int) $this->model()->markerIconSize()->value();
|
||||||
|
}
|
||||||
|
return $markerIconSize;
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,14 @@ export default {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
markerIconUrl: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
markerIconSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 40,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
|
@ -138,6 +146,8 @@ export default {
|
||||||
id: 'single-marker',
|
id: 'single-marker',
|
||||||
position: { lat, lon },
|
position: { lat, lon },
|
||||||
title: 'Current position',
|
title: 'Current position',
|
||||||
|
iconUrl: props.markerIconUrl,
|
||||||
|
iconSize: props.markerIconSize,
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ export default {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
background: var(--color-white);
|
background: var(--color-white);
|
||||||
transition: border-color 0.2s;
|
transition: border-color 0.2s;
|
||||||
color: #000;
|
color: #fff;
|
||||||
background: var(--input-color-back);
|
background: var(--input-color-back);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,25 @@ export default {
|
||||||
const el = document.createElement("div");
|
const el = document.createElement("div");
|
||||||
el.className = "custom-marker";
|
el.className = "custom-marker";
|
||||||
|
|
||||||
|
// Check if custom icon is provided
|
||||||
|
if (markerData.iconUrl) {
|
||||||
|
// Use custom image
|
||||||
|
el.classList.add("custom-icon");
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = markerData.iconUrl;
|
||||||
|
img.className = "marker-icon-image";
|
||||||
|
|
||||||
|
// Set size from marker data or default to 40px
|
||||||
|
const size = markerData.iconSize || 40;
|
||||||
|
img.style.width = `${size}px`;
|
||||||
|
img.style.height = `${size}px`;
|
||||||
|
|
||||||
|
if (props.selectedMarkerId === markerData.id) {
|
||||||
|
img.classList.add("selected");
|
||||||
|
}
|
||||||
|
el.appendChild(img);
|
||||||
|
} else {
|
||||||
|
// Use default pin marker
|
||||||
// Create inner wrapper for visual transforms (isolates from MapLibre transforms)
|
// Create inner wrapper for visual transforms (isolates from MapLibre transforms)
|
||||||
const inner = document.createElement("div");
|
const inner = document.createElement("div");
|
||||||
inner.className = "marker-inner";
|
inner.className = "marker-inner";
|
||||||
|
|
@ -194,6 +213,7 @@ export default {
|
||||||
numberEl.textContent = index + 1;
|
numberEl.textContent = index + 1;
|
||||||
inner.appendChild(numberEl);
|
inner.appendChild(numberEl);
|
||||||
el.appendChild(inner);
|
el.appendChild(inner);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const coords = [markerData.position.lon, markerData.position.lat];
|
const coords = [markerData.position.lon, markerData.position.lat];
|
||||||
|
|
@ -252,6 +272,7 @@ export default {
|
||||||
function updateMarkerSelection(selectedId) {
|
function updateMarkerSelection(selectedId) {
|
||||||
markerElements.value.forEach(({ element }, markerId) => {
|
markerElements.value.forEach(({ element }, markerId) => {
|
||||||
if (element) {
|
if (element) {
|
||||||
|
// Handle default pin marker
|
||||||
const inner = element.querySelector('.marker-inner');
|
const inner = element.querySelector('.marker-inner');
|
||||||
if (inner) {
|
if (inner) {
|
||||||
if (markerId === selectedId) {
|
if (markerId === selectedId) {
|
||||||
|
|
@ -260,6 +281,16 @@ export default {
|
||||||
inner.classList.remove("selected");
|
inner.classList.remove("selected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle custom icon marker
|
||||||
|
const img = element.querySelector('.marker-icon-image');
|
||||||
|
if (img) {
|
||||||
|
if (markerId === selectedId) {
|
||||||
|
img.classList.add("selected");
|
||||||
|
} else {
|
||||||
|
img.classList.remove("selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -399,6 +430,30 @@ export default {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Custom icon marker */
|
||||||
|
.custom-marker.custom-icon {
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-marker.custom-icon:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marker-icon-image {
|
||||||
|
object-fit: contain;
|
||||||
|
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marker-icon-image:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.4));
|
||||||
|
}
|
||||||
|
|
||||||
|
.marker-icon-image.selected {
|
||||||
|
filter: drop-shadow(0 4px 12px rgba(52, 152, 219, 0.8));
|
||||||
|
}
|
||||||
|
|
||||||
/* MapLibre controls styling */
|
/* MapLibre controls styling */
|
||||||
.maplibregl-ctrl-group {
|
.maplibregl-ctrl-group {
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue