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,性能效率双提升
随着深度学习模型复杂度和数据集规模的增大,计算效率的提升成为不可忽视的问题。然而,算法网络的多样性、输入数据的不确定性以及硬件之间的差异性,使得网络调优耗费巨大成本,即使是经验丰富的专家,也需要耗费数天的时…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...