openlayers - 在地图中生成真正的点圈
问题描述
我正在尝试围绕特定坐标生成一圈可点击点。到目前为止,我正确生成了点,但由于地球的形状,点创建的形状不是圆形。 问题示例
我不知道如何在地图上画一个真正的圆圈,我想我需要玩投影(也许?)但我不知道怎么做。这是我当前的代码:
import 'ol/ol.css';
import {Map, View} from 'ol';
import {fromLonLat} from 'ol/proj';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import OSM from 'ol/source/OSM';
import {click} from 'ol/events/condition';
import VectorSource from 'ol/source/Vector';
import Select from 'ol/interaction/Select';
import GeoJSON from 'ol/format/GeoJSON';
import { transform } from 'ol/proj';
import 'regenerator-runtime/runtime';
var raster = new TileLayer({
source: new OSM({
attributions: [
'All maps © <a href="https://outdoormaps.eu/">OpeOutdoorsMap</a>',
],
url: 'https://tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=583288f0eab044aa8e826df27c403ce1'
})
});
var countries = new VectorLayer({
source: new VectorSource({
url: "https://raw.githubusercontent.com/tsamaya/random-points-generator/master/resources/world_countries.geojson",
format: new GeoJSON()
})
});
const map = new Map({
target: 'map',
layers: [raster,countries],
view: new View({
center: fromLonLat([0,0]),
zoom: 3,
maxZoom: 8,
projection: 'EPSG:3857'
})
});
var pointsLayer = null;
var selectClick = function() {
var selectedClick = new Select({
condition: click
});
map.addInteraction(selectedClick);
if(selectedClick !== null) {
selectedClick.on('select',async function(event) {
if(event.target.getFeatures().getArray().length > 0) {
//Remove previous points layer
if(pointsLayer != null) {
map.removeLayer(pointsLayer);
}
var coord = event.mapBrowserEvent.coordinate;
coord = transform(coord, 'EPSG:3857', 'EPSG:4326');
var features_geojson = {
"type":"FeatureCollection",
"features":[]
};
var number_of_points = 20
var angle_value = 360 / number_of_points;
for (let angle = 0; angle < 360; angle += angle_value) {
var x = Math.cos(angle)*4 + coord[0];
var y = Math.sin(angle)*4 + coord[1];
var point = {
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[x,y]},
"properties":{}
}
features_geojson["features"].push(point);
}
//Add new points to layer
pointsLayer = new VectorLayer({
projection: map.displayProjection,
source: new VectorSource({
features: (new GeoJSON()).readFeatures(features_geojson,{featureProjection:"EPSG:3857"}),
})
});
//Add layer to map
map.addLayer(pointsLayer);
}
});
}
}
selectClick();
谢谢你的帮助。
解决方案
您可以使用内置的方法
在地图投影中看起来像一个圆圈
import Circle from 'ol/geom/Circle'
import {fromCircle} from 'ol/geom/Polygon'
coordinatesArray = fromCircle(new Circle(center, radius), 20).getCoordinates()[0].slice(0, -1);
球体上的测地圆
import {circular} from 'ol/geom/Polygon'
coordinatesArray = circular(toLonLat(center), radius, 20).transform('EPSG:4326', map.getView().getProjection()).getCoordinates()[0].slice(0, -1);
<html>
<head>
<link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css" type="text/css">
<script src="https://openlayers.org/en/latest/build/ol.js"></script>
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script>
var source = new ol.source.Vector();
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Vector({
source: source
})
],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([110, 70]),
zoom: 4
})
});
var coordinatesArray1 = ol.geom.Polygon.fromCircle(
new ol.geom.Circle(ol.proj.fromLonLat([100, 70]), 500000), 20
).getCoordinates()[0].slice(0, -1);
source.addFeature(new ol.Feature(new ol.geom.MultiPoint(coordinatesArray1)));
var coordinatesArray2 = ol.geom.Polygon.circular(
[120, 70], 200000, 20
).transform('EPSG:4326', map.getView().getProjection()).getCoordinates()[0].slice(0, -1);
source.addFeature(new ol.Feature(new ol.geom.MultiPoint(coordinatesArray2)));
</script>
</body>
</html>