将Google Maps JS API ImageMapType剪辑为多边形

如何将Google地图中的MapType剪切为任意多边形。 例如,如果我有一个自定义ImageMapType覆盖大面积(即所有的世界),但我只想显示在一个给定的多边形内(即一个国家)。

有没有办法将ImageMapType剪辑到给定的多边形,或者实现一个自定义的MapType来实现这种行为? 它应该允许正常缩放和平移。

地图的其余部分应该保持不变,并且将会有一个只覆盖特定区域的MapType。 因此,不可能简单地覆盖多边形来覆盖多边形之外的区域以显示所需要的内容。

像这样:

澳大利亚地图与南澳大利亚剪辑覆盖

服务器端裁剪不是一个选项。

我已经写了一个覆盖地图types的代码,做你想做的。 一定要testing你的目标浏览器。 小提琴

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> 

你需要坚持Google地图吗? 我知道Openlayers 3为这类东西提供了更好的支持。 例如,看看这个 。

如果您真的必须使用Google地图,我build议您实施自己的MapType并使用MapTiler自行生成覆盖多边形区域所需的图块 。 (MapTiler也为您生成一个示例Google Maps实现,所以不要太难。)

你可以在你的地图上放置一个DIV,绝对定位和高Z指数。 然后,将多边形掩码应用于该DIV,如下所示: -webkit-clip-path: polygon(0 0, 0 100%, 100% 0);

您可以使用HTML5中的canvas.toDataURI()选项来获取ImageMapType getTileUrl()所需的url。

 getTileUrl: function(coord, zoom) { var normalizedCoord = getNormalizedCoord(coord, zoom); if (!normalizedCoord) { return null; } var bound = Math.pow(2, zoom); // reset and clip the preloaded image in a hidden canvas to your required height and width clippedImage = canvas.toDataURL(); return clippedImage; } 
  • 要设置图像大小并调整其大小,请使用canvas.drawImage()
  • 要将图像从canvas剪辑到任何非矩形维度,请使用canvas clip() 示例代码 。

我看到你不能使用正常的遮罩策略,因为你需要能够看到底层。 我可以build议SVG的更完整的剪辑套件? 看到这里 。

浏览器的兼容性不错,但不是很好,但是你完全可以完成你在这里尝试的东西(除非你需要平移/缩放地图,然后你被搞砸了,直到地图实现这样的事情)。

你可以使用svg clippath,与foreignobject svg标签一起在svg中放置一个html文档,然后将其剪切到所需的形状,如codepen.io/yoksel/pen/oggRwR的代码:

 @import url(http://fonts.googleapis.com/css?family=Arvo:700); .svg { display: block; width: 853px; height: 480px; margin: 2em auto; } text { font: bold 5.3em/1 Arvo, Arial sans-serif; } 
 <svg class="svg"> <clippath id="cp-circle"> <circle r="180" cx="50%" cy="42%"></circle> <text text-anchor="middle" x="50%" y="98%" >Soldier Of Fortune</text> </clippath> <g clip-path="url(#cp-circle)"> <foreignObject width="853" x="0" y="0" height="480"> <body xmlns="http://www.w3.org/1999/xhtml"> <iframe width="853" height="480" src="//www.youtube.com/embed/RKrNdxiBW3Y" frameborder="0" allowfullscreen></iframe> </body> </foreignObject> </g> </svg>