将Google Maps JS API ImageMapType剪辑为多边形 [英] Clip Google Maps JS API ImageMapType to a polygon

查看:301
本文介绍了将Google Maps JS API ImageMapType剪辑为多边形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆