UNPKG

tchen-vuelayers

Version:

Web map Vue components with the power of OpenLayers

437 lines (380 loc) 10.9 kB
/** * 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 };