Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple markers with one icon #2068

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions folium/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ class Icon(MacroElement):
var {{ this.get_name() }} = L.AwesomeMarkers.icon(
{{ this.options|tojavascript }}
);
{{ this._parent.get_name() }}.setIcon({{ this.get_name() }});
{% endmacro %}
"""
)
Expand Down Expand Up @@ -402,9 +401,7 @@ def __init__(
draggable=draggable or None, autoPan=draggable or None, **kwargs
)
if icon is not None:
# this makes sure it is added only once
self._parent.add_child(icon, name=icon.get_name(), index=0)
self.icon = icon
self.add_child(icon)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did the above code not work?

Copy link
Member Author

@Conengmo Conengmo Jan 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It worked I think, but it's not necessary. Figure.script is an OrderedDict, so we are already guaranteed that multiple renders of the same Icon object will result in only one entry in Figure.script.

  • Multiple markers may now have the same Icon object as child.
  • In the first rendering pass, of MacroElement.render, that one Icon object is rendered multiple times
  • Those multiple renders are added to Figure.script with the Icon object name as key. So each render overwrites the previous one, and the result is the Icon object appears in the final output only once.

if popup is not None:
self.add_child(popup if isinstance(popup, Popup) else Popup(str(popup)))
if tooltip is not None:
Expand All @@ -421,12 +418,13 @@ def _get_self_bounds(self) -> TypeBoundsReturn:
return cast(TypeBoundsReturn, [self.location, self.location])

def render(self):
if self.icon:
self.add_child(self.SetIcon(marker=self, icon=self.icon))
if self.location is None:
raise ValueError(
f"{self._name} location must be assigned when added directly to map."
)
for child in list(self._children.values()):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks strange to me. A marker can have only one Icon, correct? Why do we need to look through all the children? Would it not be easier to use self.icon?

Copy link
Member Author

@Conengmo Conengmo Jan 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it not be easier to use self.icon?

That would not work for the case where the icon is added using marker.add_child(icon) or icon.add_to(marker).

By looking through the children, we catch the icon whichever way it was added.

if isinstance(child, Icon):
self.add_child(self.SetIcon(marker=self, icon=child))
super().render()


Expand Down