将Google Maps JS API ImageMapType剪辑为多边形 [英] Clip Google Maps JS API ImageMapType to a polygon
问题描述
如何将Google地图中的MapType剪辑为任意多边形。例如,如果我有一个覆盖大面积的自定义
this.polygon =多边形; this.map = map;} ClipMapType.prototype.getTile = function(coord,zoom,ownerDocument){var map = this.map; var scale = Math.pow(2,zoom); if(coord.y< 0 || coord.y> = scale)return ownerDocument.createElement('div'); var tileX =((coord.x%scale)+ scale)%scale; var tileY = coord.y; //你的网址格式在var url =https://khms0.google.com/kh/v=694&x=+ tileX +& y =+ tileY +& z =+ zoom; var image = new Image(); image.src = url; var canvas = ownerDocument.createElement('canvas'); canvas.width = this.tileSize.width; canvas.height = this.tileSize.height; var context = canvas.getContext('2d'); var xdif = coord.x * this.tileSize.width; var ydif = coord.y * this.tileSize.height; var ring = this.polygon.getArray()[0]; var points = ring.getArray()。map(function(x){var worldPoint = map.getProjection()。fromLatLngToPoint(x); return new google.maps.Point((worldPoint.x)* scale - xdif,(worldPoint .y)* scale - ydif);}); image.onload = function(){context.beginPath(); context.moveTo(points [0] .x,points [0] .y); var count = points.length; for(var i = 0; i< count; i ++){context.lineTo(points [i] .x,points [i] .y); } context.lineTo(points [count - 1] .x,points [count - 1] .y); context.clip(); context.drawImage(image,0,0); context.closePath(); }; return map;};函数initMap(){var map = new google.maps.Map(document.getElementById('map'),{zoom:4,center:{lat:15,lng:15}}); var polygon = new google.maps.Data.Polygon([[{lat:0,lng:0},{lat:30,lng:30},{lat:0,lng:30}]]); var mapType = new ClipMapType(polygon,map); map.overlayMapTypes.insertAt(0,mapType);}
html,body {height:100%;保证金:0; padding:0;}#map {height:100%;}
< div id =map>< / div>< script async defer src =https://maps.googleapis.com/maps/api/js?callback=initMap>< /脚本>
工作原理
基本上
ClipMapType
class是一个MapType接口。调用此接口的 getTile
方法,使用瓦片坐标和缩放级别为每个瓦片获取瓦片。 ClipMapType
创建一个画布元素作为一个贴图,并将贴图裁剪到多边形的内部。如果性能很重要,可以进行优化以加快工作速度。 免责声明
通过黑客入侵URL来使用Google磁贴服务器可能违反了Google地图服务条款。我用它来演示,不建议在生产中使用它。我的回答是试图让你洞悉你创建自己的解决方案。
How can I clip a MapType in Google Maps to an arbitrary polygon. For example, if I have a custom ImageMapType that covers a large area (i.e. all the world), but I want to show it only inside a given polygon (i.e. one country).
Is there a way to clip the ImageMapType to a given polygon, or to implement a custom MapType to achieve this behaviour? It should allow for zooming and panning normally.
The rest of the map should stay the same, and there would be a MapType covering only a specific area. Therefore, it is not possible to simply overlay a polygon to cover the areas outside the polygon to display just what is needed.
Like so:
Server-side clipping is not an option.
I have written the code for an overlay map type that does what you want. Be sure to test in your target browsers. Fiddle
function ClipMapType(polygon, map) {
this.tileSize = new google.maps.Size(256, 256);
this.polygon = polygon;
this.map = map;
}
ClipMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
var map = this.map;
var scale = Math.pow(2, zoom);
if (coord.y < 0 || coord.y >= scale) return ownerDocument.createElement('div');
var tileX = ((coord.x % scale) + scale) % scale;
var tileY = coord.y;
// Your url pattern below
var url = "https://khms0.google.com/kh/v=694&x=" + tileX + "&y=" + tileY + "&z=" + zoom;
var image = new Image();
image.src = url;
var canvas = ownerDocument.createElement('canvas');
canvas.width = this.tileSize.width;
canvas.height = this.tileSize.height;
var context = canvas.getContext('2d');
var xdif = coord.x * this.tileSize.width;
var ydif = coord.y * this.tileSize.height;
var ring = this.polygon.getArray()[0];
var points = ring.getArray().map(function(x) {
var worldPoint = map.getProjection().fromLatLngToPoint(x);
return new google.maps.Point((worldPoint.x) * scale - xdif, (worldPoint.y) * scale - ydif);
});
image.onload = function() {
context.beginPath();
context.moveTo(points[0].x, points[0].y);
var count = points.length;
for (var i = 0; i < count; i++) {
context.lineTo(points[i].x, points[i].y);
}
context.lineTo(points[count - 1].x, points[count - 1].y);
context.clip();
context.drawImage(image, 0, 0);
context.closePath();
};
return canvas;
};
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {
lat: 15,
lng: 15
}
});
var polygon = new google.maps.Data.Polygon([
[{
lat: 0,
lng: 0
}, {
lat: 30,
lng: 30
}, {
lat: 0,
lng: 30
}]
]);
var mapType = new ClipMapType(polygon, map);
map.overlayMapTypes.insertAt(0, mapType);
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
<div id="map"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
How it works
Basically ClipMapType
class is a MapType interface. getTile
method of this interface is called with tile coordinates and zoom level to get tile for every tile. ClipMapType
creates a canvas element to act as a tile and draws the tile image clipped to inside of the polygon. If performance is important, it can be optimized to work faster.
Disclaimer
Usage of Google tile servers by hacking the URL, probably violates Google Maps Terms of Service. I used it for demonstration and don't recommend using it in production. My answer is an attempt to give you an insight for you to create your own solution.
这篇关于将Google Maps JS API ImageMapType剪辑为多边形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!