Я пытался визуализировать векторные данные. Я использую Tegola в качестве сервера векторных плиток. Моим первым выбором библиотеки визуализации был Leaflet, но библиотека Leaflet Vector.Grid , похоже, имеет некоторые проблемы с точечными данными;
- Ошибка на странице Tegola's Github.
- Проблема в проекте Leaflet.VectorGrid на Github.
Итак, я перешел на OpenLayers. OpenLayers имеет очень инклюзивную библиотеку, и существует множество примеров и учебников .
Мне потребовалось полдня, чтобы понять новую версию и завершить семинар по ссылке выше. OpenLayers, кажется, решение для моих нужд. Но я не знаю, как переписать код, который я подготовил на семинаре, который написан для запуска на сервере web.pack. Я хочу визуализировать слои и добавить несколько узлов, которые удовлетворят мои потребности на карте.
Моя карта работает на сервере web.pack;
Но я хочу сделать эту карту в Узле. Итак, я написал файл сервера;
// Get dependencies
const express = require('express');
const http = require('http');
const bodyParser = require('body-parser');
const dotenv = require('dotenv')
const logger = require('./services/logger');
const cors = require('cors');
const { Pool, Client } = require('pg')
const pool = new Pool()
dotenv.config();
// Get our API routes
const api = require('./routes/api.router');
const client = new Client()
const app = express();
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors());
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/script'));
app.get('/', function (req, res) {
// res.sendFile(__dirname + "/views/index.html");
res.render('index', { title: 'Map' });
});
// Set our api routes
app.use('/api', api);
app.use((req, res, next) => {
const err = new Error('Not Found');
err.status = 404;
logger.error(`Request Error ${req.url} - ${err.status}`)
next(err);
});
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
error: {
message: err.message
}
});
});
/**
* Get port from environment and store in Express.
*/
const port = process.env.PORT || '3000';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log(`API running on localhost:${port}`));
Запутанная часть начинается здесь, я использую тот же HTML-файл на сервере мастерской (web.pack). Но я не знаю, как ссылаться на файл main.js на этот файл HTML. Как вы можете видеть ниже, в этом файле нет ссылки на файл main.js.
Как web.pack объединяет эти два файла? И возможно ли то же самое с помощью Express в NodeJS?
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenLayers</title>
<style>
html,
body,
#map-container {
margin: 0;
height: 100%;
width: 100%;
font-family: sans-serif;
}
.arrow_box {
position: relative;
background: #000;
border: 1px solid #003c88;
}
.arrow_box:after,
.arrow_box:before {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.arrow_box:after {
border-color: rgba(0, 0, 0, 0);
border-top-color: #000;
border-width: 10px;
margin-left: -10px;
}
.arrow_box:before {
border-color: rgba(0, 60, 136, 0);
border-top-color: #003c88;
border-width: 11px;
margin-left: -11px;
}
.arrow_box {
border-radius: 5px;
padding: 10px;
opacity: 0.8;
background-color: black;
color: white;
}
#popup-content {
max-height: 200px;
overflow: auto;
}
#popup-content th {
text-align: left;
width: 125px;
}
</style>
</head>
<body>
<div id="map-container"></div>
<div class="arrow_box" id="popup-container">
<div id="popup-content"></div>
</div>
</body>
</html>
main.js
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import MVT from 'ol/format/MVT';
import VectorTileLayer from 'ol/layer/VectorTile';
import VectorTileSource from 'ol/source/VectorTile';
import TileLayer from 'ol/layer/Tile';
import XYZSource from 'ol/source/XYZ';
import Overlay from 'ol/Overlay';
import { Style, Fill, Stroke, Circle, Text } from 'ol/style';
import { fromLonLat } from 'ol/proj';
const map = new Map({
target: 'map-container',
view: new View({
center: fromLonLat([34.633623, 39.818770]),
zoom: 7
})
});
const layer = new VectorTileLayer({
source: new VectorTileSource({
attributions: [
'<a href="http://www.openmaptiles.org/" target="_blank">© OpenMapTiles</a>',
'<a href="http://www.openstreetmap.org/about/" target="_blank">© OpenStreetMap contributors</a>'
],
format: new MVT(),
url: `http://localhost:8090/maps/observation/{z}/{x}/{y}.vector.pbf`,
maxZoom: 24,
type: 'base'
})
});
const baseLayer = new TileLayer({
source: new XYZSource({
url: 'http://tile.stamen.com/terrain/{z}/{x}/{y}.jpg'
}),
type: 'base'
});
map.addLayer(baseLayer);
const overlay = new Overlay({
element: document.getElementById('popup-container'),
positioning: 'bottom-center',
offset: [0, -10],
autoPan: true
});
map.addOverlay(overlay);
overlay.getElement().addEventListener('click', function () {
overlay.setPosition();
});
map.addLayer(layer);
layer.setStyle(function (feature, resolution) {
const properties = feature.getProperties();
if (properties.layer == 'temperature_stations' || properties.layer == 'temperature_stations_simple') {
const point = new Style({
image: new Circle({
radius: 5,
fill: new Fill({
color: 'red'
}),
stroke: new Stroke({
color: 'grey'
})
})
})
return point
}
if (properties.layer == 'aws_stations') {
const point = new Style({
image: new Circle({
radius: 5,
fill: new Fill({
color: 'blue'
}),
stroke: new Stroke({
color: 'grey'
})
})
})
return point
}
if (properties.layer == 'spa_stations') {
const point = new Style({
image: new Circle({
radius: 10,
fill: new Fill({
color: 'green'
}),
stroke: new Stroke({
color: 'grey'
})
})
})
return point
}
if (properties.layer == 'syn_stations') {
const point = new Style({
image: new Circle({
radius: 10,
fill: new Fill({
color: 'purple'
}),
stroke: new Stroke({
color: 'grey'
})
})
})
return point
}
});
map.on('pointermove', function (e) {
let markup = '';
map.forEachFeatureAtPixel(e.pixel, function (feature) {
markup += `${markup && '<hr>'}<table>`;
const properties = feature.getProperties();
for (const property in properties) {
markup += `<tr><th>${property}</th><td>${properties[property]}</td></tr>`;
}
markup += '</table>';
}, { hitTolerance: 0 });
if (markup) {
document.getElementById('popup-content').innerHTML = markup;
overlay.setPosition(e.coordinate);
} else {
overlay.setPosition();
}
});