olMap.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // 引入OpenLayers的主模块
  2. import Map from 'ol/Map';
  3. import View from 'ol/View';
  4. import Feature from 'ol/Feature';
  5. import Point from 'ol/geom/Point';
  6. import VectorLayer from 'ol/layer/Vector';
  7. import VectorSource from 'ol/source/Vector';
  8. import Style from 'ol/style/Style';
  9. import Icon from 'ol/style/Icon';
  10. import Text from 'ol/style/Text';
  11. import Projection from 'ol/proj/Projection';
  12. import { getWidth, getTopLeft } from 'ol/extent';
  13. import TileLayer from 'ol/layer/Tile';
  14. import WMTS from 'ol/source/WMTS';
  15. import WMTSTileGrid from 'ol/tilegrid/WMTS';
  16. import WMTSCapabilities from 'ol/format/WMTSCapabilities';
  17. import { Fill, Stroke } from 'ol/style';
  18. import proj4 from 'proj4';
  19. import { register } from 'ol/proj/proj4';
  20. import { defaults } from 'ol/control';
  21. import Vector from 'ol/layer/Vector';
  22. import SourceVector from 'ol/source/Vector';
  23. import GeoJSON from 'ol/format/GeoJSON';
  24. import { fromLonLat } from 'ol/proj';
  25. import axios from 'axios';
  26. import { fromExtent } from 'ol/geom/Polygon';
  27. import { LinearRing, Polygon } from 'ol/geom';
  28. import { Tile } from 'ol';
  29. // import olPlot from 'ol-plot';
  30. // import { activate } from '../ol-plot/ol-plot'
  31. proj4.defs('EPSG:4490', '+proj=longlat +ellps=GRS80 +no_defs +type=crs');
  32. 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');
  33. register(proj4);
  34. const commonUrl = import.meta.env.VITE_APP_BASE_API2 + 'api/oneShare/proxyHandler/gd/';
  35. const projection = new Projection({
  36. code: 'EPSG:4490',
  37. units: 'degrees'
  38. });
  39. const projectionExtent = [-180, -90, 180, 90];
  40. const size = getWidth(projectionExtent) / 256;
  41. const resolutions = [];
  42. for (let z = 2; z < 22; ++z) {
  43. resolutions[z] = size / Math.pow(2, z);
  44. }
  45. export class olMap {
  46. private map;
  47. private options;
  48. private markers = [];
  49. private drawOptions = {
  50. graphicsType: 'circle',
  51. strokeColor: '#f80102',
  52. strokeOpacity: 1,
  53. strokeWeight: 2,
  54. fillColor: '#f80102',
  55. fillOpacity: 0,
  56. strokeStyle: 'solid'
  57. };
  58. // private { currentState, commit, undo, history, future } = useHistory();
  59. private overlays = [];
  60. private overlaysData = [];
  61. private graphicsType = '';
  62. private plot;
  63. private vectorLayer;
  64. private maskLayer;
  65. constructor(options) {
  66. this.options = options;
  67. this.map = new Map({
  68. controls: defaults({
  69. zoom: false,
  70. rotate: false
  71. }),
  72. layers: [],
  73. target: options.dom,
  74. view: new View({
  75. center: options.center && options.center.length === 2 ? [options.center[0], options.center[1]] : [110.90153121597234, 21.98323671981171],
  76. zoom: options.zoom ? options.zoom : 9.6,
  77. projection: projection,
  78. maxZoom: options.maxZoom ? options.maxZoom : 18,
  79. minZoom: options.minZoom ? options.minZoom : 1
  80. })
  81. });
  82. // 初始化比例尺
  83. if (options.showScale) {
  84. // map.addControl(new AMap.Scale());
  85. }
  86. if (options.drawTool?.use) {
  87. this.initMouseTool(options.drawTool);
  88. }
  89. this.initLayer(options);
  90. }
  91. async initLayer(options) {
  92. // 添加新的图层
  93. if (Array.isArray(options.id)) {
  94. for (const layer of options.id) {
  95. await this.formatXml(layer); // 等待当前 layer 处理完成
  96. }
  97. } else if (options.id) {
  98. // 如果 options.id 不是数组,但确实是一个图层,则直接处理
  99. await this.formatXml(options.id);
  100. }
  101. console.log('wan');
  102. // 创建Vector层并添加到地图上
  103. this.vectorLayer = new VectorLayer({
  104. source: new VectorSource({
  105. features: []
  106. })
  107. });
  108. this.map.addLayer(this.vectorLayer);
  109. if (typeof this.options.onLoadCompleted === 'function') {
  110. this.options.onLoadCompleted(this.map);
  111. }
  112. }
  113. formatXml(code, minZoom, maxZoom, zIndex, visible) {
  114. const xml = new WMTSCapabilities();
  115. // axios.post(commonUrl + 'YZT1723547712680', '<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs"service="WFS"version="1.0.0"outputFormat="GeoJson"maxFeatures="99999"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.opengis.net/wfshttp://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd">\n' +
  116. // '<wfs:QuerytypeName="GDSMMSZJGZDTJX_2023"userecent="true"/>\n' +
  117. // '</wfs:GetFeature>');
  118. return this.getCapabilities(code).then((lists) => {
  119. const geojson = xml.read(lists.data);
  120. debugger
  121. const data = geojson.Contents.Layer[0];
  122. const layerParam = {
  123. layerName: data.Abstract,
  124. styleName: data.Identifier,
  125. tilematrixset: data.TileMatrixSetLink[0].TileMatrixSet,
  126. format: data.Format[0]
  127. };
  128. this.createWmsLayer(code, layerParam, minZoom, maxZoom, zIndex, visible);
  129. });
  130. }
  131. // 请求接口获取地图信息
  132. getCapabilities(code) {
  133. return axios.get(commonUrl + code + '?SERVICE=WMTS&REQUEST=GetCapabilities');
  134. }
  135. // 请求地图图片加载图层
  136. createWmsLayer(code, layerParam, minZoom = 0, maxZoom, zIndex = -1, visible = true) {
  137. const source = new WMTS({
  138. url: commonUrl + code,
  139. crossOrigin: 'Anonymous',
  140. layer: layerParam.layerName,
  141. style: layerParam.styleName,
  142. matrixSet: layerParam.tilematrixset,
  143. format: layerParam.format,
  144. wrapX: true,
  145. tileGrid: new WMTSTileGrid({
  146. origin: getTopLeft(projectionExtent),
  147. resolutions: resolutions,
  148. matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21']
  149. })
  150. });
  151. const layer = new TileLayer({
  152. source: source,
  153. zIndex: zIndex,
  154. minZoom: minZoom,
  155. maxZoom,
  156. visible: visible
  157. });
  158. layer.set('layerName', code);
  159. this.map.addLayer(layer);
  160. console.log(code);
  161. }
  162. // 初始化绘画工具
  163. initMouseTool(options) {
  164. this.drawOptions = {
  165. graphicsType: options.graphicsType ? options.graphicsType : 'cirlce',
  166. strokeColor: options.color,
  167. strokeOpacity: 1,
  168. strokeWeight: 2,
  169. fillColor: options.color,
  170. fillOpacity: options.drawType === '1' ? 0 : 0.5,
  171. strokeStyle: 'solid'
  172. };
  173. // this.plot = new olPlot(this.map, {
  174. // zoomToExtent: true,
  175. // ...this.drawOptions
  176. // });
  177. // this.plot.plotDraw.on('drawEnd', this.onDrawEnd.bind(this));
  178. }
  179. // 绘制结束事件
  180. onDrawEnd(event) {
  181. const feature = event.feature;
  182. const aa = feature.getGeometry();
  183. // 继续编辑编辑
  184. this.drawGraphics(this.drawOptions.graphicsType);
  185. }
  186. // 绘制图形
  187. drawGraphics(type: string) {
  188. if (type === 'circle') {
  189. // 绘制圆形
  190. // activate('Circle');
  191. } else if (type === 'rectangle') {
  192. // 绘制矩形
  193. this.plot.plotDraw.activate('RectAngle');
  194. } else if (type === 'polygon') {
  195. // 绘制多边形
  196. this.plot.plotDraw.activate('Polygon');
  197. } else if (type === 'freePolygon') {
  198. // 绘制索套
  199. this.plot.plotDraw.activate('FreePolygon');
  200. }
  201. }
  202. // 关闭绘制
  203. closeDraw() {
  204. this.plot.plotDraw.deactivate();
  205. }
  206. // 切换图层
  207. async replaceLayers(newLayers) {
  208. // 遍历当前的所有图层并移除它们
  209. this.map.getLayers().forEach((layer) => {
  210. this.map.removeLayer(layer);
  211. });
  212. // 添加新的图层
  213. if (Array.isArray(newLayers)) {
  214. for (const layer of newLayers) {
  215. await this.formatXml(layer); // 等待当前 layer 处理完成
  216. }
  217. } else if (newLayers) {
  218. // 如果 options.id 不是数组,但确实是一个图层,则直接处理
  219. await this.formatXml(newLayers);
  220. }
  221. // 创建Vector层并添加到地图上
  222. this.vectorLayer = new VectorLayer({
  223. source: new VectorSource({
  224. features: []
  225. })
  226. });
  227. this.map.addLayer(this.vectorLayer);
  228. const point = JSON.parse(JSON.stringify(this.markers));
  229. this.markers = [];
  230. this.addMarker(point);
  231. }
  232. addMarker(points) {
  233. this.clearMarker('point');
  234. points.forEach((point) => {
  235. // 创建标注点
  236. const feature = new Feature({
  237. geometry: new Point(point.lnglat),
  238. name: point.name
  239. });
  240. // 定义样式
  241. const style = new Style({
  242. image: new Icon({
  243. anchor: [0.5, point.size[1]],
  244. anchorXUnits: 'fraction',
  245. anchorYUnits: 'pixels',
  246. src: point.icon
  247. }),
  248. text: new Text({
  249. text: point.name,
  250. fill: new Fill({
  251. color: '#000'
  252. }),
  253. stroke: new Stroke({
  254. color: '#fff',
  255. width: 3
  256. })
  257. })
  258. });
  259. feature.setStyle(style);
  260. this.markers.push(point);
  261. this.vectorLayer.getSource().addFeature(feature);
  262. });
  263. }
  264. // 清除所有标加
  265. clearMarker(id) {
  266. if (!this.vectorLayer) return;
  267. this.vectorLayer.getSource().clear();
  268. }
  269. /**
  270. *
  271. * @param {Geojon} chaozhou 根据geojson对象创建Featrue对象
  272. * @returns VectorLayer
  273. */
  274. createVecByJson(json, options) {
  275. const format = new GeoJSON();
  276. const fs = format.readFeatures(json);
  277. const converLayer = new VectorLayer({
  278. source: new VectorSource(),
  279. style: new Style({
  280. fill: new Fill({
  281. color: options.fillColor ? options.fillColor : 'rgba(16, 36, 59, 0.65)'
  282. }),
  283. stroke: new Stroke({
  284. color: options.strokeColor ? options.strokeColor : 'rgba(38, 138, 185, 1)',
  285. width: 2
  286. })
  287. }),
  288. zIndex: options.zIndex ? options.zIndex : 99
  289. });
  290. this.map.addLayer(this.maskLayer);
  291. const extent = [-180, -90, 180, 90];
  292. const polygonRing = fromExtent(extent);
  293. fs.forEach((x) => {
  294. const ft = x.values_.geometry;
  295. const coords = ft.getCoordinates();
  296. coords.forEach((coord) => {
  297. const linearRing = new LinearRing(coord[0]);
  298. polygonRing.appendLinearRing(linearRing);
  299. });
  300. });
  301. const convertFt = new Feature({
  302. geometry: polygonRing
  303. });
  304. this.maskLayer.getSource().addFeature(convertFt);
  305. }
  306. // 分布图遮罩层
  307. createMask(data) {
  308. this.removeMask();
  309. if (!data || data.length === 0) return;
  310. data.forEach((item) => {
  311. // 遮罩图层的样式
  312. const maskStyle = new Style({
  313. fill: new Fill({
  314. color: item.color // 红色遮罩,50%透明度
  315. }),
  316. stroke: new Stroke({
  317. color: 'rgba(159,159,159,0.7)',
  318. width: 1
  319. })
  320. });
  321. // 遮罩图层的矢量数据源(初始为空)
  322. const maskSource = new VectorSource();
  323. // 创建一个多边形特征
  324. const polygonFeature = new Feature({
  325. geometry: new Polygon(item.points)
  326. });
  327. const maskLayer = new VectorLayer({
  328. source: maskSource,
  329. style: maskStyle,
  330. properties: {
  331. name: 'mask'
  332. }
  333. });
  334. this.map.addLayer(maskLayer);
  335. // 将多边形特征添加到遮罩数据源中
  336. maskSource.addFeature(polygonFeature);
  337. });
  338. }
  339. removeMask() {
  340. //移除图层
  341. const layersArray = this.map.getLayers().getArray();
  342. layersArray.forEach((layer) => {
  343. // 检查图层是否有自定义属性,并且该属性是否匹配你要移除的图层的标识符
  344. if (layer.get('name') === 'mask') {
  345. this.map.removeLayer(layer);
  346. }
  347. });
  348. }
  349. removeMask2() {
  350. if (this.maskLayer) {
  351. this.map.removeLayer(this.maskLayer);
  352. this.maskLayer = null;
  353. }
  354. }
  355. }