【问题标题】:How to use OpenLayers 5 with Node (express)?如何将 OpenLayers 5 与 Node (express) 一起使用?
【发布时间】:2019-07-26 11:12:46
【问题描述】:

我一直在尝试可视化 Vector 数据。我使用Tegola 作为矢量切片服务器。我第一选择的可视化库是Leaflet,但是Leaflet的Vector.Grid库好像点数据有点问题;

  1. Issue on tegola's Github page.
  2. Issue on Leaflet.VectorGrid project on Github.

所以我已经切换到 OpenLayers。 OpenLayers 有一个非常包容的库,有很多 examplestutorials

我花了半天时间来了解新版本并完成上面链接上的工作坊。 OpenLayers 似乎是满足我需求的解决方案。但是我不知道如何重写我在研讨会上准备的代码,这些代码是为了在 web.pack 服务器上运行而编写的。我想渲染图层并添加一些节点来满足我在地图上的需求。

我的地图在 web.pack 服务器上运行;

但我想在 Node.js 中渲染这张地图。所以我写了一个服务器文件;

// 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}`));

令人困惑的部分从这里开始,我在研讨会服务器(web.pack)中使用相同的 HTML 文件。但我不知道如何将 main.js 文件引用到这个 HTML 文件。正如您在下面看到的,此文件中没有对 main.js 文件的引用。 web.pack 如何结合这两个文件?在 NodeJS 中使用 express 是否有可能?

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>

ma​​in.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">&copy; OpenMapTiles</a>',
            '<a href="http://www.openstreetmap.org/about/" target="_blank">&copy; 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();
    }
});

【问题讨论】:

  • 你能解决这个问题吗?
  • 是的,我做到了。但是没时间在这里发帖。
  • 你能指导我找到你的解决方案吗?.. :D 如果你有时间

标签: node.js express webpack openlayers


【解决方案1】:

研讨会使用 webpack 开发服务器为应用程序提供开发服务。最后一章解释了如何构建用于生产的应用程序:https://openlayers.org/workshop/en/deploying/。此处解释的步骤解释了如何使用 webpack 为您提供静态 Web 应用程序,您将在 Express 应用程序中使用生成的工件作为静态文件:https://expressjs.com/en/starter/static-files.html

【讨论】:

  • 您好,我已经了解如何使用静态文件。我实际上正在寻找一种直接在 Node 环境中使用 main.js 的方法。我想,要做到这一点,我必须编写一个代码,当我在 Node 中启动服务器时自动编译 main.js。
  • 这需要一个构建步骤,使用 webpack。工作流程的最后一章解释了如何做到这一点。有关更多详细信息,请参阅我的答案中的第一个链接。当您使用 webpack 的 --watch 选项时,客户端 js 代码的更改将触发重新构建,您无需运行任何额外的脚本来更新客户端代码。
猜你喜欢
  • 1970-01-01
  • 2018-06-25
  • 1970-01-01
  • 2014-03-16
  • 2012-11-12
  • 1970-01-01
  • 2011-08-18
  • 2019-06-03
  • 1970-01-01
相关资源
最近更新 更多