首页IT科技openlayers加载天地图(openlayers加载离线地图并实现深色地图)

openlayers加载天地图(openlayers加载离线地图并实现深色地图)

时间2025-06-20 03:44:05分类IT科技浏览5565
导读:问题背景...

问题背景

      我们自己一直使用的openlayer+geoserver自己发布的地图              ,使用的是矢量地图              。但是由于政府地图大都使用为天地图                     ,所以需要将geoserver的矢量地图更改为天地图       ,并且依旧是搭配openlayers来使用                     。

解决步骤

一:加载离线地图(参考了https://juejin.cn/post/7017301189406490655的文章)

      ● 获取离线地图瓦片

      ● openlayers加载离线地图瓦片

      ● 显示地理坐标

      ● 显示地理坐标范围       。

二:颜色切换效果(参考https://www.cnblogs.com/m7777/p/16280817.html这篇文章)

      ● openlayers瓦片预处理

      ● 出现的各种问题修复

这里的解决方案我也是查了很多的博客和技术文章看的       ,但是其中的出现的问题真的很多很多啊              。所以自己写一篇                     ,记录一下                     。

一:加载离线地图

a.下载离线地图瓦片

      首先需要做的是下载瓦片       。

      ● 下载离线地图瓦片              ,网上有很多方法              、大部分收费 找个合适的工具真的难       ,找到一个能用的免费贡献出来了全能地图下载器

      ● 链接:https://pan.baidu.com/s/18LiUAh1-5CsVxzhX77ZReg 提取码:yd88

● 1.下载完成后打开这个

2.选择需要下载的离线地图的瓦片(注意啊                     ,这里的地图只能选高德地图的瓦片              ,其他地图的瓦片要么没有,要么就对不上号                     ,会导致加载图片失败       。很坑                     ,一开始我以为是我代码的问题,结果并不是                     。这里我是先尝试              ,所以先下一个高德地图的瓦片试试                     ,后面再用其他工具下天地图的瓦片       ,把瓦片换成天地图的瓦片              ,一样的)

错误大概是这样子的                     ,不要怀疑自己       ,那是因为下载的瓦片不对       ,或者下载的瓦片不全导致的              。如果是完全没出来                     ,那就是下载器的问题              ,如果是部分没出来       ,那就是没下全瓦片       。

b.发布离线数据

      ● 地图离线瓦片肯定是要放在服务器上的                     ,放在项目里有点过于庞大了                     。

      ● 本地测试的话              ,本地起一个服务用来访问地图离线瓦片,本文采用 http-server 猛击查看安装 一行命令              。

步骤很简单                     ,就是1.找到你下载地图离线瓦片的目录                     ,然后npm i http-server。 2.然后再在那个目录上运行 http-server,这样子你的静态瓦片就能被别人访问到了(模拟了放在服务器上访问的效果)                     。

c.openlayers 加载离线地图 本文以 vue2 项目为例

1.安装ol

      ● npm install ol

2.加载离线的瓦片

      这里的注意点就是 a.盒子必须要有宽高 b.url请换成你起http-server的服务地址 c.地图坐标中心点必须换成你下载城市的那个坐标范围                     。

<template> <div class="home"> <div style="width: 100%; height: 100%"> <div class="map" id="map"></div> </div> </div> </template> <script> import ol/ol.css import Map from ol/Map import { Tile as TileLayer } from ol/layer import View from ol/View import XYZ from ol/source/XYZ export default { name: HomeView, components: {}, data () { return { mapObj: null, mapDom: null, mapPointList: [], pointLayerSource: null, pointLayer: null, } }, mounted () { this.initMap() }, methods: { // 清除地图 某些情况 地图容器会存在两个 导致地图无法正常显示 这个问题折腾了我半天。 // 找了半天官方貌似也没有提供 对应的 api              ,自己动手了              。 mapClear () { if (this.mapDom) { this.mapDom.innerHTML = this.mapDom = null } }, // 初始化地图 initMap () { // 先尝试清除 // this.mapClear() // 获取地图容器 this.mapDom = document.getElementById(map) // 初始化地图配置 this.mapObj = new Map({ target: this.mapDom, // 地图容器 view: new View({ center: [112.475243, 23.077845], // 地图中心点 zoom: 13, // 缩放 projection: EPSG:4326, // 坐标系 }), }) // 添加一个使用离线瓦片地图的层 const offlineMapLayer = new TileLayer({ source: new XYZ({ url: http://169.254.231.19:8081 + /{z}/{x}/{y}.png, // 设置本地离线瓦片所在路径,前面的地址是你输入http-server之后的服务地址 // tileLoadFunction: (imageTile, src)=> { // console.log(imageTile,src) // // 使用滤镜 将白色修改为深色 // let img = new Image() // // img.crossOrigin = // // 设置图片不从缓存取                     ,从缓存取可能会出现跨域       ,导致加载失败 // img.setAttribute(crossOrigin, anonymous) // img.onload = ()=> { // let canvas = document.createElement(canvas) // let w = img.width // let h = img.height // canvas.width = w // canvas.height = h // let context = canvas.getContext(2d) // context.filter = grayscale(98%) invert(100%) sepia(20%) hue-rotate(180deg) saturate(1600%) brightness(80%) contrast(90%) // context.drawImage(img, 0, 0, w, h, 0, 0, w, h) // imageTile.getImage().src = canvas.toDataURL(image/png) // }, // img.onerror = ()=>{ // imageTile.getImage().src = require(@/assets/logo.png) // } // img.src = src // }, }), }) // 将图层添加到地图 this.mapObj.addLayer(offlineMapLayer) // 加载地理坐标 // this.addPoint() }, }, beforeDestroy () { this.mapClear() }, } </script> <style lang="less"> .map { width: 1900px; height: 1000px; // background-color: red; } </style>

如果你进行到了这一步              ,恭喜你                     ,你成功的利用openlayers加载了离线地图       ,在你运行项目之后       ,你应该能看到属于你的地图了

二:颜色切换效果

      思路参考:https://blog.csdn.net/qq_32077521/article/details/123224974(这边文章写的挺好的                     ,大概讲了怎么样去更改自己地图的主题的几种办法                     。我之前用的是第二种使用filter来直接变色       。结果导致了只要是地图上的东西              ,都会经过染色变成其他颜色       ,很不好!然后左思冥想                     ,想到能不能只让该地图图层加上filter来变色              ,其他图层都不会有filter的变色效果,找了很久                     ,找到了下面这个)

实现参考:https://www.cnblogs.com/m7777/p/16280817.html

a.openlayers瓦片预处理

利用openlayers中的tileLoadFunction 的函数回调进行变色                     ,结合css的filter属性来进行变色              。

大概就是这一段

tileLoadFunction函数解释

:这个api大概就是让你在加载瓦片时进行操作                     。

css的filter属性解释

:大概就是改变你图片的色相,饱和度              ,黑白                     ,通透性等等       ,来实现图片变色的效果       。(缺点              ,不能让地图指定哪个颜色                     ,只能调个大概的好看的颜色       。)

下面我放完整的代码       ,大家复制这个就行                     。因为上面参考的代码还有坑点 <template> <div class="home"> <div style="width: 100%; height: 100%"> <div class="map" id="map"></div> </div> </div> </template> <script> import ol/ol.css import Map from ol/Map import { Tile as TileLayer } from ol/layer import View from ol/View import XYZ from ol/source/XYZ export default { name: HomeView, components: {}, data () { return { mapObj: null, mapDom: null, mapPointList: [], pointLayerSource: null, pointLayer: null, } }, mounted () { this.initMap() }, methods: { // 清除地图 某些情况 地图容器会存在两个 导致地图无法正常显示 这个问题折腾了我半天              。 // 找了半天官方貌似也没有提供 对应的 api       ,自己动手了       。 mapClear () { if (this.mapDom) { this.mapDom.innerHTML = this.mapDom = null } }, // 初始化地图 initMap () { // 先尝试清除 // this.mapClear() // 获取地图容器 this.mapDom = document.getElementById(map) // 初始化地图配置 this.mapObj = new Map({ target: this.mapDom, // 地图容器 view: new View({ center: [112.475243, 23.077845], // 地图中心点 zoom: 13, // 缩放 projection: EPSG:4326, // 坐标系 }), }) // 添加一个使用离线瓦片地图的层 const offlineMapLayer = new TileLayer({ source: new XYZ({ url: http://169.254.231.19:8081 + /{z}/{x}/{y}.png, // 设置本地离线瓦片所在路径,前面的地址是你输入http-server之后的服务地址 tileLoadFunction: (imageTile, src)=> { console.log(imageTile,src) // 使用滤镜 将白色修改为深色 let img = new Image() // img.crossOrigin = // 设置图片不从缓存取                     ,从缓存取可能会出现跨域              ,导致加载失败 img.setAttribute(crossOrigin, anonymous) img.onload = ()=> { let canvas = document.createElement(canvas) let w = img.width let h = img.height canvas.width = w canvas.height = h let context = canvas.getContext(2d) context.filter = grayscale(98%) invert(100%) sepia(20%) hue-rotate(180deg) saturate(1600%) brightness(80%) contrast(90%) context.drawImage(img, 0, 0, w, h, 0, 0, w, h) imageTile.getImage().src = canvas.toDataURL(image/png) }, img.onerror = ()=>{ imageTile.getImage().src = require(@/assets/logo.png) } img.src = src }, }), }) // 将图层添加到地图 this.mapObj.addLayer(offlineMapLayer) // 加载地理坐标 // this.addPoint() }, }, beforeDestroy () { this.mapClear() }, } </script> <style lang="less"> .map { width: 1900px; height: 1000px; // background-color: red; } </style>

b.出现的各种问题解决

1.如果你复制了上面的代码       ,去运行                     。第一个发现的就是会跨域!!!!!那么说明了我们的静态资源文件有跨域的限制                     ,虽然百度了说设置img.setAttribute(‘crossOrigin’, ‘anonymous’)这个有用              ,但是经过实验其实没用              。

所以第一步:我们需要解决跨域的问题

**如何解决?**将刚才启动的http-server命令,换成http-server --cors(学过node应该了解一点                     ,加上cors可以取消跨域)                     ,再次运行,你就会能运行上来了              ,注意看这个cors已经加上了

2.到这里我本以为已经是大功告成                     ,但是       ,远远没有这么简单。原因就是出bug了                     。由于我们添加了这个函数              ,然后有些瓦片又不齐全                     ,导致了加载了404的瓦片       ,再次缩放回来瓦片就没了!!!(这个我思考了很久才想到应该是这个问题导致的       ,大概的效果就是如下图)

解决办法:添加图片的onerror事件                     ,把imageTile.getImage().src = require(‘@/assets/logo.png’)设置为一个图片出错时的替换图片就ok了                     。对于404的图片              ,大家也可以这样子设置       ,设置成需要替换的图片就行

总结

      filter+openlayers的tileLoadFunction实现地图的变色                     ,但是只能配出大概的整体好看的颜色。不能一一自定义某个图层的颜色              ,比如设置树的颜色,设置海滩的颜色              。这些是需要自己发布地图服务来弄的                     。但是对于目前的离线地图需求的来说                     ,实现业务需求已经可以了       。毕竟我们自己搭的地图服务用的是Open Street Map ,可是业务觉得天地图是必须的                     ,深色也是必须的,有利有弊              ,可以抉择              。

另外https://blog.csdn.net/qq_32077521/article/details/123224974这篇文章也说了怎么样自定义离线地图颜色的                     ,大家也可以参考下       ,我觉得是挺不错的              ,开阔自己的思路

demo地址:https://github.com/rui-rui-an/offlinemap                     ,这个demo还需要配合瓦片的服务来       ,瓦片我就没上传了       ,太大                     ,自己去下一个吧                     。我这个demo下载的是肇庆市的              ,大家可以下载肇庆的瓦片配合这个demo来看

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
顺昌县最新消息(顺昌新闻今日头条最新消息) 网站的记录没了怎么办(揭秘网站历史收录:了解网站背后的故事)