From 9aef1eaa185c689548fc183a4e8ecebb67c92f2c Mon Sep 17 00:00:00 2001 From: Vladimir Vershinin Date: Fri, 6 Sep 2019 20:11:31 +0300 Subject: [PATCH 01/11] vl-source-cluster: reformat component, additional watchers --- src/component/cluster-source/source.vue | 141 ++++++++++++------------ test/app.vue | 72 ++++++------ 2 files changed, 113 insertions(+), 100 deletions(-) diff --git a/src/component/cluster-source/source.vue b/src/component/cluster-source/source.vue index ee7129a5..0fb2ff07 100644 --- a/src/component/cluster-source/source.vue +++ b/src/component/cluster-source/source.vue @@ -1,91 +1,94 @@ From 69c81511e958c4dd8bc4cd7060cdbb3a3b9835b2 Mon Sep 17 00:00:00 2001 From: Vladimir Vershinin Date: Fri, 6 Sep 2019 23:22:24 +0300 Subject: [PATCH 03/11] add id prop for all components by default --- .../draw-interaction/interaction.vue | 3 +- src/component/feature/feature.vue | 24 ++--- src/component/geoloc/geoloc.vue | 17 +++- src/component/graticule/graticule.vue | 18 +++- src/component/group-layer/layer.vue | 1 + src/component/map/map.vue | 12 ++- src/component/map/view.vue | 17 +++- .../modify-interaction/interaction.vue | 3 +- src/component/overlay/overlay.vue | 13 +-- .../select-interaction/interaction.vue | 5 +- src/component/style-box/style.vue | 17 ---- src/component/style-func/style.vue | 3 +- src/component/text-style/style.vue | 3 +- src/mixin/geometry-container.js | 18 +--- src/mixin/geometry.js | 26 +++++- src/mixin/image-source.js | 5 +- src/mixin/image-style.js | 3 +- src/mixin/interaction.js | 9 +- src/mixin/layer.js | 17 ++-- src/mixin/ol-cmp.js | 19 +++- src/mixin/ol-virt-cmp.js | 8 ++ src/mixin/source.js | 18 +++- src/mixin/style.js | 22 ++++- src/mixin/tile-source.js | 4 +- src/mixin/vector-source.js | 7 +- src/mixin/with-fill-stroke-style.js | 89 +++++++++---------- src/mixin/wms-source.js | 6 +- src/ol-ext/geom.js | 35 ++++++++ src/ol-ext/index.js | 1 + src/ol-ext/map.js | 24 +++++ src/ol-ext/source.js | 35 ++++++++ src/ol-ext/style.js | 44 +++++++++ src/util/assert.js | 4 + 33 files changed, 365 insertions(+), 165 deletions(-) create mode 100644 src/ol-ext/source.js diff --git a/src/component/draw-interaction/interaction.vue b/src/component/draw-interaction/interaction.vue index 38d90b1d..b842b792 100644 --- a/src/component/draw-interaction/interaction.vue +++ b/src/component/draw-interaction/interaction.vue @@ -29,7 +29,8 @@ empty: false, attrs () { return { - class: this.$options.name, + id: this.vmId, + class: this.cmpName, } }, }, diff --git a/src/component/feature/feature.vue b/src/component/feature/feature.vue index 86898270..ba9b7ee2 100644 --- a/src/component/feature/feature.vue +++ b/src/component/feature/feature.vue @@ -1,17 +1,16 @@ diff --git a/src/component/style-func/style.vue b/src/component/style-func/style.vue index af746dc2..de8165ca 100644 --- a/src/component/style-func/style.vue +++ b/src/component/style-func/style.vue @@ -124,7 +124,8 @@ empty: false, attrs () { return { - class: this.$options.name, + id: this.vmId, + class: this.cmpName, } }, }, diff --git a/src/component/text-style/style.vue b/src/component/text-style/style.vue index 5a81e62c..09c79ad5 100644 --- a/src/component/text-style/style.vue +++ b/src/component/text-style/style.vue @@ -157,7 +157,8 @@ empty: false, attrs () { return { - class: this.$options.name, + id: this.vmId, + class: this.cmpName, } }, }, diff --git a/src/mixin/geometry-container.js b/src/mixin/geometry-container.js index ccf6a833..36c7c193 100644 --- a/src/mixin/geometry-container.js +++ b/src/mixin/geometry-container.js @@ -45,6 +45,10 @@ export default { } if (geom !== this._geometry) { + /** + * @type {module:ol/geom/Geometry~Geometry|undefined} + * @private + */ this._geometry = geom } @@ -54,18 +58,4 @@ export default { } }, }, - created () { - /** - * @type {module:ol/geom/Geometry~Geometry|undefined} - * @private - */ - this._geometry = undefined - - Object.defineProperties(this, { - $geometry: { - enumerable: true, - get: this.getGeometry, - }, - }) - }, } diff --git a/src/mixin/geometry.js b/src/mixin/geometry.js index 287958fb..c35b5232 100644 --- a/src/mixin/geometry.js +++ b/src/mixin/geometry.js @@ -1,5 +1,12 @@ import { distinctUntilChanged, map as mapObs, throttleTime } from 'rxjs/operators' -import { boundingExtent, findPointOnSurface, transforms } from '../ol-ext' +import { + boundingExtent, + findPointOnSurface, + getGeometryId, + initializeGeometry, + setGeometryId, + transforms, +} from '../ol-ext' import { observableFromOlEvent } from '../rx-ext' import { hasGeometry } from '../util/assert' import { isEqual } from '../util/minilo' @@ -76,8 +83,12 @@ export default { * @return {module:ol/geom/Geometry~Geometry|Promise} * @protected */ - createOlObject () { - return this.createGeometry() + async createOlObject () { + const geometry = await this.createGeometry() + + initializeGeometry(geometry, this.id) + + return geometry }, /** * @return {module:ol/geom/Geometry~Geometry|Promise} @@ -183,6 +194,13 @@ export default { }, }, watch: { + id (value) { + if (!this.$geometry || value === getGeometryId(this.$geometry)) { + return + } + + setGeometryId(this.$geometry, value) + }, coordinates (value) { if (!this.$geometry || !this.$view) return @@ -208,7 +226,7 @@ export default { }, stubVNode: { empty () { - return this.$options.name + return this.vmId() }, }, created () { diff --git a/src/mixin/image-source.js b/src/mixin/image-source.js index 6426470f..de313158 100644 --- a/src/mixin/image-source.js +++ b/src/mixin/image-source.js @@ -1,7 +1,6 @@ import { observableFromOlEvent } from '../rx-ext' import { EPSG_3857 } from '../ol-ext/consts' import { hasSource } from '../util/assert' -import { isEqual } from '../util/minilo' import { makeWatchers } from '../util/vue-helpers' import source from './source' @@ -51,9 +50,7 @@ export default { watch: { ...makeWatchers([ 'crossOrigin', - ], () => function (value, prevValue) { - if (isEqual(value, prevValue)) return - + ], () => function () { this.scheduleRecreate() }), }, diff --git a/src/mixin/image-style.js b/src/mixin/image-style.js index e129b01c..77314d39 100644 --- a/src/mixin/image-style.js +++ b/src/mixin/image-style.js @@ -50,7 +50,8 @@ export default { empty: false, attrs () { return { - class: this.$options.name, + id: this.vmId, + class: this.cmpName, } }, }, diff --git a/src/mixin/interaction.js b/src/mixin/interaction.js index 2342e380..958f6e92 100644 --- a/src/mixin/interaction.js +++ b/src/mixin/interaction.js @@ -1,4 +1,3 @@ -import uuid from 'uuid/v4' import { getInteractionId, getInteractionPriority, @@ -14,10 +13,6 @@ import useMapCmp from './use-map-cmp' export default { mixins: [cmp, useMapCmp], props: { - id: { - type: [String, Number], - default: () => uuid(), - }, active: { type: Boolean, default: true, @@ -120,7 +115,7 @@ export default { }, watch: { id (value) { - if (!this.$interaction || isEqual(value, getInteractionId(value))) { + if (!this.$interaction || isEqual(value, getInteractionId(this.$interaction))) { return } @@ -149,7 +144,7 @@ export default { }, stubVNode: { empty () { - return this.$options.name + return this.vmId }, }, created () { diff --git a/src/mixin/layer.js b/src/mixin/layer.js index 72c3b27f..8aa1e87c 100644 --- a/src/mixin/layer.js +++ b/src/mixin/layer.js @@ -1,4 +1,3 @@ -import uuid from 'uuid/v4' import Vue from 'vue' import { getLayerId, initializeLayer, setLayerId } from '../ol-ext' import { hasLayer, hasMap } from '../util/assert' @@ -13,10 +12,6 @@ import useMapCmp from './use-map-cmp' export default { mixins: [cmp, useMapCmp, sourceContainer], props: { - id: { - type: [String, Number], - default: () => uuid(), - }, /** * The bounding extent for layer rendering defined in the map view projection. * The layer will not be rendered outside of this extent. @@ -230,17 +225,15 @@ export default { }, ...makeWatchers([ 'overlay', - ], () => function (value, prevValue) { - if (isEqual(value, prevValue)) return - + ], () => function () { this.scheduleRecreate() }), }, stubVNode: { attrs () { return { - id: [this.$options.name, this.id].join('-'), - class: this.$options.name, + id: this.vmId, + class: this.cmpName, } }, }, @@ -255,6 +248,10 @@ function defineServices () { enumerable: true, get: () => this.$olObject, }, + $source: { + enumerable: true, + get: this.getSource, + }, $map: { enumerable: true, get: () => this.$services && this.$services.map, diff --git a/src/mixin/ol-cmp.js b/src/mixin/ol-cmp.js index 09da176b..b903f4bc 100644 --- a/src/mixin/ol-cmp.js +++ b/src/mixin/ol-cmp.js @@ -1,6 +1,7 @@ import debounce from 'debounce-promise' import { interval as intervalObs } from 'rxjs/observable' import { first as firstObs, skipUntil, skipWhile } from 'rxjs/operators' +import uuid from 'uuid/v4' import { log } from '../util/log' import { identity, isFunction } from '../util/minilo' import identMap from './ident-map' @@ -18,14 +19,26 @@ export default { VM_PROP, INSTANCE_PROMISE_POOL, mixins: [identMap, rxSubs, services], + props: { + id: { + type: [String, Number], + default: () => uuid(), + }, + }, data () { return { rev: 0, } }, computed: { - name () { - return [this.$options.name, this.id].filter(identity).join(' ') + cmpName () { + return this.$options.name + }, + vmId () { + return [this.cmpName, this.id].filter(identity).join('-') + }, + vmName () { + return [this.cmpName, this.id].filter(identity).join(' ') }, }, methods: { @@ -186,7 +199,7 @@ function defineLifeCyclePromises () { this.$emit(event, this) if (process.env.VUELAYERS_DEBUG) { - log(event, this.name) + log(event, this.vmName) } return this diff --git a/src/mixin/ol-virt-cmp.js b/src/mixin/ol-virt-cmp.js index 2ea36eea..433b9d0d 100644 --- a/src/mixin/ol-virt-cmp.js +++ b/src/mixin/ol-virt-cmp.js @@ -81,4 +81,12 @@ export default { this::cmp.methods.subscribeAll() }, }, + stubVNode: { + attrs () { + return { + id: this.vmId, + class: this.cmpName, + } + }, + }, } diff --git a/src/mixin/source.js b/src/mixin/source.js index 1f1ef1da..5d210025 100644 --- a/src/mixin/source.js +++ b/src/mixin/source.js @@ -1,3 +1,4 @@ +import { getSourceId, initializeSource, setSourceId } from '../ol-ext' import { isArray, isEqual, isString } from '../util/minilo' import mergeDescriptors from '../util/multi-merge-descriptors' import cmp from './ol-virt-cmp' @@ -34,8 +35,12 @@ export default { * @return {module:ol/source/Source~Source|Promise} * @protected */ - createOlObject () { - return this.createSource() + async createOlObject () { + const source = await this.createSource() + + initializeSource(source, this.id) + + return source }, /** * @return {module:ol/source/Source~Source|Promise} @@ -127,6 +132,13 @@ export default { }, }, watch: { + id (value) { + if (!this.$source || value === getSourceId(this.$source)) { + return + } + + setSourceId(this.$source, value) + }, attributions (value) { if (!this.$source || isEqual(value, this.$source.getAttributions())) { return @@ -161,7 +173,7 @@ export default { }, stubVNode: { empty () { - return this.$options.name + return this.vmId }, }, created () { diff --git a/src/mixin/style.js b/src/mixin/style.js index 3902bd12..bcfbdb0b 100644 --- a/src/mixin/style.js +++ b/src/mixin/style.js @@ -1,6 +1,7 @@ import { first as firstObs } from 'rxjs/operators' -import mergeDescriptors from '../util/multi-merge-descriptors' +import { getStyleId, initializeStyle, setStyleId } from '../ol-ext' import { observableFromOlEvent } from '../rx-ext' +import mergeDescriptors from '../util/multi-merge-descriptors' import cmp from './ol-virt-cmp' import useMapCmp from './use-map-cmp' @@ -14,8 +15,12 @@ export default { * @return {OlStyle|Promise} * @protected */ - createOlObject () { - return this.createStyle() + async createOlObject () { + const style = await this.createStyle() + + initializeStyle(style) + + return style }, /** * @return {OlStyle|Promise} @@ -72,12 +77,21 @@ export default { }, stubVNode: { empty () { - return this.$options.name + return this.vmId }, }, created () { this::defineServices() }, + watch: { + id (value) { + if (!this.$style || value === getStyleId(this.$style)) { + return + } + + setStyleId(this.$style, value) + }, + }, } function defineServices () { diff --git a/src/mixin/tile-source.js b/src/mixin/tile-source.js index 0fff10e0..41b17ec8 100644 --- a/src/mixin/tile-source.js +++ b/src/mixin/tile-source.js @@ -186,9 +186,7 @@ export default { 'maxZoom', 'minZoom', 'tileSize', - ], () => function (value, prevValue) { - if (isEqual(value, prevValue)) return - + ], () => function () { this.scheduleRecreate() }), }, diff --git a/src/mixin/vector-source.js b/src/mixin/vector-source.js index fea6edb5..10ca522e 100644 --- a/src/mixin/vector-source.js +++ b/src/mixin/vector-source.js @@ -1,7 +1,7 @@ import { merge as mergeObs } from 'rxjs/observable' import { debounceTime } from 'rxjs/operators' import { observableFromOlEvent } from '../rx-ext' -import * as assert from '../util/assert' +import { hasSource } from '../util/assert' import mergeDescriptors from '../util/multi-merge-descriptors' import { makeWatchers } from '../util/vue-helpers' import featuresContainer from './features-container' @@ -98,14 +98,15 @@ export default { empty: false, attrs () { return { - class: this.$options.name, + id: this.vmId, + class: this.cmpName, } }, }, } function subscribeToEvents () { - assert.hasSource(this) + hasSource(this) const add = observableFromOlEvent(this.getFeaturesCollection(), 'add') const remove = observableFromOlEvent(this.getFeaturesCollection(), 'remove') diff --git a/src/mixin/with-fill-stroke-style.js b/src/mixin/with-fill-stroke-style.js index 1be21a5a..c0c74a84 100644 --- a/src/mixin/with-fill-stroke-style.js +++ b/src/mixin/with-fill-stroke-style.js @@ -1,60 +1,55 @@ import Vue from 'vue' -const methods = { - /** - * @param {Fill|Vue|undefined} fill - * @return {void} - * @protected - */ - setFill (fill) { - fill = fill instanceof Vue ? fill.$style : fill +export default { + methods: { + /** + * @param {Fill|Vue|undefined} fill + * @return {void} + * @protected + */ + setFill (fill) { + fill = fill instanceof Vue ? fill.$style : fill - if (fill !== this._fill) { - this._fill = fill - } - if (this.$style && fill !== this.$style.getFill()) { - this.$style.setFill(fill) - this.scheduleRefresh() - } - }, - /** - * @param {Stroke|Vue|undefined} stroke - * @return {void} - * @protected - */ - setStroke (stroke) { - stroke = stroke instanceof Vue ? stroke.$style : stroke + if (fill !== this._fill) { + /** + * @type {Fill|undefined} + * @private + */ + this._fill = fill + } + if (this.$style && fill !== this.$style.getFill()) { + this.$style.setFill(fill) + this.scheduleRefresh() + } + }, + /** + * @param {Stroke|Vue|undefined} stroke + * @return {void} + * @protected + */ + setStroke (stroke) { + stroke = stroke instanceof Vue ? stroke.$style : stroke - if (stroke !== this._stroke) { - this._stroke = stroke - } - if (this.$style && stroke !== this.$style.getStroke()) { - this.$style.setStroke(stroke) - this.scheduleRefresh() - } + if (stroke !== this._stroke) { + /** + * @type {Stroke|undefined} + * @private + */ + this._stroke = stroke + } + if (this.$style && stroke !== this.$style.getStroke()) { + this.$style.setStroke(stroke) + this.scheduleRefresh() + } + }, }, -} - -export default { - methods, stubVNode: { empty: false, attrs () { return { - class: this.$options.name, + id: this.vmId, + class: this.cmpName, } }, }, - created () { - /** - * @type {Fill|undefined} - * @private - */ - this._fill = undefined - /** - * @type {Stroke|undefined} - * @private - */ - this._stroke = undefined - }, } diff --git a/src/mixin/wms-source.js b/src/mixin/wms-source.js index cd0c0db8..afc06c8a 100644 --- a/src/mixin/wms-source.js +++ b/src/mixin/wms-source.js @@ -1,6 +1,6 @@ import { WMS_VERSION } from '../ol-ext' import { hasSource, hasView } from '../util/assert' -import { isEqual, reduce } from '../util/minilo' +import { reduce } from '../util/minilo' import { makeWatchers } from '../util/vue-helpers' const cleanExtParams = params => reduce(params, (params, value, key) => { @@ -109,9 +109,7 @@ const watch = { 'format', 'bgColor', 'time', - ], prop => function (value, prevValue) { - if (isEqual(value, prevValue)) return - + ], prop => function (value) { prop = prop.toUpperCase() this.$source && this.$source.updateParams({ [prop]: value }) }), diff --git a/src/ol-ext/geom.js b/src/ol-ext/geom.js index 008d5703..076d206f 100644 --- a/src/ol-ext/geom.js +++ b/src/ol-ext/geom.js @@ -1,3 +1,6 @@ +import Vue from 'vue' +import Geometry from 'ol/geom/Geometry' +import uuid from 'uuid/v4' import pointOnFeature from '@turf/point-on-feature' import Circle from 'ol/geom/Circle' import GeometryCollection from 'ol/geom/GeometryCollection' @@ -132,3 +135,35 @@ export function findPointOnSurface (geom) { return pointFeature.geometry.coordinates } } + +export function getGeometryId (geometry) { + if (geometry instanceof Vue) { + return geometry.id + } else if (geometry instanceof Geometry) { + return geometry.get('id') + } + + throw new Error('Illegal geometry argument') +} + +export function setGeometryId (geometry, geometryId) { + if (geometry instanceof Vue) { + geometry.id = geometryId + + return geometry + } else if (geometry instanceof Geometry) { + geometry.set('id', geometryId) + + return geometry + } + + throw new Error('Illegal geometry argument') +} + +export function initializeGeometry (geometry, defaultGeometryId) { + if (getGeometryId(geometry) == null) { + setGeometryId(geometry, defaultGeometryId || uuid()) + } + + return geometry +} diff --git a/src/ol-ext/index.js b/src/ol-ext/index.js index 1244966b..eddd1734 100644 --- a/src/ol-ext/index.js +++ b/src/ol-ext/index.js @@ -10,6 +10,7 @@ export * from './load-strategy' export * from './map' export * from './overlay' export * from './proj' +export * from './source' export * from './style' export * from './tile-grid' export * from './util' diff --git a/src/ol-ext/map.js b/src/ol-ext/map.js index 2f8ecb5d..f70d8f42 100644 --- a/src/ol-ext/map.js +++ b/src/ol-ext/map.js @@ -1,6 +1,30 @@ import PluggableMap from 'ol/PluggableMap' import Vue from 'vue' +export function getMapId (map) { + if (map instanceof Vue) { + return map.id + } else if (map instanceof PluggableMap) { + return map.get('id') + } + + throw new Error('Illegal map argument') +} + +export function setMapId (map, mapId) { + if (map instanceof Vue) { + map.id = mapId + + return map + } else if (map instanceof PluggableMap) { + map.set('id', mapId) + + return map + } + + throw new Error('Illegal map argument') +} + export function getMapDataProjection (map) { if (map instanceof Vue) { return map.dataProjection diff --git a/src/ol-ext/source.js b/src/ol-ext/source.js new file mode 100644 index 00000000..88453959 --- /dev/null +++ b/src/ol-ext/source.js @@ -0,0 +1,35 @@ +import Source from 'ol/source/Source' +import uuid from 'uuid/v4' +import Vue from 'vue' + +export function getSourceId (source) { + if (source instanceof Vue) { + return source.id + } else if (source instanceof Source) { + return source.get('id') + } + + throw new Error('Illegal source argument') +} + +export function setSourceId (source, sourceId) { + if (source instanceof Vue) { + source.id = sourceId + + return source + } else if (source instanceof Source) { + source.set('id', sourceId) + + return source + } + + throw new Error('Illegal source argument') +} + +export function initializeSource (source, defaultSourceId) { + if (getSourceId(source) == null) { + setSourceId(source, defaultSourceId || uuid()) + } + + return source +} diff --git a/src/ol-ext/style.js b/src/ol-ext/style.js index d2a73481..1ea23f80 100644 --- a/src/ol-ext/style.js +++ b/src/ol-ext/style.js @@ -6,11 +6,55 @@ import RegularShape from 'ol/style/RegularShape' import Stroke from 'ol/style/Stroke' import Style from 'ol/style/Style' import Text from 'ol/style/Text' +import Vue from 'vue' +import uuid from 'uuid/v4' import parseColor from 'parse-color' import { isFunction, isNumeric, lowerFirst, pick, reduce, upperFirst } from '../util/minilo' import { GEOMETRY_TYPE } from './consts' import * as geomHelper from './geom' +export function getStyleId (style) { + if ( + style instanceof Vue || + style instanceof Style || + style instanceof ImageStyle || + style instanceof Text || + style instanceof Stroke || + style instanceof Fill || + style instanceof Function + ) { + return style.id + } + + throw new Error('Illegal style argument') +} + +export function setStyleId (style, styleId) { + if ( + style instanceof Vue || + style instanceof Style || + style instanceof ImageStyle || + style instanceof Text || + style instanceof Stroke || + style instanceof Fill || + style instanceof Function + ) { + style.id = styleId + + return style + } + + throw new Error('Illegal style argument') +} + +export function initializeStyle (style, defaultStyleId) { + if (getStyleId(style) == null) { + setStyleId(style, defaultStyleId || uuid()) + } + + return style +} + /** * @return {VlStyle[]} */ diff --git a/src/util/assert.js b/src/util/assert.js index af5e8839..5d4816b2 100644 --- a/src/util/assert.js +++ b/src/util/assert.js @@ -107,6 +107,10 @@ export function hasSource (vm) { assert(vm.$source, 'component has "$source" property') } +export function hasInnerSource (vm) { + assert(vm.$innerSource, 'component has "$innerSource" property') +} + /** * @param {Object} vm * @return {void} From 8171ce454feeb56f8a3d897fa2e1288fe5d2d421 Mon Sep 17 00:00:00 2001 From: Vladimir Vershinin Date: Thu, 12 Sep 2019 09:14:14 +0300 Subject: [PATCH 04/11] Increase counters width in documentation --- docs/home.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/home.md b/docs/home.md index aa367f52..e47c6e62 100644 --- a/docs/home.md +++ b/docs/home.md @@ -7,10 +7,10 @@ [![License](https://img.shields.io/github/license/ghettovoice/vuelayers.svg)](https://github.com/ghettovoice/vuelayers/blob/master/LICENSE) + frameborder="0" scrolling="0" class="github-button vld-github-btn" width="140px" height="30px"> + frameborder="0" scrolling="0" class="github-button vld-github-btn" width="140px" height="30px"> ## Overview From 98a70c796cfc9427eb8afb79a4ffd0b75c801867 Mon Sep 17 00:00:00 2001 From: Vladimir Vershinin Date: Fri, 27 Sep 2019 17:05:53 +0300 Subject: [PATCH 05/11] Improve ol events transmitting Let Vue update reactive properties before transmitting ol events. So at the event time all computed properties (like source features) should be already updated. #132 #224 #225 #226 --- .gitignore | 30 ++++++++++++- .idea/dictionaries/ghetto.xml | 37 ++++++++++++++++ src/component/cluster-source/source.vue | 15 ++++++- src/mixin/features-container.js | 58 ++++++++++++------------- src/mixin/geometry.js | 5 ++- src/mixin/image-source.js | 8 +++- src/mixin/interactions-container.js | 11 ++--- src/mixin/layer.js | 8 +++- src/mixin/layers-container.js | 11 ++--- src/mixin/overlays-container.js | 11 ++--- src/mixin/tile-source.js | 8 +++- src/mixin/vector-source.js | 21 ++------- 12 files changed, 155 insertions(+), 68 deletions(-) create mode 100644 .idea/dictionaries/ghetto.xml diff --git a/.gitignore b/.gitignore index d58f498a..91ee0be7 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,34 @@ # .nfs files are created when an open file is removed but is still being accessed .nfs* +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + ### Node template node_modules # Logs @@ -80,7 +108,7 @@ typings/ # User-specific stuff: .idea/**/workspace.xml .idea/**/tasks.xml -.idea/dictionaries +#.idea/dictionaries # Sensitive or high-churn files: .idea/**/dataSources/ diff --git a/.idea/dictionaries/ghetto.xml b/.idea/dictionaries/ghetto.xml new file mode 100644 index 00000000..1abf92fd --- /dev/null +++ b/.idea/dictionaries/ghetto.xml @@ -0,0 +1,37 @@ + + + + addfeature + arcgis + bingmaps + declutter + deinit + drawend + drawstart + geoloc + hidpi + imageloadend + imageloaderror + imageloadstart + modifyend + modifystart + moveend + movestart + pluggable + pointerdrag + postcompose + postrender + precompose + proj + propertychange + removefeature + rendercomplete + reprojection + singleclick + tileloadend + tileloaderror + tileloadstart + wmts + + + \ No newline at end of file diff --git a/src/component/cluster-source/source.vue b/src/component/cluster-source/source.vue index a94e4906..368f4f8b 100644 --- a/src/component/cluster-source/source.vue +++ b/src/component/cluster-source/source.vue @@ -1,11 +1,12 @@ diff --git a/src/mixin/features-container.js b/src/mixin/features-container.js index b5e8ffb3..2f85e9f4 100644 --- a/src/mixin/features-container.js +++ b/src/mixin/features-container.js @@ -2,7 +2,7 @@ import Collection from 'ol/Collection' import Feature from 'ol/Feature' import Vue from 'vue' import { merge as mergeObs } from 'rxjs/observable' -import { tap, debounceTime } from 'rxjs/operators' +import { debounceTime } from 'rxjs/operators' import { getFeatureId, getObjectUid, initializeFeature, mergeFeatures } from '../ol-ext' import { instanceOf } from '../util/assert' import { forEach, isPlainObject } from '../util/minilo' @@ -123,39 +123,39 @@ export default { this._featuresCollection = new Collection() this._featureSubs = {} - const add = observableFromOlEvent(this._featuresCollection, 'add') - .pipe( - tap(({ element }) => { - const elementUid = getObjectUid(element) - const propChanges = observableFromOlEvent(element, 'propertychange') - const otherChanges = observableFromOlEvent(element, 'change') - const featureChanges = mergeObs(propChanges, otherChanges).pipe( - debounceTime(1000 / 60) - ) - - this._featureSubs[elementUid] = this.subscribeTo(featureChanges, () => { - ++this.rev - }) - }) + const adds = observableFromOlEvent(this._featuresCollection, 'add') + this.subscribeTo(adds, ({ element }) => { + const elementUid = getObjectUid(element) + const propChanges = observableFromOlEvent(element, 'propertychange') + const otherChanges = observableFromOlEvent(element, 'change') + const featureChanges = mergeObs(propChanges, otherChanges).pipe( + debounceTime(1000 / 60) ) - const remove = observableFromOlEvent(this._featuresCollection, 'remove') - .pipe( - tap(({ element }) => { - const elementUid = getObjectUid(element) - if (!this._featureSubs[elementUid]) { - return - } - this.unsubscribe(this._featureSubs[elementUid]) - delete this._featureSubs[elementUid] - }) - ) - const events = mergeObs(add, remove) + this._featureSubs[elementUid] = this.subscribeTo(featureChanges, () => { + ++this.rev + }) - this.subscribeTo(events, ({ type, element }) => { ++this.rev - this.$emit(type + ':feature', element) + this.$nextTick(() => { + this.$emit('add:feature', element) + }) + }) + + const removes = observableFromOlEvent(this._featuresCollection, 'remove') + this.subscribeTo(removes, ({ element }) => { + const elementUid = getObjectUid(element) + if (this._featureSubs[elementUid]) { + this.unsubscribe(this._featureSubs[elementUid]) + delete this._featureSubs[elementUid] + } + + ++this.rev + + this.$nextTick(() => { + this.$emit('remove:feature', element) + }) }) }, } diff --git a/src/mixin/geometry.js b/src/mixin/geometry.js index c35b5232..55b45f96 100644 --- a/src/mixin/geometry.js +++ b/src/mixin/geometry.js @@ -293,7 +293,10 @@ function subscribeToGeomChanges () { this.subscribeTo(changes, ({ prop, value }) => { ++this.rev - this.$emit(`update:${prop}`, value) + + this.$nextTick(() => { + this.$emit(`update:${prop}`, value) + }) }) } diff --git a/src/mixin/image-source.js b/src/mixin/image-source.js index de313158..6423c6e9 100644 --- a/src/mixin/image-source.js +++ b/src/mixin/image-source.js @@ -65,5 +65,11 @@ function subscribeToSourceEvents () { 'imageloadstart', ]) - this.subscribeTo(events, evt => this.$emit(evt.type, evt)) + this.subscribeTo(events, evt => { + ++this.rev + + this.$nextTick(() => { + this.$emit(evt.type, evt) + }) + }) } diff --git a/src/mixin/interactions-container.js b/src/mixin/interactions-container.js index 96c913c9..a77f9c9f 100644 --- a/src/mixin/interactions-container.js +++ b/src/mixin/interactions-container.js @@ -109,14 +109,15 @@ export default { */ this._interactionsCollection = new Collection() - const add = observableFromOlEvent(this._interactionsCollection, 'add') - const remove = observableFromOlEvent(this._interactionsCollection, 'remove') - const events = mergeObs(add, remove) + const adds = observableFromOlEvent(this._interactionsCollection, 'add') + const removes = observableFromOlEvent(this._interactionsCollection, 'remove') - this.subscribeTo(events, ({ type, element }) => { + this.subscribeTo(mergeObs(adds, removes), ({ type, element }) => { ++this.rev - this.$emit(type + ':interaction', element) + this.$nextTick(() => { + this.$emit(type + ':interaction', element) + }) }) }, } diff --git a/src/mixin/layer.js b/src/mixin/layer.js index 8aa1e87c..30bc7e4a 100644 --- a/src/mixin/layer.js +++ b/src/mixin/layer.js @@ -276,5 +276,11 @@ function subscribeToLayerEvents () { 'render', ]) - this.subscribeTo(events, evt => this.$emit(evt.type, evt)) + this.subscribeTo(events, evt => { + ++this.rev + + this.$nextTick(() => { + this.$emit(evt.type, evt) + }) + }) } diff --git a/src/mixin/layers-container.js b/src/mixin/layers-container.js index d4bd66dd..de863e04 100644 --- a/src/mixin/layers-container.js +++ b/src/mixin/layers-container.js @@ -86,14 +86,15 @@ export default { */ this._layersCollection = new Collection() - const add = observableFromOlEvent(this._layersCollection, 'add') - const remove = observableFromOlEvent(this._layersCollection, 'remove') - const events = mergeObs(add, remove) + const adds = observableFromOlEvent(this._layersCollection, 'add') + const removes = observableFromOlEvent(this._layersCollection, 'remove') - this.subscribeTo(events, ({ type, element }) => { + this.subscribeTo(mergeObs(adds, removes), ({ type, element }) => { ++this.rev - this.$emit(type + ':layer', element) + this.$nextTick(() => { + this.$emit(type + ':layer', element) + }) }) }, } diff --git a/src/mixin/overlays-container.js b/src/mixin/overlays-container.js index 9d590b1d..bcf7795b 100644 --- a/src/mixin/overlays-container.js +++ b/src/mixin/overlays-container.js @@ -86,14 +86,15 @@ export default { */ this._overlaysCollection = new Collection() - const add = observableFromOlEvent(this._overlaysCollection, 'add') - const remove = observableFromOlEvent(this._overlaysCollection, 'remove') - const events = mergeObs(add, remove) + const adds = observableFromOlEvent(this._overlaysCollection, 'add') + const removes = observableFromOlEvent(this._overlaysCollection, 'remove') - this.subscribeTo(events, ({ type, element }) => { + this.subscribeTo(mergeObs(adds, removes), ({ type, element }) => { ++this.rev - this.$emit(type + ':overlay', element) + this.$nextTick(() => { + this.$emit(type + ':overlay', element) + }) }) }, } diff --git a/src/mixin/tile-source.js b/src/mixin/tile-source.js index 41b17ec8..c414a4f5 100644 --- a/src/mixin/tile-source.js +++ b/src/mixin/tile-source.js @@ -201,5 +201,11 @@ function subscribeToSourceEvents () { 'tileloaderror', ]) - this.subscribeTo(events, evt => this.$emit(evt.type, evt)) + this.subscribeTo(events, evt => { + ++this.rev + + this.$nextTick(() => { + this.$emit(evt.type, evt) + }) + }) } diff --git a/src/mixin/vector-source.js b/src/mixin/vector-source.js index 10ca522e..595bbcef 100644 --- a/src/mixin/vector-source.js +++ b/src/mixin/vector-source.js @@ -1,7 +1,4 @@ -import { merge as mergeObs } from 'rxjs/observable' -import { debounceTime } from 'rxjs/operators' -import { observableFromOlEvent } from '../rx-ext' -import { hasSource } from '../util/assert' +import debounce from 'debounce-promise' import mergeDescriptors from '../util/multi-merge-descriptors' import { makeWatchers } from '../util/vue-helpers' import featuresContainer from './features-container' @@ -68,7 +65,6 @@ export default { */ subscribeAll () { this::source.methods.subscribeAll() - this::subscribeToEvents() }, /** * @param feature @@ -93,6 +89,9 @@ export default { ], () => function () { return this.scheduleRecreate() }), + featuresDataProj: debounce(function (features) { + this.$emit('update:features', features) + }, 1000 / 60), }, stubVNode: { empty: false, @@ -104,15 +103,3 @@ export default { }, }, } - -function subscribeToEvents () { - hasSource(this) - - const add = observableFromOlEvent(this.getFeaturesCollection(), 'add') - const remove = observableFromOlEvent(this.getFeaturesCollection(), 'remove') - const events = mergeObs(add, remove).pipe(debounceTime(1000 / 60)) - // emit event to allow `sync` modifier - this.subscribeTo(events, () => { - this.$emit('update:features', this.featuresDataProj) - }) -} From 0847d3b4001b52ea2ef9638119bd5ec7f1905b1b Mon Sep 17 00:00:00 2001 From: Vladimir Vershinin Date: Fri, 27 Sep 2019 19:28:00 +0300 Subject: [PATCH 06/11] Fix broken vl-source-vector sync features #225 --- package.json | 3 +- src/component/map/map.vue | 4 +- .../select-interaction/interaction.vue | 6 +- src/component/vector-source/source.vue | 92 ++---- src/mixin/features-container.js | 78 +++-- test/app.vue | 306 +----------------- 6 files changed, 92 insertions(+), 397 deletions(-) diff --git a/package.json b/package.json index 8fa86424..1ca994a1 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,7 @@ "ol-tilecache": "^3.0.1", "parse-color": "^1.0.0", "rxjs": "^6.3.3", - "uuid": "^3.3.2", - "whatwg-fetch": "^3.0.0" + "uuid": "^3.3.2" }, "peerDependencies": { "vue": "^2.3.0" diff --git a/src/component/map/map.vue b/src/component/map/map.vue index 4923dd30..d4d4092b 100644 --- a/src/component/map/map.vue +++ b/src/component/map/map.vue @@ -340,7 +340,7 @@ if (this._featuresOverlay == null) return this._featuresOverlay.setSource(new VectorSource({ - features: this._featuresCollection, + features: this.$featuresCollection, wrapX: value, })) }, @@ -365,7 +365,7 @@ // prepare default overlay this._featuresOverlay = new VectorLayer({ source: new VectorSource({ - features: this._featuresCollection, + features: this.$featuresCollection, wrapX: this.wrapX, }), }) diff --git a/src/component/select-interaction/interaction.vue b/src/component/select-interaction/interaction.vue index ce39c70a..e23fc5cc 100644 --- a/src/component/select-interaction/interaction.vue +++ b/src/component/select-interaction/interaction.vue @@ -139,7 +139,7 @@ */ createInteraction () { return new SelectInteraction({ - features: this._featuresCollection, + features: this.$featuresCollection, multi: this.multi, wrapX: this.wrapX, filter: this.filter, @@ -313,11 +313,11 @@ function subscribeToInteractionChanges () { hasInteraction(this) - const select = observableFromOlEvent(this._featuresCollection, 'add') + const select = observableFromOlEvent(this.$featuresCollection, 'add') .pipe( mapOp(({ element }) => ({ type: 'select', feature: element })) ) - const unselect = observableFromOlEvent(this._featuresCollection, 'remove') + const unselect = observableFromOlEvent(this.$featuresCollection, 'remove') .pipe( mapOp(({ element }) => ({ type: 'unselect', feature: element })) ) diff --git a/src/component/vector-source/source.vue b/src/component/vector-source/source.vue index 7b3a3ad1..c06ffbb4 100644 --- a/src/component/vector-source/source.vue +++ b/src/component/vector-source/source.vue @@ -1,9 +1,9 @@ From 3a649009c12bbf99010305965402d5e0c53ed68f Mon Sep 17 00:00:00 2001 From: Vladimir Vershinin Date: Fri, 27 Sep 2019 20:05:37 +0300 Subject: [PATCH 07/11] Update internal api to use getter too --- src/component/map/map.vue | 16 +++++++--- src/component/vector-source/source.vue | 5 ++- src/mixin/geometry.js | 2 +- src/mixin/ident-map.js | 10 ++++++ src/mixin/interactions-container.js | 42 +++++++++++++++++--------- src/mixin/layers-container.js | 40 ++++++++++++++++-------- src/mixin/overlays-container.js | 40 ++++++++++++++++-------- test/app.vue | 30 ++++++++++++++++-- 8 files changed, 133 insertions(+), 52 deletions(-) diff --git a/src/component/map/map.vue b/src/component/map/map.vue index d4d4092b..8c4afc9c 100644 --- a/src/component/map/map.vue +++ b/src/component/map/map.vue @@ -137,10 +137,10 @@ keyboardEventTarget: this.keyboardEventTarget, maxTilesLoading: this.maxTilesLoading, controls: this._controlsCollection, - interactions: this._interactionsCollection, - layers: this._layersCollection, - overlays: this._overlaysCollection, - view: this._view, + interactions: this.$interactionsCollection, + layers: this.$layersCollection, + overlays: this.$overlaysCollection, + view: this.$view, }) setMapId(map, this.id) @@ -252,6 +252,12 @@ this.$map.setView(view) } }, + /** + * @return {module:ol/View~View} + */ + getView () { + return this._view + }, /** * @return {void} * @protected @@ -390,7 +396,7 @@ */ $view: { enumerable: true, - get: () => this._view, + get: this.getView, }, }) } diff --git a/src/component/vector-source/source.vue b/src/component/vector-source/source.vue index c06ffbb4..c346e8b3 100644 --- a/src/component/vector-source/source.vue +++ b/src/component/vector-source/source.vue @@ -1,5 +1,4 @@ + - + diff --git a/docs/quickstart.md b/docs/quickstart.md index 59846700..249f71e2 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -31,8 +31,6 @@ You can browse the source of the npm package at [unpkg.com/vuelayers/](https://u ```html - - diff --git a/test/umd.html b/test/umd.html index 0bbd09de..4d0208a0 100644 --- a/test/umd.html +++ b/test/umd.html @@ -65,7 +65,6 @@ -