Skip to content

Instantly share code, notes, and snippets.

@kieraneglin
Created June 8, 2017 01:40
Show Gist options
  • Save kieraneglin/231ddf57d26206cf917fe61385290705 to your computer and use it in GitHub Desktop.
Save kieraneglin/231ddf57d26206cf917fe61385290705 to your computer and use it in GitHub Desktop.
js-map-label for Node

Author

Original author is rcknr. I manually transpiled to use JS classes

Usage

See here

Otherwise, put this gist into a file called map-label.js and include with import MapLabel from './map-label'. From there, follow the instructions outlined above.

/**
* @license
*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Map Label.
*
* @author Luke Mahe (lukem@google.com),
* Chris Broadfoot (cbro@google.com)
*/
/**
* Creates a new Map Label
* @constructor
* @extends google.maps.OverlayView
* @param {Object.<string, *>=} opt_options Optional properties to set.
*/
class MapLabel {
constructor(opt_options) {
if (!MapLabel.prototype.setValues) {
for (const property in google.maps.OverlayView.prototype) {
if(!MapLabel.prototype.hasOwnProperty(property)) {
MapLabel.prototype[property] = google.maps.OverlayView.prototype[property];
}
}
}
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(opt_options);
}
/** @inheritDoc */
changed(prop) {
switch (prop) {
case 'fontFamily':
case 'fontSize':
case 'fontColor':
case 'strokeWeight':
case 'strokeColor':
case 'text':
this.drawCanvas_();
break;
case 'align':
case 'maxZoom':
case 'minZoom':
case 'position':
return this.draw();
}
}
/**
* Draws the label to the canvas 2d context.
* @private
*/
drawCanvas_() {
const canvas = this.canvas_;
if (!canvas) return;
const style = canvas.style;
style.position = 'absolute';
style.zIndex = /** @type number */(this.get('zIndex'));
const ctx = canvas.getContext('2d');
ctx.font = `${this.get('fontSize')}px ${this.get('fontFamily')}`;
const strokeWeight = Number(this.get('strokeWeight'));
const text = this.get('text');
const textMeasure = ctx.measureText(text);
canvas.width = Math.ceil(textMeasure.width + strokeWeight * 2);
canvas.height = Math.ceil(parseInt(this.get('fontSize'), 10) + 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;
ctx.strokeText(text, strokeWeight, strokeWeight);
}
ctx.fillText(text, strokeWeight, strokeWeight);
}
}
/**
* @inheritDoc
*/
onAdd() {
const canvas = this.canvas_ = document.createElement('canvas');
this.drawCanvas_();
const panes = this.getPanes();
if (panes) {
panes.overlayLayer.appendChild(canvas);
}
}
/**
* @inheritDoc
*/
draw() {
const projection = this.getProjection();
if (!projection) {
// The map projection is not ready yet so do nothing
return;
}
if (!this.canvas_) {
// onAdd has not been called yet.
return;
}
const latLng = /** @type {google.maps.LatLng} */ (this.get('position'));
if (!latLng) {
return;
}
const pos = projection.fromLatLngToDivPixel(latLng);
const style = this.canvas_.style;
style.top = `${pos.y}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.left = `${pos.x}px`;
style['margin-left'] = '1em';
style['margin-top'] = '-0.4em';
break;
default:
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_();
}
/**
* Get the visibility of the label.
* @private
* @return {string} blank string if visible, 'hidden' if invisible.
*/
getVisible_() {
const minZoom = /** @type number */(this.get('minZoom'));
const maxZoom = /** @type number */(this.get('maxZoom'));
if (minZoom === undefined && maxZoom === undefined) {
return '';
}
const map = this.getMap();
if (!map) {
return '';
}
const mapZoom = map.getZoom();
if (mapZoom < minZoom || mapZoom > maxZoom) {
return 'hidden';
}
return '';
}
/**
* @inheritDoc
*/
onRemove() {
const canvas = this.canvas_;
if (canvas && canvas.parentNode) {
canvas.parentNode.removeChild(canvas);
}
}
}
window.MapLabel = MapLabel;
export default MapLabel;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment