Vue2中CesiumV1.113.0加载离线地图,本文以天地图为例。
1.使用nodejs获取天地图
新建nodejsdownmap项目文件夹,初始化项目
npm init -y
src/index.js
// An highlighted block var Bagpipe = require('bagpipe') var fs = require("fs"); var request = require("request"); var bou = [-180, -85, 180,85];//下载范围 var Minlevel = 0;//最小层级 var Maxlevel = 8;//最大层级 var token = '天地图token';//天地图key(如果失效去天地图官网申请) var zpath = './text'; // 瓦片目录 var speed = 200;//并发数 var mapstyle = 'vec_w';//地图类型(img_w:影像底图 cia_w:影像标注 vec_w:街道底图 cva_w街道标注,备注,自己再api找相对于的) var all = []; var user_agent_list_2 = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0", "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.3.4000 Chrome/30.0.1599.101 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36" ] /** * 计算经纬度转换成瓦片坐标 * @param {Number} lng 经度 * @param {Number} lat 纬度 * @param {Number} level 层级 */ function calcXY(lng, lat, level) { let x = (lng + 180) / 360 let title_X = Math.floor(x * Math.pow(2, level)) let lat_rad = lat * Math.PI / 180 let y = (1 - Math.log(Math.tan(lat_rad) + 1 / Math.cos(lat_rad)) / Math.PI) / 2 let title_Y = Math.floor(y * Math.pow(2, level)) return { title_X, title_Y } } /** * 计算每个层级的瓦片坐标 * @param {Arr} bounding 范围 * @param {Number} Minlevel 最小层级 * @param {Number} Maxlevel 最大层级 */ function mainnAllXY(bounding, Minlevel, Maxlevel) { for (i = Minlevel; i <= Maxlevel; i++) { alli = {} let p1 = calcXY(bounding[2], bounding[3], i); let p2 = calcXY(bounding[0], bounding[1], i); alli.t = i // 层级 alli.x = [p2.title_X, p1.title_X] // 瓦片横坐标范围(左至右) alli.y = [p1.title_Y, p2.title_Y] // 瓦片纵坐标范围(下至上) all.push(alli) } createDir() } mainnAllXY(bou, Minlevel, Maxlevel) function createDir() { fs.access(zpath, fs.constants.F_OK, err => { // 创建tiles文件夹 if (err) fs.mkdir(zpath, err => { }) for (let z = 0; z <= all.length - 1; z++) { fs.access(`${zpath}/${all[z].t}`, fs.constants.F_OK, err => { // 创建tiles/Z文件夹 ,Z是层级 if (err) fs.mkdir(`${zpath}/${all[z].t}`, err => { }) for (let x = all[z].x[0]; x <= all[z].x[1]; x++) { fs.access(`${zpath}/${all[z].t}/${x}`, fs.constants.F_OK, err => { // 创建tiles/Z/X文件夹 ,X是瓦片横坐标 if (err) fs.mkdir(`${zpath}/${all[z].t}/${x}`, err => { }) }) } }) } // 文件夹可能较多,等待2s开始下载 setTimeout(() => { task() }, 2000) }) } /** * 创建下载队列 */ var sum = 0; var bag = new Bagpipe(speed, { timeout: 1000 }) function task() { for (let z = 0; z <= all.length - 1; z++) { for (let x = all[z].x[0]; x <= all[z].x[1]; x++) { for (let y = all[z].y[0]; y <= all[z].y[1]; y++) { // 将下载任务推入队列 ++sum bag.push(download, x, y, all[z].t) } } } } /** * 下载图片方法 * @param {Number} x * @param {Number} y * @param {Number} z */ function download(x, y, z) { var ts = Math.floor(Math.random() * 8)//随机生成0-7台服务器 let imgurl = `http://t${ts}.tianditu.gov.cn/DataServer?T=${mapstyle}&x=${x}&y=${y}&l=${z}&tk=${token}`; var ip = Math.floor(Math.random() * 256)//随机生成IP迷惑服务器 + "." + Math.floor(Math.random() * 256) + "." + Math.floor(Math.random() * 256) + "." + Math.floor(Math.random() * 256) var v = Math.floor(Math.random() * 9) var options = { method: 'GET', url: imgurl, headers: { 'User-Agent': user_agent_list_2[v], 'X-Forwarded-For': ip, "Connection": 'keep-alive' }, timeout: 5000, forever: true }; request(options, (err, res, body) => { if (err) { bag.push(download, x, y, z) console.log("request错误", err) } }).pipe(fs.createWriteStream(`${zpath}/${z}/${x}/${y}.png`).on('finish', () => { console.log(`图片下载成功,第${z}层`) console.log(--sum) }).on('error', (err) => { console.log('发生异常:', err); })); }
package.json
{ "name": "mapdownload", "version": "1.0.0", "main": "index.js", "license": "MIT", "dependencies": { "bagpipe": "^0.3.5", "request": "^2.88.0", "tile-lnglat-transform": "^1.3.2" }, "scripts": { "start": "node ./src/index" } }
安装插件
npm i
下载地图切片
npm start
2.iis发布离线地图切片
查看
3.Cesium加载离线天地图切片
//加载离线地图 let imgLayer = new Cesium.UrlTemplateImageryProvider({ url: "SameUrlPath/{z}/{x}/{y}.png", layer: "imgLayer", minimumLevel: 0, maximumLevel:8, });
SameUrlPath为前端代理后的地址,由于直接使用iis发布后的地址会报跨域错误,所以需要前端代理。
new Promise(async (resolve, reject) => { this.viewer = new Cesium.Viewer(this.$refs.cesiumContainer, { selectionIndicator: false, infoBox: false, contextOptions: { // 硬件反走样,默认值为 1 msaaLevel: 8, requestWebgl2: true, }, animation: false, timeline: false, // 底部时间线 fullscreenButton: false, // 全屏 vrButton: false, // VR sceneModePicker: false, // 选择视角的模式(球体、平铺、斜视平铺) baseLayerPicker: false, // 图层选择器(地形影像服务) navigationHelpButton: false, // 导航帮助(手势,鼠标) geocoder: false, // 位置查找工具 homeButton: false, // 视角返回初始位置 }); this.viewer.scene.globe.baseColor = Cesium.Color.BLACK; // 设置地球颜色 this.viewer.cesiumWidget.creditContainer.style.display = "none"; // 去除logo window.viewer = this.viewer; //加载离线地图 let imgLayer = new Cesium.UrlTemplateImageryProvider({ url: "SameUrlPath/{z}/{x}/{y}.png", layer: "imgLayer", minimumLevel:0, maximumLevel:8, }); viewer.imageryLayers.addImageryProvider(imgLayer); // 加载地形数据 viewer.terrainProvider = await Cesium.createWorldTerrainAsync({ url: "https://[ t0-t7 ].tianditu.gov.cn/mapservice/swdx?tk=天地图token", //"data/sjzTerrain/", //"http://192.168.1.143:8963/",// Cesium.IonResource.fromAssetId(1), //"http://192.168.1.143:8963/" requestWaterMask: true, // 控制水的流动效果 requestVertexNormals: true, //请求地形照明数据 }); viewer.scene.globe.enableLighting = true; resolve(viewer); }).then(() => { });
SameUrlPath为前端代理
devServer: { // host: "localhost", //port: "8080", hot: true, open: false, client: { overlay: { errors: true, warnings: false, }, }, proxy: { '/SameUrlPath': { target: 'http://192.168.1.143:8769/', ws: true, //代理websockets changeOrigin: true, // 虚拟的站点需要更管origin pathRewrite: { //重写路径 比如'/api/aaa/ccc'重写为'/aaa/ccc' '^/SameUrlPath': '' } } } }
vue.config.js
const { defineConfig } = require('@vue/cli-service') const path = require('path') const webpack = require('webpack') const CopyWebpackPlugin = require('copy-webpack-plugin') const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') function resolve(dir) { return path.join(__dirname, dir) } module.exports = defineConfig({ transpileDependencies: true, configureWebpack: { name: 'vue-cesium', resolve: { alias: { '@': resolve('src') } }, plugins: [ new NodePolyfillPlugin(), new CopyWebpackPlugin({ patterns: [ { from: 'node_modules/cesium/Build/Cesium/Workers', to: 'cesium/Workers' }, { from: 'node_modules/cesium/Build/Cesium/ThirdParty', to: 'cesium/ThirdParty' }, { from: 'node_modules/cesium/Build/Cesium/Assets', to: 'cesium/Assets' }, { from: 'node_modules/cesium/Build/Cesium/Widgets', to: 'cesium/Widgets' } ] }), new webpack.DefinePlugin({ // Define relative base path in cesium for loading assets CESIUM_BASE_URL: JSON.stringify('./cesium') }) ], module: { rules: [ { test: /.js$/, include: /(cesium)/, use: { loader: '@open-wc/webpack-import-meta-loader' } } ] }, devServer: { // host: "localhost", //port: "8080", hot: true, open: false, client: { overlay: { errors: true, warnings: false, }, }, proxy: { '/SameUrlPath': { target: 'http://192.168.1.143:8769/', ws: true, //代理websockets changeOrigin: true, // 虚拟的站点需要更管origin pathRewrite: { //重写路径 比如'/api/aaa/ccc'重写为'/aaa/ccc' '^/SameUrlPath': '' } } } } } })