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