ol3-google-maps
Version:
OpenLayers 3 Google Maps integration library
491 lines (413 loc) • 15.1 kB
JavaScript
goog.provide('olgm.gm');
goog.require('ol.geom.LineString');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.geom.MultiLineString');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.MultiPoint');
goog.require('ol.proj');
goog.require('ol.style.Circle');
goog.require('ol.style.Icon');
goog.require('ol.style.RegularShape');
goog.require('olgm');
goog.require('olgm.asserts');
goog.require('olgm.gm.MapLabel');
goog.require('olgm.gm.MapIcon');
// === Data ===
/**
* Create a Google Maps feature using an OpenLayers one.
* @param {ol.Feature} feature feature to create
* @param {ol.Map=} opt_ol3map For reprojection purpose. If undefined, then
* `EPSG:3857` is used.
* @return {google.maps.Data.Feature} google Feature
*/
olgm.gm.createFeature = function(feature, opt_ol3map) {
var geometry = /** @type {ol.geom.Geometry} */ (feature.getGeometry());
var gmapGeometry = olgm.gm.createFeatureGeometry(geometry, opt_ol3map);
return new google.maps.Data.Feature({
geometry: gmapGeometry
});
};
/**
* Create a Google Maps geometry using an OpenLayers one.
* @param {ol.geom.Geometry} geometry geometry to create
* @param {ol.Map=} opt_ol3map For reprojection purpose. If undefined, then
* `EPSG:3857` is used.
* @return {google.maps.Data.Geometry|google.maps.LatLng|google.maps.LatLng}
* google Geometry or LatLng
*/
olgm.gm.createFeatureGeometry = function(geometry, opt_ol3map) {
var gmapGeometry = null;
if (geometry instanceof ol.geom.Point) {
gmapGeometry = olgm.gm.createLatLng(geometry, opt_ol3map);
} else if (geometry instanceof ol.geom.MultiPoint ||
geometry instanceof ol.geom.LineString ||
geometry instanceof ol.geom.MultiLineString ||
geometry instanceof ol.geom.Polygon ||
geometry instanceof ol.geom.MultiPolygon) {
gmapGeometry = olgm.gm.createGeometry(geometry, opt_ol3map);
}
olgm.asserts.assert(gmapGeometry !== null,
'Expected geometry to be ol.geom.Point|MultiPoint|LineString|MultiLineString|Polygon|MultiPolygon');
return gmapGeometry;
};
/**
* Create a Google Maps LatLng object using an OpenLayers Point.
* @param {ol.geom.Point|ol.Coordinate} object coordinate to create
* @param {ol.Map=} opt_ol3map For reprojection purpose. If undefined, then
* `EPSG:3857` is used.
* @return {google.maps.LatLng} google LatLng object
*/
olgm.gm.createLatLng = function(object, opt_ol3map) {
var inProj = (opt_ol3map !== undefined) ?
opt_ol3map.getView().getProjection() : 'EPSG:3857';
var coordinates;
if (object instanceof ol.geom.Point) {
coordinates = object.getCoordinates();
} else {
coordinates = object;
}
var lonLatCoords = ol.proj.transform(coordinates, inProj, 'EPSG:4326');
return new google.maps.LatLng(lonLatCoords[1], lonLatCoords[0]);
};
/**
* Create a Google Maps LineString or Polygon object using an OpenLayers one.
* @param {ol.geom.MultiPoint|ol.geom.LineString|ol.geom.Polygon|ol.geom.MultiLineString|ol.geom.MultiPolygon} geometry geometry to create
* @param {ol.Map=} opt_ol3map For reprojection purpose. If undefined, then
* `EPSG:3857` is used.
* @return {google.maps.Data.MultiPoint|google.maps.Data.LineString|google.maps.Data.MultiLineString|google.maps.Data.Polygon|google.maps.Data.MultiPolygon} google
* LineString or Polygon
*/
olgm.gm.createGeometry = function(geometry, opt_ol3map) {
var inProj = (opt_ol3map !== undefined) ?
opt_ol3map.getView().getProjection() : 'EPSG:3857';
var gmapGeometry = null;
if (geometry instanceof ol.geom.LineString) {
var lineStringlatLngs = olgm.gm.genLatLngs_(
geometry.getCoordinates(),
inProj
);
gmapGeometry = new google.maps.Data.LineString(lineStringlatLngs);
} else if (geometry instanceof ol.geom.Polygon) {
var polygonlatLngs = olgm.gm.genLatLngs_(
geometry.getCoordinates()[0],
inProj
);
gmapGeometry = new google.maps.Data.Polygon([polygonlatLngs]);
} else if (geometry instanceof ol.geom.MultiLineString) {
var multiLineStringlatLngs = olgm.gm.genMultiLatLngs_(
geometry.getCoordinates(),
inProj
);
gmapGeometry = new google.maps.Data.MultiLineString(multiLineStringlatLngs);
} else if (geometry instanceof ol.geom.MultiPolygon) {
var multiPolygons = olgm.gm.genMultiPolygon_(
geometry.getPolygons(),
inProj
);
gmapGeometry = new google.maps.Data.MultiPolygon(multiPolygons);
} else if (geometry instanceof ol.geom.MultiPoint) {
var multiPoints = olgm.gm.genLatLngs_(
geometry.getCoordinates(),
inProj
);
gmapGeometry = new google.maps.Data.MultiPoint(multiPoints);
}
return gmapGeometry;
};
/**
* Convert a list of OpenLayers coordinates to a list of google maps LatLng.
*
* @param {Array.<ol.Coordinate>} coordinates List of coordinate
* @param {ol.ProjectionLike=} opt_inProj Projection of the features.
* @return {Array.<google.maps.LatLng>} List of lat lng.
* @private
*/
olgm.gm.genLatLngs_ = function(coordinates, opt_inProj) {
var inProj = opt_inProj || 'EPSG:3857';
var latLngs = [];
var lonLatCoords;
for (var i = 0, ii = coordinates.length; i < ii; i++) {
lonLatCoords = ol.proj.transform(coordinates[i], inProj, 'EPSG:4326');
latLngs.push(new google.maps.LatLng(lonLatCoords[1], lonLatCoords[0]));
}
return latLngs;
};
/**
* Convert a list of OpenLayers multi-coordinates to a list of multi
* google maps LatLng.
*
* @param {Array.<Array.<ol.Coordinate>>} coordinates List of multi coordinate
* @param {ol.ProjectionLike=} opt_inProj Projection of the features.
* @return {Array.<Array.<google.maps.LatLng>>} List of multi lat lng.
* @private
*/
olgm.gm.genMultiLatLngs_ = function(coordinates, opt_inProj) {
var inProj = opt_inProj || 'EPSG:3857';
var multiLatLngs = [];
for (var i = 0, len = coordinates.length; i < len; i++) {
multiLatLngs.push(olgm.gm.genLatLngs_(coordinates[i], inProj));
}
return multiLatLngs;
};
/**
* Convert a list of OpenLayers polygons to a list of google maps polygons.
*
* @param {Array.<ol.geom.Polygon>} polygons List of polygons.
* @param {ol.ProjectionLike=} opt_inProj Projection of the features.
* @return {Array.<google.maps.Data.Polygon>} List of polygons.
* @private
*/
olgm.gm.genMultiPolygon_ = function(polygons, opt_inProj) {
var mutliPolygons = [];
for (var i = 0, len = polygons.length; i < len; i++) {
var latLgns = olgm.gm.genMultiLatLngs_(polygons[i].getCoordinates(), opt_inProj);
var multiPolygon = new google.maps.Data.Polygon(latLgns);
mutliPolygons.push(multiPolygon);
}
return mutliPolygons;
};
// === Style ===
/**
* Create a Google Maps data style options from an OpenLayers object.
* @param {ol.style.Style|ol.StyleFunction|ol.layer.Vector|ol.Feature}
* object style object
* @param {olgmx.gm.MapIconOptions} mapIconOptions map icon options
* @param {number=} opt_index index for the object
* @return {?google.maps.Data.StyleOptions} google style options
*/
olgm.gm.createStyle = function(object, mapIconOptions, opt_index) {
var gmStyle = null;
var style = olgm.getStyleOf(object);
if (style) {
gmStyle = olgm.gm.createStyleInternal(style, mapIconOptions, opt_index);
}
return gmStyle;
};
/**
* Create a Google Maps data style options from an OpenLayers style object.
* @param {ol.style.Style} style style object
* @param {olgmx.gm.MapIconOptions} mapIconOptions map icon options
* @param {number=} opt_index index for the object
* @return {google.maps.Data.StyleOptions} google style options
*/
olgm.gm.createStyleInternal = function(style, mapIconOptions, opt_index) {
var gmStyle = /** @type {google.maps.Data.StyleOptions} */ ({});
// strokeColor
// strokeOpacity
// strokeWeight
var stroke = style.getStroke();
if (stroke) {
var strokeColor = stroke.getColor();
if (strokeColor) {
gmStyle['strokeColor'] = olgm.getColor(strokeColor);
var strokeOpacity = olgm.getColorOpacity(strokeColor);
if (strokeOpacity !== null) {
gmStyle['strokeOpacity'] = strokeOpacity;
}
}
var strokeWidth = stroke.getWidth();
if (strokeWidth) {
gmStyle['strokeWeight'] = strokeWidth;
}
}
// fillColor
// fillOpacity
var fill = style.getFill();
if (fill) {
var fillColor = fill.getColor();
if (fillColor) {
gmStyle['fillColor'] = olgm.getColor(fillColor);
var fillOpacity = olgm.getColorOpacity(fillColor);
if (fillOpacity !== null) {
gmStyle['fillOpacity'] = fillOpacity;
}
}
}
var image = style.getImage();
if (image) {
var gmIcon = {};
var gmSymbol = {};
var useCanvas = mapIconOptions.useCanvas !== undefined ?
mapIconOptions.useCanvas : false;
if (image instanceof ol.style.Circle ||
image instanceof ol.style.RegularShape) {
// --- ol.style.Circle ---
if (image instanceof ol.style.Circle) {
gmSymbol['path'] = google.maps.SymbolPath.CIRCLE;
} else if (image instanceof ol.style.RegularShape) {
// Google Maps support SVG Paths. We'll build one manually.
var path = 'M ';
// Get a few variables from the image style;
var nbPoints = image.getPoints();
var outerRadius = image.getRadius();
var innerRadius = image.getRadius2() !== undefined ?
image.getRadius2() : image.getRadius();
var size = 0.1;
var rotation = image.getRotation() + image.getAngle();
if (innerRadius == 0 && image.getRadius2() === undefined) {
nbPoints = nbPoints / 2;
}
if (innerRadius !== outerRadius) {
nbPoints = nbPoints * 2;
}
for (var i = 0; i < nbPoints; i++) {
var radius = i % 2 == 0 ? outerRadius : innerRadius;
var angle = (i * 2 * Math.PI / nbPoints) - (Math.PI / 2) + rotation;
var x = size * radius * Math.cos(angle);
var y = size * radius * Math.sin(angle);
path += x + ',' + y + ' ';
}
// Close the path
path += 'Z';
gmSymbol['path'] = path;
}
var imageStroke = image.getStroke();
if (imageStroke) {
var imageStrokeColor = imageStroke.getColor();
if (imageStrokeColor) {
gmSymbol['strokeColor'] = olgm.getColor(imageStrokeColor);
}
gmSymbol['strokeWeight'] = imageStroke.getWidth();
}
var imageFill = image.getFill();
if (imageFill) {
var imageFillColor = imageFill.getColor();
if (imageFillColor) {
gmSymbol['fillColor'] = olgm.getColor(imageFillColor);
var imageFillOpacity = olgm.getColorOpacity(imageFillColor);
if (imageFillOpacity !== null) {
gmSymbol['fillOpacity'] = imageFillOpacity;
} else {
// Google Maps default fill opacity of images is `0`. In ol3,
// it's `1`.
gmSymbol['fillOpacity'] = 1;
}
}
}
var imageRadius = image.getRadius();
if (imageRadius) {
gmSymbol['scale'] = imageRadius;
}
} else if (image instanceof ol.style.Icon && !useCanvas) {
// --- ol.style.Icon ---
var imageSrc = image.getSrc();
if (imageSrc) {
gmSymbol['url'] = imageSrc;
}
var imageScale = image.getScale();
var imageAnchor = image.getAnchor();
if (imageAnchor) {
if (imageScale !== undefined) {
gmSymbol['anchor'] = new google.maps.Point(
imageAnchor[0] * imageScale, imageAnchor[1] * imageScale);
} else {
gmSymbol['anchor'] = new google.maps.Point(
imageAnchor[0], imageAnchor[1]);
}
}
var imageOrigin = image.getOrigin();
if (imageOrigin) {
gmSymbol['origin'] = new google.maps.Point(
imageOrigin[0], imageOrigin[1]);
}
var imageSize = image.getSize();
if (imageSize) {
gmSymbol['size'] = new google.maps.Size(imageSize[0], imageSize[1]);
if (imageScale !== undefined) {
gmSymbol['scaledSize'] = new google.maps.Size(
imageSize[0] * imageScale, imageSize[1] * imageScale);
}
}
// NOTE - google.maps.Icon does not support opacity
}
if (Object.keys(gmIcon).length) {
gmStyle['icon'] = /** @type {google.maps.Icon} */ (gmIcon);
} else if (Object.keys(gmSymbol).length) {
gmStyle['icon'] = /** @type {google.maps.Symbol} */ (gmSymbol);
}
}
// if, at this very last point, there aren't any style options that have
// been set, then tell Google Maps to render the feature invisible because
// we're dealing with an empty `ol.style.Style` object.
if (Object.keys(/** @type {!Object} */ (gmStyle)).length === 0) {
gmStyle['visible'] = false;
} else if (opt_index !== undefined) {
var zIndex = opt_index * 2;
gmStyle['zIndex'] = zIndex;
}
return gmStyle;
};
// === Label ===
/**
* Create a MapLabel object from a text style and Lat/Lng location.
* @param {ol.style.Text} textStyle style for the text
* @param {google.maps.LatLng} latLng position of the label
* @param {number} index index for the label
* @return {olgm.gm.MapLabel} map label
*/
olgm.gm.createLabel = function(textStyle, latLng, index) {
var labelOptions = {
align: 'center',
position: latLng,
zIndex: index * 2 + 1
};
var text = textStyle.getText();
if (text) {
labelOptions['text'] = text;
}
var font = textStyle.getFont();
if (font) {
labelOptions['font'] = font;
}
var fill = textStyle.getFill();
if (fill) {
var fillColor = fill.getColor();
if (fillColor) {
labelOptions['fontColor'] = fillColor;
}
}
var stroke = textStyle.getStroke();
if (stroke) {
var strokeColor = stroke.getColor();
if (strokeColor) {
labelOptions['strokeColor'] = strokeColor;
}
var strokeWidth = stroke.getWidth();
if (strokeWidth) {
labelOptions['strokeWeight'] = strokeWidth;
}
}
var offsetX = textStyle.getOffsetX();
if (offsetX) {
labelOptions['offsetX'] = offsetX;
}
var offsetY = textStyle.getOffsetY();
if (offsetY) {
labelOptions['offsetY'] = offsetY;
}
var textAlign = textStyle.getTextAlign();
if (textAlign) {
labelOptions['textAlign'] = textAlign;
}
var textBaseline = textStyle.getTextBaseline();
if (textBaseline) {
labelOptions['textBaseline'] = textBaseline;
}
return new olgm.gm.MapLabel(labelOptions);
};
/**
* Create a mapIcon object from an image style and Lat/Lng location
* @param {ol.style.Icon} iconStyle style for the icon
* @param {google.maps.LatLng} latLng position of the label
* @param {number} index index for the label
* @return {olgm.gm.MapIcon} map label
*/
olgm.gm.createMapIcon = function(iconStyle, latLng, index) {
var iconOptions = {
align: 'center',
position: latLng,
zIndex: index * 2 + 1
};
return new olgm.gm.MapIcon(iconStyle, iconOptions);
};