开源

cesium使用天地图

2022-10-19  本文已影响0人  xiudaozhe

cesium中默认的底图是bingmap。在国内还是天地图靠谱一点。操作如下:

一、创建provider.js

export function getProviderViewModels() {
    const tiandiKey = "****";       //天地图key,官网申请
    const baseUrl = 'http://t{s}.tianditu.com';
    //天地图矢量
    let tiandiVec = new Cesium.UrlTemplateImageryProvider({
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: baseUrl + '/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=' + tiandiKey
    });
    //天地图影像
    let tiandiImg = new Cesium.UrlTemplateImageryProvider({
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: baseUrl + '/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=' + tiandiKey
    });
    //天地图标注
    let tiandiCva = new Cesium.UrlTemplateImageryProvider({
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: baseUrl + '/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=' + tiandiKey
    });

    let tiandiVecModel = new Cesium.ProviderViewModel({
        name: '天地图',
        category: '国内地图资源',
        iconUrl: Cesium.buildModuleUrl('./Widgets/Images/ImageryProviders/openStreetMap.png'),
        tooltip: 'WMTS 地图服务',
        creationFunction: function () {
            return [tiandiVec, tiandiCva];
        }
    });
    let tiandiImgModel = new Cesium.ProviderViewModel({
        name: '天地图影像',
        category: '国内地图资源',
        iconUrl: Cesium.buildModuleUrl('./Widgets/Images/ImageryProviders/esriWorldImagery.png'),
        tooltip: 'WMTS 影像服务',
        creationFunction: function () {
            return [tiandiImg, tiandiCva];
        }
    });

    return [tiandiVecModel, tiandiImgModel]
}


二、使用天地图

情况①:只使用天地图,去掉默认的一系列底图

import { getProviderViewModels } from "./gis/provider.js";
...
let [tiandiVecModel, tiandiImgModel] = getProviderViewModels();
viewer = new Cesium.Viewer("cesiumContainer", {
  imageryProviderViewModels: [tiandiVecModel, tiandiImgModel],
})
...

情况②:在原底图列表中再附加天地图

import { getProviderViewModels } from "./gis/provider.js";
...
let [tiandiVecModel, tiandiImgModel] = getProviderViewModels();
viewer = new Cesium.Viewer("cesiumContainer", {
 // imageryProviderViewModels: [tiandiVecModel, tiandiImgModel],
})
viewer.baseLayerPicker.viewModel.imageryProviderViewModels.unshift(
    tiandiImgModel
);
viewer.baseLayerPicker.viewModel.imageryProviderViewModels.unshift(
    tiandiVecModel
);
...

三、新版天地图api

天地图api有tianditu.com和tianditu.gov.cn两种。目前两种均能使用,官方文档中使用的是tianditu.gov.cn。但注意了!官方文档居然接口有错,官网中url为TILEMATRIX={z}&TILEROW={x}&TILECOL={y}。应该改成TILEMATRIX={z}&TILEROW={y}&TILECOL={x}。使用tianditu.gov.cn如下:
同样创建provider.js

export function getProviderViewModels() {
    const tiandiKey = "****";       //天地图key,官网申请
    const baseUrl = 'http://t{s}.tianditu.gov.cn';
   //天地图
    let tiandiVec = new Cesium.UrlTemplateImageryProvider({
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: baseUrl + '/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk='+tiandiKey
    });
    //天地图影像
    let tiandiImg = new Cesium.UrlTemplateImageryProvider({
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: baseUrl + '/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk='+tiandiKey
    });
    //天地图标注
    let tiandiCva = new Cesium.UrlTemplateImageryProvider({
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: baseUrl + '/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk='+tiandiKey
    });
    //天地图影像标注
    let tiandiCia = new Cesium.UrlTemplateImageryProvider({
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: baseUrl + '/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk='+tiandiKey
    });
    return [tiandiVecModel, tiandiImgModel]
}

四、electron接入天地图

天地图有三种key,分别是浏览器端的、安卓端的和服务器端的。但使用时发现,无论哪个端的,在electron打包成pc端app后,地图均返回403。经过我各种尝试后,发现使用nginx代理+浏览器key模拟浏览器情况能解决这个问题。
客户端:将baseUrl(http://t{s}.tianditu.gov.cn)改为(http://127.0.0.1)
服务端nginx反向代理:

      location /vec_w/ {
            add_header Access-Control-Allow-Headers X-Requested-With;
            add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
            proxy_set_header referer http://localhost/;    //重点
            proxy_pass http://t0.tianditu.gov.cn;
        }

        location /cva_w/ {
            add_header Access-Control-Allow-Headers X-Requested-With;
            add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
            proxy_set_header referer http://localhost/;
            proxy_pass http://t0.tianditu.gov.cn;
        }
        
        location /img_w/ {
            add_header Access-Control-Allow-Headers X-Requested-With;
            add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
            proxy_set_header referer http://localhost/;
            proxy_pass http://t0.tianditu.gov.cn;
        }

        location /cia_w/ {
            add_header Access-Control-Allow-Headers X-Requested-With;
            add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
            proxy_set_header referer http://localhost/;
            proxy_pass http://t0.tianditu.gov.cn;
        }

重点是在代理时设置referer,欺骗天地图服务端,让它以为请求是浏览器访问

采用node代理

由于nginx代理需要部署nginx,较为麻烦。本次使用node代理代替nginx。可以做到打包为exe后不再需要其余部署。创建proxy.js

const http = require('http');
const url = require('url');
const httpProxy = require('http-proxy');


    const proxy = httpProxy.createProxyServer();

    //获取天地图host
    function getTianditu() {
        let rand = Math.floor(Math.random() * 8)
        return `t${rand}.tianditu.gov.cn`
    }

    let server = http.createServer(function (req, res) {
        const { pathname } = url.parse(req.url)
        let host = getTianditu()
        if (pathname === '/DataServer') {
            //天地图走代理
            proxy.on('proxyReq', function (proxyReq, req, res, options) {
                proxyReq.setHeader('Host', host);  //重要
                proxyReq.setHeader('referer', 'http://localhost/');  //重要
            });
            proxy.web(req, res, {
                target: 'http://' + host
            });
            //监听代理服务错误
            proxy.on('error', function (err) {
                console.log(err);
            });
        } else {
            res.end();
        }
    });
    server.listen(80, '0.0.0.0');


以上文件在electron.js中调用,即可做到打开exe开启node代理服务(electron.js在electron项目的package.json的main中引入)

//electron.js部分代码
//...
const mainWindow = new BrowserWindow({
        width: 1440,
        height: 900,
        icon: path.join(__dirname, "../dist/****.ico"),
        webPreferences: {
            preload: path.join(__dirname, 'proxy.js'),
            nodeIntegration: true,
            webviewTag:true,
        },
    });
//...
上一篇 下一篇

猜你喜欢

热点阅读