UNPKG

@terrestris/vectortiles

Version:

A simple library that makes use of free available world-wide terrestris vectortiles in MapBox MVT format from OpenStreetMap data

415 lines (338 loc) 15.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.terrestrisVectorTiles = void 0; var _styleRoads = require("./styles/style-roads"); var _styleBuildings = require("./styles/style-buildings"); var _styleBluebackground = require("./styles/style-bluebackground"); var _styleLandusage = require("./styles/style-landusage"); var _styleWaterways = require("./styles/style-waterways"); var _styleWaterareas = require("./styles/style-waterareas"); var _styleCountries = require("./styles/style-countries"); var _Style = _interopRequireDefault(require("ol/style/Style")); var _Stroke = _interopRequireDefault(require("ol/style/Stroke")); var _Text = _interopRequireDefault(require("ol/style/Text")); var _Fill = _interopRequireDefault(require("ol/style/Fill")); var _Icon = _interopRequireDefault(require("ol/style/Icon")); var _Attribution = _interopRequireDefault(require("ol/control/Attribution")); var _Point = _interopRequireDefault(require("ol/geom/Point")); var _VectorTile = _interopRequireDefault(require("ol/layer/VectorTile")); var _VectorTile2 = _interopRequireDefault(require("ol/source/VectorTile")); var _MVT = _interopRequireDefault(require("ol/format/MVT")); var _color = require("ol/color"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } /** * @param {Object} config The config object used to generate the layer * @example * const layer = new terrestrisVectorTiles({ * declutter: false, * usePlaceLabels: false, * style_roads: [{ * ... * }] * }) */ var terrestrisVectorTiles = function terrestrisVectorTiles(config) { // should labels be decluttered? var useDeclutter = config && config.declutter === false ? false : true; // should places and countries receive labels? var usePlacesLabels = config && config.usePlacesLabels === false ? false : true; // resources like imagery for highway label signs var babImg = document.createElement('img'); babImg.src = config && config.babImage ? config.babImage : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAbCAYAAADo' + 'OQYqAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4gIID' + 'jocExrEmgAAAlVJREFUWMPtmM1OE1EUx393vtoy7dDWpCBgVQJNrGhiYuI7GN2ZuPAdfAV9Bt' + '/BhWufwrAh0UBSQeRToUBhOlOZGWaOiylQjR9BWbRJ/5ubyZ2593fOvZOc/1EiMg68BW4BMSD' + '8oxIRkiQdRQRNKZQCTSk0TfEfUoAOLAGPlIjMA/cvskKcCEEYE0YJQRQThDFBELPQ2Gehscf8' + '0h7buz5TYza3p8vcnS1zr3aFopPBMnUypoZlpaOhaxcNYF6JiAfYv3vD9SPafki7E+F1IjwvZ' + 'O2rx4dPLZY+H7K42mK1cQDtADIGZHQwNVAKROAkgTCGIAZL5+pMmfp0ifrNEvUbRWanHAqOhZ' + '0zcWyTwoiFY5t/OhlfiYgLFPzjE740O+wfHbPb+obnBuwcHPNx84jlrTYrGy4rmy40fTC0FM7' + 'QQVfps/rLxTqdjxOIfwqmnGVy0qFWHWV6okDtmsNUxSY3YlEpZ6mUckxUbOysAdBWichRY+3Q' + 'efHqHdtuwHazw8aOT9j0081MDUwdNJUCnmZAuBwpIAGSnmCiGBKBUo7qeJ7qeJ6p0Qwvnz+gd' + 'r3oGiLCh+UWb16/h7E8aKRgxeyvN7ks2N71FKBr6a9m6YDZnRPWt9qsb7iw4/HkYY3Z6ijG2Y' + 'd5K81qP0mpNBBdpXzdhGk/3Ld+1umJnEEPmIbQQ+gh9BB6CD2EHkIPOHRPMdK36inqzqs8L4Q' + 'oSZ2F9EnJJ5IagyhJ+bqJNZRSzM2UePrsTn86l8lz5zI3U0IpxWB6xEF14wPZ9xjrdpjqA9Bh' + 'WgQefwcq3oy642N9sQAAAABJRU5ErkJggg=='; // the OSM-attribution var attribution = config && config.attribution ? config.attribution : new _Attribution["default"]({ html: '© terrestris GmbH & Co. KG<br>' + 'Data © OpenStreetMap <a href="http://www.openstreetmap.org/copyright/en" ' + 'target="_blank">contributors</a>' }); // the style template used for labels var labelStyle = new _Style["default"]({ text: new _Text["default"]({ font: '13px sans-serif', fill: new _Fill["default"]({ color: '#000' }), stroke: new _Stroke["default"]({ color: '#fff', width: 3 }), placement: 'line', maxAngle: 0.4, padding: [10, 10, 10, 10] }) }); // the style template used for linestrings var lineStringStyleBelow = new _Style["default"]({ stroke: new _Stroke["default"]({ color: 'black', width: 2, lineCap: 'butt', lineDash: [] }), zIndex: 0 }); // the style template used for linestrings var lineStringStyleAbove = new _Style["default"]({ stroke: new _Stroke["default"]({ color: 'white', width: 1, lineCap: 'round', lineDash: [] }), zIndex: 1 }); // the style template used for polygons var polygonStyleFill = new _Fill["default"]({ color: 'blue' }); var polygonStyleStroke = new _Stroke["default"]({ color: 'blue', width: 1, lineCap: 'round' }); var polygonStyle = new _Style["default"]({ fill: polygonStyleFill, stroke: polygonStyleStroke, zIndex: 0 }); // the style template used for highway icons var iconStyle = new _Style["default"]({ image: new _Icon["default"]({ scale: 0.9, imgSize: [45, 27], img: babImg, opacity: 0.8 }), text: new _Text["default"]({ padding: [50, 50, 50, 50], font: '12px sans-serif', fill: new _Fill["default"]({ color: '#fff' }), stroke: new _Stroke["default"]({ color: '#fff', width: 0.8 }) }), zIndex: 0 }); /** * Creates a style for labels of places like countries or cities * * @param {ol.Feature} feature The feature to style * @param {Number} resolution The current maps resolution * @return {ol.style.Style[]} The style to use for the given feature */ var buildLabelStyle = function buildLabelStyle(feature, resolution) { var text = feature.get('name'); var type = feature.get('type'); var population = feature.get('population'); var fontString = 'px sans-serif'; var fontSize; if (type === 'country') { fontSize = 17; } else if (type === 'city') { fontSize = 16; } else if (type === 'town' && resolution < 600) { fontSize = 15; } else if (type === 'village' && resolution < 75) { fontSize = 14; } else { return null; } fontString = fontSize + fontString; var olText = labelStyle.getText(); olText.getFill().setColor('#000'); olText.getStroke().setColor('#fff'); olText.getStroke().setWidth(5); olText.setPlacement('point'); olText.setText(text); olText.setFont(fontString); var zIndex = population ? population : fontSize + 1000; labelStyle.setZIndex(useDeclutter ? -zIndex : zIndex); return [labelStyle]; }; /** * [description] * @param {ol.Feature} feature The feature to style * @param {Number} resolution The current maps resolution * @param {Object[]} styleArray The array of style objects to use * @param {String} geom The geometry type, e.g. 'polygon' * @return {ol.style.Style[]} The style to use for the given feature */ var buildStyle = function buildStyle(feature, resolution, styleArray, geom) { if (!styleArray) { return null; } var props = feature.getProperties(); var type = props.type || ''; var text = props.name || props.ref || null; var isHighWay = (type.indexOf('motorway') > -1 || type.indexOf('trunk') > -1) && props["class"] === 'highway' && props.ref.indexOf('A') === 0; var styleToUse; styleArray.forEach(function (el) { if (el.minResolution <= resolution && el.maxResolution >= resolution) { styleToUse = el.style; } }); if (!styleToUse || !styleToUse[type]) { return null; } var style = []; var stroke; var strokeAbove; var fill; if (geom === 'line') { stroke = lineStringStyleBelow.getStroke(); stroke.setColor(styleToUse[type].colors[0] || 'black'); stroke.setWidth(styleToUse[type].widths[0] || 2); stroke.setLineCap(styleToUse[type].caps[0] || 'butt'); stroke.setLineDash(styleToUse[type].dasharray ? styleToUse[type].dasharray.split(' ') : []); lineStringStyleBelow.setZIndex(feature.get('z_order') || 0); if (styleToUse[type].opacity) { setOpacity(stroke, styleToUse[type].opacity); } style.push(lineStringStyleBelow); // check if we need a "outline" for this road if (styleToUse[type].widths.length > 1) { strokeAbove = lineStringStyleAbove.getStroke(); strokeAbove.setColor(styleToUse[type].colors[1] || 'white'); strokeAbove.setWidth(styleToUse[type].widths[1] || 1); strokeAbove.setLineCap(styleToUse[type].caps[1] || 'round'); strokeAbove.setLineDash(styleToUse[type].dasharray ? styleToUse[type].dasharray.split(' ') : []); lineStringStyleAbove.setZIndex(feature.get('z_order') + 1 || 1); if (styleToUse[type].opacity) { setOpacity(strokeAbove, styleToUse[type].opacity); } style.push(lineStringStyleAbove); } } else if (geom === 'polygon') { var hasFill = styleToUse[type].fillColor || styleToUse[type].fillOpacity; var hasStroke = styleToUse[type].strokeColor || styleToUse[type].strokeWidth; if (hasFill) { fill = polygonStyle.getFill(); if (!fill) { fill = polygonStyleFill; polygonStyle.setFill(fill); } fill.setColor(styleToUse[type].fillColor || 'blue'); } else { polygonStyle.setFill(undefined); } if (hasStroke) { stroke = polygonStyle.getStroke(); if (!stroke) { stroke = polygonStyleStroke; polygonStyle.setStroke(stroke); } stroke.setColor(styleToUse[type].strokeColor || 'blue'); stroke.setWidth(styleToUse[type].strokeWidth || 1); stroke.setLineCap(styleToUse[type].lineCap || 'round'); } else { polygonStyle.setStroke(undefined); } polygonStyle.setZIndex(styleToUse[type].zIndex || feature.get('z_order') || 0); // set the alpha values if (fill && styleToUse[type].fillOpacity) { setOpacity(fill, styleToUse[type].fillOpacity); } if (stroke && styleToUse[type].strokeOpacity) { setOpacity(stroke, styleToUse[type].strokeOpacity); } style.push(polygonStyle); } if (styleToUse[type].useLabels !== false) { if (isHighWay && resolution < 300) { // try to extract coordinates from an ol.render.feature var coords = feature.getGeometry().getFlatCoordinates(); if (coords && coords.length > 1) { var point = new _Point["default"]([coords[0], coords[1]]); iconStyle.setGeometry(point); iconStyle.getText().setText(props.ref || props.name); style.push(iconStyle); } } else if (resolution < 300) { // care about labels for streets, buildings etc. var olText = labelStyle.getText(); fill = olText.getFill(); stroke = olText.getStroke(); fill.setColor(styleToUse[type].textFillColor || 'black'); stroke.setColor(styleToUse[type].textStrokeColor || 'white'); stroke.setWidth(styleToUse[type].textStrokeWidth || 5); olText.setPlacement(styleToUse[type].textPlacement || 'line'); olText.setText(text); olText.setFont(styleToUse[type].font || '13px sans-serif'); var zIndex = feature.get('z_order') || 1; labelStyle.setZIndex(useDeclutter ? -zIndex : zIndex); style.push(labelStyle); } } return style; }; /** * Sets the opacity on a style * @param {OlStyleFill or OlStyleStroke} style The style to set the opacity on * @param {Number} opacity The opacity value to set */ var setOpacity = function setOpacity(style, opacity) { var color = (0, _color.asArray)(style.getColor()); color[3] = opacity; style.setColor(color); }; /** * Creates and returns the terrestris OSM VectorTile layer * @return {ol.layer.VectorTile} The terrestris OSM VectorTile layer */ var getOSMLayer = function getOSMLayer() { var osmLayer = new _VectorTile["default"]({ name: 'terrestris-vectortiles', declutter: useDeclutter, source: new _VectorTile2["default"]({ format: new _MVT["default"](), url: 'https://ows.terrestris.de/osm-vectortiles/' + 'osm:osm_world_vector' + '@mapbox-vector-tiles@pbf/{z}/{x}/{-y}.pbf', attributions: [attribution] }), style: function style(feature, resolution) { var l = feature.get('layer'); var style; switch (l) { case 'osm_roads': style = buildStyle(feature, resolution, config && config.style_roads ? config.style_roads : _styleRoads.style_roads, 'line'); break; case 'osm_roads_gen0': style = buildStyle(feature, resolution, config && config.style_roads ? config.style_roads : _styleRoads.style_roads, 'line'); break; case 'osm_roads_gen1': style = buildStyle(feature, resolution, config && config.style_roads ? config.style_roads : _styleRoads.style_roads, 'line'); break; case 'osm_buildings': style = buildStyle(feature, resolution, config && config.style_buildings ? config.style_buildings : _styleBuildings.style_buildings, 'polygon'); break; case 'bluebackground_no_limit': style = buildStyle(feature, resolution, config && config.style_bluebackground ? config.style_bluebackground : _styleBluebackground.style_bluebackground, 'polygon'); break; case 'osm_places': if (usePlacesLabels) { style = buildLabelStyle(feature, resolution); } break; case 'osm_landusages': style = buildStyle(feature, resolution, config && config.style_landusage ? config.style_landusage : _styleLandusage.style_landusage, 'polygon'); break; case 'osm_landusages_gen0': style = buildStyle(feature, resolution, config && config.style_landusage ? config.style_landusage : _styleLandusage.style_landusage, 'polygon'); break; case 'osm_waterways': style = buildStyle(feature, resolution, config && config.style_waterways ? config.style_waterways : _styleWaterways.style_waterways, 'line'); break; case 'osm_waterareas': style = buildStyle(feature, resolution, config && config.style_waterareas ? config.style_waterareas : _styleWaterareas.style_waterareas, 'polygon'); break; case 'osm_waterareas_gen0': style = buildStyle(feature, resolution, config && config.style_waterareas ? config.style_waterareas : _styleWaterareas.style_waterareas, 'polygon'); break; case 'world_boundaries_labels': style = buildStyle(feature, resolution, config && config.style_countries ? config.style_countries : _styleCountries.style_countries, 'polygon'); break; default: break; } return style; } }); return osmLayer; }; return getOSMLayer(config); }; exports.terrestrisVectorTiles = terrestrisVectorTiles; var _default = terrestrisVectorTiles; exports["default"] = _default;