diff --git a/packages/maptalks/src/core/util/draw.ts b/packages/maptalks/src/core/util/draw.ts index 5231b1dba7..4397f921ed 100644 --- a/packages/maptalks/src/core/util/draw.ts +++ b/packages/maptalks/src/core/util/draw.ts @@ -4,6 +4,7 @@ import { isGradient } from './style'; import { isNumber } from './common'; import Canvas from '../Canvas'; import { ResourceCache } from '../../renderer/layer/CanvasRenderer' +import { BBOX } from './bbox'; export function drawImageMarker(ctx: CanvasRenderingContext2D, image, point, symbol) { let w = symbol && symbol['markerWidth']; @@ -22,7 +23,7 @@ export function getImage(resources: ResourceCache, url: string) { return img || null; } -export function drawVectorMarker(ctx: CanvasRenderingContext2D, point, symbol, resources: ResourceCache) { +export function drawVectorMarker(ctx: CanvasRenderingContext2D, point, symbol, resources: ResourceCache, bbox?: BBOX) { const strokeAndFill = translateMarkerLineAndFill(symbol); const style = symbol, markerType = style['markerType'].toLowerCase(), @@ -44,7 +45,8 @@ export function drawVectorMarker(ctx: CanvasRenderingContext2D, point, symbol, r const width = style['markerWidth'], height = style['markerHeight'], - hLineWidth = style['markerLineWidth'] / 2; + lineWidth = style['markerLineWidth'] || 0, + hLineWidth = lineWidth / 2; if (markerType === 'ellipse') { //ellipse default Canvas.ellipse(ctx, point, width / 2, height / 2, height / 2, lineOpacity, fillOpacity); @@ -85,6 +87,14 @@ export function drawVectorMarker(ctx: CanvasRenderingContext2D, point, symbol, r } else { throw new Error('unsupported markerType: ' + markerType); } + if (bbox) { + //record marker bbox if need + const { x, y } = point; + bbox[0] = x - width / 2 - lineWidth; + bbox[1] = y - height / 2 - lineWidth; + bbox[2] = x + width / 2 + lineWidth; + bbox[3] = y + height / 2 + lineWidth; + } return ctx.canvas; } diff --git a/packages/maptalks/src/renderer/geometry/symbolizers/VectorMarkerSymbolizer.ts b/packages/maptalks/src/renderer/geometry/symbolizers/VectorMarkerSymbolizer.ts index 06062abad6..468f9a9253 100644 --- a/packages/maptalks/src/renderer/geometry/symbolizers/VectorMarkerSymbolizer.ts +++ b/packages/maptalks/src/renderer/geometry/symbolizers/VectorMarkerSymbolizer.ts @@ -13,10 +13,12 @@ import { Geometry } from '../../../geometry'; import Painter from '../Painter'; import { Extent } from '../../../geo'; import { ResourceCache } from '../../layer/CanvasRenderer'; +import { getDefaultBBOX, resetBBOX } from '../../../core/util/bbox'; const MARKER_SIZE: [number, number] = [0, 0]; const TEMP_EXTENT = new PointExtent(); const DEFAULT_ANCHOR = new Point(0, 0); +const TEMP_BBOX = getDefaultBBOX(); export default class VectorMarkerSymbolizer extends PointSymbolizer { //@internal @@ -66,14 +68,16 @@ export default class VectorMarkerSymbolizer extends PointSymbolizer { this.geometry.getLayer().getMask() === this.geometry || this._dynamic || this.geometry.getLayer().options['cacheVectorOnCanvas'] === false) { - this._drawMarkers(ctx, cookedPoints, resources); + //动态样式或者不缓存,function-type style, or not cache vector on canvas + this._drawMarkersWithDynamic(ctx, cookedPoints, resources); } else { this._drawMarkersWithCache(ctx, cookedPoints, resources); } } + //rename to _drawMarkersWithDynamic //@internal - _drawMarkers(ctx: CanvasRenderingContext2D, cookedPoints: any[], resources: ResourceCache) { + _drawMarkersWithDynamic(ctx: CanvasRenderingContext2D, cookedPoints: any[], resources: ResourceCache) { for (let i = cookedPoints.length - 1; i >= 0; i--) { let point = cookedPoints[i]; const size = calVectorMarkerSize(MARKER_SIZE, this.style); @@ -90,13 +94,17 @@ export default class VectorMarkerSymbolizer extends PointSymbolizer { this.rotations.push(rad); } - this._drawVectorMarker(ctx, point, resources); + const bbox = this._drawVectorMarker(ctx, point, resources); if (origin) { ctx.restore(); this._setBBOX(ctx, extent.xmin, extent.ymin, extent.xmax, extent.ymax); } else { - const { x, y } = point; - this._setBBOX(ctx, x, y, x + width, y + height); + if (bbox) { + this._setBBOX(ctx, bbox[0], bbox[1], bbox[2], bbox[3]); + } else { + const { x, y } = point; + this._setBBOX(ctx, x, y, x + width, y + height); + } } } } @@ -203,15 +211,21 @@ export default class VectorMarkerSymbolizer extends PointSymbolizer { //@internal _drawVectorMarker(ctx: CanvasRenderingContext2D, point: Point, resources: ResourceCache) { - drawVectorMarker(ctx, point, this.style, resources); + resetBBOX(TEMP_BBOX); + drawVectorMarker(ctx, point, this.style, resources, TEMP_BBOX); + return TEMP_BBOX; } getFixedExtent(): PointExtent { - const isDynamic = this.isDynamicSize(); - const w = this.style.markerWidth; - const h = this.style.markerHeight; + // const isDynamic = this.isDynamicSize(); + // const w = this.style.markerWidth; + // const h = this.style.markerHeight; + // this._fixedExtent = this._fixedExtent || new PointExtent(); + // return getVectorMarkerFixedExtent(this._fixedExtent, this.style, isDynamic ? [128, 128 * (w === 0 ? 1 : h / w)] : null); + this._fixedExtent = this._fixedExtent || new PointExtent(); - return getVectorMarkerFixedExtent(this._fixedExtent, this.style, isDynamic ? [128, 128 * (w === 0 ? 1 : h / w)] : null); + return getVectorMarkerFixedExtent(this._fixedExtent, this.style, null); + } translate(): any { diff --git a/packages/maptalks/test/geometry/MarkerSpec.js b/packages/maptalks/test/geometry/MarkerSpec.js index e722ea8bfb..9d2df06850 100644 --- a/packages/maptalks/test/geometry/MarkerSpec.js +++ b/packages/maptalks/test/geometry/MarkerSpec.js @@ -674,6 +674,74 @@ describe('Geometry.Marker', function () { .addTo(map); }); + + it('#2511 vector marker with function-type getFixedExtent', function (done) { + map.config('zoomAnimation', false); + var marker = new maptalks.Marker(map.getCenter(), { + properties: { name: '1111' }, + // symbol: { + // markerType: "ellipse", + // markerWidth: 50, + // markerHeight: 50 + // }, + symbol: [ + { + markerType: "ellipse", + // markerWidth: 50, + // markerHeight: 50, + markerWidth: { + stops: [ + [1, 10], + [17, 60], + ], + }, + markerHeight: { + stops: [ + [1, 10], + [17, 60], + ], + }, + markerDy: { + stops: [ + [1, -2], + [17, -80], + ], + }, + markerFill: { + type: "radial", + colorStops: [ + [0.0, "rgba(216,115,149,0)"], + [0.5, "rgba(216,115,149,0.7)"], + [1.0, "rgba(216,115,149,1)"], + ], + }, + markerLineWidth: 1, + }, + + ] + }); + var layer = new maptalks.VectorLayer('id', { 'drawImmediate': true }).addTo(map); + layer.addGeometry([marker]); + + setTimeout(() => { + const extent = marker._getPainter().getFixedExtent(); + const { xmin, ymin, xmax, ymax } = extent; + expect(Math.floor(xmin)).to.be.eql(-31); + // eslint-disable-next-line no-undef + if (isWindows()) { + expect(Math.floor(xmax)).to.be.eql(29); + expect(Math.floor(ymin)).to.be.eql(-105); + expect(Math.floor(ymax)).to.be.eql(-46); + } else { + expect(Math.floor(xmax)).to.be.eql(31); + expect(Math.floor(ymin)).to.be.eql(-111); + expect(Math.floor(ymax)).to.be.eql(-49); + } + done(); + }, 1000); + + + }); }); describe('marker rotation', function () {