From fabdacd656931adc3b3094dec56a6f971626b385 Mon Sep 17 00:00:00 2001 From: Sergii Kauk Date: Wed, 27 Apr 2016 22:20:15 +0200 Subject: [PATCH 1/7] Put labels on overlayLayer pane --- src/maplabel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/maplabel.js b/src/maplabel.js index 71c88ca..6303104 100755 --- a/src/maplabel.js +++ b/src/maplabel.js @@ -117,7 +117,7 @@ MapLabel.prototype.onAdd = function() { var panes = this.getPanes(); if (panes) { - panes.mapPane.appendChild(canvas); + panes.overlayLayer.appendChild(canvas); } }; MapLabel.prototype['onAdd'] = MapLabel.prototype.onAdd; From b7021eec79b3159b80e82e1673b679f6d1b67703 Mon Sep 17 00:00:00 2001 From: Sergii Kauk Date: Wed, 27 Apr 2016 22:22:05 +0200 Subject: [PATCH 2/7] Support asynchronous loading --- src/maplabel.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/maplabel.js b/src/maplabel.js index 6303104..fd4570f 100755 --- a/src/maplabel.js +++ b/src/maplabel.js @@ -30,6 +30,12 @@ * @param {Object.=} opt_options Optional properties to set. */ function MapLabel(opt_options) { + if (!MapLabel.prototype.setValues) { + for (var property in google.maps.OverlayView.prototype) { + MapLabel.prototype[property] = google.maps.OverlayView.prototype[property]; + } + } + this.set('fontFamily', 'sans-serif'); this.set('fontSize', 12); this.set('fontColor', '#000000'); @@ -41,7 +47,6 @@ function MapLabel(opt_options) { this.setValues(opt_options); } -MapLabel.prototype = new google.maps.OverlayView; window['MapLabel'] = MapLabel; From f5b4c4868bf4df3a07522ca4425ead6419006df1 Mon Sep 17 00:00:00 2001 From: Sergii Kauk Date: Wed, 27 Apr 2016 22:26:11 +0200 Subject: [PATCH 3/7] HiDPI support, canvas context and styles re-arrangements --- src/maplabel.js | 73 ++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/src/maplabel.js b/src/maplabel.js index fd4570f..b85917f 100755 --- a/src/maplabel.js +++ b/src/maplabel.js @@ -78,17 +78,35 @@ MapLabel.prototype.drawCanvas_ = function() { if (!canvas) return; var style = canvas.style; + style.position = 'absolute'; style.zIndex = /** @type number */(this.get('zIndex')); var ctx = canvas.getContext('2d'); - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.strokeStyle = this.get('strokeColor'); - ctx.fillStyle = this.get('fontColor'); ctx.font = this.get('fontSize') + 'px ' + this.get('fontFamily'); var strokeWeight = Number(this.get('strokeWeight')); - var text = this.get('text'); + var textMeasure = ctx.measureText(text); + + canvas.width = Math.ceil(textMeasure.width + strokeWeight * 2); + canvas.height = Math.ceil(parseInt(this.get('fontSize')) + strokeWeight * 2); + + if (window.devicePixelRatio > 1) { + style.width = canvas.width + 'px'; + style.height = canvas.height + 'px'; + canvas.width = canvas.width * window.devicePixelRatio; + canvas.height = canvas.height * window.devicePixelRatio; + ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + } + + ctx.lineJoin = 'round'; + ctx.textBaseline = 'top'; + ctx.textAlign = 'left'; + ctx.strokeStyle = this.get('strokeColor'); + ctx.fillStyle = this.get('fontColor'); + ctx.font = this.get('fontSize') + 'px ' + this.get('fontFamily'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + if (text) { if (strokeWeight) { ctx.lineWidth = strokeWeight; @@ -96,13 +114,6 @@ MapLabel.prototype.drawCanvas_ = function() { } ctx.fillText(text, strokeWeight, strokeWeight); - - var textMeasure = ctx.measureText(text); - var textWidth = textMeasure.width + strokeWeight; - style.marginLeft = this.getMarginLeft_(textWidth) + 'px'; - // Bring actual text top in line with desired latitude. - // Cheaper than calculating height of text. - style.marginTop = '-0.4em'; } }; @@ -111,12 +122,6 @@ MapLabel.prototype.drawCanvas_ = function() { */ MapLabel.prototype.onAdd = function() { var canvas = this.canvas_ = document.createElement('canvas'); - var style = canvas.style; - style.position = 'absolute'; - - var ctx = canvas.getContext('2d'); - ctx.lineJoin = 'round'; - ctx.textBaseline = 'top'; this.drawCanvas_(); @@ -127,22 +132,6 @@ MapLabel.prototype.onAdd = function() { }; MapLabel.prototype['onAdd'] = MapLabel.prototype.onAdd; -/** - * Gets the appropriate margin-left for the canvas. - * @private - * @param {number} textWidth the width of the text, in pixels. - * @return {number} the margin-left, in pixels. - */ -MapLabel.prototype.getMarginLeft_ = function(textWidth) { - switch (this.get('align')) { - case 'left': - return 0; - case 'right': - return -textWidth; - } - return textWidth / -2; -}; - /** * @inheritDoc */ @@ -168,7 +157,23 @@ MapLabel.prototype.draw = function() { var style = this.canvas_.style; style['top'] = pos.y + 'px'; - style['left'] = pos.x + 'px'; + //style['left'] = pos.x + 'px'; + + switch(this.get('align')) { + case 'left': + style['left'] = pos.x - (this.canvas_.width / (window.devicePixelRatio ? window.devicePixelRatio : 1)) + 'px'; + style['margin-left'] = '-1em'; + style['margin-top'] = '-0.4em'; + break; + case 'right': + style['margin-top'] = '-0.4em'; + style['margin-left'] = '1em'; + style['left'] = pos.x + 'px'; + break; + default: + style['margin-top'] = '1em'; //'1em'; + style['left'] = (pos.x - (this.canvas_.width / (window.devicePixelRatio ? window.devicePixelRatio : 1)) / 2) + 'px'; + } style['visibility'] = this.getVisible_(); }; From 580b483c5bf9325272ca65039a0c7e27a63ab012 Mon Sep 17 00:00:00 2001 From: Sergii Kauk Date: Wed, 27 Apr 2016 22:29:03 +0200 Subject: [PATCH 4/7] Re-arrange properties, default font to fit Maps --- src/maplabel.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/maplabel.js b/src/maplabel.js index b85917f..5e0fb58 100755 --- a/src/maplabel.js +++ b/src/maplabel.js @@ -36,13 +36,12 @@ function MapLabel(opt_options) { } } - this.set('fontFamily', 'sans-serif'); - this.set('fontSize', 12); + this.set('align', 'center'); this.set('fontColor', '#000000'); - this.set('strokeWeight', 4); + this.set('fontFamily', 'Roboto,Arial,sans-serif'); + this.set('fontSize', 12); this.set('strokeColor', '#ffffff'); - this.set('align', 'center'); - + this.set('strokeWeight', 4); this.set('zIndex', 1e3); this.setValues(opt_options); From 31c458f554dc39da105a9fdba9f9870782b307e7 Mon Sep 17 00:00:00 2001 From: Sergii Kauk Date: Wed, 27 Apr 2016 23:03:11 +0200 Subject: [PATCH 5/7] Cleanup & closure compilation --- src/maplabel-compiled.js | 13 +++++++------ src/maplabel.js | 5 ++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/maplabel-compiled.js b/src/maplabel-compiled.js index e45170b..933486e 100755 --- a/src/maplabel-compiled.js +++ b/src/maplabel-compiled.js @@ -1,4 +1,4 @@ -(function(){/* +/* Copyright 2011 Google Inc. @@ -7,7 +7,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -15,7 +15,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -var d="prototype";function e(a){this.set("fontFamily","sans-serif");this.set("fontSize",12);this.set("fontColor","#000000");this.set("strokeWeight",4);this.set("strokeColor","#ffffff");this.set("align","center");this.set("zIndex",1E3);this.setValues(a)}e.prototype=new google.maps.OverlayView;window.MapLabel=e;e[d].changed=function(a){switch(a){case "fontFamily":case "fontSize":case "fontColor":case "strokeWeight":case "strokeColor":case "align":case "text":return h(this);case "maxZoom":case "minZoom":case "position":return this.draw()}}; -function h(a){var b=a.a;if(b){var f=b.style;f.zIndex=a.get("zIndex");var c=b.getContext("2d");c.clearRect(0,0,b.width,b.height);c.strokeStyle=a.get("strokeColor");c.fillStyle=a.get("fontColor");c.font=a.get("fontSize")+"px "+a.get("fontFamily");var b=Number(a.get("strokeWeight")),g=a.get("text");if(g){if(b)c.lineWidth=b,c.strokeText(g,b,b);c.fillText(g,b,b);a:{c=c.measureText(g).width+b;switch(a.get("align")){case "left":a=0;break a;case "right":a=-c;break a}a=c/-2}f.marginLeft=a+"px";f.marginTop= -"-0.4em"}}}e[d].onAdd=function(){var a=this.a=document.createElement("canvas");a.style.position="absolute";var b=a.getContext("2d");b.lineJoin="round";b.textBaseline="top";h(this);(b=this.getPanes())&&b.mapPane.appendChild(a)};e[d].onAdd=e[d].onAdd; -e[d].draw=function(){var a=this.getProjection();if(a&&this.a){var b=this.get("position");if(b){b=a.fromLatLngToDivPixel(b);a=this.a.style;a.top=b.y+"px";a.left=b.x+"px";var b=this.get("minZoom"),f=this.get("maxZoom");if(b===void 0&&f===void 0)b="";else{var c=this.getMap();c?(c=c.getZoom(),b=cf?"hidden":""):b=""}a.visibility=b}}};e[d].draw=e[d].draw;e[d].onRemove=function(){var a=this.a;a&&a.parentNode&&a.parentNode.removeChild(a)};e[d].onRemove=e[d].onRemove;})() +function d(b){if(!MapLabel.prototype.setValues)for(var a in google.maps.OverlayView.prototype)MapLabel.prototype[a]=google.maps.OverlayView.prototype[a];this.set("align","center");this.set("fontColor","#000000");this.set("fontFamily","Roboto,Arial,sans-serif");this.set("fontSize",12);this.set("strokeColor","#ffffff");this.set("strokeWeight",4);this.set("zIndex",1E3);this.setValues(b)}window.MapLabel=d; +d.prototype.g=function(){var b=this.a=document.createElement("canvas"),a=this.a;if(a){var f=a.style;f.position="absolute";f.zIndex=this.get("zIndex");var c=a.getContext("2d");c.font=this.get("fontSize")+"px "+this.get("fontFamily");var e=Number(this.get("strokeWeight")),g=this.get("text");a.width=Math.ceil(c.measureText(g).width+2*e);a.height=Math.ceil(parseInt(this.get("fontSize"),10)+2*e);1f?"hidden":""):a=""}b.visibility=a}}};d.prototype.draw=d.prototype.c;d.prototype.h=function(){var b=this.a;b&&b.parentNode&&b.parentNode.removeChild(b)};d.prototype.onRemove=d.prototype.h; diff --git a/src/maplabel.js b/src/maplabel.js index 5e0fb58..9b2fd70 100755 --- a/src/maplabel.js +++ b/src/maplabel.js @@ -88,7 +88,7 @@ MapLabel.prototype.drawCanvas_ = function() { var textMeasure = ctx.measureText(text); canvas.width = Math.ceil(textMeasure.width + strokeWeight * 2); - canvas.height = Math.ceil(parseInt(this.get('fontSize')) + strokeWeight * 2); + canvas.height = Math.ceil(parseInt(this.get('fontSize'), 10) + strokeWeight * 2); if (window.devicePixelRatio > 1) { style.width = canvas.width + 'px'; @@ -156,7 +156,6 @@ MapLabel.prototype.draw = function() { var style = this.canvas_.style; style['top'] = pos.y + 'px'; - //style['left'] = pos.x + 'px'; switch(this.get('align')) { case 'left': @@ -170,7 +169,7 @@ MapLabel.prototype.draw = function() { style['left'] = pos.x + 'px'; break; default: - style['margin-top'] = '1em'; //'1em'; + style['margin-top'] = '1em'; style['left'] = (pos.x - (this.canvas_.width / (window.devicePixelRatio ? window.devicePixelRatio : 1)) / 2) + 'px'; } From d6d49004b9f169693a6a5c36dbbb3f95131f4848 Mon Sep 17 00:00:00 2001 From: Sergii Kauk Date: Thu, 28 Apr 2016 12:41:01 +0200 Subject: [PATCH 6/7] Prototype override fix, cleanup --- src/maplabel-compiled.js | 11 ++++++----- src/maplabel.js | 15 +++++++++------ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/maplabel-compiled.js b/src/maplabel-compiled.js index 933486e..46c5265 100755 --- a/src/maplabel-compiled.js +++ b/src/maplabel-compiled.js @@ -15,8 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -function d(b){if(!MapLabel.prototype.setValues)for(var a in google.maps.OverlayView.prototype)MapLabel.prototype[a]=google.maps.OverlayView.prototype[a];this.set("align","center");this.set("fontColor","#000000");this.set("fontFamily","Roboto,Arial,sans-serif");this.set("fontSize",12);this.set("strokeColor","#ffffff");this.set("strokeWeight",4);this.set("zIndex",1E3);this.setValues(b)}window.MapLabel=d; -d.prototype.g=function(){var b=this.a=document.createElement("canvas"),a=this.a;if(a){var f=a.style;f.position="absolute";f.zIndex=this.get("zIndex");var c=a.getContext("2d");c.font=this.get("fontSize")+"px "+this.get("fontFamily");var e=Number(this.get("strokeWeight")),g=this.get("text");a.width=Math.ceil(c.measureText(g).width+2*e);a.height=Math.ceil(parseInt(this.get("fontSize"),10)+2*e);1f?"hidden":""):a=""}b.visibility=a}}};d.prototype.draw=d.prototype.c;d.prototype.h=function(){var b=this.a;b&&b.parentNode&&b.parentNode.removeChild(b)};d.prototype.onRemove=d.prototype.h; +function d(a){if(!MapLabel.prototype.setValues)for(var b in google.maps.OverlayView.prototype)MapLabel.prototype.hasOwnProperty(b)||(MapLabel.prototype[b]=google.maps.OverlayView.prototype[b]);this.set("align","center");this.set("fontColor","#000000");this.set("fontFamily","Roboto,Arial,sans-serif");this.set("fontSize",12);this.set("strokeColor","#ffffff");this.set("strokeWeight",4);this.set("zIndex",1E3);this.setValues(a)}window.MapLabel=d; +d.prototype.changed=function(a){switch(a){case "fontFamily":case "fontSize":case "fontColor":case "strokeWeight":case "strokeColor":case "text":h(this);case "align":case "maxZoom":case "minZoom":case "position":return this.b()}}; +function h(a){var b=a.a;if(b){var f=b.style;f.position="absolute";f.zIndex=a.get("zIndex");var c=b.getContext("2d");c.font=a.get("fontSize")+"px "+a.get("fontFamily");var e=Number(a.get("strokeWeight")),g=a.get("text");b.width=Math.ceil(c.measureText(g).width+2*e);b.height=Math.ceil(parseInt(a.get("fontSize"),10)+2*e);1f?"hidden":""):b=""}a.visibility=b}}};d.prototype.draw=d.prototype.b;d.prototype.onRemove=function(){var a=this.a;a&&a.parentNode&&a.parentNode.removeChild(a)};d.prototype.onRemove=d.prototype.onRemove; diff --git a/src/maplabel.js b/src/maplabel.js index 9b2fd70..1e62a29 100755 --- a/src/maplabel.js +++ b/src/maplabel.js @@ -32,7 +32,9 @@ function MapLabel(opt_options) { if (!MapLabel.prototype.setValues) { for (var property in google.maps.OverlayView.prototype) { - MapLabel.prototype[property] = google.maps.OverlayView.prototype[property]; + if(!MapLabel.prototype.hasOwnProperty(property)) { + MapLabel.prototype[property] = google.maps.OverlayView.prototype[property]; + } } } @@ -58,9 +60,9 @@ MapLabel.prototype.changed = function(prop) { case 'fontColor': case 'strokeWeight': case 'strokeColor': - case 'align': case 'text': - return this.drawCanvas_(); + this.drawCanvas_(); + case 'align': case 'maxZoom': case 'minZoom': case 'position': @@ -164,13 +166,14 @@ MapLabel.prototype.draw = function() { style['margin-top'] = '-0.4em'; break; case 'right': - style['margin-top'] = '-0.4em'; - style['margin-left'] = '1em'; style['left'] = pos.x + 'px'; + style['margin-left'] = '1em'; + style['margin-top'] = '-0.4em'; break; default: - style['margin-top'] = '1em'; style['left'] = (pos.x - (this.canvas_.width / (window.devicePixelRatio ? window.devicePixelRatio : 1)) / 2) + 'px'; + style['margin-left'] = 0; + style['margin-top'] = '1em'; } style['visibility'] = this.getVisible_(); From b0000a9244fd2d3ccdf5b5cab647bbb5d9208364 Mon Sep 17 00:00:00 2001 From: Sergii Kauk Date: Thu, 28 Apr 2016 13:52:01 +0200 Subject: [PATCH 7/7] Closure Compiler parameters on top --- src/maplabel-compiled.js | 12 ++++++------ src/maplabel.js | 7 ++++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/maplabel-compiled.js b/src/maplabel-compiled.js index 46c5265..389ad02 100755 --- a/src/maplabel-compiled.js +++ b/src/maplabel-compiled.js @@ -15,9 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -function d(a){if(!MapLabel.prototype.setValues)for(var b in google.maps.OverlayView.prototype)MapLabel.prototype.hasOwnProperty(b)||(MapLabel.prototype[b]=google.maps.OverlayView.prototype[b]);this.set("align","center");this.set("fontColor","#000000");this.set("fontFamily","Roboto,Arial,sans-serif");this.set("fontSize",12);this.set("strokeColor","#ffffff");this.set("strokeWeight",4);this.set("zIndex",1E3);this.setValues(a)}window.MapLabel=d; -d.prototype.changed=function(a){switch(a){case "fontFamily":case "fontSize":case "fontColor":case "strokeWeight":case "strokeColor":case "text":h(this);case "align":case "maxZoom":case "minZoom":case "position":return this.b()}}; -function h(a){var b=a.a;if(b){var f=b.style;f.position="absolute";f.zIndex=a.get("zIndex");var c=b.getContext("2d");c.font=a.get("fontSize")+"px "+a.get("fontFamily");var e=Number(a.get("strokeWeight")),g=a.get("text");b.width=Math.ceil(c.measureText(g).width+2*e);b.height=Math.ceil(parseInt(a.get("fontSize"),10)+2*e);1f?"hidden":""):b=""}a.visibility=b}}};d.prototype.draw=d.prototype.b;d.prototype.onRemove=function(){var a=this.a;a&&a.parentNode&&a.parentNode.removeChild(a)};d.prototype.onRemove=d.prototype.onRemove; +MapLabel=function(a){if(!MapLabel.prototype.setValues)for(var b in google.maps.OverlayView.prototype)MapLabel.prototype.hasOwnProperty(b)||(MapLabel.prototype[b]=google.maps.OverlayView.prototype[b]);this.set("align","center");this.set("fontColor","#000000");this.set("fontFamily","Roboto,Arial,sans-serif");this.set("fontSize",12);this.set("strokeColor","#ffffff");this.set("strokeWeight",4);this.set("zIndex",1E3);this.setValues(a)};window.MapLabel=MapLabel; +MapLabel.prototype.changed=function(a){switch(a){case "fontFamily":case "fontSize":case "fontColor":case "strokeWeight":case "strokeColor":case "text":g(this);case "align":case "maxZoom":case "minZoom":case "position":return this.draw()}}; +function g(a){var b=a.a;if(b){var e=b.style;e.position="absolute";e.zIndex=a.get("zIndex");var c=b.getContext("2d");c.font=a.get("fontSize")+"px "+a.get("fontFamily");var d=Number(a.get("strokeWeight")),f=a.get("text");b.width=Math.ceil(c.measureText(f).width+2*d);b.height=Math.ceil(parseInt(a.get("fontSize"),10)+2*d);1e?"hidden":""):b=""}a.visibility=b}}};MapLabel.prototype.draw=MapLabel.prototype.draw;MapLabel.prototype.onRemove=function(){var a=this.a;a&&a.parentNode&&a.parentNode.removeChild(a)};MapLabel.prototype.onRemove=MapLabel.prototype.onRemove; diff --git a/src/maplabel.js b/src/maplabel.js index 1e62a29..1e51847 100755 --- a/src/maplabel.js +++ b/src/maplabel.js @@ -1,3 +1,8 @@ +// ==ClosureCompiler== +// @output_file_name maplabels-compiled.js +// @compilation_level ADVANCED_OPTIMIZATIONS +// @externs_url https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/maps/google_maps_api_v3.js +// ==/ClosureCompiler== /** * @license * @@ -29,7 +34,7 @@ * @extends google.maps.OverlayView * @param {Object.=} opt_options Optional properties to set. */ -function MapLabel(opt_options) { +MapLabel = function(opt_options) { if (!MapLabel.prototype.setValues) { for (var property in google.maps.OverlayView.prototype) { if(!MapLabel.prototype.hasOwnProperty(property)) {