From 38962ebeece5484a70320791a2837e39c8813007 Mon Sep 17 00:00:00 2001 From: luoxiao Date: Thu, 9 May 2024 14:37:03 +0800 Subject: [PATCH] =?UTF-8?q?[fix]=E7=9F=A2=E9=87=8F=E7=93=A6=E7=89=87?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E5=9D=90=E6=A0=87=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../layers/src/tile/tileLayer/BaseLayer.ts | 6 ++- packages/maps/src/mapbox/utils.ts | 52 ++++++++++++++++--- packages/source/src/source/vector.ts | 13 ++++- .../src/tileset-manager/tileset-manager.ts | 8 ++- .../src/tileset-manager/utils/lonlat-tile.ts | 9 ++-- 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/packages/layers/src/tile/tileLayer/BaseLayer.ts b/packages/layers/src/tile/tileLayer/BaseLayer.ts index d699ef476fa..2a7fa14740b 100644 --- a/packages/layers/src/tile/tileLayer/BaseLayer.ts +++ b/packages/layers/src/tile/tileLayer/BaseLayer.ts @@ -72,7 +72,7 @@ export default class BaseTileLayer { } const { latLonBounds, zoom } = this.getCurrentView(); - this.tilesetManager?.update(zoom, latLonBounds); + this.tilesetManager?.update(zoom, latLonBounds, this.getMap()); } protected mapchange = () => { const { latLonBounds, zoom } = this.getCurrentView(); @@ -112,6 +112,10 @@ export default class BaseTileLayer { return { latLonBounds, zoom }; } + getMap() { + return this.mapService.map; + } + private bindTilesetEvent() { // 瓦片数据加载成功 // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/packages/maps/src/mapbox/utils.ts b/packages/maps/src/mapbox/utils.ts index 18202c78c00..8d0e4b6fa73 100644 --- a/packages/maps/src/mapbox/utils.ts +++ b/packages/maps/src/mapbox/utils.ts @@ -1,6 +1,6 @@ import mapboxgl from 'mapbox-gl'; +import { CoordinateSystem } from '../../../core/src/services/coordinate/ICoordinateSystemService'; import { getScaleByZoom } from '../viewport-mercator-project'; -import { CoordinateSystem } from "../../../core/src/services/coordinate/ICoordinateSystemService"; const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12; // mapboxgl多坐标系,投影计算 @@ -14,7 +14,6 @@ export function fromWGS84( return map.getCRS().fromWGS84([lng, lat]); } - export function toWGS84( coor: [number, number] | undefined, map: mapboxgl.Map | maplibregl.Map, @@ -24,6 +23,16 @@ export function toWGS84( // @ts-ignore return map.getCRS().toWGS84([x, y]); } +export function toLngLat( + coor: [number, number] | undefined, + map: mapboxgl.Map | maplibregl.Map, +) { + if (!coor) return; + const [x, y] = coor || []; + // @ts-ignore + const {lng, lat}= map.getCRS().toLngLat(x, y); + return [lng, lat]; +} // mapboxgl多坐标系,获取extent @@ -82,9 +91,9 @@ export function transformLnglat( const origin = targetLnglat ? fromWGS84(targetLnglat, map) : [extent[0], extent[3]]; - const y = origin[1] - (((xy[1]/worldScales)) * height) - const x = (xy[0]/ worldScales * width) + origin[0]; - return toWGS84([x,y], map); + const y = origin[1] - (xy[1] / worldScales) * height; + const x = (xy[0] / worldScales) * width + origin[0]; + return toWGS84([x, y], map); } export function isMultiCoor(map: any): boolean { @@ -93,18 +102,45 @@ export function isMultiCoor(map: any): boolean { } return true; } -export function getCoordinateSystem(map: any, offsetCoordinate = true): boolean { +export function getCoordinateSystem( + map: any, + offsetCoordinate = true, +): boolean { if (!map) { return false; } if (map.getZoom() > LNGLAT_OFFSET_ZOOM_THRESHOLD && offsetCoordinate) { const crs = map.getCRS(); - if (crs && ( crs.unit==='degrees' || crs.unit==='degree' || crs.epsgCode==='EPSG:3857' )) { + if ( + crs && + (crs.unit === 'degrees' || + crs.unit === 'degree' || + crs.epsgCode === 'EPSG:3857') + ) { return CoordinateSystem.LNGLAT_OFFSET; - }else{ + } else { return CoordinateSystem.METER_OFFSET; } } else { return CoordinateSystem.LNGLAT; } } +// 当前级别一张瓦片代表的地理宽度 +function getResolutionRatio(zoom:number, map: mapboxgl.Map) { + const extent = getCRSExtent(map); + const width = extent[2] - extent[0]; + const height = extent[3] - extent[1]; + const ratio_0 = Math.max(width, height) / 512; + const ratio = ratio_0 / Math.pow(2, zoom); + return ratio * 512; +} +export function getTileXY(lnglat: [number, number], z:number, map: mapboxgl.Map) { + // 当前级别一张瓦片代表的地理宽度 + const ratio = getResolutionRatio(z, map); + const extent = getCRSExtent(map); + const [x, y] = fromWGS84(lnglat, map); + + const tileX = (x - extent[0]) / ratio; + const tileY = (extent[3] - y) / ratio; + return [Math.floor(tileX), Math.floor(tileY)]; +} diff --git a/packages/source/src/source/vector.ts b/packages/source/src/source/vector.ts index 21c34ddbf04..ce9d3d75155 100644 --- a/packages/source/src/source/vector.ts +++ b/packages/source/src/source/vector.ts @@ -1,7 +1,11 @@ -import { VectorTile } from '@mapbox/vector-tile'; import { Feature, Properties } from '@turf/helpers'; import Protobuf from 'pbf'; import { ITileSource } from '../interface'; +import { toLngLat } from '../../../maps/src/mapbox/utils' +import { global } from '../../../maps/src/mapbox/mapInstance' + +const VectorTile = window.mapboxgl.mapbox.VectorTile; + export default class VectorSource implements ITileSource { private vectorTile: VectorTile; private vectorLayerCache: { @@ -41,7 +45,12 @@ export default class VectorSource implements ITileSource { const features: Array> = []; for (let i = 0; i < vectorTile.length; i++) { const vectorTileFeature = vectorTile.feature(i); - const feature = vectorTileFeature.toGeoJSON(this.x, this.y, this.z); + // const toLngLat = map.getCRS().toWGS84 + const toLngLat1 = function (x, y) { + const forward = toLngLat([x, y], global.map) + return forward; + }; + const feature = vectorTileFeature.toGeoJSON(this.x, this.y, this.z, toLngLat1); features.push({ ...feature, diff --git a/packages/utils/src/tileset-manager/tileset-manager.ts b/packages/utils/src/tileset-manager/tileset-manager.ts index 6881f6ef5ab..f18318ec6fd 100644 --- a/packages/utils/src/tileset-manager/tileset-manager.ts +++ b/packages/utils/src/tileset-manager/tileset-manager.ts @@ -52,6 +52,7 @@ export class TilesetManager extends EventEmitter { latLonBounds: [number, number, number, number]; latLonBoundsBuffer: [number, number, number, number]; }; + private map: any; constructor(options: Partial) { super(); @@ -88,10 +89,12 @@ export class TilesetManager extends EventEmitter { // 更新 // 1.瓦片序号发生改变 2.瓦片新增 3.瓦片显隐控制 - public update(zoom: number, latLonBounds: [number, number, number, number]) { + public update(zoom: number, latLonBounds: [number, number, number, number], map?: any) { // 校验层级,向上取整 const verifyZoom = Math.max(0, Math.ceil(zoom)); - + if(map) { + this.map = map; + } if ( this.lastViewStates && this.lastViewStates.zoom === verifyZoom && @@ -311,6 +314,7 @@ export class TilesetManager extends EventEmitter { zoom, latLonBounds, extent, + map: this.map }); return indices; diff --git a/packages/utils/src/tileset-manager/utils/lonlat-tile.ts b/packages/utils/src/tileset-manager/utils/lonlat-tile.ts index c61e1872095..ef1221299c7 100644 --- a/packages/utils/src/tileset-manager/utils/lonlat-tile.ts +++ b/packages/utils/src/tileset-manager/utils/lonlat-tile.ts @@ -1,5 +1,6 @@ import { DEFAULT_EXTENT } from '../const'; import { TileBounds } from '../types'; +import { getTileXY } from '../.../../../../../maps/src/mapbox/utils' // // https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#ECMAScript_.28JavaScript.2FActionScript.2C_etc..29 export function osmLonLat2TileXY(lon: number, lat: number, zoom: number) { @@ -47,6 +48,7 @@ export function getTileIndices({ minZoom = 0, zoomOffset = 0, extent = DEFAULT_EXTENT, + map }: { zoom: number; latLonBounds: TileBounds; @@ -66,7 +68,6 @@ export function getTileIndices({ if (Number.isFinite(maxZoom) && z > maxZoom) { z = maxZoom; } - const [minLng, minLat, maxLng, maxLat] = latLonBounds; const bounds = [ Math.max(minLng, extent[0]), @@ -77,8 +78,10 @@ export function getTileIndices({ const indices = []; - const [minX, maxY] = osmLonLat2TileXY(bounds[0], bounds[1], z); - const [maxX, minY] = osmLonLat2TileXY(bounds[2], bounds[3], z); + // const [minX, maxY] = osmLonLat2TileXY(bounds[0], bounds[1], z); + // const [maxX, minY] = osmLonLat2TileXY(bounds[2], bounds[3], z); + const [minX, maxY] = getTileXY([bounds[0], bounds[1]], z, map); + const [maxX, minY] = getTileXY([bounds[2], bounds[3]], z, map); for (let x = minX; x <= maxX; x++) { for (let y = minY; y <= maxY; y++) {