google-maps - 将自定义背景图像添加到谷歌地图中的可拖动多边形?
问题描述
我想在谷歌地图中向我的可拖动多边形添加自定义背景图像。我已经使用 Polygon 类制作了一个可以旋转的可拖动多边形。我想给它添加背景图片。我读过其他帖子,他们提到了“自定义叠加”,但这是地图上的固定图像,不支持拖动/旋转。我该怎么做呢?
更新:我用我的图像创建了一个自定义图层,并将其添加到地图中,其坐标与多边形相同。每当我的多边形边界发生变化时,我也会更新我的自定义层,使它们总是重叠。但是,如 gif 中所示,https: //imgur.com/3oaktIY ,多边形和图像不同步并且存在延迟。
还有其他方法吗?
解决方案
没有在网上找到解决方案,所以我自己用这个工作演示解决了这个问题:draggable polygon with image。我结合了自定义叠加层和法线多边形库。您可以单击多边形旋转并拖动它。
plz see jsfiddle
代码片段:
// This example adds hide() and show() methods to a custom overlay's prototype.
// These methods toggle the visibility of the container <div>.
// Additionally, we add a toggleDOM() method, which attaches or detaches the
// overlay to or from the map.
var overlay;
USGSOverlay.prototype = new google.maps.OverlayView();
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 20,
center: {
lat: 33.678,
lng: -116.243
},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
var rectangle = new google.maps.Rectangle({
strokeColor: 'red',
strokeOpacity: 0,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0,
map: map,
bounds: calcBounds(map.getCenter(), new google.maps.Size(2.7, 20))
});
var rectPoly = createPolygonFromRectangle(rectangle); //create a polygom from a rectangle
rectPoly.addListener('click', function(e) {
rotatePolygon(rectPoly, 10);
rectPoly.rotation += 10;
console.log(rectPoly.rotation)
overlay.div_.style.transform = 'rotate(' + rectPoly.rotation + 'deg)';
});
rectPoly.addListener('drag', function() {
console.log('Drag end!');
let bounds = new google.maps.LatLngBounds();
var i;
// The Bermuda Triangle
let polygonCoords = rectPoly.getPath().getArray();
for (i = 0; i < polygonCoords.length; i++) {
bounds.extend(polygonCoords[i]);
}
// The Center of the Bermuda Triangle - (25.3939245, -72.473816)
center = bounds.getCenter();
overlay.bounds_ = calcBounds(center, new google.maps.Size(2.7, 20))
overlay.draw();
});
function calcBounds(center, size) {
var n = google.maps.geometry.spherical.computeOffset(center, size.height / 2, 0).lat(),
s = google.maps.geometry.spherical.computeOffset(center, size.height / 2, 180).lat(),
e = google.maps.geometry.spherical.computeOffset(center, size.width / 2, 90).lng(),
w = google.maps.geometry.spherical.computeOffset(center, size.width / 2, 270).lng();
return new google.maps.LatLngBounds(new google.maps.LatLng(s, w),
new google.maps.LatLng(n, e))
}
var srcImage = 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/talkeetna.png';
overlay = new USGSOverlay(rectangle.bounds, srcImage, map, rectPoly);
// The custom USGSOverlay object contains the USGS image,
// the bounds of the image, and a reference to the map.
}
/** @constructor */
function USGSOverlay(bounds, image, map, rectPoly) {
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
this.rectPoly_ = rectPoly
// Define a property to hold the image's div. We'll
// actually create this div upon receipt of the onAdd()
// method so we'll leave it null for now.
this.div_ = null;
// Explicitly call setMap on this overlay
this.setMap(map);
}
/**
* onAdd is called when the map's panes are ready and the overlay has been
* added to the map.
*/
USGSOverlay.prototype.onAdd = function() {
var div = document.createElement('div');
div.style.border = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
rectPoly = this.rectPoly_;
// Create the img element and attach it to the div.
var img = document.createElement('img');
img.src = this.image_;
img.style.width = '100%';
img.style.height = '100%';
div.appendChild(img);
this.div_ = div;
// Add the element to the "overlayImage" pane.
var panes = this.getPanes();
panes.overlayImage.appendChild(this.div_);
};
USGSOverlay.prototype.draw = function() {
// We use the south-west and north-east
// coordinates of the overlay to peg it to the correct position and size.
// To do this, we need to retrieve the projection from the overlay.
var overlayProjection = this.getProjection();
// Retrieve the south-west and north-east coordinates of this overlay
// in LatLngs and convert them to pixel coordinates.
// We'll use these coordinates to resize the div.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's div to fit the indicated dimensions.
var div = this.div_;
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
};
USGSOverlay.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
};
// Set the visibility to 'hidden' or 'visible'.
function createPolygonFromRectangle(rectangle) {
var map = rectangle.getMap();
var coords = [{
lat: rectangle.getBounds().getNorthEast().lat(),
lng: rectangle.getBounds().getNorthEast().lng()
},
{
lat: rectangle.getBounds().getNorthEast().lat(),
lng: rectangle.getBounds().getSouthWest().lng()
},
{
lat: rectangle.getBounds().getSouthWest().lat(),
lng: rectangle.getBounds().getSouthWest().lng()
},
{
lat: rectangle.getBounds().getSouthWest().lat(),
lng: rectangle.getBounds().getNorthEast().lng()
}
];
// Construct the polygon.
var rectPoly = new google.maps.Polygon({
path: coords,
draggable: true,
rotation: 0
});
var properties = ["strokeColor", "strokeOpacity", "strokeWeight", "fillOpacity", "fillColor"];
//inherit rectangle properties
var options = {};
properties.forEach(function(property) {
if (rectangle.hasOwnProperty(property)) {
options[property] = rectangle[property];
}
});
rectPoly.setOptions(options);
rectangle.setMap(null);
rectPoly.setMap(map);
return rectPoly;
}
function rotatePolygon(polygon, angle) {
var map = polygon.getMap();
var prj = map.getProjection();
var bounds = new google.maps.LatLngBounds();
var i;
// The Bermuda Triangle
var polygonCoords = polygon.getPath().getArray();
for (i = 0; i < polygonCoords.length; i++) {
bounds.extend(polygonCoords[i]);
}
// The Center of the Bermuda Triangle - (25.3939245, -72.473816)
console.log(bounds.getCenter());
var origin = prj.fromLatLngToPoint(bounds.getCenter()); //rotate around first point
//var origin2 = prj.fromLatLngToPoint(polygon.getPath().getAt(1)); //rotate around first point
var coords = polygon.getPath().getArray().map(function(latLng) {
var point = prj.fromLatLngToPoint(latLng);
var rotatedLatLng = prj.fromPointToLatLng(rotatePoint(point, origin, angle));
return {
lat: rotatedLatLng.lat(),
lng: rotatedLatLng.lng()
};
});
polygon.setPath(coords);
}
function rotatePoint(point, origin, angle) {
var angleRad = angle * Math.PI / 180.0;
return {
x: Math.cos(angleRad) * (point.x - origin.x) - Math.sin(angleRad) * (point.y - origin.y) + origin.x,
y: Math.sin(angleRad) * (point.x - origin.x) + Math.cos(angleRad) * (point.y - origin.y) + origin.y
};
}
google.maps.event.addDomListener(window, 'load', initMap);
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: 'Roboto', 'sans-serif';
line-height: 30px;
padding-left: 10px;
}
<!-- Add an input button to initiate the toggle method on the overlay. -->
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>