OpenLayers 教程
在WebGIS开发中经常遇到空间分析,常见的有联合、差异、相交、抽稀、缓冲分析等。
Openlayers 中没有提供空间分析方法,需要使用三方工具实现,前端常用的工具有 turf、jsts,本文以 turf 为例。
turf 官网
turf js版
注意:前端仅限于操作小数据量,数据量大的话,一般是由后台处理。
注意:turf 使用的 geojson 格式的对象,如果使用 geojson 字符串会报错!
Openlayers 拓扑-联合、差异、相交、抽稀、缓冲、挖洞
<html lang="en">
<head>
<meta charSet="utf-8">
<link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
float: left;
}
</style>
<script src="http://openlayers.vip/examples/resources/ol.js"></script>
<script src="./turf.min.js"></script>
<script src="./tiandituLayers.js"></script>
<title>OpenLayers example</title>
</head>
<body>
<h2>OpenLayers feature topology</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
var map = new ol.Map({
target: 'map',
layers: [
getIMG_CLayer(),
getIBO_CLayer(),
getCIA_CLayer(),
],
view: new ol.View({
projection: "EPSG:4326",
center: [115.67724700667199, 37.73879478106912],
zoom: 6,
maxZoom: 18,
minZoom: 1,
})
});
var defaultStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'white',
width: 2,
}),
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.7)',
}),
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'white',
})
})
})
var layer = initVectorLayer();
var features = [];
addFeatures();
function addFeatures() {
features.push(getFeatureByWKT("POLYGON((112.80630306271966 46.27140545436643,116.23403743771966 44.33781170436643,117.81606868771966 40.29484295436643,117.90395931271966 38.36124920436643,117.81606868771966 35.02140545436643,116.14614681271966 32.38468670436643,113.50942806271966 33.26359295436643,111.75161556271966 34.58195232936643,110.60903743771966 35.46085857936643,113.28970150021968 36.03214764186642,111.35610775021968 36.33976482936642,110.91665462521968 36.91105389186642,111.22427181271968 37.52628826686642,112.10317806271968 37.30656170436642,112.41079525021968 37.78996014186642,112.32290462521968 38.36124920436642,111.44399837521968 38.66886639186642,110.52114681271968 39.10831951686642,110.38931087521968 39.81144451686642,111.09243587521968 40.07511639186642,112.19106868771968 40.38273357936642,112.49868587521968 41.04191326686642,111.88345150021968 41.21769451686642,111.26821712521968 40.86613201686642,110.43325618771968 40.91007732936642,110.65298275021968 41.39347576686642,110.47720150021968 42.66788982936642,111.79556087521968 42.75578045436642,110.38931087521968 43.19523357936642,110.56509212521968 44.24992107936642,111.44399837521968 43.76652264186642,111.79556087521968 44.16203045436642,111.09243587521968 44.60148357936642,111.22427181271968 45.30460857936642,112.10317806271968 44.95304607936642,112.67446712521968 45.26066326686642,111.75161556271968 45.78800701686642,111.88345150021968 46.40324139186642,112.14712337521968 47.94132732936642,112.45474056271968 47.15031170436642,113.99282650021968 47.28214764186642,113.28970150021968 46.79874920436642,114.95962337521968 46.71085857936642,112.80630306271966 46.27140545436643))"));
features.push(getFeatureByWKT("POLYGON((124.1455078125 44.03320312500001,114.6533203125 37.26562500000001,129.990234375 28.212890625,136.8896484375 42.01171875,133.1982421875 45.5712890625,124.1455078125 44.03320312500001))"));
features.push(getFeatureByWKT("POLYGON((125.48696587513709 40.418890353749546,124.32241509388709 39.715765353749546,125.17934868763709 39.188421603749546,124.73989556263709 38.023870822499546,125.81655571888709 37.694280978749546,126.58559868763709 37.079046603749546,125.92641900013709 36.639593478749546,126.43179009388709 35.694769259999546,125.55288384388709 34.486273166249546,127.33266900013709 33.871038791249546,129.3761260313871 34.793890353749546,129.8814971251371 36.046331759999546,129.3321807188871 37.914007541249546,128.2335479063871 39.254339572499546,127.61831353138709 40.155218478749546,128.0357940001371 40.968206759999546,126.62954400013709 40.968206759999546,125.94839165638709 41.034124728749546,125.48696587513709 40.418890353749546))"));
layer.getSource().addFeatures(features);
map.getView().fit(layer.getSource().getExtent(), {
duration: 1,
callback: null,
});
}
function initVectorLayer() {
let source = new ol.source.Vector();
let customVectorLayer = new ol.layer.Vector({
source: source,
zIndex: 2,
style: defaultStyle,
});
map.addLayer(customVectorLayer);
return customVectorLayer;
}
function getFeatureByWKT(wkt, sourceCode, targetCode) {
try {
let view = map.getView();
if (!wkt) {
return null;
}
let format = new ol.format.WKT();
let feature;
feature = format.readFeature(wkt, {
featureProjection: targetCode || view.getProjection(),
dataProjection: sourceCode || view.getProjection(),
});
return feature;
} catch (e) {
console.log(e);
return null;
}
}
function getGeoJsonByFeature (feature, sourceCode, targetCode) {
if (!feature) {
return null;
}
let view = map.getView();
let geojson;
if (feature instanceof Array) {
geojson = (new ol.format.GeoJSON()).writeFeatures(feature, {
dataProjection: sourceCode || view.getProjection(),
featureProjection: targetCode || view.getProjection()
});
} else {
geojson = (new ol.format.GeoJSON()).writeFeature(feature, {
dataProjection: sourceCode || view.getProjection(),
featureProjection: targetCode || view.getProjection()
});
}
return geojson;
}
function getFeatureByGeoJson(geojson, sourceCode, targetCode) {
let view = map.getView();
if (!geojson) {
return null;
}
let feature;
if ((typeof geojson) == 'string') {
while (geojson.indexOf('null') != -1) {
geojson = geojson.replace("null", "");
}
}
feature = (new ol.format.GeoJSON()).readFeature(geojson, {
dataProjection: sourceCode || view.getProjection(),
featureProjection: targetCode || view.getProjection()
});
return feature;
}
function lineStyle() {
let styleLine = [];
let steps = 10;
for (let i = 0; i < steps; i++) {
styleLine.push(
new ol.style.Style({
stroke: new ol.style.Stroke({
color: [0, 255, 255, 1 / (steps - i)],
width: (steps - i) * 2 - 1
}),
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.05)',
}),
})
);
}
return styleLine;
}
var tempFeatures = [];
function turfCommon(type) {
restore();
let geoObj1 = JSON.parse(getGeoJsonByFeature(features[0]));
let geoObj2 = JSON.parse(getGeoJsonByFeature(features[1]));
let geoObj3 = JSON.parse(getGeoJsonByFeature(features[2]));
let unionObj;
switch (type) {
case 'union':
unionObj = turf.union(geoObj1,geoObj2);
alert('两个多边形联合成为一个多边形!')
break;
case 'intersect':
unionObj = turf.intersect(geoObj1,geoObj2);
alert('多边形A跟多边形B重合的部分!')
break;
case 'difference':
unionObj = turf.difference(geoObj1,geoObj2);
alert('多边形A去除与多边形B重合的部分!')
break;
case 'hole':
unionObj = turf.difference(geoObj2,geoObj3);
alert('多边形B挖去多边形C部分!')
break;
case 'simplify':
let options = {tolerance: 100, highQuality: true, mutate: false};
unionObj = turf.simplify(geoObj1, options);
alert('多边形A简化!')
break;
case 'buffer':
unionObj = turf.buffer(geoObj1, 50, {units: 'kilometers'});
alert('多边形A的周边范围!')
break;
}
let tempFeature = getFeatureByGeoJson(unionObj);
tempFeature.setStyle(lineStyle())
tempFeatures.push(tempFeature);
layer.getSource().addFeatures([tempFeature]);
}
function restore() {
for (let i = 0; i < tempFeatures.length; i++) {
layer.getSource().removeFeature(tempFeatures[i])
}
}
</script>
<button id="unionFeature" onClick="turfCommon('union')">联合</button>
<button id="difference" onClick="turfCommon('difference')">差异</button>
<button id="intersect" onClick="turfCommon('intersect')">相交</button>
<button id="hole" onClick="turfCommon('hole')">挖洞</button>
<button id="simplify" onClick="turfCommon('simplify')">抽稀</button>
<button id="buffer" onClick="turfCommon('buffer')">缓冲</button>
<button id="restore" onClick="restore()">还原</button>
</body>
</html>
在线示例
Openlayers topo样式演示:Openlayers topo
|