概况
JSTS是JavaScript 空间分析库,常见API有buffer、union、intersection、symDifference、getBoundary、getCentroid、convexHull,css样式可以根据自己的需求写。
环境:webpack构建的vue项目,另外,JS资源官网是可以找到的。
一、需要在项目中引入用到的文件
二、写一个工具类文件Utils.js
包含创建地图,添加图层,数据的转换,JSTS API 的使用
let wktReader = new OpenLayers.Format.WKT();
// 初始化地图
let initMap = (name, url) => {
OpenLayers.Layer.OFFLINEMAP = OpenLayers.Class(
OpenLayers.Layer.XYZ,
{
name: 'MAP',
url: 'https://yoururl/${z}/${x}/${y}.png', // 这是你发布的地图
sphericalMercator: true, // 是否应将平铺范围设置为球形墨卡托的默认值,地图才可以显示
wrapDateLine: true, // 允许拖动平移地图
tileOptions: null,
isBaseLayer: true,
zoom: 10,
initialize: function (a, b, c) {
OpenLayers.Layer.XYZ.prototype.initialize.apply(this, arguments)
this.tileOptions = OpenLayers.Util.extend(
{ crossOriginKeyword: 'anonymous' },
this.options && this.options.tileOptions
)
},
clone: function (a) {
a == null && (a = new OFFLINEMAP(this.name, this.url, this.getOptions()));
return a = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [a])
},
getOption(){
// console.log(this.getOptions())
},
CLASS_NAME: 'OpenLayers.Layer.OFFLINEMAP'
}
)
}
// 创建地图
let CreatMap = (_this, name) => {
_this.map = new OpenLayers.Map({
div: 'map',
projection: new OpenLayers.Projection('EPSG:900913'), // 指定添加到此地图的图层的默认投影
displayProjection: new OpenLayers.Projection('EPSG:4326'), // 要求proj4js支持EPSG:4326的其他投影
center: [12614654.172192, 2647187.2285552], // 中心点
isBaseLayer: true,
numZoomLevels: [0, 24], // 地图缩放级别
resolutions: [ // 地图分辨率的列表(每像素地图单位)以降序排列
0.0439453125,
0.703125,
0.3515625,
0.17578125,
0.087890625,
0.0439453125
],
zoom: 16, // 设置地图级别 ,貌似没有效果
});
var configIP = 'https://yourUrl/${z}/${x}/${y}.png';
var mapoptions = {
name: 'map',
url: configIP,
sphericalMercator: true,
wrapDateLine: true,
tileOptions: null,
box: true, // 允许框选
numZoomLevels: 24,
isBaseLayer: true,
controls: [],
zoom: 16
};
// * 集合图层,从layer中继承
var layer = new OpenLayers.Layer.OFFLINEMAP(mapoptions);
layer.getOption()
_this.map.addLayer(layer);
// 设置图层样式
var polystyle = new OpenLayers.Style(
{
pointRadius: 3.5,
fillOpacity: 0.7,
fillColor: 'black',
strokeWidth: 1,
strokeOpacity: 1,
graphicZIndex: 1
},
{
rules:[
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: 'COLOR',
value: 1
}),
symbolizer: {
fillOpacity: 0.9,
fillColor: '#03A9F4',
strokeWidth: 0.5,
strokeOpacity: 0.9,
strokeColor: 'white'
}
}),
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: 'COLOR',
value: 2
}),
symbolizer: {
fillOpacity: 0.9,
fillColor: '#82d09a',
strokeWidth: 0.5,
strokeOpacity: 0.9,
strokeColor: 'white'
}
}),
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: 'COLOR',
value: 3
}),
symbolizer: {
fillOpacity: 0.9,
fillColor: '#ffbc00',
strokeWidth: 3,
strokeOpacity: 0.9,
strokeColor: '#ffbc00'
}
}),
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: 'COLOR',
value: 4
}),
symbolizer: {
fillOpacity: 0.9,
fillColor: '#a7fff7',
strokeWidth: 3,
strokeOpacity: 0.9,
strokeColor: '#a7fff7'
}
})
]
}
);
// 创建一个图层,添加需要计算的polygon
var wfslayer = new OpenLayers.Layer.Vector(name, {
styleMap: new OpenLayers.StyleMap({
'default': polystyle
})
});
this.layer = wfslayer;
_this.map.addLayer(wfslayer)
};
// 把 wkt 转成 geometry
let toGeometryFromWkt = (wkt) => {
var geometry = wktReader.read(wkt);
var attributes = {
name:'name',
wkt: wkt
}
geometry.attributes = attributes;
return geometry
};
// 添加一个 feature 到图层
let addFeature = (wkt, layer, i) => {
var geometry = toGeometryFromWkt(wkt);
// 扩展属性
$.extend(geometry.attributes, {
NAME: 'name',
WKT: wkt,
COLOR: i
});
if (wkt != null) {
this.layer.addFeatures(geometry)
}
}
// 清除
let removeFeature = (_this, name, clearName) => {
if (clearName.length) {
for (let i = 0; i < clearName.length; i++) {
_this[clearName[i]] = ''
}
}
var layer = _this.map.getLayersByName(name);
if (layer.length > 0) {
layer[0].removeAllFeatures()
}
_this.map.setCenter([12614654.172192, 2647187.2285552], 24);
}
// jsts API
let JstsUtils = (param) => {
var firstGeom = null;
var secondGeom = null;
var jstsFirstGeom = null;
var jstsSecondGeom = null;
var jstsResultGeom = null;
var jstsReader = new jsts.io.WKTReader();
var jstsParser = new jsts.io.OpenLayersParser();
if (param.firstwkt) {
firstGeom = toGeometryFromWkt(param.firstwkt);
jstsFirstGeom = jstsParser.read(firstGeom.geometry)
}
if (param.secondwkt) {
secondGeom = toGeometryFromWkt(param.secondwkt);
jstsSecondGeom = jstsParser.read(secondGeom.geometry)
}
// 空间分析功能
switch (param.name) {
case 'buffer':
jstsResultGeom = jstsFirstGeom.buffer(parseFloat(param.radiu == null ? 0.0 : param.radiu))
break;
case 'union':
jstsResultGeom = jstsFirstGeom.union(jstsSecondGeom);
break;
case 'intersection':
jstsResultGeom = jstsFirstGeom.intersection(jstsSecondGeom);
break;
case 'symDifference':
jstsResultGeom = jstsFirstGeom.symDifference(jstsSecondGeom);
break;
case 'getBoundary':
jstsResultGeom = jstsFirstGeom.getBoundary();
break;
case 'getCentroid':
jstsResultGeom = jstsFirstGeom.getCentroid();
break;
case 'convexHull':
jstsResultGeom = jstsFirstGeom.convexHull();
break;
default:
throw 'data format error!';
}
// 转成openlayer geometry 对象
return jstsParser.write(jstsResultGeom)
};
export {
initMap,
CreatMap,
toGeometryFromWkt,
addFeature,
JstsUtils,
removeFeature
}
三、写一个公共的组件public-single-space.vue
<template>
<div class="col-md-12">
<div class="layout">
<div class="nav">
<div class="feature">
<div class="coll_btn_box">
<button @click="drawGeometry">绘制</button>
<button @click="drawRun">运行</button>
<button @click="revertMap">清除</button>
</div>
<div class="legend_btn_box">
<div :class="item.cla" v-for="(item,index) in btnData" :key="index">
<span class="rect"></span>
<span class="txt">{{item.text}}</span>
</div>
</div>
</div>
<textarea v-model="value" class="text_area"></textarea>
</div>
<div class="map">
<div id="map" class="map_box"></div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "public-single-space",
props:{
btnData:{
type: [Array,Object]
},
value:{
type: String,
default: ''
}
},
methods:{
drawGeometry(){
this.$emit('draw_geometry');
},
drawRun(){
this.$emit('draw_run');
},
revertMap(){
this.$emit('revert_map');
}
},
};
</script>
<style scoped>
@import "../assets/css/common.css";
</style>
四、使用,单个图形(以convexHull为案例)
- convexHull(外接矩形)
- buffer(缓冲区)
- getCentroid(中心点)
- getBoundary(边框)
<template>
<publicSingleSpace
:btnData="btnData"
:value="polygon"
@draw_geometry="drawGeometry"
@draw_run="drawRun"
@revert_map="revertMap">
</publicSingleSpace>
</template>
<script>
import publicSingleSpace from './public-single-space'
import {
initMap,
CreatMap,
addFeature,
toGeometryFromWkt,
JstsUtils,
removeFeature
} from './Utils.js'
export default {
nam: 'ConvexHull',
components: {
publicSingleSpace
},
data() {
return {
map: null,
polygon: "POLYGON((113.31886002411747 23.12592000980574,113.31973442425445 23.125826276039394,113.31975051750989 23.1248050670806,113.31944474568361 23.125628941581002,113.3187741934338 23.12513067078125,113.31862398972841 23.125638808311095,113.31886002411747 23.12592000980574))",
layerName: 'convexHull_layer',
wkt: '',
btnData:[
{ cla: 'legend_blue', text: '多边形'},
{ cla: 'legend_red', text: '边界'},
],
}
},
mounted() {
initMap();
CreatMap(this, this.layerName);
},
methods: {
drawGeometry() {
var geometry = toGeometryFromWkt(this.polygon);
var feature = geometry.geometry.transform(
new OpenLayers.Projection("EPSG:4326"),
new OpenLayers.Projection("EPSG:900913")
);
this.wkt = feature.toString();
addFeature(this.wkt, this.map.layers, 1);
},
drawRun() {
if(this.wkt != ''){
var convexHullFeature = new OpenLayers.Feature.Vector("convexHullVector");
convexHullFeature.geometry = JstsUtils({
name: "convexHull",
firstwkt: this.wkt
});
var feature = convexHullFeature.geometry.toString();
addFeature(feature, this.map.layers, 3);
}
},
revertMap() {
removeFeature(this, this.layerName,['wkt'])
}
}
};
</script>
<style scoped>
@import "../assets/css/common.css";
</style>
五、单个图形效果
六、使用,两个图形(以intersection为例)
- intersection(相交区)
- symDifference(不同区)
- union(合并区)
<template>
<div class="col-md-12">
<div class="layout">
<div class="nav twoNav">
<div class="left">
<div class="feature">
<div class="coll_btn_box">
<button @click="drawGeometry(1)">绘制</button>
</div>
<div class="legend_btn_box">
<div class="legend_blue">
<span class="rect"></span>
<span class="txt">几何体1</span>
</div>
<div class="legend_green">
<span class="rect"></span>
<span class="txt">几何体2</span>
</div>
<div class="legend_red">
<span class="rect"></span>
<span class="txt">相交区</span>
</div>
</div>
</div>
<textarea v-model="value1" class="text_area"> </textarea>
</div>
<div class="right">
<div class="feature">
<div class="coll_btn_box">
<button @click="drawGeometry(2)">绘制</button>
<button @click="drawRun">运行</button>
<button @click="revertMap">清除</button>
</div>
</div>
<textarea v-model="value2" class="text_area"> </textarea>
</div>
</div>
<div class="map">
<div id="map" class="map_box"></div>
</div>
</div>
</div>
</template>
<script>
import {
initMap,
CreatMap,
addFeature,
toGeometryFromWkt,
JstsUtils,
removeFeature
} from './Utils.js'
export default {
nam: "Intersection",
data() {
return {
map: null,
value1: "POLYGON((113.31886002411747 23.12592000980574,113.31973442425445 23.125826276039394,113.31975051750989 23.1248050670806,113.31944474568361 23.125628941581002,113.3187741934338 23.12513067078125,113.31862398972841 23.125638808311095,113.31886002411747 23.12592000980574))",
value2: "POLYGON((113.31875810016938 23.125846009469857,113.31926235546736 23.125323072596977,113.31904241432473 23.124652131736205,113.31856498112215 23.124775466705003,113.31880637993568 23.12506160339534,113.31875810016938 23.125846009469857))",
layerName: 'intersection_layer',
wkt: '',
wktS: '',
};
},
mounted() {
initMap();
CreatMap(this, this.layerName);
},
methods: {
drawGeometry(index) {
var val = index == 1 ? this.value1 : this.value2;
var geometry = toGeometryFromWkt(val);
var featrue = geometry.geometry.transform(
new OpenLayers.Projection("EPSG:4326"),
new OpenLayers.Projection("EPSG:900913")
);
var string = featrue.toString();
if(index == 1){
this.wkt = string;
}else{
this.wktS = string;
}
addFeature(string, this.map.layers, index);
},
drawRun() {
var convexHullFeature = new OpenLayers.Feature.Vector("convexHullVector");
convexHullFeature.geometry = JstsUtils({
name: "intersection", // symDifference/合并区
firstwkt: this.wkt,
secondwkt: this.wktS
});
var feature = convexHullFeature.geometry.toString();
addFeature(feature, this.map.layers, 3);
},
revertMap(){
removeFeature(this, this.layerName, ['wkt','wktS'])
}
}
};
</script>
<style scoped>
@import "../assets/css/common.css";
</style>