leaflet-plugins icon indicating copy to clipboard operation
leaflet-plugins copied to clipboard

Added support for KML IconStyle scale and BalloonStyle text

Open tatsubori opened this issue 10 years ago • 6 comments

Popups on Placemarks now behave like GoogleEarth - they work only when BalloonStyle/displayMode is not 'hide', to show: name
description if Placemark/description is provided. Otherwise the content of BaloonStyle/text is used. c.f. https://developers.google.com/kml/documentation/kmlreference#balloonstyle

tatsubori avatar Nov 11 '15 08:11 tatsubori

@tatsubori thx for the patch, i got a doubt on handling scale property since this one is used "kind of magically" on google earth/maps side. I was going to implement this in #159 but it seems google tools presuppose that default icon size is 64 and default scale is 0.5...

Anyway, if you want to handle scale, you have to apply its ration on anchorRef too, in order to position icons correctly. Here is a kml file that show different result before/after your patch cause it use hotSpot tag for IconStyle http://labo.eliaz.fr/IMG/kml/autour_de_pleumeur.kml

Any thoughts about it ?

brunob avatar Dec 02 '15 16:12 brunob

@brunob Hmm. To "scale" anchorRef properly, we need to know the original icon size. Do you have any idea on how to get it? It would also solve an issue with the current hack assuming the original icon should have 1:1 proportion in width and height.

tatsubori avatar Dec 09 '15 07:12 tatsubori

we need to know the original icon size

In fact it's one the problems that made me think that scale would be hard to handle (+ the fact that google tools generate kml's that contain weird size/scale ratio).

Do you have any idea on how to get it ?

Not for now, and KML is a so terrible mess that i don't really want to work on it every day ^^ I've spent a lot of time on last kml script refactoring...

brunob avatar Dec 09 '15 16:12 brunob

The original icon size can be obtained and scaled according to scale property as follows:

@@
        parseStyle: function (xml) {
                var style = {}, poptions = {}, ioptions = {}, el, id;

-               var attributes = {color: true, width: true, Icon: true, href: true, hotSpot: true};
+               var attributes = {color: true, width: true, Icon: true, href: true, hotSpot: true, scale: true};

                function _parse (xml) {
                        var options = {};


@@
                                        } else if (key === 'Icon') {
                                                ioptions = _parse(e);
                                                if (ioptions.href) { options.href = ioptions.href; }
+                                               if (ioptions.scale) { options.scale = parseFloat(ioptions.scale); }
                                        } else if (key === 'href') {
                                                options.href = value;
+                                       } else if (key === 'scale') {
+                                               options.scale = parseFloat(value);
                                        }
                                }
                        }


@@
                if (el && el[0]) { ioptions = _parse(el[0]); }
                if (ioptions.href) {
                        style.icon = new L.KMLIcon({
                                iconUrl: ioptions.href,
+                               iconScale: ioptions.scale ? ioptions.scale : 1.0,
                                shadowUrl: null,
                                anchorRef: {x: ioptions.x, y: ioptions.y},
                                anchorType: {x: ioptions.xunits, y: ioptions.yunits}
                        });


@@ 
 L.KMLIcon = L.Icon.extend({
+       createIcon: function () {
+               var scale = this.options.iconScale;
+               var img = this._createIcon('icon');
+               img.onload = function () {
+                       var i = new Image();
+                       i.src = this.src;
+                       this.style.width = Math.ceil(i.width * scale) + 'px';
+                       this.style.height = Math.ceil(i.height * scale) + 'px';
+                       };
+               return img;
+       },
+
        _setIconStyles: function (img, name) {
                L.Icon.prototype._setIconStyles.apply(this, [img, name]);
                var options = this.options;

kkdd avatar Apr 25 '16 14:04 kkdd

Thx @kkdd i've made such code when attempting to handle icon scale, but there's still to handle the problem that some kmls generated by google use "de facto" 0.5 scale without providing the info in xml. So it would generate icons 2 times bigger on some existing maps...

brunob avatar Apr 25 '16 15:04 brunob

I found that the people in stackoverflow discussed the pre-scaling of icon size (see Showing custom icons in KML at their actual sizes). It seems to be such normalization that min(the width and height of icon size) should be 32-pixels.

kkdd avatar Apr 29 '16 06:04 kkdd