tchen-vuelayers
Version:
Web map Vue components with the power of OpenLayers
437 lines (380 loc) • 10.9 kB
JavaScript
/**
* VueLayers
* Web map Vue components with the power of OpenLayers
*
* @package vuelayers
* @author Vladimir Vershinin <ghettovoice@gmail.com>
* @version 0.11.1
* @license MIT
* @copyright (c) 2017-2019, Vladimir Vershinin <ghettovoice@gmail.com>
*/
import _defineProperty from '@babel/runtime-corejs2/helpers/esm/defineProperty';
import _Object$assign from '@babel/runtime-corejs2/core-js/object/assign';
import _Object$defineProperties from '@babel/runtime-corejs2/core-js/object/define-properties';
import _Object$create from '@babel/runtime-corejs2/core-js/object/create';
import Feature from 'ol/Feature';
import { Observable } from 'rxjs/_esm5/internal/Observable';
import { merge } from 'rxjs/_esm5/internal/observable/merge';
import { distinctUntilChanged } from 'rxjs/_esm5/internal/operators/distinctUntilChanged';
import { map } from 'rxjs/_esm5/internal/operators/map';
import { mergeAll } from 'rxjs/_esm5/internal/operators/mergeAll';
import { throttleTime } from 'rxjs/_esm5/internal/operators/throttleTime';
import uuid from 'uuid/v4';
import geometryContainer from '../mixin/geometry-container';
import olCmp from '../mixin/ol-cmp';
import projTransforms from '../mixin/proj-transforms';
import stylesContainer from '../mixin/styles-container';
import useMapCmp from '../mixin/use-map-cmp';
import { findPointOnSurface } from '../ol-ext/geom';
import observableFromOlEvent from '../rx-ext/from-ol-event';
import { hasFeature, hasMap } from '../util/assert';
import { isEqual, plainProps, pick } from '../util/minilo';
import mergeDescriptors from '../util/multi-merge-descriptors';
/**
* @vueProps
*/
var props =
/** @lends module:feature/feature# */
{
/**
* Feature identifier.
* @type {string|number}
* @default UUID
* @vueSync
*/
id: {
type: [String, Number],
default: function _default() {
return uuid();
}
},
/**
* All feature properties.
* @type {Object}
* @default {}
* @vueSync
*/
properties: {
type: Object,
default: function _default() {
return _Object$create(null);
}
}
/**
* @vueComputed
*/
};
var computed =
/** @lends module:feature/feature# */
{
/**
* **GeoJSON** encoded geometry.
* @type {Object|undefined}
*/
geometry: function geometry() {
if (this.rev && this.resolvedDataProjection && this.$geometry) {
return this.writeGeometryInDataProj(this.$geometry);
}
},
/**
* @return {number[]|undefined}
*/
point: function point() {
if (this.pointViewProj && this.resolvedDataProjection) {
return this.pointToDataProj(this.pointViewProj);
}
},
geometryViewProj: function geometryViewProj() {
if (this.rev && this.resolvedDataProjection && this.$geometry) {
return this.writeGeometryInViewProj(this.$geometry);
}
},
pointViewProj: function pointViewProj() {
if (this.rev && this.$geometry) {
return findPointOnSurface(this.$geometry);
}
}
};
/**
* @vueMethods
*/
var methods =
/** @lends module:feature/feature# */
{
/**
* Create feature without inner style applying, feature level style
* will be applied in the layer level style function.
* @return {Feature}
* @protected
*/
createOlObject: function createOlObject() {
var feature = new Feature(this.properties);
feature.setId(this.id);
feature.setGeometry(this.$geometry);
return feature;
},
/**
* @return {{
* getGeometry: function(): (Geometry|undefined),
* setGeometry: function((Geometry|undefined)): void
* }|Feature|undefined}
* @protected
*/
getGeometryTarget: function getGeometryTarget() {
return this.$feature;
},
/**
* @return {Object}
* @protected
*/
getServices: function getServices() {
var vm = this;
return mergeDescriptors(olCmp.methods.getServices.call(this), geometryContainer.methods.getServices.call(this), stylesContainer.methods.getServices.call(this), {
get feature() {
return vm.$feature;
}
});
},
/**
* @return {Feature|undefined}
* @protected
*/
getStyleTarget: function getStyleTarget() {
return this.$feature;
},
/**
* Checks if feature lies at `pixel`.
* @param {number[]} pixel
* @return {boolean}
*/
isAtPixel: function isAtPixel(pixel) {
var _this = this;
hasMap(this);
return this.$map.forEachFeatureAtPixel(pixel, function (f) {
return f === _this.$feature;
}, {
layerFilter: function layerFilter(l) {
return l === _this.$layer;
}
});
},
/**
* @return {void}
* @protected
*/
mount: function mount() {
this.$featuresContainer && this.$featuresContainer.addFeature(this);
this.subscribeAll();
},
/**
* @return {void}
* @protected
*/
unmount: function unmount() {
this.unsubscribeAll();
this.$featuresContainer && this.$featuresContainer.removeFeature(this);
},
/**
* @return {void}
* @protected
*/
subscribeAll: function subscribeAll() {
subscribeToFeatureChanges.call(this);
}
};
var watch = {
/**
* @param {string|number} value
*/
id: function id(value) {
if (this.$feature && value !== this.$feature.getId()) {
this.$feature.setId(value);
}
},
/**
* @param {Object} value
*/
properties: function properties(value) {
value = plainProps(value);
if (this.$feature && !isEqual(value, plainProps(this.$feature.getProperties()))) {
this.$feature.setProperties(plainProps(value));
}
}
};
/**
* A vector object for geographic features with a geometry and other attribute properties,
* similar to the features in vector file formats like **GeoJSON**.
*
* @title vl-feature
* @alias module:feature/feature
* @vueProto
*
* @vueSlot default [scoped] Default **scoped** slot with current feature state: `id`, `properties`, GeoJSON `geometry`.
*/
var script = {
name: 'vl-feature',
mixins: [olCmp, useMapCmp, geometryContainer, stylesContainer, projTransforms],
props: props,
computed: computed,
methods: methods,
watch: watch,
created: function created() {
var _this2 = this;
_Object$defineProperties(this,
/** @lends module:feature/feature# */
{
/**
* Reference to `ol.Feature` instance.
* @type {Feature|undefined}
*/
$feature: {
enumerable: true,
get: function get() {
return _this2.$olObject;
}
},
/**
* Reference to parent `Layer` instance.
* @type {Layer|undefined}
*/
$layer: {
enumerable: true,
get: function get() {
return _this2.$services && _this2.$services.layer;
}
},
/**
* Reference to `ol.Map` instance.
* @type {Map|undefined}
*/
$map: {
enumerable: true,
get: function get() {
return _this2.$services && _this2.$services.map;
}
},
/**
* Reference to `ol.View` instance.
* @type {View|undefined}
*/
$view: {
enumerable: true,
get: function get() {
return _this2.$services && _this2.$services.view;
}
},
/**
* Reference to `featuresContainer`.
* @type {Object|undefined}
*/
$featuresContainer: {
enumerable: true,
get: function get() {
return _this2.$services && _this2.$services.featuresContainer;
}
}
});
}
};
/**
* @return {void}
* @private
*/
function subscribeToFeatureChanges() {
var _this3 = this;
hasFeature(this);
var getPropValue = function getPropValue(prop) {
return _this3.$feature.get(prop);
};
var ft = 100; // all plain properties
var propChanges = observableFromOlEvent(this.$feature, 'propertychange', function (_ref) {
var key = _ref.key;
return {
prop: key,
value: getPropValue(key)
};
}).pipe(throttleTime(ft), distinctUntilChanged(isEqual)); // id, style and other generic changes
var changes = observableFromOlEvent(this.$feature, 'change').pipe(map(function () {
return Observable.create(function (obs) {
if (_this3.$feature.getId() !== _this3.id) {
obs.next({
prop: 'id',
value: _this3.$feature.getId()
});
} // todo style?
});
}), mergeAll(), throttleTime(ft), distinctUntilChanged(isEqual)); // all changes
var allChanges = merge(propChanges, changes);
this.subscribeTo(allChanges, function (_ref2) {
var prop = _ref2.prop,
value = _ref2.value;
++_this3.rev;
if (prop === 'id') {
_this3.$emit("update:".concat(prop), value);
} else if (prop !== _this3.$feature.getGeometryName()) {
_this3.$emit('update:properties', _Object$assign({}, _this3.properties, _defineProperty({}, prop, value)));
}
});
}
/* script */
var __vue_script__ = script;
/* template */
var __vue_render__ = function __vue_render__() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c('i', {
class: [_vm.$options.name],
staticStyle: {
"display": "none !important"
},
attrs: {
"id": [_vm.$options.name, _vm.id].join('-')
}
}, [_vm._t("default", null, {
id: _vm.id,
properties: _vm.properties,
geometry: _vm.geometry,
point: _vm.point
})], 2);
};
var __vue_staticRenderFns__ = [];
/* style */
var __vue_inject_styles__ = undefined;
/* scoped */
var __vue_scope_id__ = undefined;
/* module identifier */
var __vue_module_identifier__ = undefined;
/* functional template */
var __vue_is_functional_template__ = false;
/* component normalizer */
function __vue_normalize__(template, style, script$$1, scope, functional, moduleIdentifier, createInjector, createInjectorSSR) {
var component = (typeof script$$1 === 'function' ? script$$1.options : script$$1) || {}; // For security concerns, we use only base name in production mode.
component.__file = "feature.vue";
if (!component.render) {
component.render = template.render;
component.staticRenderFns = template.staticRenderFns;
component._compiled = true;
if (functional) component.functional = true;
}
component._scopeId = scope;
return component;
}
/* style inject */
/* style inject SSR */
var Feature$1 = __vue_normalize__({
render: __vue_render__,
staticRenderFns: __vue_staticRenderFns__
}, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, undefined, undefined);
function plugin(Vue) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (plugin.installed) {
return;
}
plugin.installed = true;
options = pick(options, 'dataProjection');
_Object$assign(Feature$1, options);
Vue.component(Feature$1.name, Feature$1);
}
export default plugin;
export { Feature$1 as Feature, plugin as install };