本文介绍以下,根据多边形数据创建网格图层,一般应用于公里网格。
本文包括核心代码、完整代码以及在线示例。
网格图层最开始通过循环实现,但是效果不太好,这里通过 turf 实现:
// 网格参数
let options = {
// 单位
units: 'kilometers',
// 网格数据范围
mask: JSON.parse(getGeoJsonByFeature(feature)),
};
// 创建网格数据
let squareGrid = turf.squareGrid(
// 网格范围
feature.getGeometry().getExtent(),
// 网格边长
0.1,
options);
let features = getFeatureByGeoJson(squareGrid);
networkLayer.getSource().addFeatures(features);
// 创建一个选择交互实例
const selectInteraction = new ol.interaction.Select({
// 设置触发选择的事件条件为点击事件
condition: ol.events.condition.pointerMove,
// 设置图层
layers: [networkLayer],
});
// 将选择交互添加到地图实例中
map.addInteraction(selectInteraction);
<html lang="en">
<head>
<meta charSet="utf-8">
<!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
<link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
<style>
/* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */
.map {
height: 400px;
width: 100%;
float: left;
}
</style>
<!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
<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>
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?f80a36f14f8a73bb0f82e0fdbcee3058";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body>
<h2>OpenLayers feature grid</h2>
<!--地图容器,需要指定 id -->
<div id="map" className="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,
})
});
// 获取颜色
function getStyle(color = '#00ffff') {
return new ol.style.Style({
//边框样式
stroke: new ol.style.Stroke({
color: color,
width: 2,
}),
//填充样式
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.2)',
}),
})
}
// 初始化图层
var layer = initVectorLayer();
//创建网格图层
const networkLayer = initVectorLayer();
networkLayer.setStyle(getStyle('#ffffff'))
// 初始默认数据
let polygon = "POLYGON((116.26201501649226 40.00016773213365,116.26416078370417 39.99651992787339,116.26690736573542 39.996734504594585,116.26785150330866 39.99639118184068,116.26973977845515 39.99712074269273,116.27313009064997 39.99733531941392,116.27416005891169 39.99518955220201,116.27476087373103 39.991241340532085,116.27321592133845 39.98909557332017,116.27188554566706 39.984975700273296,116.27201429169978 39.98334491719224,116.27437463563288 39.980469589128276,116.27317300599421 39.97986877430894,116.27072683137263 39.979997520341655,116.26828065675105 39.98132789601304,116.26471868317927 39.981499557389995,116.26227250855769 39.983774070634624,116.259268434461 39.98484695424058,116.25707975190485 39.98716438282945,116.25429025452937 39.99111259449937,116.25729432862605 39.99488914479234,116.25883928101862 39.99690616597154,116.26201501649226 40.00016773213365))";
let feature = getFeatureByWKT(polygon);
layer.getSource().addFeature(feature);
map.getView().fit(layer.getSource().getExtent(), {
duration: 1,//动画的持续时间,
callback: null,
});
/**
* @todo 矢量图层
* @returns {VectorLayer}
* @constructor
*/
function initVectorLayer() {
//实例化一个矢量图层Vector作为绘制层
let source = new ol.source.Vector();
//创建一个图层
let customVectorLayer = new ol.layer.Vector({
source: source,
zIndex: 2,
//设置样式
style: getStyle(),
});
//将绘制层添加到地图容器中
map.addLayer(customVectorLayer);
return customVectorLayer;
}
/**
* @todo wkt格式数据转化成图形对象
* @param {string} wkt "POINT(112.7197265625,39.18164062499999)" 格式数据
* @param {string|Projection} sourceCode 源投影坐标系
* @param {string|Projection} targetCode 目标投影坐标系
* @returns {Feature}
*/
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;
}
}
/**
* todo 通过feature获取geojson字符串
* @param feature
* @param code
* @param sourceCode
* @returns {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(), // 设定JSON数据使用的坐标系
featureProjection: targetCode || view.getProjection() // 设定当前地图使用的feature的坐标系
});
} else {
geojson = (new ol.format.GeoJSON()).writeFeature(feature, {
dataProjection: sourceCode || view.getProjection(), // 设定JSON数据使用的坐标系
featureProjection: targetCode || view.getProjection() // 设定当前地图使用的feature的坐标系
});
}
return geojson;
}
/**
* @todo 图形对象转化成GeoJson格式数据(postgis)
* @param {string|object} geojson geojson字符串或者对象
* @param {string|Projection} sourceCode 源投影坐标系
* @param {string|Projection} targetCode 目标投影坐标系
* @returns {Feature}
*/
function getFeatureByGeoJson(geojson, sourceCode, targetCode) {
let view = map.getView();
if (!geojson) {
return null;
}
let feature;
if ((typeof geojson) == 'string') {
// 替换 null 字符
while (geojson.indexOf('null') != -1) {
// geojson = geojson
geojson = geojson.replace("null", "");
}
}
feature = (new ol.format.GeoJSON()).readFeatures(geojson, {
dataProjection: sourceCode || view.getProjection(), // 设定JSON数据使用的坐标系
featureProjection: targetCode || view.getProjection() // 设定当前地图使用的feature的坐标系
});
return feature;
}
/**
* todo 增加网格
* @param feature wkt或者feature
* @param unit 米
*/
function addNetworkGrid() {
// 网格参数
let options = {
// 单位
units: 'kilometers',
// 网格数据范围
mask: JSON.parse(getGeoJsonByFeature(feature)),
};
// 创建网格数据
let squareGrid = turf.squareGrid(
// 网格范围
feature.getGeometry().getExtent(),
// 网格边长
0.1,
options);
let features = getFeatureByGeoJson(squareGrid);
networkLayer.getSource().addFeatures(features);
// 创建一个选择交互实例
const selectInteraction = new ol.interaction.Select({
// 设置触发选择的事件条件为点击事件
condition: ol.events.condition.pointerMove,
// 设置图层
layers: [networkLayer],
});
// 将选择交互添加到地图实例中
map.addInteraction(selectInteraction);
}
// 还原样式
function restore() {
networkLayer.getSource().clear();
}
</script>
<button id="unionFeature" onClick="addNetworkGrid()">创建网格</button>
<button id="restore" onClick="restore()">还原</button>
</body>
</html>