openlayers加载离线地图并实现深色地图
问题背景
我们自己一直使用的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.widthlet h = img.heightcanvas.width = wcanvas.height = hlet 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这篇文章也说了怎么样自定义离线地图颜色的,大家也可以参考下,我觉得是挺不错的,开阔自己的思路
相关文章:

openlayers加载离线地图并实现深色地图
问题背景 我们自己一直使用的openlayergeoserver自己发布的地图,使用的是矢量地图。但是由于政府地图大都使用为天地图,所以需要将geoserver的矢量地图更改为天地图,并且依旧是搭配openlayers来使用。 解决步骤 一:加载离线地图&a…...
socket,tcp,http三者之间的区别和原理
目录 一、OSI模型也称七层网络模型 1、TCP/IP连接 1.1三次握手与四次挥手的简单理解:(面试重点) 1.2面试考题:如果已经建立了连接,但是客户端突然出现故障了怎么办? 1.3 socket、tcp、http三者之间有什…...

红日(vulnstack)1 内网渗透ATTCK实战
环境准备 靶机链接:百度网盘 请输入提取码 提取码:sx22 攻击机系统:kali linux 2022.03 网络配置: win7配置: kali配置: kali 192.168.1.108 192.168.111.129 桥接一块,自定义网卡4 win7 1…...
ik 分词器怎么调用缓存的词库
IK 分词器是一个基于 Java 实现的中文分词器,它支持在分词时调用缓存的词库。 要使用 IK 分词器调用缓存的词库,你需要完成以下步骤: 创建 IK 分词器实例 首先,你需要创建一个 IK 分词器的实例。可以通过以下代码创建一个 IK 分…...

ROS1/2机器人操作系统与时间Time的不解之缘
时间对于机器人操作系统非常重要。所有机器人类的编程中所涉及的变量如果需要在网络中传输都需要这个数据结构的时间戳。宏观上,ROS1、ROS2各版本都有官方支持的时间节点。ROS时钟--支持时间倒计时小工具效果如下:如果要部署机器人操作系统,R…...
华为OD机试真题2022(JAVA)
华为机试题库已换 →→→ 华为OD机试2023(JAVA) 以下题目为旧版题库,供大家课外消遣 基础题: 序号题目分值1查找众数及中位数1002出错的或电路1003连续字母长度1004分班1005计算面积1006最远足迹1007判断一组不等式是否满足约束…...

【3】MyBatis+Spring+SpringMVC+SSM整合一套通关
三、SpringMVC 1、SpringMVC简介 1.1、什么是MVC MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分 M:Model,模型层,指工程中的JavaBean,作用是处理数据 JavaBean分为两类: 一类称为实体…...
20道前端高频面试题(附答案)
ES6新特性 1.ES6引入来严格模式变量必须声明后在使用函数的参数不能有同名属性, 否则报错不能使用with语句 (说实话我基本没用过)不能对只读属性赋值, 否则报错不能使用前缀0表示八进制数,否则报错 (说实话我基本没用过)不能删除不可删除的数据, 否则报错不能删除变量delete p…...

android EditText设置后缀
有两种实现方案。 方案一:是自己写一个TextWatcher。 方案二:是重写TextView的getOffsetForPosition方法,返回一个计算好的offset。 我在工作时,使用的是方案一。在离职之后,我还是对这个问题耿耿于怀,所以…...

prometheus+cadvisor监控docker
官方解释 cAdvisor(ContainerAdvisor)为容器用户提供了对其运行容器的资源使用和性能特性的了解。它是一个正在运行的守护程序,用于收集、聚合、处理和导出有关正在运行的容器的信息。具体来说,它为每个容器保存资源隔离参数、历史…...

正演(1): 二维声波正演模拟程序(中心差分)Python实现
目录 1、原理: 1)二维声波波动方程: 编辑 2)收敛条件(不是很明白) 3)雷克子波 4)二维空间衰减函数 5)边界吸收条件 (不是很明白。。) 2、编程实现 1)参数设置&…...

珠海数据智能监控器+SaaS平台 轻松实现SMT生产管控
数据智能监控器 兼容市面上99%的SMT设备 直接读取设备生产数据与状态,如:计划产出、实际产出、累计产出、停机、节拍、线利用率、直通率、停产时间、工单状态、OEE…… 产品功能价值 ◎ OEE不达标报警,一手掌握生产效能 ◎ 首检/巡检/成…...
习题22对前面21节的归纳总结
笨方法学python --习题22 Vi---Rum 于 2021-01-12 14:16:10 发布 python 习题22 这节内容主要是归纳总结 ex1.py 第一次学习 1.print:打印 2.# :是注释的意思,井号右边的内容不再执行 3.end"":,在句子结尾加上这个就不会再换行…...
使用Vite快速构建前端React项目
一、Vite简介 Vite是一种面向现代浏览器的一个更轻、更快的前端构建工具,能够显著提升前端开发体验。除了Vite外,前端著名的构建工具还有Webpack和Gulp。目前,Vite已经发布了Vite3,Vite全新的插件架构、丝滑的开发体验,可以和Vue3完美结合。 相比Webpack和Gulp等构建工具…...

人工智能高等数学--人工智能需要的数学知识_微积分_线性代数_概率论_最优化---人工智能工作笔记0024
然后我们看一下人工智能中需要的数学知识 数学知识是重要的,对于理解人工智能底层原理来说很重要,但是工作中 工作中一般都不会涉及的自己写算法之类的,只是面试,或者理解底层原理的时候需要 然后看一下人工智能需要哪些数学知识 这里需要微积分 线性代数 概率论 最优化的知识…...

阿里大数据之路总结
一、数据采集 二、数据同步 2.1、数据同步方式: 数据同步的三种方式:直连方式、数据文件同步、数据库日志解析方式 关系型数据库的结构化数据:MYSQL、Oracle、DB2、SQL Server非关系型数据库的非结构化数据(数据库表形式存储&am…...

ABAP中Literals的用法(untyped literal vs. typed literal)
1. 什么是Literals ? Literals的字面意思即“文字”。其实,Literals就是在ABAP代码中直接指定的一个字符串,但注意哦,这个字符串并不意味着其类型一定是string哦。 要弄清这个概念,就要清楚ABAP对于Literals 的定义和处理方式。…...

tensorflow1.14.0安装教程
1首先电脑安装好Anaconda3(Anaconda介绍、安装及使用教程 - 知乎 (zhihu.com),) 蟒蛇 |全球最受欢迎的数据科学平台 (anaconda.com) 2打开Anaconda Prompt(本人更新win11后,主菜单不再显示,那么我们可以打…...

C++赋值运算符重载
赋值运算符重载 目录赋值运算符重载示例1:示例2:示例3:示例4:很巧妙的是,在编写这篇文章时(2023年2月27日),再加100天就是6月7日,恰好是今年高考的百日誓师! …...

网络性能总不好?专家帮你来“看看”— CANN 6.0 黑科技 | 网络调优专家AOE,性能效率双提升
随着深度学习模型复杂度和数据集规模的增大,计算效率的提升成为不可忽视的问题。然而,算法网络的多样性、输入数据的不确定性以及硬件之间的差异性,使得网络调优耗费巨大成本,即使是经验丰富的专家,也需要耗费数天的时…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...