77"""
88from jinja2 import Template
99import json
10- import base64
1110
1211from .utilities import color_brewer , _parse_size , legend_scaler , _locations_mirror , _locations_tolist , write_png ,\
13- mercator_transform
12+ image_to_url
1413from .six import text_type , binary_type
1514
1615from .element import Element , Figure , JavascriptLink , CssLink , Div , MacroElement
@@ -557,43 +556,19 @@ def __init__(self, image, bounds, opacity=1., attribution=None, origin='upper',
557556 origin : ['upper' | 'lower'], optional, default 'upper'
558557 Place the [0,0] index of the array in the upper left or lower left
559558 corner of the axes.
560-
561559 colormap : callable, used only for `mono` image.
562560 Function of the form [x -> (r,g,b)] or [x -> (r,g,b,a)]
563561 for transforming a mono image into RGB.
564562 It must output iterables of length 3 or 4, with values between 0. and 1.
565563 Hint : you can use colormaps from `matplotlib.cm`.
566-
567564 mercator_project : bool, default False, used only for array-like image.
568565 Transforms the data to project (longitude,latitude) coordinates to the Mercator projection.
569566 """
570567 super (ImageOverlay , self ).__init__ ()
571568 self ._name = 'ImageOverlay'
572569
573- if hasattr (image ,'read' ):
574- # We got an image file.
575- if hasattr (image ,'name' ):
576- # we try to get the image format from the file name.
577- fileformat = image .name .lower ().split ('.' )[- 1 ]
578- else :
579- fileformat = 'png'
580- self .url = "data:image/{};base64,{}" .format (fileformat ,
581- base64 .b64encode (image .read ()).decode ('utf-8' ))
582- elif (not (isinstance (image ,text_type ) or isinstance (image ,binary_type ))) and hasattr (image ,'__iter__' ):
583- # We got an array-like object
584- if mercator_project :
585- data = mercator_transform (image ,
586- [bounds [0 ][0 ], bounds [1 ][0 ]],
587- origin = origin )
588- else :
589- data = image
590- self .url = "data:image/png;base64," + \
591- base64 .b64encode (write_png (data , origin = origin , colormap = colormap )).decode ('utf-8' )
592- else :
593- # We got an url
594- self .url = json .loads (json .dumps (image ))
570+ self .url = image_to_url (image , origin = origin , mercator_project = mercator_project , bounds = bounds )
595571
596- self .url = self .url .replace ('\n ' ,' ' )
597572 self .bounds = json .loads (json .dumps (bounds ))
598573 options = {
599574 'opacity' : opacity ,
@@ -610,3 +585,60 @@ def __init__(self, image, bounds, opacity=1., attribution=None, origin='upper',
610585 ).addTo({{this._parent.get_name()}});
611586 {% endmacro %}
612587 """ )
588+
589+ class CustomIcon (Icon ):
590+ def __init__ (self , icon_image , icon_size = None , icon_anchor = None ,
591+ shadow_image = None , shadow_size = None , shadow_anchor = None ,
592+ popup_anchor = None ):
593+ """Create a custom icon, based on an image.
594+
595+ Parameters
596+ ----------
597+ icon_image : string, file or array-like object
598+ The data you want to use as an icon.
599+ * If string, it will be written directly in the output file.
600+ * If file, it's content will be converted as embeded in the output file.
601+ * If array-like, it will be converted to PNG base64 string and embeded in the output.
602+ icon_size : tuple of 2 int
603+ Size of the icon image in pixels.
604+ icon_anchor : tuple of 2 int
605+ The coordinates of the "tip" of the icon (relative to its top left corner).
606+ The icon will be aligned so that this point is at the marker's geographical location.
607+ shadow_image : string, file or array-like object
608+ The data for the shadow image. If not specified, no shadow image will be created.
609+ shadow_size : tuple of 2 int
610+ Size of the shadow image in pixels.
611+ shadow_anchor : tuple of 2 int
612+ The coordinates of the "tip" of the shadow (relative to its top left corner)
613+ (the same as icon_anchor if not specified).
614+ popup_anchor : tuple of 2 int
615+ The coordinates of the point from which popups will "open", relative to the icon anchor.
616+ """
617+ super (Icon , self ).__init__ ()
618+ self ._name = 'CustomIcon'
619+ self .icon_url = image_to_url (icon_image )
620+ self .icon_size = icon_size
621+ self .icon_anchor = icon_anchor
622+
623+ self .shadow_url = image_to_url (shadow_image ) if shadow_image is not None else None
624+ self .shadow_size = shadow_size
625+ self .shadow_anchor = shadow_anchor
626+ self .popup_anchor = popup_anchor
627+
628+ self ._template = Template (u"""
629+ {% macro script(this, kwargs) %}
630+
631+ var {{this.get_name()}} = L.icon({
632+ iconUrl: '{{this.icon_url}}',
633+ {% if this.icon_size %}iconSize: [{{this.icon_size[0]}},{{this.icon_size[1]}}],{% endif %}
634+ {% if this.icon_anchor %}iconAnchor: [{{this.icon_anchor[0]}},{{this.icon_anchor[1]}}],{% endif %}
635+
636+ {% if this.shadow_url %}shadowUrl: '{{this.shadow_url}}',{% endif %}
637+ {% if this.shadow_size %}shadowSize: [{{this.shadow_size[0]}},{{this.shadow_size[1]}}],{% endif %}
638+ {% if this.shadow_anchor %}shadowAnchor: [{{this.shadow_anchor[0]}},{{this.shadow_anchor[1]}}],{% endif %}
639+
640+ {% if this.popup_anchor %}popupAnchor: [{{this.popup_anchor[0]}},{{this.popup_anchor[1]}}],{% endif %}
641+ });
642+ {{this._parent.get_name()}}.setIcon({{this.get_name()}});
643+ {% endmacro %}
644+ """ )
0 commit comments