tchen-vuelayers
Version:
Web map Vue components with the power of OpenLayers
345 lines (283 loc) • 8.56 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 _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 };