openlayers 和 turf 网格应用
<template>
<div class="main">
<div class="map" id="map"></div>
</div>
</template>
<script lang="ts">
import {Component, Vue} from "vue-property-decorator"
import * as turf from '@turf/turf'
import 'ol/ol.css'
import {Feature, Map, Overlay, View} from 'ol'
import OSM from 'ol/source/OSM'
import {Tile, Vector} from 'ol/layer'
import {Zoom, Rotate, Attribution, Control, defaults, FullScreen, ScaleLine} from 'ol/control'
import {DragRotate, DragRotateAndZoom, defaults as defaultInteractions} from "ol/interaction";
import {toStringXY} from "ol/coordinate";
import {ImageCanvas, ImageStatic, TileDebug, TileImage} from "ol/source";
import ImageLayer from "ol/layer/Image";
import Projection from "ol/proj/Projection";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import {LineString, Point} from "ol/geom";
import {Circle, Fill, Icon, Stroke, Style} from "ol/style";
import {GeoJSON} from "ol/format";
import TileGrid from "ol/tilegrid/TileGrid";
import {transform} from "ol/proj";
import CircleStyle from "ol/style/Circle";
import {getVectorContext} from "ol/render";
@Component({})
export default class Ol extends Vue {
map: any = null;
markers: Array<any> = [];
mounted() {
this.initMarkers()
this.$nextTick(() => {
this.initMap()
})
}
initMap() {
let resolutions = [];
for (let i = 0; i < 19; i++) {
resolutions[i] = (Math.pow(2, 18 - i))
}
let projection = new ol.proj.get('EPSG:3857');
let projectionExtent = projection.getExtent();
let imgSource = new TileImage({
//指定切片所用的坐标系
//EPSG:4326 国际标准(地理坐标)
//EPSG:3857 球体墨卡托(投影坐标)
projection: projection,
tileGrid: new TileGrid({
// origin: ol.extent.getBottomLeft(projectionExtent),
origin: [0, 0],
//ol.proj.get('EPSG: 3857').getExtent()投影坐标系范围
// origin: ol.extent.getBottomLeft(ol.proj.get('EPSG:3857').getExtent()),
//自定义分辨率数组
resolutions: resolutions,
extent: projectionExtent,
tileSize: [256, 256]
}),
tileUrlFunction: (tileCoord: any, pixelRatio: any, proj: any) => {
if (!tileCoord) {
return ""
}
let z = tileCoord[0];//缩放级别
let x = tileCoord[1];//x索引
let y = tileCoord[2];//y索引
x = x < 0 ? "M" + (-x) : x;
y = y < 0 ? -y : "M" + y;
return "https://online3.map.bdimg.com/onlinelabel/?qt=tile&x=" + x + "&y=" + y + "&z=" + z + "&styles=pl&udt=20210730&scaler=1&p=1";
}
})
this.map = new Map({
target: 'map',
interactions: defaultInteractions().extend([
new DragRotateAndZoom()
]),
controls: defaults().extend([
new FullScreen(),
new Rotate(),
new ScaleLine(),
]),
layers: [
new Tile({
source: imgSource
}),
new Tile({
source: new TileDebug({
projection: projection,
tileGrid: imgSource.getTileGrid()
})
}),
new VectorLayer({
source: new VectorSource({
features: this.markers
}),
zIndex: 2,
})
],
view: new View({
center: ol.proj.transform([104.06, 20], "EPSG:4326", "EPSG:3857"),
zoom: 5,
resolutions: resolutions
})
});
this.map.on('click', (e: any) => {
console.log(e.coordinate)
})
this.initGrid();
}
//初始化点位
initMarkers() {
let coordinates = [[104, 30], [104, 20], [105, 25], [101, 25]]
this.markers = coordinates.map((item: any, index: number) => {
let point = new Feature(new Point(ol.proj.transform(item, "EPSG:4326", "EPSG:3857")));
point.setId(index);
point.setStyle(new Style({
image: new Icon({
anchor: [0.1, 0.1],
src: require('@/assets/login/sys.png')
})
}))
return point;
})
}
//初始化网格
initGrid() {
//extent: [minX, minY, maxX, maxY] 左下角 -》 右上角
let bbox: any = [10663983.31137481, 2059417.837748297 ,12188497.832018718, 3566205.4453614634];
let cellSide = 500;
let options: any = {units: 'kilometers'};
let squareGrid = turf.squareGrid(bbox, cellSide, options);
// var point = turf.point(transform([114.2058, 33.2469], 'EPSG:4326','EPSG:3857'));
let innerPolygon: any = [];
let outPolygon:any = [];
//遍历小网格
turf.geomEach(squareGrid, (cur: any, index:any, properties:any,bbox:any)=>{
// console.log(cur, properties)
//筛选网格内的点位
let count = this.markers.filter((e: any) =>{
//判断点是否在小网格内
return turf.booleanPointInPolygon(turf.point(e.values_.geometry.flatCoordinates),cur)
})
if(count.length > 0){
innerPolygon.push(cur);
}else{
outPolygon.push(cur);
}
})
let source1 = new VectorSource();
source1.addFeatures(new GeoJSON().readFeatures(turf.featureCollection(outPolygon)));
// source.addFeature(new GeoJSON().readFeature(point));
let source2 = new VectorSource();
source2.addFeatures(new GeoJSON().readFeatures(turf.featureCollection(innerPolygon)));
this.map.addLayer(new VectorLayer({source: source1}))
this.map.addLayer(new VectorLayer({
source: source2,
style: new Style({
fill: new Fill({
color: '#00ff00'
})
})
}))
}
}
</script>
<style lang="scss" scoped>
.main {
width: 100%;
height: 100%;
.map {
width: 50%;
height: 50%;
}
}
</style>
<template>