123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- // 引入OpenLayers的主模块
- import Map from 'ol/Map';
- import View from 'ol/View';
- import Feature from 'ol/Feature';
- import Point from 'ol/geom/Point';
- import VectorLayer from 'ol/layer/Vector';
- import VectorSource from 'ol/source/Vector';
- import Style from 'ol/style/Style';
- import Icon from 'ol/style/Icon';
- import Text from 'ol/style/Text';
- import Projection from 'ol/proj/Projection';
- import { getWidth, getTopLeft } from 'ol/extent';
- import TileLayer from 'ol/layer/Tile';
- import WMTS from 'ol/source/WMTS';
- import WMTSTileGrid from 'ol/tilegrid/WMTS';
- import WMTSCapabilities from 'ol/format/WMTSCapabilities';
- import { Fill, Stroke } from 'ol/style';
- import proj4 from 'proj4';
- import { register } from 'ol/proj/proj4';
- import { defaults } from 'ol/control';
- import Vector from 'ol/layer/Vector';
- import SourceVector from 'ol/source/Vector';
- import GeoJSON from 'ol/format/GeoJSON';
- import { fromLonLat } from 'ol/proj';
- import axios from 'axios';
- import { fromExtent } from 'ol/geom/Polygon';
- import { LinearRing, Polygon } from 'ol/geom';
- import { Tile } from 'ol';
- import {Graticule} from "ol/layer";
- import { mergeGeoJsonPolygons } from '@/utils/gisUtils';
- // import olPlot from 'ol-plot';
- // import { activate } from '../ol-plot/ol-plot'
- const commonUrl = import.meta.env.VITE_APP_BASE_API2 + 'api/oneShare/proxyHandler/gd/';
- // proj4.defs('EPSG:4490', '+proj=longlat +ellps=GRS80 +no_defs +type=crs');
- proj4.defs('EPSG:4490', 'GEOGCS["China Geodetic Coordinate System 2000",DATUM["China_2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","1043"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]');
- // proj4.defs('EPSG:4525', '+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=37500000 +y_0=0 +ellps=GRS80 +units=m +no_defs +type=crs');
- register(proj4);
- const projection = new Projection({
- code: 'EPSG:4490',
- units: 'degrees',
- axisOrientation: 'neu'
- });
- projection.setExtent([-180, -90, 180, 90])
- projection.setWorldExtent([-180, -90, 180, 90])
- const projectionExtent = [-180, -90, 180, 90];
- const size = getWidth(projectionExtent) / 256;
- const resolutions = [];
- for (let z = 2; z < 22; ++z) {
- resolutions[z] = size / Math.pow(2, z);
- }
- export class olMap {
- private map;
- private options;
- private markers = [];
- private drawOptions = {
- graphicsType: 'circle',
- strokeColor: '#f80102',
- strokeOpacity: 1,
- strokeWeight: 2,
- fillColor: '#f80102',
- fillOpacity: 0,
- strokeStyle: 'solid'
- };
- // private { currentState, commit, undo, history, future } = useHistory();
- private overlays = [];
- private overlaysData = [];
- private graphicsType = '';
- private plot;
- private vectorLayer;
- private maskLayer;
- private maskLayer2 = [];
- constructor(options) {
- this.options = options;
- this.map = new Map({
- controls: defaults({
- zoom: false,
- rotate: false
- }),
- layers: [],
- target: options.dom,
- view: new View({
- center: options.center && options.center.length === 2 ? [options.center[0], options.center[1]] : [110.90153121597234, 21.98323671981171],
- zoom: options.zoom ? options.zoom : 9.6,
- projection: projection,
- maxZoom: options.maxZoom ? options.maxZoom : 18,
- minZoom: options.minZoom ? options.minZoom : 1
- })
- });
- // 初始化比例尺
- if (options.showScale) {
- // this.map.addControl(new AMap.Scale());
- }
- if (options.drawTool?.use) {
- this.initMouseTool(options.drawTool);
- }
- this.initLayer(options);
- }
- async initLayer(options) {
- // 添加新的图层
- if (Array.isArray(options.id)) {
- for (const layer of options.id) {
- if (typeof layer === "string") {
- await this.formatXml(layer); // 等待当前 layer 处理完成
- } else {
- await this.formatXml(layer.id, layer.minZoom, layer.maxZoom, layer.zIndex, layer.visible); // 等待当前 layer 处理完成
- }
- }
- } else if (options.id) {
- // 如果 options.id 不是数组,但确实是一个图层,则直接处理
- await this.formatXml(options.id, options.minZoom, options.maxZoom, options.zIndex, options.visible);
- }
- // 创建Vector层并添加到地图上
- this.vectorLayer = new VectorLayer({
- source: new VectorSource({
- features: []
- })
- });
- this.map.addLayer(this.vectorLayer);
- if (typeof this.options.onLoadCompleted === 'function') {
- this.options.onLoadCompleted(this.map);
- }
- }
- formatXml(code: string, minZoom?: number, maxZoom?: number, zIndex?: number, visible?: boolean) {
- const xml = new WMTSCapabilities();
- return this.getCapabilities(code).then((lists) => {
- const geojson = xml.read(lists.data);
- const data = geojson.Contents.Layer[0];
- const layerParam = {
- layerName: data.Abstract,
- styleName: data.Identifier,
- tilematrixset: data.TileMatrixSetLink[0].TileMatrixSet,
- format: data.Format[0]
- };
- this.createWmsLayer(code, layerParam, minZoom, maxZoom, zIndex, visible);
- });
- }
- // 请求接口获取地图信息
- getCapabilities(code) {
- return axios.get(commonUrl + code + '?SERVICE=WMTS&REQUEST=GetCapabilities');
- }
- // 请求地图图片加载图层
- createWmsLayer(code, layerParam, minZoom = 0, maxZoom, zIndex = -1, visible = true) {
- const source = new WMTS({
- url: commonUrl + code,
- crossOrigin: 'Anonymous',
- layer: layerParam.layerName,
- style: layerParam.styleName,
- matrixSet: layerParam.tilematrixset,
- format: layerParam.format,
- wrapX: true,
- tileGrid: new WMTSTileGrid({
- origin: getTopLeft(projectionExtent),
- resolutions: resolutions,
- matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21']
- })
- });
- const layer = new TileLayer({
- name: code,
- source: source,
- zIndex: zIndex,
- minZoom: minZoom,
- maxZoom,
- visible: visible
- });
- layer.set('layerName', code);
- this.map.addLayer(layer);
- }
- // 初始化绘画工具
- initMouseTool(options) {
- this.drawOptions = {
- graphicsType: options.graphicsType ? options.graphicsType : 'cirlce',
- strokeColor: options.color,
- strokeOpacity: 1,
- strokeWeight: 2,
- fillColor: options.color,
- fillOpacity: options.drawType === '1' ? 0 : 0.5,
- strokeStyle: 'solid'
- };
- // this.plot = new olPlot(this.map, {
- // zoomToExtent: true,
- // ...this.drawOptions
- // });
- // this.plot.plotDraw.on('drawEnd', this.onDrawEnd.bind(this));
- }
- // 绘制结束事件
- onDrawEnd(event) {
- const feature = event.feature;
- const aa = feature.getGeometry();
- // 继续编辑编辑
- this.drawGraphics(this.drawOptions.graphicsType);
- }
- // 绘制图形
- drawGraphics(type: string) {
- if (type === 'circle') {
- // 绘制圆形
- // activate('Circle');
- } else if (type === 'rectangle') {
- // 绘制矩形
- this.plot.plotDraw.activate('RectAngle');
- } else if (type === 'polygon') {
- // 绘制多边形
- this.plot.plotDraw.activate('Polygon');
- } else if (type === 'freePolygon') {
- // 绘制索套
- this.plot.plotDraw.activate('FreePolygon');
- }
- }
- // 关闭绘制
- closeDraw() {
- this.plot.plotDraw.deactivate();
- }
- // 切换图层
- async replaceLayers(newLayers, loadendFunc) {
- // 遍历当前的所有图层并移除它们
- this.map.getLayers().forEach((layer) => {
- this.map.removeLayer(layer);
- });
- if (Array.isArray(newLayers)) {
- for (const layer of newLayers) {
- if (typeof layer === "string") {
- await this.formatXml(layer); // 等待当前 layer 处理完成
- } else {
- await this.formatXml(layer.id, layer.minZoom, layer.maxZoom, layer.zIndex, layer.visible); // 等待当前 layer 处理完成
- }
- }
- } else {
- // 如果 options.id 不是数组,但确实是一个图层,则直接处理
- await this.formatXml(newLayers.id, newLayers.minZoom, newLayers.maxZoom, newLayers.zIndex, newLayers.visible);
- }
- // 创建Vector层并添加到地图上
- this.vectorLayer = new VectorLayer({
- source: new VectorSource({
- features: []
- })
- });
- this.map.addLayer(this.vectorLayer);
- const point = JSON.parse(JSON.stringify(this.markers));
- this.markers = [];
- this.addMarker(point);
- if (loadendFunc) {
- loadendFunc();
- }
- }
- addMarker(points) {
- this.clearMarker('point');
- points.forEach((point) => {
- // 创建标注点
- const feature = new Feature({
- geometry: new Point(point.lnglat),
- name: point.name
- });
- // 定义样式
- const style = new Style({
- image: new Icon({
- anchor: [0.5, point.size[1]],
- anchorXUnits: 'fraction',
- anchorYUnits: 'pixels',
- src: point.icon
- }),
- text: new Text({
- text: point.name,
- fill: new Fill({
- color: '#000'
- }),
- stroke: new Stroke({
- color: '#fff',
- width: 3
- })
- })
- });
- feature.setStyle(style);
- this.markers.push(point);
- this.vectorLayer.getSource().addFeature(feature);
- });
- }
- // 清除所有标加
- clearMarker(id) {
- if (!this.vectorLayer) return;
- this.vectorLayer.getSource().clear();
- }
- /**
- *
- * @param {Geojon} chaozhou 根据geojson对象创建Featrue对象
- * @returns VectorLayer
- */
- createVecByJson(json, options) {
- const format = new GeoJSON();
- const fs = format.readFeatures(json);
- this.maskLayer = new VectorLayer({
- source: new VectorSource(),
- style: new Style({
- fill: new Fill({
- color: options.fillColor ? options.fillColor : 'rgba(16, 36, 59, 0.65)'
- }),
- stroke: new Stroke({
- color: options.strokeColor ? options.strokeColor : 'rgba(38, 138, 185, 1)',
- width: 2
- })
- }),
- zIndex: options.zIndex ? options.zIndex : 99
- });
- this.map.addLayer(this.maskLayer);
- const extent = [-180, -90, 180, 90];
- const polygonRing = fromExtent(extent);
- fs.forEach((x) => {
- const ft = x.values_.geometry;
- const coords = ft.getCoordinates();
- coords.forEach((coord) => {
- const linearRing = new LinearRing(coord[0]);
- polygonRing.appendLinearRing(linearRing);
- });
- });
- const convertFt = new Feature({
- geometry: polygonRing
- });
- this.maskLayer.getSource().addFeature(convertFt);
- }
- createVecByJson2(json, options) {
- if (this.maskLayer2 && this.maskLayer2.length > 0) {
- this.maskLayer2.forEach((layer) => {
- this.map.addLayer(layer);
- });
- } else {
- // const layer = new VectorLayer({
- // source: new VectorSource(),
- // style: new Style({
- // fill: new Fill({
- // color: options.fillColor ? options.fillColor : 'rgba(16, 36, 59, 0.65)'
- // }),
- // stroke: new Stroke({
- // color: options.strokeColor ? options.strokeColor : 'rgba(38, 138, 185, 1)',
- // width: 2
- // })
- // }),
- // zIndex: options.zIndex ? options.zIndex : 99
- // });
- // // 合并区边界
- // const format = new GeoJSON();
- // const data2 = mergeGeoJsonPolygons(json);
- // const fs = format.readFeatures(data2);
- // const extent = [-180, -90, 180, 90];
- // const polygonRing = fromExtent(extent);
- // fs.forEach((x) => {
- // const ft = x.values_.geometry;
- // const coords = ft.getCoordinates();
- // coords.forEach((coord) => {
- // const linearRing = new LinearRing(coord[0]);
- // polygonRing.appendLinearRing(linearRing);
- // });
- // });
- // const convertFt = new Feature({
- // geometry: polygonRing
- // });
- // layer.getSource().addFeature(convertFt);
- // this.maskLayer2.push(layer);
- // this.map.addLayer(layer);
- // 边界部分
- json.features.forEach((feature) => {
- if (feature.geometry.type === 'Polygon') {
- const polygonPath = feature.geometry.coordinates[0].map((coord) => {
- return [coord[0], coord[1]];
- });
- const feature2 = new Feature({
- geometry: new Polygon([polygonPath])
- });
- const vector = new VectorLayer({
- source: new VectorSource(),
- style: new Style({
- fill: new Fill({
- color: 'rgba(0, 0, 0, 0)'
- }),
- stroke: new Stroke({
- color: options.strokeColor ? options.strokeColor : '#268ab9',
- width: options.strokeWeight ? options.strokeWeight : 1
- })
- })
- });
- vector.getSource().addFeature(feature2);
- this.maskLayer2.push(vector);
- this.map.addLayer(vector);
- } else if (feature.geometry.type === 'MultiPolygon') {
- feature.geometry.coordinates.forEach((polygonCoords) => {
- const polygonPath = polygonCoords.map((ring) => {
- return ring.map((coord) => {
- return [coord[0], coord[1]];
- });
- });
- const outerPath = polygonPath;
- const feature2 = new Feature({ geometry: new Polygon(outerPath), });
- const vector = new VectorLayer({
- source: new VectorSource(),
- style: new Style({
- fill: new Fill({
- color: 'rgba(0, 0, 0, 0)'
- }),
- stroke: new Stroke({
- color: options.strokeColor ? options.strokeColor : '#268ab9',
- width: options.strokeWeight ? options.strokeWeight : 1
- })
- })
- });
- vector.getSource().addFeature(feature2);
- this.maskLayer2.push(vector);
- this.map.addLayer(vector);
- });
- }
- });
- }
- }
- /**
- * @description 创建矢量图层
- * @param {String} layerName 图层名称
- * @param {Number} zIndex 地图层级默认是0
- * @returns
- */
- createVecLayer(layerName = '', zIndex = 0) {
- const source = new SourceVector({
- crossOrigin: 'anonymous'
- });
- const layer = new Vector({
- source,
- zIndex
- });
- layer.set('layerName', layerName);
- return layer;
- }
- // 分布图遮罩层
- createMask(data) {
- this.removeMask();
- if (!data || data.length === 0) return;
- data.forEach((item) => {
- if (!item.points || item.points.length === 0) return;
- // 遮罩图层的样式
- const maskStyle = new Style({
- fill: new Fill({
- color: item.color // 红色遮罩,50%透明度
- }),
- stroke: new Stroke({
- color: 'rgba(159,159,159,0.7)',
- width: 1
- })
- });
- // 遮罩图层的矢量数据源(初始为空)
- const maskSource = new VectorSource();
- // 创建一个多边形特征
- const polygonFeature = new Feature({
- geometry: new Polygon(item.points)
- });
- const maskLayer = new VectorLayer({
- source: maskSource,
- style: maskStyle,
- properties: {
- name: 'mask'
- }
- });
- this.map.addLayer(maskLayer);
- // 将多边形特征添加到遮罩数据源中
- maskSource.addFeature(polygonFeature);
- });
- }
- removeMask() {
- //移除图层
- const layersArray = this.map.getLayers().getArray();
- layersArray.forEach((layer) => {
- // 检查图层是否有自定义属性,并且该属性是否匹配你要移除的图层的标识符
- if (layer.get('name') === 'mask') {
- this.map.removeLayer(layer);
- }
- });
- }
- removeMask2() {
- if (this.maskLayer) {
- this.map.removeLayer(this.maskLayer);
- this.maskLayer = null;
- }
- }
- removeMask3(isHide) {
- if (this.maskLayer2 && this.maskLayer2.length > 0) {
- this.maskLayer2.forEach((layer) => {
- this.map.removeLayer(layer);
- });
- if (!isHide) {
- this.maskLayer2 = [];
- }
- }
- }
- /**
- * 绘制经纬线
- * visible: boolean 是否可见
- */
- handleLngLatLine(visible: boolean) {
- // 创建经纬网图层
- const graticule = new Graticule({
- name: 'Graticule',
- showLabels: true, // 为每条刻度线绘制一个带有各自纬度/经度的标签
- wrapX: false, // 是否水平重复经纬网
- targetSize: 230,
- zIndex: 99999,
- strokeStyle: new Stroke({ // 用于绘制刻度线的样式
- color: '#dcdcdc', // 线条颜色
- width: 1, // 线条宽度
- }),
- lonLabelStyle: new Text({
- font: '12px Calibri,sans-serif',
- textBaseline: 'bottom',
- fill: new Fill({
- color: '#9d9d9d'
- })
- }),
- latLabelPosition: 0,
- latLabelStyle: new Text({
- font: '12px Calibri,sans-serif',
- textAlign: 'left',
- textBaseline: 'end',
- fill: new Fill({
- color: '#9d9d9d'
- })
- })
- });
- if (visible) {
- this.map.addLayer(graticule)
- } else {
- this.removeLayer('Graticule')
- }
- }
- /**
- * 移除指定name的layer
- * layerName: string
- * */
- removeLayer(layerName: string) {
- const layers = this.map.getLayers();
- layers.forEach((element) => {
- if (!!element && element.get('name') === layerName) {
- //移除
- this.map.removeLayer(element);
- }
- });
- }
- }
|