UNPKG

tchen-vuelayers

Version:

Web map Vue components with the power of OpenLayers

345 lines (283 loc) 8.56 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 _slicedToArray from '@babel/runtime-corejs2/helpers/esm/slicedToArray'; import _regeneratorRuntime from '@babel/runtime-corejs2/regenerator'; import _Array$isArray from '@babel/runtime-corejs2/core-js/array/is-array'; import _asyncToGenerator from '@babel/runtime-corejs2/helpers/esm/asyncToGenerator'; import VectorSource from 'ol/source/Vector'; import { fetch } from 'whatwg-fetch'; import vectorSource from '../mixin/vector-source'; import { getFeatureId } from '../ol-ext/feature'; import { createGeoJsonFmt } from '../ol-ext/format'; import { loadingAll } from '../ol-ext/load-strategy'; import { transform } from '../ol-ext/proj'; import { constant, difference, isEmpty, isFinite, isFunction, stubArray, pick } from '../util/minilo'; import _Object$assign from '@babel/runtime-corejs2/core-js/object/assign'; var props = { /** * Array of GeoJSON features with coordinates in the map view projection. * @type {Object[]} features */ features: { type: Array, default: stubArray }, /** * Source loader factory. * Source loader should load features from some remote service, decode them and pas to `features` prop to render. * @type {(function(): FeatureLoader|undefined)} loaderFactory */ loaderFactory: { type: Function, default: defaultLoaderFactory }, /** * Source format factory * @type {(function(): Feature|undefined)} formatFactory */ formatFactory: { type: Function, default: defaultFormatFactory }, /** * String or url factory * @type {(string|function(): string|FeatureUrlFunction|undefined)} url */ url: [String, Function], /** * Loading strategy factory. * Extent here in map view projection. * @type {(function(): LoadingStrategy|undefined)} strategyFactory */ strategyFactory: { type: Function, default: defaultStrategyFactory }, overlaps: { type: Boolean, default: true } }; var computed = { featureIds: function featureIds() { return this.features.map(getFeatureId); } }; var methods = { /** * @return {VectorSource} * @protected */ createSource: function createSource() { return new VectorSource({ attributions: this.attributions, projection: this.resolvedDataProjection, loader: this.createLoader(), useSpatialIndex: this.useSpatialIndex, wrapX: this.wrapX, logo: this.logo, strategy: this.strategyFactory.call(undefined, this), format: this.formatFactory.call(undefined, this), url: this.createUrlFunc(), overlaps: this.overlaps }); }, /** * @protected */ createUrlFunc: function createUrlFunc() { var _this = this; if (!this.url) { return; } var url = this.url; if (!isFunction(url)) { url = constant(this.url); } // wrap strategy function to transform map view projection to source projection return function (extent, resolution, projection) { return url(transformExtent(extent, projection, _this.resolvedDataProjection), resolution, _this.resolvedDataProjection); }; }, /** * @protected */ createLoader: function createLoader() { var _this2 = this; if (!this.url) { return; } var loader = this.loaderFactory.call(undefined, this); // wrap strategy function to transform map view projection to source projection return ( /*#__PURE__*/ function () { var _ref = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee(extent, resolution, projection) { var features; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return loader(transformExtent(extent, projection, _this2.resolvedDataProjection), resolution, _this2.resolvedDataProjection); case 2: features = _context.sent; if (_Array$isArray(features)) { _this2.$source.addFeatures(features); } case 4: case "end": return _context.stop(); } } }, _callee, this); })); return function (_x, _x2, _x3) { return _ref.apply(this, arguments); }; }() ); }, /** * @return {void} * @protected */ mount: function mount() { vectorSource.methods.mount.call(this); this.addFeatures(this.features); }, /** * @return {void} * @protected */ unmount: function unmount() { this.clear(); vectorSource.methods.unmount.call(this); } }; var diffById = function diffById(a, b) { return a.id === b.id; }; var watch = { features: function features(value, oldValue) { if (!this.$source) return; var forAdd = difference(value, oldValue, diffById); var forRemove = difference(oldValue, value, diffById); this.addFeatures(forAdd); this.removeFeatures(forRemove); } }; var script = { name: 'vl-source-vector', mixins: [vectorSource], props: props, computed: computed, methods: methods, watch: watch /** * @return {LoadingStrategy} */ }; function defaultStrategyFactory() { return loadingAll; } /** * @return {GeoJSON} */ function defaultFormatFactory() { return createGeoJsonFmt(); } /** * Default loader for provided URL. * * @param vm * @return {Function} */ function defaultLoaderFactory(vm) { return function (extent, resolution, projection) { var url = vm.$source.getUrl(); if (isFunction(url)) { url = url(extent, resolution, projection); } if (isEmpty(url)) { return []; } return fetch(url, { credentials: 'same-origin', mode: 'cors' }).then(function (response) { return response.text(); }).then(function (text) { if (!vm.$source) { return []; } return vm.$source.getFormat().readFeatures(text, { featureProjection: vm.viewProjection, dataProjection: vm.resolvedDataProjection }); }); }; } function transformExtent(extent, sourceProj, destProj) { extent = extent.slice(); if (isFinite(extent[0]) && isFinite(extent[1])) { var _transform = transform([extent[0], extent[1]], sourceProj, destProj); var _transform2 = _slicedToArray(_transform, 2); extent[0] = _transform2[0]; extent[1] = _transform2[1]; } if (isFinite(extent[2]) && isFinite(extent[3])) { var _transform3 = transform([extent[2], extent[3]], sourceProj, destProj); var _transform4 = _slicedToArray(_transform3, 2); extent[2] = _transform4[0]; extent[3] = _transform4[1]; } return extent; } /* script */ var __vue_script__ = script; /* template */ /* 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__ = undefined; /* 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 = "source.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 Source = __vue_normalize__({}, __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(Source, options); Vue.component(Source.name, Source); } export default plugin; export { Source, plugin as install };