Google 地图多边形:为相交的圆设置透明
Google map Polygon: Set transparent for circles intersecting
我遵循postChange map opacity outside circle of Google Maps JavaScript API v3,但我有多个圈子,有时它们是相交的。在相交处,它们是不透明的。如何将它们设置为透明?
谢谢。
// This example uses the Google Maps JavaScript API's Data layer
// to create a rectangular polygon with 2 holes in it.
const places = [
{
center: { "lat": 1.3512492664554796, "lng": 103.85072488875811 },
radius: 2000
},
{
center: { "lat": 1.3225896205754812, "lng": 103.86600275130694 },
radius: 2000
},
{
center:{ "lat": 1.3136655910729036, "lng": 103.88866205306475 },
radius: 2000
},
{
center: { "lat": 1.305427997082587, "lng": 103.83613367171709 },
radius: 2000
}
];
let map;
const mapDefault = {
};
function initMap() {
map = new google.maps.Map(document.getElementById('map'), mapDefault);
const bounds = new google.maps.LatLngBounds();
let pathsCircle = [];
places.forEach(place => {
bounds.extend(place.center);
pathsCircle.push(drawCircle(place.center, place.radius, 1));
});
map.fitBounds(bounds);
const worldCoords = [
new google.maps.LatLng(-85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 0)
];
new google.maps.Polygon({
paths: [worldCoords, ...pathsCircle],
strokeColor: '#fff',
strokeOpacity: 0,
strokeWeight: 0,
fillColor: '#000',
fillOpacity: 0.3,
map,
});
}
function drawCircle(point, radius, dir) {
}
这是我的代码。
为了避免 non-transparent 相交,需要将圆组合成一个多边形。
一种选择是使用 JSTS library 计算圆的并集。
var geometryFactory = new jsts.geom.GeometryFactory();
var poly1,poly2,polyunion;
var polys = [];
for (var i=0; i<pathsCircle.length; i++) {
if (i==0) {
poly1 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly1.normalize();
polys[i] = poly1;
} else {
poly2 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly2.normalize();
polys[i] = polys[i-1].union(poly2);
polys[i].normalize();
}
}
polys[i-1].normalize();
var boundary = polys[i-1].getBoundary();
var outputPath = jsts2googleMaps(boundary);
var jsts2googleMaps = function (geometry) {
var coordArray = geometry.getCoordinates();
GMcoords = [];
for (var i = 0; i < coordArray.length; i++) {
GMcoords.push(new google.maps.LatLng(coordArray[i].x, coordArray[i].y));
}
return GMcoords;
}
var array2JSTS = function(boundaries) {
var coordinates = [];
for (var i = 0; i < boundaries.length; i++) {
coordinates.push(new jsts.geom.Coordinate(
boundaries[i].lat, boundaries[i].lng));
}
return coordinates;
};
代码片段:
const places = [
{
center: { "lat": 1.3512492664554796, "lng": 103.85072488875811 },
radius: 2000
},
{
center: { "lat": 1.3225896205754812, "lng": 103.86600275130694 },
radius: 2000
},
{
center:{ "lat": 1.3136655910729036, "lng": 103.88866205306475 },
radius: 2000
},
{
center: { "lat": 1.305427997082587, "lng": 103.83613367171709 },
radius: 2000
}
];
let map;
const mapDefault = {
center: places[0].center,
zoom: 10,
minZoom: 1,
maxZoom: 19,
clickableIcons: false
};
function initMap() {
map = new google.maps.Map(document.getElementById('map'), mapDefault);
const bounds = new google.maps.LatLngBounds();
let pathsCircle = [];
places.forEach(place => {
bounds.extend(place.center);
pathsCircle.push(drawCircle(place.center, place.radius, 1));
});
map.fitBounds(bounds);
const worldCoords = [
new google.maps.LatLng(-85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 0)
];
var geometryFactory = new jsts.geom.GeometryFactory();
var poly1,poly2,polyunion;
var polys = [];
for (var i=0; i<pathsCircle.length; i++) {
if (i==0) {
poly1 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly1.normalize();
polys[i] = poly1;
} else {
poly2 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly2.normalize();
polys[i] = polys[i-1].union(poly2);
polys[i].normalize();
}
}
polys[i-1].normalize();
var boundary = polys[i-1].getBoundary();
var outputPath = jsts2googleMaps(boundary);
new google.maps.Polygon({
paths: [worldCoords, outputPath],
strokeColor: '#fff',
strokeOpacity: 0,
strokeWeight: 0,
fillColor: '#000',
fillOpacity: 0.3,
map,
});
}
function drawCircle(point, radius, dir) {
let d2r = Math.PI / 180; // degrees to radians
let r2d = 180 / Math.PI; // radians to degrees
let earthsradius = 6378137; // 6378137 is the radius of the earth in metters
let points = 128; // number of point to draw Circle
// find the raidus in lat/lon
let rlat = (radius / earthsradius) * r2d;
let rlng = rlat / Math.cos(point.lat * d2r);
let extp = [];
let start, end;
if (dir == 1) { // one extra here makes sure we connect the
start = 0; end = points + 1
} else {
start = points + 1; end = 0
}
for (let i = start; (dir == 1 ? i < end : i > end); i = i + dir) {
let theta = Math.PI * (i / (points / 2));
const ey = point.lng + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
const ex = point.lat + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push({
lat: ex,
lng: ey,
});
}
return extp;
}
var jsts2googleMaps = function (geometry) {
var coordArray = geometry.getCoordinates();
GMcoords = [];
for (var i = 0; i < coordArray.length; i++) {
GMcoords.push(new google.maps.LatLng(coordArray[i].x, coordArray[i].y));
}
return GMcoords;
}
var array2JSTS = function(boundaries) {
var coordinates = [];
for (var i = 0; i < boundaries.length; i++) {
coordinates.push(new jsts.geom.Coordinate(
boundaries[i].lat, boundaries[i].lng));
}
return coordinates;
};
/* 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;
}
<!DOCTYPE html>
<html>
<head>
<title>Data Layer: Polygon</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://cdn.jsdelivr.net/npm/jsts@2.8.1/dist/jsts.js"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="map"></div>
<!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&v=weekly&channel=2"
async
></script>
</body>
</html>
我遵循postChange map opacity outside circle of Google Maps JavaScript API v3,但我有多个圈子,有时它们是相交的。在相交处,它们是不透明的。如何将它们设置为透明?
谢谢。
// This example uses the Google Maps JavaScript API's Data layer
// to create a rectangular polygon with 2 holes in it.
const places = [
{
center: { "lat": 1.3512492664554796, "lng": 103.85072488875811 },
radius: 2000
},
{
center: { "lat": 1.3225896205754812, "lng": 103.86600275130694 },
radius: 2000
},
{
center:{ "lat": 1.3136655910729036, "lng": 103.88866205306475 },
radius: 2000
},
{
center: { "lat": 1.305427997082587, "lng": 103.83613367171709 },
radius: 2000
}
];
let map;
const mapDefault = {
};
function initMap() {
map = new google.maps.Map(document.getElementById('map'), mapDefault);
const bounds = new google.maps.LatLngBounds();
let pathsCircle = [];
places.forEach(place => {
bounds.extend(place.center);
pathsCircle.push(drawCircle(place.center, place.radius, 1));
});
map.fitBounds(bounds);
const worldCoords = [
new google.maps.LatLng(-85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 0)
];
new google.maps.Polygon({
paths: [worldCoords, ...pathsCircle],
strokeColor: '#fff',
strokeOpacity: 0,
strokeWeight: 0,
fillColor: '#000',
fillOpacity: 0.3,
map,
});
}
function drawCircle(point, radius, dir) {
}
这是我的代码。
为了避免 non-transparent 相交,需要将圆组合成一个多边形。
一种选择是使用 JSTS library 计算圆的并集。
var geometryFactory = new jsts.geom.GeometryFactory();
var poly1,poly2,polyunion;
var polys = [];
for (var i=0; i<pathsCircle.length; i++) {
if (i==0) {
poly1 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly1.normalize();
polys[i] = poly1;
} else {
poly2 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly2.normalize();
polys[i] = polys[i-1].union(poly2);
polys[i].normalize();
}
}
polys[i-1].normalize();
var boundary = polys[i-1].getBoundary();
var outputPath = jsts2googleMaps(boundary);
var jsts2googleMaps = function (geometry) {
var coordArray = geometry.getCoordinates();
GMcoords = [];
for (var i = 0; i < coordArray.length; i++) {
GMcoords.push(new google.maps.LatLng(coordArray[i].x, coordArray[i].y));
}
return GMcoords;
}
var array2JSTS = function(boundaries) {
var coordinates = [];
for (var i = 0; i < boundaries.length; i++) {
coordinates.push(new jsts.geom.Coordinate(
boundaries[i].lat, boundaries[i].lng));
}
return coordinates;
};
代码片段:
const places = [
{
center: { "lat": 1.3512492664554796, "lng": 103.85072488875811 },
radius: 2000
},
{
center: { "lat": 1.3225896205754812, "lng": 103.86600275130694 },
radius: 2000
},
{
center:{ "lat": 1.3136655910729036, "lng": 103.88866205306475 },
radius: 2000
},
{
center: { "lat": 1.305427997082587, "lng": 103.83613367171709 },
radius: 2000
}
];
let map;
const mapDefault = {
center: places[0].center,
zoom: 10,
minZoom: 1,
maxZoom: 19,
clickableIcons: false
};
function initMap() {
map = new google.maps.Map(document.getElementById('map'), mapDefault);
const bounds = new google.maps.LatLngBounds();
let pathsCircle = [];
places.forEach(place => {
bounds.extend(place.center);
pathsCircle.push(drawCircle(place.center, place.radius, 1));
});
map.fitBounds(bounds);
const worldCoords = [
new google.maps.LatLng(-85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 0)
];
var geometryFactory = new jsts.geom.GeometryFactory();
var poly1,poly2,polyunion;
var polys = [];
for (var i=0; i<pathsCircle.length; i++) {
if (i==0) {
poly1 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly1.normalize();
polys[i] = poly1;
} else {
poly2 = geometryFactory.createPolygon(geometryFactory.createLinearRing(array2JSTS(pathsCircle[i])));
poly2.normalize();
polys[i] = polys[i-1].union(poly2);
polys[i].normalize();
}
}
polys[i-1].normalize();
var boundary = polys[i-1].getBoundary();
var outputPath = jsts2googleMaps(boundary);
new google.maps.Polygon({
paths: [worldCoords, outputPath],
strokeColor: '#fff',
strokeOpacity: 0,
strokeWeight: 0,
fillColor: '#000',
fillOpacity: 0.3,
map,
});
}
function drawCircle(point, radius, dir) {
let d2r = Math.PI / 180; // degrees to radians
let r2d = 180 / Math.PI; // radians to degrees
let earthsradius = 6378137; // 6378137 is the radius of the earth in metters
let points = 128; // number of point to draw Circle
// find the raidus in lat/lon
let rlat = (radius / earthsradius) * r2d;
let rlng = rlat / Math.cos(point.lat * d2r);
let extp = [];
let start, end;
if (dir == 1) { // one extra here makes sure we connect the
start = 0; end = points + 1
} else {
start = points + 1; end = 0
}
for (let i = start; (dir == 1 ? i < end : i > end); i = i + dir) {
let theta = Math.PI * (i / (points / 2));
const ey = point.lng + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
const ex = point.lat + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push({
lat: ex,
lng: ey,
});
}
return extp;
}
var jsts2googleMaps = function (geometry) {
var coordArray = geometry.getCoordinates();
GMcoords = [];
for (var i = 0; i < coordArray.length; i++) {
GMcoords.push(new google.maps.LatLng(coordArray[i].x, coordArray[i].y));
}
return GMcoords;
}
var array2JSTS = function(boundaries) {
var coordinates = [];
for (var i = 0; i < boundaries.length; i++) {
coordinates.push(new jsts.geom.Coordinate(
boundaries[i].lat, boundaries[i].lng));
}
return coordinates;
};
/* 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;
}
<!DOCTYPE html>
<html>
<head>
<title>Data Layer: Polygon</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://cdn.jsdelivr.net/npm/jsts@2.8.1/dist/jsts.js"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="map"></div>
<!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&v=weekly&channel=2"
async
></script>
</body>
</html>