From f001650437dbff6bc67015457d23068e9a99d4a4 Mon Sep 17 00:00:00 2001 From: deyihu Date: Thu, 21 Dec 2023 10:25:44 +0800 Subject: [PATCH 1/9] UIMarker Can only be added to the map --- src/layer/OverlayLayer.js | 27 +++++++++++++++++++++++---- src/map/Map.js | 1 + src/ui/UIComponent.js | 1 + src/ui/UIMarker.js | 6 ++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/layer/OverlayLayer.js b/src/layer/OverlayLayer.js index 1c63b9ec9b..3e38e845fc 100644 --- a/src/layer/OverlayLayer.js +++ b/src/layer/OverlayLayer.js @@ -6,6 +6,10 @@ import { createFilter, getFilterFeature, compileStyle } from '@maptalks/feature- import Layer from './Layer'; import GeoJSON from '../geometry/GeoJSON'; +function isGeometry(geo) { + return geo && (geo instanceof Geometry); +} + /** * @property {Boolean} [options.drawImmediate=false] - (Only for layer rendered with [CanvasRenderer]{@link renderer.CanvasRenderer})
* In default, for performance reason, layer will be drawn in a frame requested by RAF(RequestAnimationFrame).
@@ -35,7 +39,7 @@ const TMP_EVENTS_ARR = []; class OverlayLayer extends Layer { constructor(id, geometries, options) { - if (geometries && (!(geometries instanceof Geometry) && !Array.isArray(geometries) && GEOJSON_TYPES.indexOf(geometries.type) < 0)) { + if (geometries && (!isGeometry(geometries) && !Array.isArray(geometries) && GEOJSON_TYPES.indexOf(geometries.type) < 0)) { options = geometries; geometries = null; } @@ -226,12 +230,18 @@ class OverlayLayer extends Layer { const last = arguments[count - 1]; geometries = Array.prototype.slice.call(arguments, 0, count - 1); fitView = last; - if (last && isObject(last) && (('type' in last) || last instanceof Geometry)) { + if (last && isObject(last) && (('type' in last) || isGeometry(last))) { geometries.push(last); fitView = false; } + for (let i = 0, len = geometries.length; i < len; i++) { + if (!isGeometry(geometries[i])) { + console.warn(geometries[i], 'is not Geometry,This may not be a correct operation'); + } + } return this.addGeometry(geometries, fitView); } else if (geometries.length === 0) { + console.warn('geometries is empty'); return this; } this._initCache(); @@ -244,12 +254,17 @@ class OverlayLayer extends Layer { for (let i = 0, l = geometries.length; i < l; i++) { let geo = geometries[i]; if (!geo) { - throw new Error('Invalid geometry to add to layer(' + this.getId() + ') at index:' + i); + console.error('Invalid geometry to add to layer(' + this.getId() + ') at index:' + i); + continue; + } + if (geo.isUI) { + console.error(geo, 'is UI,can not add to layer'); + continue; } if (geo.getLayer && geo.getLayer() === this) { continue; } - if (!(geo instanceof Geometry)) { + if (!isGeometry(geo)) { geo = Geometry.fromJSON(geo); if (Array.isArray(geo)) { for (let ii = 0, ll = geo.length; ii < ll; ii++) { @@ -258,6 +273,10 @@ class OverlayLayer extends Layer { } } } + if (!geo || !isGeometry(geo)) { + console.error(geo, 'is not Geometry'); + continue; + } if (!Array.isArray(geo)) { this._add(geo, extent, i); geos.push(geo); diff --git a/src/map/Map.js b/src/map/Map.js index d85c9c1ef8..08a1aa8394 100644 --- a/src/map/Map.js +++ b/src/map/Map.js @@ -253,6 +253,7 @@ class Map extends Handlerable(Eventable(Renderable(Class))) { this._Load(); this.proxyOptions(); + this.isMap = true; } /** diff --git a/src/ui/UIComponent.js b/src/ui/UIComponent.js index b02e750881..82a73e77a1 100644 --- a/src/ui/UIComponent.js +++ b/src/ui/UIComponent.js @@ -93,6 +93,7 @@ class UIComponent extends Eventable(Class) { constructor(options) { super(options); this.proxyOptions(); + this.isUI = true; } /** diff --git a/src/ui/UIMarker.js b/src/ui/UIMarker.js index 4eee5c69c7..a9559945b0 100644 --- a/src/ui/UIMarker.js +++ b/src/ui/UIMarker.js @@ -325,7 +325,13 @@ class UIMarker extends Handlerable(UIComponent) { } onAdd() { + if (this._owner && !this._owner.isMap) { + console.error('UIMarker Can only be added to the map,but owner is:', this._owner); + delete this._owner; + return this; + } this.show(); + return this; } /** From bea8fc75ef35db0a838b6cbf8b39d735cf770c7b Mon Sep 17 00:00:00 2001 From: deyihu Date: Thu, 21 Dec 2023 10:25:53 +0800 Subject: [PATCH 2/9] spec --- test/ui/UIMarkerSpec.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/ui/UIMarkerSpec.js b/test/ui/UIMarkerSpec.js index 11e5f8e7cd..b5df9af39f 100644 --- a/test/ui/UIMarkerSpec.js +++ b/test/ui/UIMarkerSpec.js @@ -5,12 +5,14 @@ describe('UI.UIMarker', function () { var context = { }; + var layer; beforeEach(function () { var setups = COMMON_CREATE_MAP(center); container = setups.container; map = setups.map; context.map = map; + layer = new maptalks.VectorLayer('v').addTo(map); }); afterEach(function () { @@ -226,4 +228,18 @@ describe('UI.UIMarker', function () { pitch: 60 }); }); + + it('UIMarker Can only be added to the map', function (done) { + var marker = new maptalks.ui.UIMarker(map.getCenter(), { + content: '
maptalks
', + verticalAlignment: 'top', + altitude: 20, + dy: -5 + }); + layer.addGeometry(marker); + expect(layer.getGeometries().length).to.be.equal(0); + marker.addTo(layer); + expect(marker.getOwner()).to.be.equal(undefined); + done(); + }); }); From a42756f1d925d3fb249c28484aba1dd5446a4a5f Mon Sep 17 00:00:00 2001 From: deyihu Date: Thu, 21 Dec 2023 12:51:16 +0800 Subject: [PATCH 3/9] updates --- src/geometry/GeoJSON.js | 36 ++++++++++++++++++++++++++++++++++++ src/layer/OverlayLayer.js | 19 +++++-------------- test/ui/UIMarkerSpec.js | 11 ++++++++++- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/geometry/GeoJSON.js b/src/geometry/GeoJSON.js index 28e18fd3bd..950bdf8b9a 100644 --- a/src/geometry/GeoJSON.js +++ b/src/geometry/GeoJSON.js @@ -23,6 +23,9 @@ const types = { 'MultiPolygon': MultiPolygon }; +const GEOJSON_TYPES = ['Point', 'LineString', 'Polygon', + 'MultiPoint', 'MultiLineString', 'MultiPolygon', 'FeatureCollection', 'GeometryCollection', 'Feature']; + /** * GeoJSON utilities * @class @@ -160,6 +163,39 @@ const GeoJSON = { return result; } return null; + }, + + _isGeoJSON(json) { + if (!json) { + return false; + } + json = json || {}; + //is flat geometries + if (Array.isArray(json) && json.length) { + return GeoJSON.isGeoJSON(json[0]); + } + const type = json.type; + if (GEOJSON_TYPES.indexOf(type) === -1) { + return false; + } + const { features, geometries, geometry, coordinates } = json; + //FeatureCollection + if (Array.isArray(features)) { + return true; + } + //Feature + if (geometry && geometry.coordinates && Array.isArray(geometry.coordinates)) { + return true; + } + if (Array.isArray(geometries)) { + return true; + } + //Geometry + if (coordinates && Array.isArray(coordinates)) { + return true; + } + return false; + } }; diff --git a/src/layer/OverlayLayer.js b/src/layer/OverlayLayer.js index 3e38e845fc..a25e3cea8a 100644 --- a/src/layer/OverlayLayer.js +++ b/src/layer/OverlayLayer.js @@ -234,14 +234,8 @@ class OverlayLayer extends Layer { geometries.push(last); fitView = false; } - for (let i = 0, len = geometries.length; i < len; i++) { - if (!isGeometry(geometries[i])) { - console.warn(geometries[i], 'is not Geometry,This may not be a correct operation'); - } - } return this.addGeometry(geometries, fitView); } else if (geometries.length === 0) { - console.warn('geometries is empty'); return this; } this._initCache(); @@ -253,12 +247,8 @@ class OverlayLayer extends Layer { const geos = []; for (let i = 0, l = geometries.length; i < l; i++) { let geo = geometries[i]; - if (!geo) { - console.error('Invalid geometry to add to layer(' + this.getId() + ') at index:' + i); - continue; - } - if (geo.isUI) { - console.error(geo, 'is UI,can not add to layer'); + if (!(geo && (GeoJSON._isGeoJSON(geo) || isGeometry(geo)))) { + console.error(geo, 'is not Invalid geometry to add to layer(' + this.getId() + ') at index:' + i); continue; } if (geo.getLayer && geo.getLayer() === this) { @@ -273,8 +263,9 @@ class OverlayLayer extends Layer { } } } - if (!geo || !isGeometry(geo)) { - console.error(geo, 'is not Geometry'); + // geojson to Geometry may be null + if (!geo) { + console.error(geo, 'is null'); continue; } if (!Array.isArray(geo)) { diff --git a/test/ui/UIMarkerSpec.js b/test/ui/UIMarkerSpec.js index b5df9af39f..81a67397cf 100644 --- a/test/ui/UIMarkerSpec.js +++ b/test/ui/UIMarkerSpec.js @@ -202,7 +202,7 @@ describe('UI.UIMarker', function () { }); marker.addTo(map).show(); - setTimeout(function() { + setTimeout(function () { var m = document.getElementById('uimarker'); expect(m).to.be.ok(); map.getContainer().style.width = '400px'; @@ -236,10 +236,19 @@ describe('UI.UIMarker', function () { altitude: 20, dy: -5 }); + //layer add uimarker layer.addGeometry(marker); expect(layer.getGeometries().length).to.be.equal(0); + //add Invalid geometry + layer.addGeometry({ type: 'hello' }); + expect(layer.getGeometries().length).to.be.equal(0); + //uimarker add to layer marker.addTo(layer); expect(marker.getOwner()).to.be.equal(undefined); + //uimarker add Geometry + const point = new maptalks.Marker(map.getCenter()); + marker.addTo(point); + expect(marker.getOwner()).to.be.equal(undefined); done(); }); }); From 244c104a34abbf9048bd0716037d8db229e7e134 Mon Sep 17 00:00:00 2001 From: deyihu Date: Thu, 21 Dec 2023 13:00:18 +0800 Subject: [PATCH 4/9] update desc --- src/geometry/GeoJSON.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/geometry/GeoJSON.js b/src/geometry/GeoJSON.js index 950bdf8b9a..3eb70bca47 100644 --- a/src/geometry/GeoJSON.js +++ b/src/geometry/GeoJSON.js @@ -170,7 +170,7 @@ const GeoJSON = { return false; } json = json || {}; - //is flat geometries + //is flat geometries,[geometry,geometry,...] if (Array.isArray(json) && json.length) { return GeoJSON.isGeoJSON(json[0]); } @@ -187,6 +187,7 @@ const GeoJSON = { if (geometry && geometry.coordinates && Array.isArray(geometry.coordinates)) { return true; } + //GeometryCollection if (Array.isArray(geometries)) { return true; } From 87bed772caba8ceb5e9709c87013c6ad318773c1 Mon Sep 17 00:00:00 2001 From: deyihu Date: Thu, 21 Dec 2023 13:04:47 +0800 Subject: [PATCH 5/9] use GEOJSON_TYPES from Constants --- src/geometry/GeoJSON.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/geometry/GeoJSON.js b/src/geometry/GeoJSON.js index 3eb70bca47..1cd8f4364b 100644 --- a/src/geometry/GeoJSON.js +++ b/src/geometry/GeoJSON.js @@ -13,6 +13,7 @@ import MultiLineString from './MultiLineString'; import MultiPolygon from './MultiPolygon'; import GeometryCollection from './GeometryCollection'; import Geometry from './Geometry'; +import { GEOJSON_TYPES } from '../core/Constants'; const types = { 'Marker': Marker, @@ -23,9 +24,6 @@ const types = { 'MultiPolygon': MultiPolygon }; -const GEOJSON_TYPES = ['Point', 'LineString', 'Polygon', - 'MultiPoint', 'MultiLineString', 'MultiPolygon', 'FeatureCollection', 'GeometryCollection', 'Feature']; - /** * GeoJSON utilities * @class From 4769b12f6d3c5b1e479748613ece24877ed417a0 Mon Sep 17 00:00:00 2001 From: deyihu Date: Thu, 21 Dec 2023 13:07:31 +0800 Subject: [PATCH 6/9] add isLayer isGeometry for Layer and Geometry --- src/geometry/Geometry.js | 1 + src/layer/Layer.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/geometry/Geometry.js b/src/geometry/Geometry.js index 3f2eba08a6..acae2f8134 100644 --- a/src/geometry/Geometry.js +++ b/src/geometry/Geometry.js @@ -92,6 +92,7 @@ class Geometry extends JSONAble(Eventable(Handlerable(Class))) { if (!isNil(id)) { this.setId(id); } + this.isGeometry = true; } /** diff --git a/src/layer/Layer.js b/src/layer/Layer.js index da5ae857fb..0c5f85484d 100644 --- a/src/layer/Layer.js +++ b/src/layer/Layer.js @@ -80,6 +80,7 @@ class Layer extends JSONAble(Eventable(Renderable(Class))) { } } this.proxyOptions(); + this.isLayer = true; } /** From 5790dedc082556c8bc08243d19319621f9eee94c Mon Sep 17 00:00:00 2001 From: deyihu Date: Thu, 21 Dec 2023 15:43:47 +0800 Subject: [PATCH 7/9] updates --- src/geometry/GeoJSON.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/geometry/GeoJSON.js b/src/geometry/GeoJSON.js index 1cd8f4364b..2b18a2f454 100644 --- a/src/geometry/GeoJSON.js +++ b/src/geometry/GeoJSON.js @@ -173,26 +173,34 @@ const GeoJSON = { return GeoJSON.isGeoJSON(json[0]); } const type = json.type; + if (!type) { + return false; + } if (GEOJSON_TYPES.indexOf(type) === -1) { return false; } const { features, geometries, geometry, coordinates } = json; - //FeatureCollection - if (Array.isArray(features)) { - return true; - } - //Feature - if (geometry && geometry.coordinates && Array.isArray(geometry.coordinates)) { + + //Geometry + if (coordinates && Array.isArray(coordinates)) { return true; } //GeometryCollection if (Array.isArray(geometries)) { return true; } - //Geometry - if (coordinates && Array.isArray(coordinates)) { + + //FeatureCollection + if (Array.isArray(features)) { return true; } + //Feature + if (geometry) { + const coordinates = geometry.coordinates; + if (coordinates && Array.isArray(coordinates)) { + return true; + } + } return false; } From 149c9da0e7ef5c347d35e1d53b5e87f04a4af598 Mon Sep 17 00:00:00 2001 From: deyihu Date: Fri, 22 Dec 2023 17:53:31 +0800 Subject: [PATCH 8/9] updates --- src/layer/OverlayLayer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layer/OverlayLayer.js b/src/layer/OverlayLayer.js index a25e3cea8a..24c59c3555 100644 --- a/src/layer/OverlayLayer.js +++ b/src/layer/OverlayLayer.js @@ -265,7 +265,7 @@ class OverlayLayer extends Layer { } // geojson to Geometry may be null if (!geo) { - console.error(geo, 'is null'); + console.error(geo, 'is not Invalid geometry to add to layer(' + this.getId() + ') at index:' + i); continue; } if (!Array.isArray(geo)) { From b7378c6e2104d7cc12ba699c9ad3b328ecf0f326 Mon Sep 17 00:00:00 2001 From: deyihu Date: Mon, 25 Dec 2023 15:24:02 +0800 Subject: [PATCH 9/9] updates --- src/geometry/Geometry.js | 1 - src/layer/Layer.js | 1 - src/ui/UIComponent.js | 1 - 3 files changed, 3 deletions(-) diff --git a/src/geometry/Geometry.js b/src/geometry/Geometry.js index acae2f8134..3f2eba08a6 100644 --- a/src/geometry/Geometry.js +++ b/src/geometry/Geometry.js @@ -92,7 +92,6 @@ class Geometry extends JSONAble(Eventable(Handlerable(Class))) { if (!isNil(id)) { this.setId(id); } - this.isGeometry = true; } /** diff --git a/src/layer/Layer.js b/src/layer/Layer.js index 0c5f85484d..da5ae857fb 100644 --- a/src/layer/Layer.js +++ b/src/layer/Layer.js @@ -80,7 +80,6 @@ class Layer extends JSONAble(Eventable(Renderable(Class))) { } } this.proxyOptions(); - this.isLayer = true; } /** diff --git a/src/ui/UIComponent.js b/src/ui/UIComponent.js index 82a73e77a1..b02e750881 100644 --- a/src/ui/UIComponent.js +++ b/src/ui/UIComponent.js @@ -93,7 +93,6 @@ class UIComponent extends Eventable(Class) { constructor(options) { super(options); this.proxyOptions(); - this.isUI = true; } /**