nicer overlay point markers and optional clustering
This commit is contained in:
parent
b596bc9c12
commit
aea7df1b24
6 changed files with 86 additions and 41 deletions
|
@ -396,7 +396,7 @@ def create_editor_form(editor_model):
|
|||
'color_background', 'color_wall_fill', 'color_wall_border', 'color_door_fill', 'color_ground_fill',
|
||||
'color_obstacles_default_fill', 'color_obstacles_default_border', 'stroke_color', 'stroke_width',
|
||||
'stroke_opacity', 'fill_color', 'fill_opacity', 'interactive', 'point_icon', 'extra_data', 'show_label',
|
||||
'show_geometry', 'show_label', 'show_geometry', 'default_geomtype',
|
||||
'show_geometry', 'show_label', 'show_geometry', 'default_geomtype', 'cluster_points',
|
||||
"load_group_display", "load_group_contribute",
|
||||
"altitude_quest",
|
||||
]
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.1.3 on 2024-12-26 02:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mapdata', '0128_space_identifyable'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='dataoverlay',
|
||||
name='cluster_points',
|
||||
field=models.BooleanField(default=False, verbose_name='cluster points together when zoomed out'),
|
||||
),
|
||||
]
|
|
@ -26,6 +26,8 @@ class DataOverlay(TitledMixin, AccessRestrictionMixin, models.Model):
|
|||
fill_color = models.CharField(max_length=255, blank=True, null=True, verbose_name=_('default fill color'))
|
||||
fill_opacity = models.FloatField(blank=True, null=True, verbose_name=_('fill opacity'))
|
||||
|
||||
cluster_points = models.BooleanField(default=False, verbose_name=_('cluster points together when zoomed out'))
|
||||
|
||||
default_geomtype = models.CharField(max_length=255, blank=True, null=True, choices=GeometryType, verbose_name=_('default geometry type'))
|
||||
|
||||
pull_url = models.URLField(blank=True, null=True, verbose_name=_('pull URL'))
|
||||
|
|
|
@ -375,6 +375,7 @@ class DataOverlaySchema(TitledSchema, DjangoModelSchema):
|
|||
stroke_opacity: Optional[float]
|
||||
fill_color: Optional[str]
|
||||
fill_opacity: Optional[float]
|
||||
cluster_points: bool
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1880,18 +1880,6 @@ blink {
|
|||
}
|
||||
}
|
||||
|
||||
.overlay-point-icon {
|
||||
> span {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
font-family: 'Material Symbols Outlined';
|
||||
}
|
||||
}
|
||||
|
||||
.data-overlay-popup {
|
||||
.leaflet-popup-content {
|
||||
margin: 0;
|
||||
|
@ -1944,7 +1932,8 @@ blink {
|
|||
}
|
||||
}
|
||||
|
||||
.quest-icon {
|
||||
.symbol-icon {
|
||||
--icon-color: var(--color-primary);
|
||||
> span {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
|
@ -1954,15 +1943,33 @@ blink {
|
|||
font-size: 22px;
|
||||
font-family: 'Material Symbols Outlined';
|
||||
background-color: white;
|
||||
color: var(--color-primary);
|
||||
color: var(--icon-color);
|
||||
border-radius: 100%;
|
||||
box-shadow: 0 0 0 5px color-mix(in srgb, transparent, var(--color-primary) 60%);
|
||||
box-shadow: 0 0 0 5px color-mix(in srgb, transparent, var(--icon-color) 60%);
|
||||
|
||||
transition: color, background-color 150ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-primary);
|
||||
color: white;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
|
||||
&.symbol-icon-interactive {
|
||||
> span {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--icon-color);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.symbol-icon-empty {
|
||||
> span {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2775,7 +2775,7 @@ QuestsControl = ExpandingControl.extend({
|
|||
pointToLayer: (geom, latlng) => {
|
||||
return L.marker(latlng, {
|
||||
icon: L.divIcon({
|
||||
className: 'quest-icon',
|
||||
className: 'symbol-icon symbol-icon-interactive',
|
||||
html: `<span>${quest_icon}</span>`,
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12],
|
||||
|
@ -3130,6 +3130,7 @@ class DataOverlay {
|
|||
this.id = options.id;
|
||||
this.title = options.title;
|
||||
this.group = options.group;
|
||||
this.cluster_points = options.cluster_points;
|
||||
this.default_stroke_color = options.stroke_color;
|
||||
this.default_stroke_width = options.stroke_width;
|
||||
this.default_stroke_opacity = options.stroke_opacity;
|
||||
|
@ -3144,7 +3145,11 @@ class DataOverlay {
|
|||
for (const feature of features) {
|
||||
const level_id = feature.level_id;
|
||||
if (!(level_id in levels)) {
|
||||
levels[level_id] = L.layerGroup([]);
|
||||
if (this.cluster_points) {
|
||||
levels[level_id] = L.markerClusterGroup();
|
||||
} else {
|
||||
levels[level_id] = L.layerGroup();
|
||||
}
|
||||
}
|
||||
const style = {
|
||||
'color': feature.stroke_color ?? this.default_stroke_color ?? 'var(--color-map-overlay)',
|
||||
|
@ -3157,12 +3162,21 @@ class DataOverlay {
|
|||
style,
|
||||
interactive: feature.interactive,
|
||||
pointToLayer: (geom, latlng) => {
|
||||
return L.marker(latlng, {
|
||||
title: feature.title,
|
||||
icon: L.divIcon({
|
||||
className: 'symbol-icon ' + (feature.point_icon ? '' : 'symbol-icon-empty ') + (feature.interactive ? 'symbol-icon-interactive' : ''),
|
||||
html: `<span style="--icon-color: ${style.color}">${feature.point_icon ?? ''}</span>`,
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12],
|
||||
})
|
||||
});
|
||||
if (feature.point_icon !== null) {
|
||||
return L.marker(latlng, {
|
||||
title: feature.title,
|
||||
icon: L.divIcon({
|
||||
className: 'overlay-point-icon',
|
||||
html: `<span style="color: ${style.color}">${feature.point_icon}</span>`,
|
||||
className: 'symbol-icon ' + (feature.interactive ? 'symbol-icon-interactive' : ''),
|
||||
html: `<span style="--icon-color: ${style.color}">${feature.point_icon}</span>`,
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12],
|
||||
})
|
||||
|
@ -3173,27 +3187,30 @@ class DataOverlay {
|
|||
...style
|
||||
});
|
||||
}
|
||||
},
|
||||
onEachFeature: (f, layer) => {
|
||||
if (feature.interactive) {
|
||||
layer.bindPopup(() => {
|
||||
let html = `<h4>${feature.title}</h4>`;
|
||||
if (feature.external_url != null) {
|
||||
html += `<a href="${feature.external_url}" target="_blank">open external link</a>`;
|
||||
}
|
||||
if (feature.extra_data != null) {
|
||||
html += '<table>';
|
||||
for (const key in feature.extra_data) {
|
||||
html += `<tr><th>${key}</th><td>${feature.extra_data[key]}</td></tr>`;
|
||||
}
|
||||
|
||||
html += '</table>';
|
||||
}
|
||||
return html;
|
||||
}, {
|
||||
className: 'data-overlay-popup'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (feature.interactive) {
|
||||
layer.bindPopup(() => {
|
||||
let html = `<h4>${feature.title}</h4>`;
|
||||
if (feature.external_url != null) {
|
||||
html += `<a href="${feature.external_url}" target="_blank">open external link</a>`;
|
||||
}
|
||||
if (feature.extra_data != null) {
|
||||
html += '<table>';
|
||||
for (const key in feature.extra_data) {
|
||||
html += `<tr><th>${key}</th><td>${feature.extra_data[key]}</td></tr>`;
|
||||
}
|
||||
|
||||
html += '</table>';
|
||||
}
|
||||
return html;
|
||||
}, {
|
||||
className: 'data-overlay-popup'
|
||||
});
|
||||
}
|
||||
levels[level_id].addLayer(layer);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue