/**
* 地图网格工具js
*
* @author fungis@163.com
* @date 2023-05-18
*/
// 本地资源数据
import { makeStandardMapGrids } from './standardMapGrids.js'
var geojson = []
export {
gridLineStandard
}
/** 地图标准图幅格网 */
let gridLineStandard = {
currentMap: null,
currentFeatureLayerGroup: null,
AMap: null,
color: "red",
map: null,
cluster: null,
init: function () {
gridLineStandard.currentMap.remove(geojson);
if (gridLineStandard.cluster) {
gridLineStandard.cluster.setMap(null);
}
// 经纬度间隔
var map = gridLineStandard.currentMap;
// 重新添加网格图层
let gridLineLayer = gridLineStandard.currentFeatureLayerGroup;
// 生成网格
let bounds = map.getBounds();
const zoom = map.getZoom();
let scale = 1000000;
if (zoom > 13) {
scale = 1000;
} else if (zoom > 12) {
scale = 2000;
} else if (zoom > 11) {
scale = 5000;
} else if (zoom > 10) {
scale = 10000;
} else if (zoom > 9) {
scale = 25000;
} else if (zoom > 8) {
scale = 50000;
} else if (zoom > 7) {
scale = 100000;
} else if (zoom > 6) {
scale = 250000;
} else if (zoom > 4) {
scale = 500000;
}
// 东经北纬 lat 纬度 lng 经度
let grids = makeStandardMapGrids(bounds.southWest.lng, bounds.southWest.lat, bounds.northEast.lng, bounds.northEast.lat, scale);
if (grids == null) {
return;
}
geojson = new AMap.GeoJSON({
geoJSON: grids,
// 还可以自定义getMarker和getPolyline
getPolygon: function (geojson, lnglats) {
let Polygon = new AMap.Polygon({
path: lnglats,
strokeColor: 'red',
fillColor: 'red',
fillOpacity: 0,
});
Polygon.on('click', function (e) {
console.log('click', e)
})
return Polygon
}
});
map.add(geojson);
// 点聚合
gridLineStandard.cluster = new AMap.MarkerClusterer(
map, // 地图实例
grids.centerPoints, // 海量点数据,数据中需包含经纬度信息字段 lnglat
{
gridSize: 80, // 聚合网格像素大小
});
// map.on('zoomchange', e => {
// gridLineStandard.destory()
// });
},
destory: function () {
// 点聚合清空
if (gridLineStandard.cluster) {
gridLineStandard.cluster.setMap(null);
}
gridLineStandard.currentMap.remove(geojson);
}
}
/**
* 地图标准图幅计算要素生成工具js
* https://www.cnblogs.com/oloroso/p/14129066.html
*
* @author ymwh@foxmail.com
* @date 2020-12-13
*/
// 获取小数部分
const fractional = function (x) {
x = Math.abs(x);
return x - Math.floor(x);
}
const formatInt = function (x, len) {
let result = '' + x;
len = len - result.length;
while (len > 0) {
result = '0' + result;
len--;
}
return result;
}
/**
* 创建标准分幅网格
* @param west,south,east,north 传入要创建的标准分幅网格的经纬度范围
* @param scalem 表示比例尺的分母(例如 10000 表示 1:1万)
* @returns 返回一个 geojson 对象
* @author solym ymwh@foxmail.com 2020年12月13日
*/
export function makeStandardMapGrids(west, south, east, north, scalem) {
let lngDiff = 0;
let latDiff = 0;
let scaleCode = '';
switch (scalem) {
case 1000000:
lngDiff = 6;
latDiff = 4;
break;
case 500000:
lngDiff = 3;
latDiff = 2;
scaleCode = 'B';
break;
case 250000:
lngDiff = 1.5;
latDiff = 1;
scaleCode = 'C';
break;
case 100000:
lngDiff = 0.5;
latDiff = 1 / 3;
scaleCode = 'D';
break;
case 50000:
lngDiff = 0.25;
latDiff = 1 / 6;
scaleCode = 'E';
break;
case 25000:
lngDiff = 0.125;
latDiff = 1 / 12;
scaleCode = 'F';
break;
case 10000:
lngDiff = 0.0625;
latDiff = 1 / 24;
scaleCode = 'G';
break;
case 5000:
lngDiff = 0.03125;
latDiff = 1 / 48;
scaleCode = 'H';
case 2000:
lngDiff = 37.5 / 3600.0;
latDiff = 25.0 / 3600.0;
scaleCode = 'I';
break;
case 1000:
lngDiff = 18.75 / 3600.0;
latDiff = 12.5 / 3600.0;
scaleCode = 'J';
break;
case 500:
lngDiff = 9.375 / 3600.0;
latDiff = 6.25 / 3600.0;
scaleCode = 'K';
break;
default:
return null;
}
const GridX0 = -180;
const GridX1 = 180;
const GridY0 = -88;
const GridY1 = 88;
let x0 = Math.max(GridX0, west);
let y0 = Math.max(GridY0, south);
let x1 = Math.min(GridX1, east);
let y1 = Math.min(GridY1, north);
if (((x1 - x0) < lngDiff) || ((y1 - y0) < latDiff)) {
return null;
}
let features = []; // 存储生成的面要素
let coordinates = [] // 存储生成的面要素坐标对
let centerPoints = []
// 计算标准分幅网格行列范围
const col0 = parseInt((x0 - GridX0) / lngDiff);
const col1 = parseInt((x1 - GridX0) / lngDiff);
const row0 = parseInt((y0 - GridY0) / latDiff);
const row1 = parseInt((y1 - GridY0) / latDiff);
const millionRowCode = 'ABCDEFGHIJKLMNOPQRSTUV';
for (let row = row0; row <= row1; row++) {
let gy0 = GridY0 + row * latDiff;
let gy1 = gy0 + latDiff;
let gcy = (gy0 + gy1) * 0.5; // 分幅中心点 y 坐标
let millionRow = parseInt((gy0 - 0) / 4); // 1:100分幅行号
let Hemisphere = ''; // 北半球标志
if (millionRow < 0) {
millionRow = -1 - millionRow;
Hemisphere = 'S'; // 南半球标志
}
for (let col = col0; col <= col1; col++) {
let gx0 = GridX0 + col * lngDiff;
let gx1 = gx0 + lngDiff;
let gcx = (gx0 + gx1) * 0.5; // 分幅中心点 x 坐标
let millionCol = parseInt((gcx - GridX0) / 6) + 1; // 1:100分幅列号(从1开始)
coordinates = [[[gx0, gy0], [gx1, gy0], [gx1, gy1], [gx0, gy1], [gx0, gy0]]];
millionCol = (millionCol < 10) ? ('0' + millionCol) : millionCol;
let gridID = Hemisphere + millionRowCode[millionRow] + millionCol;
if (scaleCode != '') {
// 计算当前分幅在 1:100万 分幅内的行列号(注意,这里行列号从左向右,从北向南,从1开始编号)
let colID = parseInt((fractional((gcx - GridX0) / 6) * 6) / lngDiff) + 1;
let rowID = parseInt((fractional((GridY1 - gcy) / 4) * 4) / latDiff) + 1;
gridID += scaleCode + formatInt(rowID, 3) + formatInt(colID, 3);
}
// 生成矢量要素(几何信息+属性信息)
let feature = {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: coordinates
},
properties: {
ID: gridID,
extend: '西:' + gx0 + ' 东:' + gx1 + ' 南:' + gy0 + ' 北:' + gy1,
lat: gcy.toFixed(6),
lng: gcx.toFixed(6)
},
};
let centerPoint = {
lnglat: [gcx.toFixed(6), gcy.toFixed(6)]
}
features.push(feature);
centerPoints.push(centerPoint)
}
}
return {
type: "FeatureCollection",
features: features,
// 中心点坐标
centerPoints: centerPoints
};
}