diff --git a/packages/gl/src/layer/util/imageMesh.ts b/packages/gl/src/layer/util/imageMesh.ts index fe34d8eb33..01eaf63785 100644 --- a/packages/gl/src/layer/util/imageMesh.ts +++ b/packages/gl/src/layer/util/imageMesh.ts @@ -48,14 +48,16 @@ export function createImageMesh(geometry, image, extent2d, offset, scale, unifor } export function updateFilter(mesh: reshader.Mesh, map: maptalks.Map, res: number) { - const minFilter = getTexMinFilter(map); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const dpr = cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); + const minFilter = getTexMinFilter(map, zoom); if (mesh.properties.minFilter !== minFilter) { const baseColorTexture = (mesh.material.get('baseColorTexture') as any); baseColorTexture.setMinFilter(minFilter); mesh.properties.minFilter = minFilter; } - const dpr = map.getDevicePixelRatio(); const resized = map.getResolution() !== res; let magFilter: number = WebGLConstants.GL_NEAREST; @@ -69,8 +71,7 @@ export function updateFilter(mesh: reshader.Mesh, map: maptalks.Map, res: number } } -function getTexMinFilter(map: maptalks.Map) { - const zoom = map.getZoom(); +function getTexMinFilter(map: maptalks.Map, zoom: number) { const blurTexture = map.isMoving() && map.getRenderer().isViewChanged(); let minFilter; if (blurTexture) { diff --git a/packages/maptalks/src/core/mapbox/index.ts b/packages/maptalks/src/core/mapbox/index.ts index 9edeb792a9..62e6d0458b 100644 --- a/packages/maptalks/src/core/mapbox/index.ts +++ b/packages/maptalks/src/core/mapbox/index.ts @@ -22,8 +22,8 @@ export function loadGeoSymbol(symbol, geo): any { let bearing = 0, pitch = 0, zoom = 10, hasMap = !!map; if (map) { const mapId = map.id; - if (MapStateCache[mapId]) { - const cache = MapStateCache[mapId]; + const cache = MapStateCache[mapId]; + if (cache) { bearing = cache.bearing; pitch = cache.pitch; zoom = cache.zoom; diff --git a/packages/maptalks/src/geometry/Circle.ts b/packages/maptalks/src/geometry/Circle.ts index 1dc46dceb2..9a89d07b68 100644 --- a/packages/maptalks/src/geometry/Circle.ts +++ b/packages/maptalks/src/geometry/Circle.ts @@ -4,6 +4,7 @@ import Coordinate from '../geo/Coordinate'; import Extent from '../geo/Extent'; import Point from '../geo/Point'; import { CommonProjectionType } from '../geo/projection'; +import { MapStateCache } from '../map/MapStateCache'; import CenterMixin from './CenterMixin'; import Polygon, { PolygonOptionsType, RingCoordinates, RingsCoordinates } from './Polygon'; @@ -122,7 +123,9 @@ export class Circle extends CenterMixin(Polygon) { //@internal _containsPoint(point: Point, tolerance?: number): boolean { const map = this.getMap(); - if (map.getPitch()) { + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + if (pitch) { return super._containsPoint(point, tolerance); } const center = map._pointToContainerPoint(this._getCenter2DPoint()), diff --git a/packages/maptalks/src/geometry/Geometry.ts b/packages/maptalks/src/geometry/Geometry.ts index b4778fbf17..ebe95d6153 100644 --- a/packages/maptalks/src/geometry/Geometry.ts +++ b/packages/maptalks/src/geometry/Geometry.ts @@ -34,6 +34,7 @@ import type { Map } from '../map'; import { WithNull } from '../types/typings'; import { InfoWindowOptionsType } from '../ui/InfoWindow'; import { getMinMaxAltitude } from '../core/util/path'; +import { MapStateCache } from '../map/MapStateCache'; const TEMP_POINT0 = new Point(0, 0); const TEMP_EXTENT = new PointExtent(); @@ -697,7 +698,9 @@ export class Geometry extends JSONAble(Eventable(Handlerable(Class))) { map._prjToPointAtRes(min, glRes, min); map._prjToPointAtRes(max, glRes, max); this._extent2d = new PointExtent(min, max); - (this._extent2d as any).z = map.getZoom(); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + (this._extent2d as any).z = zoom; return this._extent2d; } diff --git a/packages/maptalks/src/geometry/editor/GeometryEditor.ts b/packages/maptalks/src/geometry/editor/GeometryEditor.ts index 80b9bd9f19..d8a84e8be1 100644 --- a/packages/maptalks/src/geometry/editor/GeometryEditor.ts +++ b/packages/maptalks/src/geometry/editor/GeometryEditor.ts @@ -13,6 +13,7 @@ import * as Symbolizers from '../../renderer/geometry/symbolizers'; import { GeometryEditOptionsType, GeometryEditSymbolType } from '../ext/Geometry.Edit'; import { getDefaultBBOX, pointsBBOX } from '../../core/util/bbox'; import Extent from '../../geo/Extent'; +import { MapStateCache } from '../../map/MapStateCache'; const EDIT_STAGE_LAYER_PREFIX = INTERNAL_LAYER_PREFIX + '_edit_stage_'; const SHADOW_DRAG_EVENTS = 'dragend dragstart'; @@ -39,9 +40,9 @@ function createHandleSymbol(markerType: string, opacity: number): GeometryEditSy /** * coordinate to containerPoint with altitude - * @param map - * @param coordinate - * @returns + * @param map + * @param coordinate + * @returns */ function coordinatesToContainerPoint(map, coordinate) { const glRes = map.getGLRes(); @@ -519,13 +520,18 @@ class GeometryEditor extends Eventable(Class) { _createHandleInstance(containerPoint: Point, opts: GeometryEditOptionsType): EditHandle { opts = opts || {}; const map = this.getMap(); + const symbol = loadFunctionTypes(opts['symbol'], (): any => { + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const pitch = cache ? cache.pitch : map.getPitch(); + const bearing = cache ? cache.bearing : map.getBearing(); return [ - map.getZoom(), + zoom, { - '{bearing}': map.getBearing(), - '{pitch}': map.getPitch(), - '{zoom}': map.getZoom() + '{bearing}': bearing, + '{pitch}': pitch, + '{zoom}': zoom } ]; }); diff --git a/packages/maptalks/src/geometry/ext/Geometry.Drag.ts b/packages/maptalks/src/geometry/ext/Geometry.Drag.ts index 74fcb0fcf7..6f714031c9 100644 --- a/packages/maptalks/src/geometry/ext/Geometry.Drag.ts +++ b/packages/maptalks/src/geometry/ext/Geometry.Drag.ts @@ -9,6 +9,7 @@ import { ConnectorLine } from '../ConnectorLine'; import Point from '../../geo/Point'; import Coordinate from '../../geo/Coordinate'; import { getResouceCacheInstance } from '../../core/ResourceCacheManager'; +import { MapStateCache } from '../../map/MapStateCache'; const DRAG_STAGE_LAYER_ID = INTERNAL_LAYER_PREFIX + '_drag_stage'; @@ -424,7 +425,9 @@ class GeometryDragHandler extends Handler { //@internal _correctCoord(coord: any): any { const map = this.target.getMap(); - if (!map.getPitch()) { + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + if (!pitch) { return coord; } const target = this.target; diff --git a/packages/maptalks/src/layer/ImageLayer.ts b/packages/maptalks/src/layer/ImageLayer.ts index ba7f98fb35..f9156462bc 100644 --- a/packages/maptalks/src/layer/ImageLayer.ts +++ b/packages/maptalks/src/layer/ImageLayer.ts @@ -9,6 +9,7 @@ import Layer, { LayerOptionsType } from './Layer'; import { PointExtent } from '../geo'; import { getResouceCacheInstance } from '../core/ResourceCacheManager'; import { MixinConstructor } from '../core/Mixin'; +import { MapStateCache } from '../map/MapStateCache'; /** @@ -257,7 +258,9 @@ export class ImageLayerCanvasRenderer extends ImageLayerRenderable(CanvasRendere const nw = TEMP_POINT.set(extent.xmin, extent.ymax); const point = map._pointAtResToContainerPoint(nw, map.getGLRes()); let x = point.x, y = point.y; - const bearing = map.getBearing(); + const cache = MapStateCache[map.id]; + const bearing = cache ? cache.bearing : map.getBearing(); + if (bearing) { ctx.save(); ctx.translate(x, y); diff --git a/packages/maptalks/src/layer/Layer.ts b/packages/maptalks/src/layer/Layer.ts index ce81ad984e..48e2ea4579 100644 --- a/packages/maptalks/src/layer/Layer.ts +++ b/packages/maptalks/src/layer/Layer.ts @@ -12,6 +12,7 @@ import { CommonProjectionType } from '../geo/projection'; import Coordinate from '../geo/Coordinate'; import Point from '../geo/Point'; import LayerAbstractRenderer from '../renderer/layer/LayerAbstractRenderer'; +import { MapStateCache } from '../map/MapStateCache'; /** * 配置项 @@ -501,13 +502,16 @@ class Layer extends JSONAble(Eventable(Renderable(Class))) { if (isNumber(opacity) && opacity <= 0) { return false; } - const map = this.map; - if (map) { - const zoom = map.getZoom(); - const minZoom = this.options.minZoom, maxZoom = this.options.maxZoom; - if ((!isNil(maxZoom) && maxZoom < zoom) || - (!isNil(minZoom) && minZoom > zoom)) { - return false; + const { minZoom, maxZoom } = this.options; + if (isNumber(minZoom) || isNumber(maxZoom)) { + const map = this.map; + if (map) { + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + if ((!isNil(maxZoom) && maxZoom < zoom) || + (!isNil(minZoom) && minZoom > zoom)) { + return false; + } } } diff --git a/packages/maptalks/src/layer/tile/TileLayer.ts b/packages/maptalks/src/layer/tile/TileLayer.ts index 8d5f6c620d..b17ec332cf 100644 --- a/packages/maptalks/src/layer/tile/TileLayer.ts +++ b/packages/maptalks/src/layer/tile/TileLayer.ts @@ -29,6 +29,7 @@ import { Coordinate, Extent } from '../../geo'; import { type TileLayerCanvasRenderer } from '../../renderer'; import { Tile } from '../../renderer/layer/tilelayer/TileLayerRendererable'; import { BBOX, bboxInMask } from '../../core/util/bbox'; +import { MapStateCache } from '../../map/MapStateCache'; const DEFAULT_MAXERROR = 1; const TEMP_POINT = new Point(0, 0); @@ -789,7 +790,8 @@ class TileLayer extends Layer { } // const r = 1; const error = geometricError * r / distance * this.options['tileErrorScale']; - const pitch = map.getPitch(); + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); if (pitch <= 60) { return error * 1.45; } diff --git a/packages/maptalks/src/map/Map.Camera.ts b/packages/maptalks/src/map/Map.Camera.ts index 83b95dfec6..5bde0cfc84 100644 --- a/packages/maptalks/src/map/Map.Camera.ts +++ b/packages/maptalks/src/map/Map.Camera.ts @@ -347,7 +347,7 @@ Map.include(/** @lends Map.prototype */{ return this.setCenter(coordinates) } const glRes = this.getGLRes(); - bearing = isNil(bearing) ? this.getBearing(): bearing; + bearing = isNil(bearing) ? this.getBearing() : bearing; pitch = isNil(pitch) ? this.getPitch() : pitch; const radPitch = pitch * RADIAN; const radBearing = bearing * RADIAN; @@ -749,6 +749,10 @@ Map.include(/** @lends Map.prototype */{ this._mapGlRes = this.getGLRes(); this._mapExtent2D = this.get2DExtent(); this._mapGlExtent2D = this.get2DExtentAtRes(this._mapGlRes); + const renderer = this.getRenderer(); + if (renderer && renderer._updateMapStateCache) { + renderer._updateMapStateCache(); + } }; }(), diff --git a/packages/maptalks/src/map/MapStateCache.ts b/packages/maptalks/src/map/MapStateCache.ts index f56b5646b5..d96d7cd62b 100644 --- a/packages/maptalks/src/map/MapStateCache.ts +++ b/packages/maptalks/src/map/MapStateCache.ts @@ -3,6 +3,8 @@ type MapStateCacheValue = { bearing: number, zoom: number, devicePixelRatio: number; + resolution: number; + center: any; //other states can be added later } export const MapStateCache: Record = { @@ -18,7 +20,9 @@ export function updateMapStateCache(map) { pitch: map.getPitch(), bearing: map.getBearing(), zoom: map.getZoom(), - devicePixelRatio: map.getDevicePixelRatio() + devicePixelRatio: map.getDevicePixelRatio(), + resolution: map.getResolution(), + center: map.getCenter(), //other states can be added later }; } diff --git a/packages/maptalks/src/renderer/edit/EditHandle.ts b/packages/maptalks/src/renderer/edit/EditHandle.ts index 085691b52e..2b2d27e4b4 100644 --- a/packages/maptalks/src/renderer/edit/EditHandle.ts +++ b/packages/maptalks/src/renderer/edit/EditHandle.ts @@ -10,6 +10,7 @@ import { BBOX, bufferBBOX, getDefaultBBOX } from '../../core/util/bbox'; import type Map from '../../map/Map'; import type GeometryEditor from '../../geometry/editor/GeometryEditor'; import { getResouceCacheInstance } from '../../core/ResourceCacheManager'; +import { MapStateCache } from '../../map/MapStateCache'; const resources = getResouceCacheInstance(); let prevX, prevY; @@ -121,7 +122,8 @@ export default class EditHandle extends Eventable(Class) { const w = this.w; const h = this.h; if (x + w > 0 && x < map.width && y + h > 0 && y < map.height) { - const dpr = map.getDevicePixelRatio(); + const cache = MapStateCache[map.id]; + const dpr = cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); ctx.globalAlpha = this.opacity; ctx.drawImage(this._img, Math.round((x + dx) * dpr), Math.round((y + dy) * dpr), Math.round(w * dpr), Math.round(h * dpr)); return true; @@ -250,7 +252,8 @@ export default class EditHandle extends Eventable(Class) { const { x, y } = this._point; const w = this.w; const h = this.h; - dpr = dpr || map.getDevicePixelRatio(); + const cache = MapStateCache[map.id]; + dpr = dpr || cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); this.bbox = this.bbox || getDefaultBBOX(); const x1 = Math.round((x + dx) * dpr); const y1 = Math.round((y + dy) * dpr); diff --git a/packages/maptalks/src/renderer/edit/EditOutline.ts b/packages/maptalks/src/renderer/edit/EditOutline.ts index dda765a135..27c2ed39c3 100644 --- a/packages/maptalks/src/renderer/edit/EditOutline.ts +++ b/packages/maptalks/src/renderer/edit/EditOutline.ts @@ -2,6 +2,7 @@ import type Map from '../../map/Map'; import type GeometryEditor from '../../geometry/editor/GeometryEditor'; import type { Point } from '../../geo'; import type { BBOX } from '../../core/util/bbox'; +import { MapStateCache } from '../../map/MapStateCache'; export interface EditOutlineOptions { zIndex?: number; @@ -49,7 +50,8 @@ export default class EditOutline { this.ymax <= 0 || this.ymin >= map.height) { return; } - const dpr = map.getDevicePixelRatio(); + const cache = MapStateCache[map.id]; + const dpr = cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); // make line thiner const padding = 0.5; function c(v: number) { diff --git a/packages/maptalks/src/renderer/geometry/Painter.ts b/packages/maptalks/src/renderer/geometry/Painter.ts index 1118d0b4e6..6fb4cb8424 100644 --- a/packages/maptalks/src/renderer/geometry/Painter.ts +++ b/packages/maptalks/src/renderer/geometry/Painter.ts @@ -14,6 +14,7 @@ import Extent from '../../geo/Extent'; import type { WithUndef } from '../../types/typings'; import { Geometries } from '../../geometry' import { ResourceCache } from '../../core/ResourceCacheManager'; +import { MapStateCache } from '../../map/MapStateCache'; //registered symbolizers //the latter will paint at the last @@ -230,9 +231,10 @@ class Painter extends Class { glScale = mapStateCache.glScale; containerExtent = mapStateCache.containerExtent; } else { + const cache = MapStateCache[map.id]; resolution = map.getResolution(); - pitch = map.getPitch(); - bearing = map.getBearing(); + pitch = cache ? cache.pitch : map.getPitch(); + bearing = cache ? cache.bearing : map.getBearing(); glScale = map.getGLScale(); containerExtent = map.getContainerExtent(); } @@ -537,7 +539,8 @@ class Painter extends Class { //@internal _2DExtent = map.get2DExtent(); glExtent = map.get2DExtentAtRes(map.getGLRes()); - pitch = map.getPitch(); + const cache = MapStateCache[map.id]; + pitch = cache ? cache.pitch : map.getPitch(); } let extent2D = _2DExtent._expand(lineWidth); if (pitch > 0 && altitude) { @@ -844,7 +847,8 @@ class Painter extends Class { this._verifyProjection(); const map = this.getMap(); resources = resources || this.getLayer()._getRenderer().resources; - const zoom = map.getZoom(); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); const isDynamicSize = this._isDynamicSize(); if (!this._extent2D || this._extent2D._zoom !== zoom || !this._fixedExtent) { if (this._extent2D && this._extent2D._zoom !== zoom) { @@ -924,7 +928,8 @@ class Painter extends Class { getFixedExtent() { const map = this.getMap(); - const zoom = map.getZoom(); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); if (this._isDynamicSize()) { return this._computeFixedExtent(null, new PointExtent()); } diff --git a/packages/maptalks/src/renderer/geometry/VectorRenderer.ts b/packages/maptalks/src/renderer/geometry/VectorRenderer.ts index f5e88b626f..72aac3f2c3 100644 --- a/packages/maptalks/src/renderer/geometry/VectorRenderer.ts +++ b/packages/maptalks/src/renderer/geometry/VectorRenderer.ts @@ -16,6 +16,7 @@ import Painter from './Painter'; import type { ProjectionType } from '../../geo/projection'; import Coordinate from '../../geo/Coordinate'; import { WithNull } from '../../types/typings'; +import { MapStateCache } from '../../map/MapStateCache'; const TEMP_WITHIN = { within: false, @@ -110,8 +111,11 @@ const el = { } const map = this.getMap(); const altitude = this._getAltitude(); - // when map is tilting, draw the circle/ellipse as a polygon by vertexes. - return altitude > 0 || map.getPitch() || ((this instanceof Ellipse) && map.getBearing()); + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + const bearing = cache ? cache.bearing : map.getBearing(); + // when map is tilting, draw the ;circle/ellipse as a polygon by vertexes. + return altitude > 0 || pitch || ((this instanceof Ellipse) && bearing); }, //@internal @@ -213,7 +217,9 @@ const sectorInclude = { // @ts-expect-error return Canvas.polygon(...args); } else { - const r = this.getMap().getBearing(); + const map = this.getMap(); + const cache = MapStateCache[map.id]; + const r = cache ? cache.bearing : map.getBearing(); if (r) { args[3] = args[3].slice(0); args[3][0] += r; diff --git a/packages/maptalks/src/renderer/geometry/symbolizers/CanvasSymbolizer.ts b/packages/maptalks/src/renderer/geometry/symbolizers/CanvasSymbolizer.ts index f8c4eb9127..1517250888 100644 --- a/packages/maptalks/src/renderer/geometry/symbolizers/CanvasSymbolizer.ts +++ b/packages/maptalks/src/renderer/geometry/symbolizers/CanvasSymbolizer.ts @@ -3,6 +3,7 @@ import { loadGeoSymbol, isFunctionDefinition, interpolated, } from '../../../cor import Symbolizer from './Symbolizer'; import Canvas from '../../../core/Canvas'; import { ResourceCache } from '../../../core/ResourceCacheManager'; +import { MapStateCache } from '../../../map/MapStateCache'; /** *所有基于 HTML5 Canvas2D 的symbolizer类 @@ -36,7 +37,9 @@ abstract class CanvasSymbolizer extends Symbolizer { } } else if (this._opacityFn) { const map = this.getMap(); - ctx.globalAlpha = this._opacityFn(map.getZoom()); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + ctx.globalAlpha = this._opacityFn(zoom); } else if (ctx.globalAlpha !== 1) { ctx.globalAlpha = 1; } diff --git a/packages/maptalks/src/renderer/geometry/symbolizers/StrokeAndFillSymbolizer.ts b/packages/maptalks/src/renderer/geometry/symbolizers/StrokeAndFillSymbolizer.ts index dd9d91b99c..f1d1bee1e8 100644 --- a/packages/maptalks/src/renderer/geometry/symbolizers/StrokeAndFillSymbolizer.ts +++ b/packages/maptalks/src/renderer/geometry/symbolizers/StrokeAndFillSymbolizer.ts @@ -4,6 +4,7 @@ import { isGradient as checkGradient } from '../../../core/util/style'; import Coordinate from '../../../geo/Coordinate'; import PointExtent from '../../../geo/PointExtent'; import { Geometry } from '../../../geometry'; +import { MapStateCache } from '../../../map/MapStateCache'; import Painter from '../Painter'; import CanvasSymbolizer from './CanvasSymbolizer'; import { ColorIn } from 'colorin'; @@ -76,7 +77,9 @@ export default class StrokeAndFillSymbolizer extends CanvasSymbolizer { style['polygonGradientExtent'] = this.geometry.getContainerExtent(); const map = this.getMap(); if (map) { - style['polygonGradientExtent'].bearing = map.getBearing(); + const cache = MapStateCache[map.id]; + const bearing = cache ? cache.bearing : map.getBearing(); + style['polygonGradientExtent'].bearing = bearing; } } // const lineWidth = style['lineWidth'] || 1; diff --git a/packages/maptalks/src/renderer/layer/tilelayer/TileLayerCanvasRenderer.ts b/packages/maptalks/src/renderer/layer/tilelayer/TileLayerCanvasRenderer.ts index dbc0ae5e7d..7bac90abb7 100644 --- a/packages/maptalks/src/renderer/layer/tilelayer/TileLayerCanvasRenderer.ts +++ b/packages/maptalks/src/renderer/layer/tilelayer/TileLayerCanvasRenderer.ts @@ -5,6 +5,7 @@ import WMSTileLayer from '../../../layer/tile/WMSTileLayer'; import CanvasRenderer from '../CanvasRenderer'; import Point from '../../../geo/Point'; import TileLayerRenderable, { RenderContext, Tile } from './TileLayerRendererable'; +import { MapStateCache } from '../../../map/MapStateCache'; const TILE_POINT = new Point(0, 0); const TEMP_POINT = new Point(0, 0); @@ -178,10 +179,11 @@ export default class TileLayerCanvasRenderer extends TileLayerRenderable(CanvasR const point = TILE_POINT.set(extent2d.xmin - offset[0], extent2d.ymax - offset[1]), tileZoom = tileInfo.z, tileId = tileInfo.id; - const zoom = map.getZoom(), + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(), ctx = this.context, cp = map._pointAtResToContainerPoint(point, tileInfo.res, 0, TEMP_POINT), - bearing = map.getBearing(), + bearing = cache ? cache.bearing : map.getBearing(), transformed = bearing || zoom !== tileZoom; const opacity = this.getTileOpacity(tileImage, tileInfo); const alpha = ctx.globalAlpha; diff --git a/packages/maptalks/src/ui/UIComponent.ts b/packages/maptalks/src/ui/UIComponent.ts index 4da353ce19..1bb33bc380 100644 --- a/packages/maptalks/src/ui/UIComponent.ts +++ b/packages/maptalks/src/ui/UIComponent.ts @@ -17,6 +17,7 @@ import Geometry from '../geometry/Geometry'; import Coordinate from '../geo/Coordinate'; import type { Map } from './../map/Map'; import { Point } from '../geo'; +import { MapStateCache } from '../map/MapStateCache'; /** * @property {Object} options @@ -669,7 +670,8 @@ class UIComponent extends Eventable(Class) { offsetY = -((bottom + margin) - mapHeight); } if (offsetX !== 0 || offsetY !== 0) { - const pitch = map.getPitch(); + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); if (pitch > 40 && offsetY !== 0 && this._coordinate) { map.animateTo({ center: this._coordinate }, { duration: map.options['panAnimationDuration'] }); } else { @@ -947,9 +949,13 @@ class UIComponent extends Eventable(Class) { return ''; } if (Browser.any3d) { - const map = this.getMap(), - bearing = map ? map.getBearing() : 0, - pitch = map ? map.getPitch() : 0; + const map = this.getMap(); + let bearing = 0, pitch = 0; + if (map) { + const cache = MapStateCache[map.id]; + bearing = cache ? cache.bearing : map.getBearing(); + pitch = cache ? cache.pitch : map.getPitch(); + } let r = ''; if (this.options['pitchWithMap'] && pitch) { r += ` rotateX(${Math.round(pitch)}deg)`; diff --git a/packages/maptalks/src/ui/UIMarker.ts b/packages/maptalks/src/ui/UIMarker.ts index 92e9ac080e..5923c9b9a7 100644 --- a/packages/maptalks/src/ui/UIMarker.ts +++ b/packages/maptalks/src/ui/UIMarker.ts @@ -8,6 +8,7 @@ import Coordinate from '../geo/Coordinate'; import Point from '../geo/Point'; import UIComponent, { UIComponentOptionsType } from './UIComponent'; import type { Map } from '../map'; +import { MapStateCache } from '../map/MapStateCache'; /** * @property {Object} options - construct options @@ -581,7 +582,8 @@ class UIMarker extends Handlerable(UIComponent) { if (!this.options['visible']) { return false; } - const zoom = map.getZoom(); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); const { minZoom, maxZoom } = this.options; if (!isNil(minZoom) && zoom < minZoom || (!isNil(maxZoom) && zoom > maxZoom)) { return false; diff --git a/packages/vt/src/layer/plugins/painters/CollisionPainter.js b/packages/vt/src/layer/plugins/painters/CollisionPainter.js index 3617c77b2a..98d285ee2a 100644 --- a/packages/vt/src/layer/plugins/painters/CollisionPainter.js +++ b/packages/vt/src/layer/plugins/painters/CollisionPainter.js @@ -105,20 +105,22 @@ export default class CollisionPainter extends BasicPainter { this._anchorCoord0 = new maptalks.Coordinate(0, 0); this._anchorCoord1 = new maptalks.Coordinate(0, 0); } + const cache = maptalks.MapStateCache[map.id]; meshContext.anchor0 = map.containerPointToCoord(this._containerAnchor0, this._anchorCoord0); meshContext.anchor1 = map.containerPointToCoord(this._containerAnchor1, this._anchorCoord1); - meshContext.anchor0.z = map.getZoom(); + meshContext.anchor0.z = cache ? cache.zoom : map.getZoom(); meshContext.anchor0.width = map.width; meshContext.anchor0.height = map.height; - meshContext.anchor0.pitch = map.getPitch(); + meshContext.anchor0.pitch = cache ? cache.pitch : map.getPitch(); } this.getMap().collisionFrameTime += performance.now() - this._startTime; } _isCachedCollisionStale(meshKey) { const map = this.getMap(); - const z = map.getZoom(); - const pitch = map.getPitch(); + const cache = maptalks.MapStateCache[map.id]; + const z = cache ? cache.zoom : map.getZoom(); + const pitch = cache ? cache.pitch : map.getPitch(); const [anchor0, anchor1] = this._getMeshAnchor(meshKey); //如果没有anchor,或者anchor距离它应该在的点的像素距离超过阈值时,则说明collision已经过期 if (!anchor0 || !anchor1 || anchor0.z !== z || @@ -141,12 +143,13 @@ export default class CollisionPainter extends BasicPainter { tags: {} }; } + const cache = maptalks.MapStateCache[map.id]; this._cachedInstances = { layer: this.layer, renderer: this.layer.getRenderer(), frameTimestamp: this.layer.getRenderer().getFrameTimestamp(), - map: this.getMap(), - zoom: map.getZoom(), + map, + zoom: cache ? cache.zoom : map.getZoom(), collisionTags: this._collisionContext.tags, isEnableUniquePlacement: this.isEnableUniquePlacement() }; @@ -623,7 +626,8 @@ export default class CollisionPainter extends BasicPainter { isCollides(box/*, tileInfo*/) { const layer = this.layer, map = layer.getMap(); - const dpr = map.getDevicePixelRatio(); + const cache = maptalks.MapStateCache[map.id]; + const dpr = cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); vec4.scale(BOX, box, 1 / dpr); if (map.isOffscreen(BOX)) { return -1; @@ -685,7 +689,8 @@ export default class CollisionPainter extends BasicPainter { box = bufferBox(BOX, box, bufferSize); } const map = this.getMap(); - const dpr = map.getDevicePixelRatio(); + const cache = maptalks.MapStateCache[map.id]; + const dpr = cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); vec4.scale(BOX, box, 1 / dpr); if (map.isOffscreen(BOX)) { return; @@ -963,7 +968,9 @@ export default class CollisionPainter extends BasicPainter { if (!this.isEnableUniquePlacement()) { return; } - const zoom = this.getMap().getZoom(); + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); let changed = !this._mergedMeshes || this._mergedMehesZoom !== zoom; if (!changed) { for (let i = 0; i < meshes.length; i++) { diff --git a/packages/vt/src/layer/plugins/painters/FillPainter.js b/packages/vt/src/layer/plugins/painters/FillPainter.js index 91e7cff997..25fbde8410 100644 --- a/packages/vt/src/layer/plugins/painters/FillPainter.js +++ b/packages/vt/src/layer/plugins/painters/FillPainter.js @@ -170,7 +170,7 @@ class FillPainter extends BasicPainter { if (!texWidth && !texHeight) { return DEFAULT_UNIFORMS['patternWidth']; } - const [ width, height ] = this._computePatternWidth(ARR_0, texWidth, texHeight, isVectorTile ? tileRatio : 1, tileCoord, tileRes); + const [width, height] = this._computePatternWidth(ARR_0, texWidth, texHeight, isVectorTile ? tileRatio : 1, tileCoord, tileRes); return vec2.set(patternWidthUniform, width, height); } }); @@ -319,7 +319,7 @@ class FillPainter extends BasicPainter { origin = COORD2.set(patternOrigin[0], patternOrigin[1]); } } - const [ scaleX, scaleY ] = this._computePatternWidth(ARR_0, width, height, tileRatio, origin, tileRes); + const [scaleX, scaleY] = this._computePatternWidth(ARR_0, width, height, tileRatio, origin, tileRes); currentScaleX = aPatternWidth[i * 2] = scaleX; currentScaleY = aPatternWidth[i * 2 + 1] = scaleY; } else { @@ -428,6 +428,7 @@ class FillPainter extends BasicPainter { const u8 = new Uint8Array(1); const u16 = new Uint16Array(2); const offsetU8 = new Uint8Array(2); + return [ { //geometry.data 中的属性数据 @@ -439,7 +440,9 @@ class FillPainter extends BasicPainter { define: 'HAS_COLOR', // evaluate: (properties, geometry) => { - let color = polygonFillFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let color = polygonFillFn(zoom, properties); if (isFunctionDefinition(color)) { color = this.evaluateInFnTypeConfig(color, geometry, map, properties, true); } @@ -457,7 +460,9 @@ class FillPainter extends BasicPainter { width: 1, define: 'HAS_OPACITY', evaluate: (properties, geometry) => { - let opacity = polygonOpacityFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let opacity = polygonOpacityFn(zoom, properties); if (isFunctionDefinition(opacity)) { opacity = this.evaluateInFnTypeConfig(opacity, geometry, map, properties); } @@ -473,7 +478,9 @@ class FillPainter extends BasicPainter { width: 2, define: 'HAS_UV_SCALE', evaluate: properties => { - const scale = uvScaleFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const scale = uvScaleFn(zoom, properties); u16[0] = scale[0] * 255; u16[1] = scale[1] * 255; return u16; @@ -486,7 +493,9 @@ class FillPainter extends BasicPainter { width: 2, define: 'HAS_UV_OFFSET', evaluate: properties => { - const offset = uvOffsetFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const offset = uvOffsetFn(zoom, properties); offsetU8[0] = offset[0] * 255; offsetU8[1] = offset[1] * 255; return offsetU8; diff --git a/packages/vt/src/layer/plugins/painters/GLTFMixin.js b/packages/vt/src/layer/plugins/painters/GLTFMixin.js index ba0a7faf6d..880f6fc3d8 100644 --- a/packages/vt/src/layer/plugins/painters/GLTFMixin.js +++ b/packages/vt/src/layer/plugins/painters/GLTFMixin.js @@ -1,4 +1,4 @@ -import { Coordinate } from 'maptalks'; +import { Coordinate, MapStateCache } from 'maptalks'; import { vec3, mat4, quat, reshader } from '@maptalks/gl'; import { setUniformFromSymbol, createColorSetter, isNumber, extend } from '../Util'; import { getCentiMeterScale, isNil } from '../../../common/Util'; @@ -334,7 +334,7 @@ const GLTFMixin = Base => const to = coord1.set(x1 * tileScale, y1 * tileScale, z1 * zScale); const dist = from.distanceTo(to); this._getSymbolRotationScaleMatrix(rotationScaleMat, features, aPickingId, i / positionSize); - const items = gltfPack.arrangeAlongLine(from, to, dist, gltfScale, 1, rotationScaleMat, options); + const items = gltfPack.arrangeAlongLine(from, to, dist, gltfScale, 1, rotationScaleMat, options); for (let j = 0; j < items.length; j++) { const item = items[j]; // const coord = item.coordinates; @@ -585,7 +585,7 @@ const GLTFMixin = Base => const y = vertex[1]; const pos = vec3.set( position, - x * tileScale - cx, + x * tileScale - cx, //vt中的y轴方向与opengl(maptalks世界坐标系)相反 -y * tileScale - cy, (vertex[2] + altitudeOffset) * zScale - cz @@ -669,8 +669,9 @@ const GLTFMixin = Base => const idx = aPickingId && aPickingId[i]; const feature = features && features[idx]; + const cache = MapStateCache[map.id]; - const zoom = map.getZoom(); + const zoom = cache ? cache.zoom : map.getZoom(); const properties = feature && feature.feature && feature.feature.properties; const heightScale = this._getModelHeightScale(zoom, properties); diff --git a/packages/vt/src/layer/plugins/painters/HeatmapPainter.js b/packages/vt/src/layer/plugins/painters/HeatmapPainter.js index 1e08896753..45252647a3 100644 --- a/packages/vt/src/layer/plugins/painters/HeatmapPainter.js +++ b/packages/vt/src/layer/plugins/painters/HeatmapPainter.js @@ -3,6 +3,7 @@ import BasicPainter from './BasicPainter'; import { interpolated } from '@maptalks/function-type'; import { prepareFnTypeData } from './util/fn_type_util'; import { setUniformFromSymbol } from '../Util'; +import { MapStateCache } from 'maptalks'; export default class HeatmapPainter extends BasicPainter { createFnTypeConfig(map, symbolDef) { @@ -16,7 +17,9 @@ export default class HeatmapPainter extends BasicPainter { width: 1, define: 'HAS_HEAT_WEIGHT', evaluate: properties => { - const x = heatWeightFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const x = heatWeightFn(zoom, properties); i16[0] = x * 255; return i16[0]; } diff --git a/packages/vt/src/layer/plugins/painters/IconPainter.js b/packages/vt/src/layer/plugins/painters/IconPainter.js index 7457861ce6..10cded653c 100644 --- a/packages/vt/src/layer/plugins/painters/IconPainter.js +++ b/packages/vt/src/layer/plugins/painters/IconPainter.js @@ -139,7 +139,7 @@ class IconPainter extends CollisionPainter { } - _prepareRequiredProps(geometry) { + _prepareRequiredProps(geometry) { const { aCount, aShape } = geometry.data; geometry.properties.aCount = aCount; delete geometry.data.aCount; @@ -293,7 +293,7 @@ class IconPainter extends CollisionPainter { let id = 0; let currentCount = aCount[0]; for (let i = 0; i < collideIds.length;) { - const next = i + currentCount * BOX_VERTEX_COUNT; + const next = i + currentCount * BOX_VERTEX_COUNT; collideIds.fill(id++, i, next); i += currentCount * BOX_VERTEX_COUNT; if (next < collideIds.length) { @@ -325,7 +325,9 @@ class IconPainter extends CollisionPainter { updateMarkerFitSize.call(this, this.getMap(), geometry); } } - const z = this.getMap().getZoom(); + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + const z = cache ? cache.zoom : map.getZoom(); for (let i = 0; i < meshes.length; i++) { if (!this.isMeshIterable(meshes[i])) { continue; @@ -801,15 +803,19 @@ class IconPainter extends CollisionPainter { } const blendFunc = this.getBlendFunc(); const blendSrc = maptalks.Util.isFunction(blendFunc.src) ? blendFunc.src() : blendFunc.src; + const cache = maptalks.MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + const bearing = cache ? cache.bearing : map.getBearing(); + const resolution = cache ? cache.resolution : map.getResolution() return { layerScale: this.layer.options['styleScale'] || 1, - mapPitch: map.getPitch() * Math.PI / 180, - mapRotation: map.getBearing() * Math.PI / 180, + mapPitch: pitch * Math.PI / 180, + mapRotation: bearing * Math.PI / 180, projViewMatrix, cameraToCenterDistance, canvasSize, iconSize: ICON_SIZE_ARR, - resolution: map.getResolution(), + resolution, //text uniforms glyphSize: GLYPH_SIZE, diff --git a/packages/vt/src/layer/plugins/painters/LinePainter.js b/packages/vt/src/layer/plugins/painters/LinePainter.js index 0a30e98cca..89b8fe9e58 100644 --- a/packages/vt/src/layer/plugins/painters/LinePainter.js +++ b/packages/vt/src/layer/plugins/painters/LinePainter.js @@ -301,7 +301,9 @@ class LinePainter extends BasicPainter { width: 4, define: 'HAS_COLOR', evaluate: (properties, geometry) => { - let color = aColorFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let color = aColorFn(zoom, properties); if (isFunctionDefinition(color)) { color = this.evaluateInFnTypeConfig(color, geometry, map, properties, true); } @@ -320,7 +322,9 @@ class LinePainter extends BasicPainter { related: ['linePatternGap'], define: 'HAS_LINE_PATTERN', evaluate: (properties, geometry, arr, index) => { - let speed = aLinePatternAnimSpeedFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let speed = aLinePatternAnimSpeedFn(zoom, properties); if (isNil(speed)) { speed = 0; } @@ -340,7 +344,9 @@ class LinePainter extends BasicPainter { related: ['linePatternAnimSpeed'], define: 'HAS_LINE_PATTERN', evaluate: (properties, geometry, arr, index) => { - let gap = aLinePatternGapFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let gap = aLinePatternGapFn(zoom, properties); if (isNil(gap)) { gap = 0; } @@ -369,7 +375,9 @@ class LinePainter extends BasicPainter { width: 1, define: 'HAS_LINE_WIDTH', evaluate: (properties, geometry) => { - let lineWidth = aLineWidthFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let lineWidth = aLineWidthFn(zoom, properties); if (isFunctionDefinition(lineWidth)) { lineWidth = this.evaluateInFnTypeConfig(lineWidth, geometry, map, properties); } @@ -385,7 +393,9 @@ class LinePainter extends BasicPainter { width: 1, define: 'HAS_STROKE_WIDTH', evaluate: properties => { - const lineStrokeWidth = aLineStrokeWidthFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const lineStrokeWidth = aLineStrokeWidthFn(zoom, properties); //乘以2是为了解决 #190 u16[0] = Math.round(lineStrokeWidth * 2.0); return u16[0]; @@ -399,7 +409,9 @@ class LinePainter extends BasicPainter { index: 0, define: 'HAS_LINE_DX', evaluate: properties => { - const lineDx = aLineDxFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const lineDx = aLineDxFn(zoom, properties); i8[0] = lineDx; return i8[0]; } @@ -412,7 +424,9 @@ class LinePainter extends BasicPainter { index: 1, define: 'HAS_LINE_DY', evaluate: properties => { - const lineDy = aLineDyFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const lineDy = aLineDyFn(zoom, properties); i8[0] = lineDy; return i8[0]; } @@ -424,7 +438,9 @@ class LinePainter extends BasicPainter { width: 1, define: 'HAS_OPACITY', evaluate: (properties, geometry) => { - let opacity = aLineOpacityFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let opacity = aLineOpacityFn(zoom, properties); if (isFunctionDefinition(opacity)) { opacity = this.evaluateInFnTypeConfig(opacity, geometry, map, properties); } diff --git a/packages/vt/src/layer/plugins/painters/MeshPainter.js b/packages/vt/src/layer/plugins/painters/MeshPainter.js index bc79f9d5b2..8ec347b650 100644 --- a/packages/vt/src/layer/plugins/painters/MeshPainter.js +++ b/packages/vt/src/layer/plugins/painters/MeshPainter.js @@ -414,7 +414,9 @@ class MeshPainter extends Painter { define: 'HAS_COLOR', // evaluate: (properties, geometry) => { - let color = fillFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let color = fillFn(zoom, properties); if (isFunctionDefinition(color)) { color = this.evaluateInFnTypeConfig(color, geometry, map, properties, true); } @@ -431,7 +433,9 @@ class MeshPainter extends Painter { width: 1, symbolName: opacityName, evaluate: (properties, geometry) => { - let polygonOpacity = opacityFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let polygonOpacity = opacityFn(zoom, properties); if (isFunctionDefinition(polygonOpacity)) { polygonOpacity = this.evaluateInFnTypeConfig(polygonOpacity, geometry, map, properties, false); } @@ -449,7 +453,9 @@ class MeshPainter extends Painter { symbolName: 'lineWidth', define: 'HAS_LINE_WIDTH', evaluate: properties => { - const lineWidth = aLineWidthFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const lineWidth = aLineWidthFn(zoom, properties); //乘以2是为了解决 #190 u16[0] = Math.round(lineWidth * 2.0); return u16[0]; diff --git a/packages/vt/src/layer/plugins/painters/NativePointPainter.js b/packages/vt/src/layer/plugins/painters/NativePointPainter.js index 32a205a919..ab5cb89059 100644 --- a/packages/vt/src/layer/plugins/painters/NativePointPainter.js +++ b/packages/vt/src/layer/plugins/painters/NativePointPainter.js @@ -9,6 +9,7 @@ import pickingVert from './glsl/native-point.vert'; import { setUniformFromSymbol, createColorSetter, toUint8ColorInGlobalVar } from '../Util'; import { isFunctionDefinition, piecewiseConstant } from '@maptalks/function-type'; import { prepareFnTypeData } from './util/fn_type_util'; +import { MapStateCache } from 'maptalks'; const DEFAULT_UNIFORMS = { markerFill: [0, 0, 0], @@ -78,11 +79,11 @@ class NativePointPainter extends BasicPainter { const { aPosition, aAltitude, aColor } = geometry.data; const position = new Int16Array([ -1, -1, - 1, -1, - -1, 1, - -1, 1, - 1, -1, - 1, 1 + 1, -1, + -1, 1, + -1, 1, + 1, -1, + 1, 1 ]); const geo = new reshader.Geometry({ aPosition: position @@ -121,7 +122,9 @@ class NativePointPainter extends BasicPainter { width: 4, define: 'HAS_COLOR', evaluate: (properties, geometry) => { - let color = aColorFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let color = aColorFn(zoom, properties); if (isFunctionDefinition(color)) { color = this.evaluateInFnTypeConfig(color, geometry, map, properties, true); } diff --git a/packages/vt/src/layer/plugins/painters/NativelinePainter.js b/packages/vt/src/layer/plugins/painters/NativelinePainter.js index 8a6fa67e16..1745b630ae 100644 --- a/packages/vt/src/layer/plugins/painters/NativelinePainter.js +++ b/packages/vt/src/layer/plugins/painters/NativelinePainter.js @@ -7,6 +7,7 @@ import wgslVert from './wgsl/native-line_vert.wgsl'; import wgslFrag from './wgsl/native-line_frag.wgsl'; import pickingVert from './glsl/native-line.vert'; import { piecewiseConstant, isFunctionDefinition } from '@maptalks/function-type'; +import { MapStateCache } from 'maptalks'; const IDENTITY_ARR = mat4.identity([]); @@ -17,7 +18,11 @@ class NativeLinePainter extends BasicPainter { if (isFunctionDefinition(this.symbolDef['lineColor'])) { const map = layer.getMap(); const fn = piecewiseConstant(this.symbolDef['lineColor']); - this.colorSymbol = properties => fn(map.getZoom(), properties); + this.colorSymbol = properties => { + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + return fn(zoom, properties) + } } } diff --git a/packages/vt/src/layer/plugins/painters/Painter.js b/packages/vt/src/layer/plugins/painters/Painter.js index cbc4aaa55d..ffd04e6e6d 100644 --- a/packages/vt/src/layer/plugins/painters/Painter.js +++ b/packages/vt/src/layer/plugins/painters/Painter.js @@ -108,7 +108,8 @@ class Painter { const { minZoom, maxZoom } = this.sceneConfig || {}; if (isNumber(minZoom) || isNumber(maxZoom)) { const map = this.getMap(); - const zoom = map.getZoom(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); if (!isNil(minZoom) && zoom < minZoom) { return false; } @@ -147,7 +148,10 @@ class Painter { if (!visibleFns[i].isFeatureConstant) { return true; } else { - visible = visibleFns[i](this.getMap().getZoom()); + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + visible = visibleFns[i](zoom); } } else { visible = this.getSymbol(symbolIndex).visible; @@ -462,7 +466,9 @@ class Painter { return; } const sceneFilter = context && context.sceneFilter; - const z = this.getMap().getZoom(); + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + const z = cache ? cache.zoom : map.getZoom(); for (let i = 0; i < meshes.length; i++) { if (!meshes[i] || !meshes[i].geometry) { continue; @@ -822,7 +828,9 @@ class Painter { const params = []; // extend(this._symbol, this.symbolDef); const loadedSymbol = FuncTypeUtil.loadSymbolFnTypes(this.symbolDef[i], () => { - params[0] = map.getZoom(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + params[0] = zoom; return params; }); for (const p in loadedSymbol) { @@ -866,7 +874,9 @@ class Painter { const map = this.getMap(); const params = []; const fn = () => { - params[0] = map.getZoom(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + params[0] = zoom; return params; }; this._symbol = []; @@ -1230,7 +1240,9 @@ class Painter { if (!fn) { fn = fnCaches[key] = isPiecewiseConstant ? piecewiseConstant(v) : interpolated(v); } - return fn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + return fn(zoom, properties); } highlight(highlights) { diff --git a/packages/vt/src/layer/plugins/painters/TextPainter.js b/packages/vt/src/layer/plugins/painters/TextPainter.js index 5c06c19ddc..6328da4770 100644 --- a/packages/vt/src/layer/plugins/painters/TextPainter.js +++ b/packages/vt/src/layer/plugins/painters/TextPainter.js @@ -22,6 +22,7 @@ import { GLYPH_SIZE } from './Constant'; import { getCentiMeterScale } from '../../../common/Util'; import { INVALID_PROJECTED_ANCHOR, INVALID_ALTITUDE } from '../../../common/Constant'; import { getVectorPacker } from '../../../packer/inject'; +import { MapStateCache } from 'maptalks'; const { TextUtil, PackUtil, FilterUtil, TEXT_MAX_ANGLE } = getVectorPacker(); @@ -343,7 +344,9 @@ export default class TextPainter extends CollisionPainter { } const map = this.getMap(); - const bearing = -map.getBearing() * Math.PI / 180; + const cache = MapStateCache[map.id]; + + const bearing = -(cache ? cache.bearing : map.getBearing()) * Math.PI / 180; const planeMatrix = mat2.fromRotation(PLANE_MATRIX, bearing); //boxVisible, mesh, meshBoxes, mvpMatrix, boxIndex const fn = (visElemts, meshBoxes, mvpMatrix, labelIndex) => { @@ -459,8 +462,9 @@ export default class TextPainter extends CollisionPainter { if (!line) { return; } - const pitch = map.getPitch(); - const bearing = map.getBearing(); + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + const bearing = cache ? cache.bearing : map.getBearing(); const { lineTextPitch: linePitch, lineTextBearing: lineBearing } = mesh.properties; // this._counter++; @@ -657,7 +661,8 @@ export default class TextPainter extends CollisionPainter { } else { elevatedAnchor = projLabelAnchor; } - const dpr = map.getDevicePixelRatio(); + const cache = MapStateCache[map.id]; + const dpr = cache ? cache.devicePixelRatio : map.getdevicePixelRatio(); vec4.scale(BOX, elevatedAnchor, 1 / dpr); if (map.isOffscreen(BOX)) { if (!enableCollision) { @@ -1034,17 +1039,21 @@ export default class TextPainter extends CollisionPainter { // 0.0, pitchSin, pitchCos // ]; const zScale = getCentiMeterScale(map.getResolution(), map); + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + const bearing = cache ? cache.bearing : map.getBearing(); + const resolution = cache ? cache.resolution : map.getResolution() return { layerScale: this.layer.options['styleScale'] || 1, - mapPitch: map.getPitch() * Math.PI / 180, - mapRotation: map.getBearing() * Math.PI / 180, + mapPitch: pitch * Math.PI / 180, + mapRotation: bearing * Math.PI / 180, projViewMatrix, viewMatrix: map.viewMatrix, cameraToCenterDistance, canvasSize, glyphSize: GLYPH_SIZE, // gammaScale : 0.64, gammaScale: GAMMA_SCALE * (this.layer.options['textGamma'] || 1), - resolution: map.getResolution(), + resolution, altitudeScale: zScale, viewport: isRenderingTerrainSkin && context && context.viewport, // 过滤 pitchAlignment 为特定值的text,0时不过滤; 1时,过滤掉viewport; 2时,过滤掉map diff --git a/packages/vt/src/layer/plugins/painters/TubePainter.js b/packages/vt/src/layer/plugins/painters/TubePainter.js index 89fd71095b..aa12ff608e 100644 --- a/packages/vt/src/layer/plugins/painters/TubePainter.js +++ b/packages/vt/src/layer/plugins/painters/TubePainter.js @@ -322,7 +322,7 @@ class TubePainter extends BasicPainter { const aLinePatternAnimSpeedFn = piecewiseConstant(symbolDef['aLinePatternAnimSpeed']); const aLinePatternGapFn = piecewiseConstant(symbolDef['aLinePatternGap']); const shapeConfigs = this.createShapeFnTypeConfigs(map, symbolDef); - const i8 = new Int8Array(2); + const i8 = new Int8Array(2); return [ { //geometry.data 中的属性数据 @@ -333,7 +333,9 @@ class TubePainter extends BasicPainter { width: 4, define: 'HAS_COLOR', evaluate: (properties, geometry) => { - let color = aColorFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let color = aColorFn(zoom, properties); if (isFunctionDefinition(color)) { color = this.evaluateInFnTypeConfig(color, geometry, map, properties, true); } @@ -352,7 +354,9 @@ class TubePainter extends BasicPainter { related: ['linePatternGap'], define: 'HAS_LINE_PATTERN', evaluate: (properties, geometry, arr, index) => { - let speed = aLinePatternAnimSpeedFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let speed = aLinePatternAnimSpeedFn(zoom, properties); if (isNil(speed)) { speed = 0; } @@ -372,7 +376,9 @@ class TubePainter extends BasicPainter { related: ['linePatternAnimSpeed'], define: 'HAS_LINE_PATTERN', evaluate: (properties, geometry, arr, index) => { - let gap = aLinePatternGapFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let gap = aLinePatternGapFn(zoom, properties); if (isNil(gap)) { gap = 0; } @@ -397,7 +403,9 @@ class TubePainter extends BasicPainter { width: 1, define: 'HAS_LINE_WIDTH', evaluate: (properties, geometry) => { - let lineWidth = aLineWidthFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let lineWidth = aLineWidthFn(zoom, properties); if (isFunctionDefinition(lineWidth)) { lineWidth = this.evaluateInFnTypeConfig(lineWidth, geometry, map, properties); } @@ -413,7 +421,9 @@ class TubePainter extends BasicPainter { width: 1, define: 'HAS_OPACITY', evaluate: (properties, geometry) => { - let opacity = aLineOpacityFn(map.getZoom(), properties); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let opacity = aLineOpacityFn(zoom, properties); if (isFunctionDefinition(opacity)) { opacity = this.evaluateInFnTypeConfig(opacity, geometry, map, properties); } diff --git a/packages/vt/src/layer/plugins/painters/pbr/ShadowMapPass.js b/packages/vt/src/layer/plugins/painters/pbr/ShadowMapPass.js index 5d2f75e0cd..1e6037a975 100644 --- a/packages/vt/src/layer/plugins/painters/pbr/ShadowMapPass.js +++ b/packages/vt/src/layer/plugins/painters/pbr/ShadowMapPass.js @@ -1,5 +1,6 @@ import { reshader, mat4, vec3 } from '@maptalks/gl'; import { isNil } from '../../Util'; +import { MapStateCache } from 'maptalks'; const COORD_THRESHOLD = 100; @@ -33,7 +34,7 @@ class VSMShadowPass { fn: function (context, props) { const lightProjViews = props['vsm_shadow_lightProjViewMatrix']; const model = props['modelMatrix']; - return mat4.multiply([], lightProjViews, model); + return mat4.multiply([], lightProjViews, model); } }); uniforms.push('vsm_shadow_shadowMap', 'vsm_shadow_opacity', 'vsm_shadow_threshold'); @@ -75,10 +76,14 @@ class VSMShadowPass { ids[m.properties.meshKey] = 1; return ids; }, {}); + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + const bearing = cache ? cache.bearing : map.getBearing(); + const center = cache ? cache.center : map.getCenter(); this._renderedView = { - center: map.getCenter(), - bearing: map.getBearing(), - pitch: map.getPitch() + center, + bearing, + pitch }; } else { matrix = this._lightProjViewMatrix; @@ -133,9 +138,12 @@ class VSMShadowPass { } const map = layer.getMap(); const cp = map.coordToContainerPoint(this._renderedView.center); + const cache = MapStateCache[map.id]; + const pitch = cache ? cache.pitch : map.getPitch(); + const bearing = cache ? cache.bearing : map.getBearing(); changed = (cp._sub(map.width / 2, map.height / 2).mag() > COORD_THRESHOLD) || - Math.abs(this._renderedView.bearing - map.getBearing()) > 30 || - Math.abs(this._renderedView.pitch - map.getPitch()) > 15; + Math.abs(this._renderedView.bearing - bearing) > 30 || + Math.abs(this._renderedView.pitch - pitch) > 15; return changed; } } diff --git a/packages/vt/src/layer/plugins/painters/util/create_marker_painter.js b/packages/vt/src/layer/plugins/painters/util/create_marker_painter.js index 4d90ce48b9..7c37e37c95 100644 --- a/packages/vt/src/layer/plugins/painters/util/create_marker_painter.js +++ b/packages/vt/src/layer/plugins/painters/util/create_marker_painter.js @@ -6,6 +6,7 @@ import { createAtlasTexture, getDefaultMarkerSize } from './atlas_util'; import { prepareFnTypeData, PREFIX, isFnTypeSymbol } from './fn_type_util'; import { prepareTextGeometry, initTextUniforms, initTextMeshDefines } from './create_text_painter'; import { limitMarkerDefinesByDevice } from './limit_defines'; +import { MapStateCache } from 'maptalks'; // import { getIconBox } from './get_icon_box'; export const BOX_ELEMENT_COUNT = 6; @@ -175,7 +176,7 @@ export function prepareDxDy(geometry) { } function setMeshUniforms(uniforms, regl, geometry, symbol) { - const [ defaultMarkerWidth, defaultMarkerHeight ] = getDefaultMarkerSize(geometry); + const [defaultMarkerWidth, defaultMarkerHeight] = getDefaultMarkerSize(geometry); setUniformFromSymbol(uniforms, 'markerOpacity', symbol, 'markerOpacity', 1); setUniformFromSymbol(uniforms, 'markerPerspectiveRatio', symbol, 'markerPerspectiveRatio', symbol.markerTextFit ? 0 : 1); setUniformFromSymbol(uniforms, 'markerWidth', symbol, 'markerWidth', defaultMarkerWidth || DEFAULT_MARKER_WIDTH); @@ -300,7 +301,7 @@ export function getMarkerFnTypeConfig(map, symbolDef) { const markerPitchAlignmentFn = piecewiseConstant(symbolDef['markerPitchAlignment']); const textPitchAlignmentFn = piecewiseConstant(symbolDef['textPitchAlignment']); const markerRotationAlignmentFn = piecewiseConstant(symbolDef['markerRotationAlignment']); - const textRotationAlignmentFn = piecewiseConstant(symbolDef['textRotationAlignment']); + const textRotationAlignmentFn = piecewiseConstant(symbolDef['textRotationAlignment']); const markerRotationFn = interpolated(symbolDef['markerRotation']); const textRotationFn = interpolated(symbolDef['textRotation']); const markerAllowOverlapFn = piecewiseConstant(symbolDef['markerAllowOverlapFn']); @@ -318,14 +319,16 @@ export function getMarkerFnTypeConfig(map, symbolDef) { width: 1, define: 'HAS_MARKER_WIDTH', evaluate: (properties, geometry, arr, index) => { + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); const value = arr[index]; const markerTextFit = symbolDef['markerTextFit']; //如果是markerTextFit,aMarkerWidth已经更新过了,直接返回原值 - const textFit = markerTextFitFn ? markerTextFitFn(map.getZoom(), properties) : markerTextFit; + const textFit = markerTextFitFn ? markerTextFitFn(zoom, properties) : markerTextFit; if (textFit === 'both' || textFit === 'width') { return value; } - let x = markerWidthFn(map.getZoom(), properties); + let x = markerWidthFn(zoom, properties); if (isFunctionDefinition(x)) { x = this.evaluateInFnTypeConfig(x, geometry, map, properties); } @@ -340,13 +343,15 @@ export function getMarkerFnTypeConfig(map, symbolDef) { width: 1, define: 'HAS_MARKER_HEIGHT', evaluate: (properties, geometry, arr, index) => { + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); const value = arr[index]; const markerTextFit = symbolDef['markerTextFit']; - const textFit = markerTextFitFn ? markerTextFitFn(map.getZoom(), properties) : markerTextFit; + const textFit = markerTextFitFn ? markerTextFitFn(zoom, properties) : markerTextFit; if (textFit === 'both' || textFit === 'height') { return value; } - let x = markerHeightFn(map.getZoom(), properties); + let x = markerHeightFn(zoom, properties); if (isFunctionDefinition(x)) { x = this.evaluateInFnTypeConfig(x, geometry, map, properties); } @@ -363,7 +368,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 0, define: 'HAS_MARKER_DX', evaluate: (properties, geometry, arr, index) => { - let x = markerDxFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let x = markerDxFn(zoom, properties); if (isFunctionDefinition(x)) { x = this.evaluateInFnTypeConfig(x, geometry, map, properties); } @@ -384,7 +391,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 1, define: 'HAS_MARKER_DY', evaluate: (properties, geometry, arr, index) => { - let x = markerDyFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let x = markerDyFn(zoom, properties); if (isFunctionDefinition(x)) { x = this.evaluateInFnTypeConfig(x, geometry, map, properties); } @@ -404,7 +413,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 2, define: 'HAS_TEXT_DX', evaluate: (properties, geometry, arr, index) => { - let x = textDxFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let x = textDxFn(zoom, properties); if (isFunctionDefinition(x)) { x = this.evaluateInFnTypeConfig(x, geometry, map, properties); } @@ -425,7 +436,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 3, define: 'HAS_TEXT_DY', evaluate: (properties, geometry, arr, index) => { - let x = textDyFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let x = textDyFn(zoom, properties); if (isFunctionDefinition(x)) { x = this.evaluateInFnTypeConfig(x, geometry, map, properties); } @@ -448,7 +461,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { evaluate: (properties, geometry) => { let opacity = 1; if (markerOpacityFn) { - opacity = markerOpacityFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + opacity = markerOpacityFn(zoom, properties); if (isFunctionDefinition(opacity)) { opacity = this.evaluateInFnTypeConfig(opacity, geometry, map, properties); } @@ -467,7 +482,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { evaluate: (properties, geometry) => { let opacity = 1; if (textOpacityFn) { - opacity = textOpacityFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + opacity = textOpacityFn(zoom, properties); if (isFunctionDefinition(opacity)) { opacity = this.evaluateInFnTypeConfig(opacity, geometry, map, properties); } @@ -484,7 +501,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 0, define: 'HAS_PITCH_ALIGN', evaluate: properties => { - const y = +(markerPitchAlignmentFn(map.getZoom(), properties) === 'map'); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = +(markerPitchAlignmentFn(zoom, properties) === 'map'); return y; } }, @@ -496,7 +515,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 1, define: 'HAS_PITCH_ALIGN', evaluate: properties => { - const y = +(textPitchAlignmentFn(map.getZoom(), properties) === 'map'); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = +(textPitchAlignmentFn(zoom, properties) === 'map'); return y; } }, @@ -508,7 +529,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 0, define: 'HAS_MARKER_ROTATION_ALIGN', evaluate: properties => { - const y = +(markerRotationAlignmentFn(map.getZoom(), properties) === 'map'); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = +(markerRotationAlignmentFn(zoom, properties) === 'map'); return y; } }, @@ -520,7 +543,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 1, define: 'HAS_TEXT_ROTATION_ALIGN', evaluate: properties => { - const y = +(textRotationAlignmentFn(map.getZoom(), properties) === 'map'); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = +(textRotationAlignmentFn(zoom, properties) === 'map'); return y; } }, @@ -532,7 +557,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 0, define: 'HAS_MARKER_ROTATION', evaluate: properties => { - const y = wrap(markerRotationFn(map.getZoom(), properties), 0, 360) * Math.PI / 180; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = wrap(markerRotationFn(zoom, properties), 0, 360) * Math.PI / 180; u16[0] = y * 9362; return u16[0]; } @@ -545,7 +572,9 @@ export function getMarkerFnTypeConfig(map, symbolDef) { index: 1, define: 'HAS_TEXT_ROTATION', evaluate: properties => { - const y = wrap(textRotationFn(map.getZoom(), properties), 0, 360) * Math.PI / 180; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = wrap(textRotationFn(zoom, properties), 0, 360) * Math.PI / 180; u16[0] = y * 9362; return u16[0]; } @@ -556,8 +585,10 @@ export function getMarkerFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: properties => { - let overlap = markerAllowOverlapFn(map.getZoom(), properties) || 0; - let placement = (markerIgnorePlacementFn ? markerIgnorePlacementFn(map.getZoom(), properties) : symbolDef['markerIgnorePlacement']) || 0; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let overlap = markerAllowOverlapFn(zoom, properties) || 0; + let placement = (markerIgnorePlacementFn ? markerIgnorePlacementFn(zoom, properties) : symbolDef['markerIgnorePlacement']) || 0; overlap = 1 << 3 + overlap * (1 << 2); placement = (markerIgnorePlacementFn ? 1 << 1 : 0) + placement; return overlap + placement; @@ -572,8 +603,10 @@ export function getMarkerFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: properties => { - let overlap = (markerAllowOverlapFn ? markerAllowOverlapFn(map.getZoom(), properties) : symbolDef['markerAllowOverlap']) || 0; - let placement = markerIgnorePlacementFn(map.getZoom(), properties) || 0; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let overlap = (markerAllowOverlapFn ? markerAllowOverlapFn(zoom, properties) : symbolDef['markerAllowOverlap']) || 0; + let placement = markerIgnorePlacementFn(zoom, properties) || 0; overlap = (markerAllowOverlapFn ? 1 << 3 : 0) + overlap * (1 << 2); placement = (1 << 1) + placement; return overlap + placement; @@ -928,7 +961,8 @@ export function updateMarkerFitSize(map, iconGeometry) { paddingFn = props._paddingFn; } } - const zoom = map.getZoom(); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); //textSize是fn-type,实时更新aMarkerHeight或者aMarkerWidth const { fitIcons, fitWidthIcons, fitHeightIcons } = props; const { aMarkerWidth, aMarkerHeight, labelShape } = props; @@ -953,7 +987,7 @@ export function updateMarkerFitSize(map, iconGeometry) { const fn = properties.textSizeFn = properties.textSizeFn || interpolated(textSize); textSize = fn(zoom, properties); } - textSize /= GLYPH_SIZE; + textSize /= GLYPH_SIZE; let fitPadding = paddingFn && paddingFn(zoom, properties) || padding; if (isFunctionDefinition(fitPadding)) { const fn = properties.fitPaddingFn = properties.fitPaddingFn || piecewiseConstant(fitPadding); diff --git a/packages/vt/src/layer/plugins/painters/util/create_text_painter.js b/packages/vt/src/layer/plugins/painters/util/create_text_painter.js index e48da1372e..6b6532946c 100644 --- a/packages/vt/src/layer/plugins/painters/util/create_text_painter.js +++ b/packages/vt/src/layer/plugins/painters/util/create_text_painter.js @@ -16,6 +16,7 @@ import { projectPoint } from './projection'; import { getLabelContent } from './get_label_content'; import { createAtlasTexture } from './atlas_util'; import { INVALID_PROJECTED_ANCHOR } from '../../../../common/Constant'; +import { MapStateCache } from 'maptalks'; const GAMMA_SCALE = 1; const BOX_ELEMENT_COUNT = 6; @@ -139,7 +140,7 @@ export function createHaloTextMesh( textMesh.setUniform('alphaTest', DEFAULT_ICON_ALPHA_TEST); // isLabelCollides 中,计算碰撞盒时需要 - Object.defineProperty(textMesh.properties, 'textSize', { + Object.defineProperty(textMesh.properties, 'textSize', { enumerable: true, get: function () { return uniforms1['textSize']; @@ -476,7 +477,9 @@ export function getTextFnTypeConfig(map, symbolDef) { width: 4, // evaluate: (properties, geometry) => { - let color = textFillFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let color = textFillFn(zoom, properties); if (isFunctionDefinition(color)) { color = this.evaluateInFnTypeConfig(color, geometry, map, properties, true); } @@ -494,7 +497,9 @@ export function getTextFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: (properties, geometry) => { - let size = textSizeFn(map.getZoom(), properties) || DEFAULT_UNIFORMS['textSize']; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let size = textSizeFn(zoom, properties) || DEFAULT_UNIFORMS['textSize']; if (isFunctionDefinition(size)) { size = this.evaluateInFnTypeConfig(size, geometry, map, properties); } @@ -512,7 +517,9 @@ export function getTextFnTypeConfig(map, symbolDef) { width: 4, // evaluate: properties => { - let color = textHaloFillFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let color = textHaloFillFn(zoom, properties); if (!Array.isArray(color)) { color = colorCache[color] = colorCache[color] || Color(color).unitArray(); } @@ -528,7 +535,9 @@ export function getTextFnTypeConfig(map, symbolDef) { index: 0, width: 2, evaluate: properties => { - const radius = textHaloRadiusFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const radius = textHaloRadiusFn(zoom, properties); u8[0] = radius; return u8[0]; } @@ -541,7 +550,9 @@ export function getTextFnTypeConfig(map, symbolDef) { index: 1, width: 2, evaluate: properties => { - const opacity = textHaloOpacityFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const opacity = textHaloOpacityFn(zoom, properties); u8[0] = opacity * 255; return u8[0]; } @@ -553,7 +564,9 @@ export function getTextFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: (properties, geometry) => { - let x = textDxFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let x = textDxFn(zoom, properties); if (isFunctionDefinition(x)) { x = this.evaluateInFnTypeConfig(x, geometry, map, properties); } @@ -568,7 +581,9 @@ export function getTextFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: (properties, geometry) => { - let y = textDyFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let y = textDyFn(zoom, properties); if (isFunctionDefinition(y)) { y = this.evaluateInFnTypeConfig(y, geometry, map, properties); } @@ -583,7 +598,9 @@ export function getTextFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: (properties, geometry) => { - let opacity = textOpacityFn(map.getZoom(), properties); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let opacity = textOpacityFn(zoom, properties); if (isFunctionDefinition(opacity)) { opacity = this.evaluateInFnTypeConfig(opacity, geometry, map, properties); } @@ -598,7 +615,9 @@ export function getTextFnTypeConfig(map, symbolDef) { width: 1, define: 'HAS_PITCH_ALIGN', evaluate: properties => { - const y = +(textPitchAlignmentFn(map.getZoom(), properties) === 'map'); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = +(textPitchAlignmentFn(zoom, properties) === 'map'); return y; } }, @@ -609,7 +628,9 @@ export function getTextFnTypeConfig(map, symbolDef) { width: 1, define: 'HAS_ROTATION_ALIGN', evaluate: properties => { - const y = +(textRotationAlignmentFn(map.getZoom(), properties) === 'map'); + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = +(textRotationAlignmentFn(zoom, properties) === 'map'); return y; } }, @@ -620,7 +641,9 @@ export function getTextFnTypeConfig(map, symbolDef) { width: 1, define: 'HAS_TEXT_ROTATION', evaluate: properties => { - const y = wrap(textRotationFn(map.getZoom(), properties), 0, 360) * Math.PI / 180; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const y = wrap(textRotationFn(zoom, properties), 0, 360) * Math.PI / 180; u16[0] = y * 9362; return u16[0]; } @@ -631,8 +654,10 @@ export function getTextFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: properties => { - let overlap = textAllowOverlapFn(map.getZoom(), properties) || 0; - let placement = (textIgnorePlacementFn ? textIgnorePlacementFn(map.getZoom(), properties) : symbolDef['textIgnorePlacement']) || 0; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let overlap = textAllowOverlapFn(zoom, properties) || 0; + let placement = (textIgnorePlacementFn ? textIgnorePlacementFn(zoom, properties) : symbolDef['textIgnorePlacement']) || 0; overlap = 1 << 3 + overlap * (1 << 2); placement = (textIgnorePlacementFn ? 1 << 1 : 0) + placement; return overlap + placement; @@ -647,8 +672,10 @@ export function getTextFnTypeConfig(map, symbolDef) { type: Uint8Array, width: 1, evaluate: properties => { - let overlap = (textAllowOverlapFn ? textAllowOverlapFn(map.getZoom(), properties) : symbolDef['textAllowOverlap']) || 0; - let placement = textIgnorePlacementFn(map.getZoom(), properties) || 0; + const cache = MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + let overlap = (textAllowOverlapFn ? textAllowOverlapFn(zoom, properties) : symbolDef['textAllowOverlap']) || 0; + let placement = textIgnorePlacementFn(zoom, properties) || 0; overlap = (textAllowOverlapFn ? 1 << 3 : 0) + overlap * (1 << 2); placement = 1 << 1 + placement; return overlap + placement; diff --git a/packages/vt/src/layer/plugins/painters/util/get_icon_box.js b/packages/vt/src/layer/plugins/painters/util/get_icon_box.js index 5694426ab3..2198b5ccf0 100644 --- a/packages/vt/src/layer/plugins/painters/util/get_icon_box.js +++ b/packages/vt/src/layer/plugins/painters/util/get_icon_box.js @@ -4,6 +4,7 @@ import { getPitchPosition, getPosition, getShapeMatrix } from './box_util'; import { getDefaultMarkerSize } from './atlas_util'; import { isNil, clamp } from '../../Util'; import { DEFAULT_MARKER_WIDTH, DEFAULT_MARKER_HEIGHT, ICON_SIZE } from '../Constant'; +import { MapStateCache } from 'maptalks'; //temparary variables const ANCHOR = [], PROJ_ANCHOR = []; @@ -16,6 +17,7 @@ const SIZE_SCALE = [1, 1]; export function getIconBox(out, mesh, i, matrix, map) { + const cache = MapStateCache[map.id]; const uniforms = mesh.material.uniforms; const cameraToCenterDistance = map.cameraToCenterDistance; const geoProps = mesh.geometry.properties; @@ -66,7 +68,7 @@ export function getIconBox(out, mesh, i, matrix, map) { vec2.multiply(br, br, AXIS_FACTOR); } - const [ defaultMarkerWidth, defaultMarkerHeight ] = getDefaultMarkerSize(mesh.geometry); + const [defaultMarkerWidth, defaultMarkerHeight] = getDefaultMarkerSize(mesh.geometry); let markerWidth = (aMarkerWidth ? aMarkerWidth[i] : symbol['markerWidth']); if (isNil(markerWidth)) { markerWidth = defaultMarkerWidth || DEFAULT_MARKER_WIDTH; @@ -96,7 +98,7 @@ export function getIconBox(out, mesh, i, matrix, map) { // 3.1 如果没有pitchWithMap,值是 shapeMatrix * shape // 3.2 如果pitchWithMap, 值是aAnchor和shape相加后,projectPoint后的计算结果 //4. 将最终计算结果与dxdy相加 - const mapRotation = map.getBearing() * Math.PI / 180; + const mapRotation = (cache ? cache.bearing : map.geBearing()) * Math.PI / 180; if (mapRotation * rotateWithMap || rotation) { const shapeMatrix = getShapeMatrix(MAT2, rotation, mapRotation, rotateWithMap, pitchWithMap); @@ -116,7 +118,7 @@ export function getIconBox(out, mesh, i, matrix, map) { getPosition(out, projAnchor, tl, tr, bl, br, dxdy, perspectiveRatio); } - const dpr = this.getMap().getDevicePixelRatio(); + const dpr = cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); if (dpr !== 1) { out[0] *= dpr; out[1] *= dpr; diff --git a/packages/vt/src/layer/plugins/painters/util/get_label_box.js b/packages/vt/src/layer/plugins/painters/util/get_label_box.js index 1d77644e8d..1bccc113a2 100644 --- a/packages/vt/src/layer/plugins/painters/util/get_label_box.js +++ b/packages/vt/src/layer/plugins/painters/util/get_label_box.js @@ -4,6 +4,7 @@ import { getPitchPosition, getPosition, getShapeMatrix } from './box_util'; import { GLYPH_SIZE } from '../Constant'; import { getCentiMeterScale } from '../../../../common/Util'; import { getVectorPacker } from '../../../../packer/inject'; +import { MapStateCache } from 'maptalks'; const { PackUtil } = getVectorPacker(); @@ -23,6 +24,7 @@ export function getLabelBox(out, anchor, projAnchor, mesh, textSize, textHaloRad const geoProps = mesh.geometry.properties; const symbol = this.getSymbol(geoProps.symbolIndex); const isAlongLine = symbol['textPlacement'] === 'line' && !isIconText(symbol); + const cache = MapStateCache[map.id]; const glyphSize = GLYPH_SIZE; @@ -95,7 +97,7 @@ export function getLabelBox(out, anchor, projAnchor, mesh, textSize, textHaloRad } else { textRotation = (symbol['textRotation'] || 0) * Math.PI / 180; } - const mapRotation = !isAlongLine ? map.getBearing() * Math.PI / 180 : 0; + const mapRotation = !isAlongLine ? (cache ? cache.bearing : map.getBearing()) * Math.PI / 180 : 0; if (textRotation || mapRotation) { const shapeMatrix = getShapeMatrix(MAT2, textRotation, mapRotation, rotateWidthMap, pitchWithMap); tl = vec2.transformMat2(tl, tl, shapeMatrix); @@ -138,17 +140,17 @@ export function getLabelBox(out, anchor, projAnchor, mesh, textSize, textHaloRad //除以10是因为赋值时, aOffset有精度修正 if (is3DPitchText) { tl = vec3.set(V2_0, aOffset[i * 3] / 10, aOffset[i * 3 + 1] / 10, aOffset[i * 3 + 2] / 10), - tr = vec3.set(V2_1, aOffset[i * 3 + 3] / 10, aOffset[i * 3 + 4] / 10, aOffset[i * 3 + 5] / 10), - bl = vec3.set(V2_2, aOffset[i * 3 + 6] / 10, aOffset[i * 3 + 7] / 10, aOffset[i * 3 + 8] / 10), - br = vec3.set(V2_3, aOffset[i * 3 + 9] / 10, aOffset[i * 3 + 10] / 10, aOffset[i * 3 + 11] / 10); + tr = vec3.set(V2_1, aOffset[i * 3 + 3] / 10, aOffset[i * 3 + 4] / 10, aOffset[i * 3 + 5] / 10), + bl = vec3.set(V2_2, aOffset[i * 3 + 6] / 10, aOffset[i * 3 + 7] / 10, aOffset[i * 3 + 8] / 10), + br = vec3.set(V2_3, aOffset[i * 3 + 9] / 10, aOffset[i * 3 + 10] / 10, aOffset[i * 3 + 11] / 10); } else { tl = vec2.set(V2_0, aOffset[i * 2] / 10, aOffset[i * 2 + 1] / 10), - tr = vec2.set(V2_1, aOffset[i * 2 + 2] / 10, aOffset[i * 2 + 3] / 10), - bl = vec2.set(V2_2, aOffset[i * 2 + 4] / 10, aOffset[i * 2 + 5] / 10), - br = vec2.set(V2_3, aOffset[i * 2 + 6] / 10, aOffset[i * 2 + 7] / 10); + tr = vec2.set(V2_1, aOffset[i * 2 + 2] / 10, aOffset[i * 2 + 3] / 10), + bl = vec2.set(V2_2, aOffset[i * 2 + 4] / 10, aOffset[i * 2 + 5] / 10), + br = vec2.set(V2_3, aOffset[i * 2 + 6] / 10, aOffset[i * 2 + 7] / 10); } if (pitchWithMap === 1) { - const altitudeScale = getCentiMeterScale(map.getResolution(), map); + const altitudeScale = getCentiMeterScale(cache ? cache.resolution : map.getResolution(), map); getPitchPosition(out, anchor, tl, tr, bl, br, matrix, dxdy, uniforms, map, cameraDistance, perspectiveRatio, is3DPitchText, altitudeScale); } else { vec2.multiply(tl, tl, AXIS_FACTOR); @@ -164,7 +166,7 @@ export function getLabelBox(out, anchor, projAnchor, mesh, textSize, textHaloRad out[2] += textHaloRadius + TEXT_BOX_MARGIN; out[3] += textHaloRadius + TEXT_BOX_MARGIN; - const dpr = this.getMap().getDevicePixelRatio(); + const dpr = cache ? cache.devicePixelRatio : map.getDevicePixelRatio(); if (dpr !== 1) { out[0] *= dpr; out[1] *= dpr; diff --git a/packages/vt/src/layer/renderer/VectorTileLayerRenderer.js b/packages/vt/src/layer/renderer/VectorTileLayerRenderer.js index 3dd49d1037..9c48944605 100644 --- a/packages/vt/src/layer/renderer/VectorTileLayerRenderer.js +++ b/packages/vt/src/layer/renderer/VectorTileLayerRenderer.js @@ -518,7 +518,10 @@ class VectorTileLayerRenderer extends CanvasCompatible(TileLayerRendererable(Lay _getTileZoomDiff(mesh) { const layer = this.layer; - let zoom = layer['_getTileZoom'](this.getMap().getZoom()); + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + + let zoom = layer['_getTileZoom'](cache ? cache.zoom : map.getZoom()); const minZoom = layer.getMinZoom(), maxZoom = layer.getMaxZoom(); zoom = maptalks.Util.clamp(zoom, minZoom, maxZoom); diff --git a/packages/vt/src/layer/vector/ExtrudePolygonLayer.ts b/packages/vt/src/layer/vector/ExtrudePolygonLayer.ts index a2c32f9581..85a87c578c 100644 --- a/packages/vt/src/layer/vector/ExtrudePolygonLayer.ts +++ b/packages/vt/src/layer/vector/ExtrudePolygonLayer.ts @@ -1,4 +1,4 @@ -import { Geometry, Circle, Rectangle, Ellipse, Sector, Coordinate, Point, Polygon, MultiPolygon } from "maptalks"; +import { Geometry, Circle, Rectangle, Ellipse, Sector, Coordinate, Point, Polygon, MultiPolygon, MapStateCache } from "maptalks"; import type { LitDataConfig, LitMaterial } from "../../types"; import { extend, isNil } from "../../common/Util"; @@ -385,7 +385,9 @@ class ExtrudePolygonLayerRenderer extends PolygonLayerRenderer { const extent = Infinity; const tileRatio = 1; // 原zoom是用来计算functiont-type 的symbol属性值 - const zoom = map.getZoom(); + const cache = MapStateCache[map.id]; + + const zoom = cache ? cache.zoom : map.getZoom(); const tilePoint = new Point(0, 0); const tileCoord = new Coordinate(0, 0); const dataConfig = extend( diff --git a/packages/vt/src/layer/vector/Vector3DLayerRenderer.js b/packages/vt/src/layer/vector/Vector3DLayerRenderer.js index f9db11414a..de52fd3cc2 100644 --- a/packages/vt/src/layer/vector/Vector3DLayerRenderer.js +++ b/packages/vt/src/layer/vector/Vector3DLayerRenderer.js @@ -714,8 +714,11 @@ class Vector3DLayerRenderer extends CanvasCompatible(LayerAbstractRenderer) { } _getPackOptions(atlas, center) { + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); const options = { - zoom: this.getMap().getZoom(), + zoom, EXTENT: Infinity, atlas, center, @@ -744,9 +747,12 @@ class Vector3DLayerRenderer extends CanvasCompatible(LayerAbstractRenderer) { updateMesh() { } _updateMarkerMesh(marker) { + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); const symbols = marker['_getInternalSymbol'](); const options = { - zoom: this.getMap().getZoom(), + zoom, isVector3D: true, defaultMarkerVerticalAlignment: 'top' }; @@ -761,7 +767,6 @@ class Vector3DLayerRenderer extends CanvasCompatible(LayerAbstractRenderer) { const params = []; const markerFeatures = []; const textFeatures = []; - const zoom = this.getMap().getZoom(); let loadedSymbols; if (Array.isArray(symbols)) { loadedSymbols = symbols.map(symbol => { @@ -868,7 +873,10 @@ class Vector3DLayerRenderer extends CanvasCompatible(LayerAbstractRenderer) { return false; } const symbols = target['_getInternalSymbol'](); - const options = { zoom: this.getMap().getZoom() }; + const map = this.getMap(); + const cache = maptalks.MapStateCache[map.id]; + const zoom = cache ? cache.zoom : map.getZoom(); + const options = { zoom }; const uid = target[ID_PROP]; let feature = this.features[uid]; if (!Array.isArray(feature)) {