openlayers系列:加载arcgis和geoserver在线离线切片

https://www.freesion.com/article/1751396517/

1.背景

有个项目需要使用openlayer加载各种服务上发布的数据,坐标系也不同,我们都知道openalyer默认可以加载EPAG:3857,要加载4490的坐标系的数据需要重新定义一下,之后再加载。一想起要重新定义坐标系感觉很难,就想放弃,其实静下心了做一下也没那么难。在此做个简单的记录,要加载的数据如下:

1.1 arcgis 服务 

1.2 本地切好的瓦片服务

1.3结果 加载好天地图、4490arcgisserver 服务、本地影像切片

 

2.解决思路

2.1 原理

使用proj4js 给所有坐标和范围提供视图投影系(默认是EPAG:3857),给每个要加载的图层设置此坐标系即可正常加载。

2.2 资源

(1).API   OpenLayers v7.4.0 API 

  (2)epsg  ​​​​​​​EPSG.io: Coordinate Systems Worldwide 

   了解有关各种投影的参数定义

  (3)proj4js proj4js (v2.9.0)   https://www.bootcdn.cn/proj4js/

2.3 重新定义坐标系步骤​​​​​​​

(1)proj4引用 前端添加Proj4js有三种方式:

  • 从​ ​http://trac.osgeo.org/proj4js/wiki/Download​​下载,获取产品包中dist/proj4.js文件。
  • 引入CDN上的Proj4js:​ ​https://cdnjs.com/libraries/proj4js​​
  • 本地有Node.js,可以直接使用​​npm install proj4 --save进行安装。

(2)基础使用

proj4.js中预定义了三个坐标系,其他的坐标系则需要自己定义了,下面以从WGS84(4326)到Web墨卡托(3857)的转换为例

function Wgs84ToMector2(lat,lng) {const proj4 = require('proj4');return proj4(proj4('EPSG:4326'), proj4('EPSG:3857'), [lng, lat])
}

 定义坐标系:

function init4490(){proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");
//4490的坐标系注册进openlayer的projection中register(proj4);
//重写projection4490,地图投影var projection = new Projection({code: 'EPSG:4490',units: 'degrees',axisOrientation: 'neu'});addProjection(projection);projection.setExtent([-180, -90, 180, 90]);projection.setWorldExtent([-180, -90, 180, 90]);projection.getMetersPerUnit = function(){return 2 * Math.PI * 6378137 / 360;};addCoordinateTransforms( "EPSG:4326","EPSG:4490", function( coordinate){return proj4("EPSG:4490", "EPSG:4326",coordinate);},function(coordinate){return proj4("ERSG:4490" , "EPSG:4326" , coordinate);});
}

其中 proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");是从epsg的网站上获取的参数,如下图:【输入4490坐标系】---【选择proj4js】---【复制】即可。

 

定义好4490坐标系后,需要注册和重写projection 

3.加载多源不同坐标系的地图

3.1加载arcgis server wmts服务

function getWMTSLayer(options) {const projections = options.projection?options.projection:projection4326;const res = getResolutionsAndMids(projections);return new TileLayer({source: new WMTS({name: "中国",url: options.url,layer: options.layer, // 图层名version: '1.0.0',// WMTS版本style: options.style?options.style:"default",matrixSet: options.matrixSet?options.matrixSet:"c", // 投影坐标系矩阵集,一定要和WMTS capabilities文档中一致,否则会加载失败format: options.format?options.format:"tiles",   // 图片格式wrapX: true,tileGrid: new WMTSTileGrid({// 投影坐标系origin: getTopLeft(projections.getExtent()),resolutions: res.resolutions,matrixIds: res.matrixIds,}),projection: projections // 投影坐标系}),})
}

3.2加载切好的本地图层

function getXYZLayer(options) {const projections = options.projection?options.projection:projection4326;return new TileLayer({title: '泾阳',source:  new XYZ({url: options.url,projection: projections})})
}

4.图层顺序

        在 openlayer 中,图层是使用 layer 对象表示的,主要有 WebGLPoints Layer、 热度图(HeatMap Layer)、图片图层(lmage Layer)、切片图层(Tile Layer)和 矢量图层(Vector Layer)五种类型,它们都是继承 Layer 类的。
常用参数

  • source,指定了图层的数据来源,图层作用是以一定的样式渲染数据,source则指定了数据visible ,是否可见;
  • zlndex,图层的叠加次序,默认是0,最底层,如果使用setMap方法添加的图层,zlndex值是Infinity,在最上层:
  • extent,图层消染的区域,即浏览器窗口中可见的地图区域。extent是一个矩形范用,格式是number, number,number, numberl 分别代表[left,botom.right.top]。为了提升染效率和加载速度,extent范用之外的瓦片是不会请求的,当然也不会演染className,图层各个元素的样式:
  • opacity,透明度,默认为 1,即完全透明:

找到新建Map对象的时候,调整layers的顺序,layer越往右,图层越往上显示。

var layer = new Vector({source: new Vector({projection: 'EPSG:4326',format: new GeoJSON()}),style: styleFunction,zIndex:9999
});

6.整体demo

openalyer.vue

<template lang="pug">
#map
</template>
<script setup>
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import {onMounted, onUnmounted, reactive} from "vue";
import {img_c} from "./map.js";
import {fromLonLat} from 'ol/proj'
onMounted(()=>{const layers1 = img_c()const map = new Map({layers: layers1,target: 'map',view: new View({center: fromLonLat([108.68, 34.6]),//地图中心// extent : [ 119.54811, 29.92294, 120.50942, 30.69748 ],zoom: 12,}),});})</script>
<style scoped lang="less">
#map {position: absolute;width: 100%;height: 900px;
}
</style>

map.js


import {register} from 'ol/proj/proj4'
import {Projection,addProjection,addCoordinateTransforms,get} from 'ol/proj';
import TileLayer from 'ol/layer/Tile.js';
import {WMTS,XYZ} from 'ol/source.js';
import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
import {getWidth,getTopLeft} from 'ol/extent';
import proj4 from 'proj4';function init4490(){proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");
//4490的坐标系注册进openlayer的projection中register(proj4);
//重写projection4490,地图投影var projection = new Projection({code: 'EPSG:4490',units: 'degrees',axisOrientation: 'neu'});addProjection(projection);projection.setExtent([-180, -90, 180, 90]);projection.setWorldExtent([-180, -90, 180, 90]);projection.getMetersPerUnit = function(){return 2 * Math.PI * 6378137 / 360;};addCoordinateTransforms( "EPSG:4326","EPSG:4490", function( coordinate){return proj4("EPSG:4490", "EPSG:4326",coordinate);},function(coordinate){return proj4("ERSG:4490" , "EPSG:4326" , coordinate);});
}init4490()
//transform([118,32] , 'EPSG:4326' , 'EPSG:4490 ');
const projection4490 = new get('EPSG:4490' );
const projection4326 = new get('EPSG:4326' );
const projection3857 = new get('EPSG:3857' );function getResolutionsAndMids(projection) {const projections = projection?projection:projection4326;let projectionExtent = projections.getExtent();let size = getWidth(projectionExtent) / 256; //size就是一个像素代表的经纬度let matrixIds = [];let resolutions = [];for (let z = 0; z < 20; ++z) {resolutions[z] = size / Math.pow(2, z);matrixIds[z] = z;}return {"resolutions":resolutions,"matrixIds":matrixIds};
}export function getProjection() {return projection4490
}
// WMTS 形式
function getWMTSLayer(options) {const projections = options.projection?options.projection:projection4326;const res = getResolutionsAndMids(projections);return new TileLayer({source: new WMTS({name: "中国",url: options.url,layer: options.layer, // 图层名version: '1.0.0',// WMTS版本style: options.style?options.style:"default",matrixSet: options.matrixSet?options.matrixSet:"c", 
// 投影坐标系矩阵集,一定要和WMTS capabilities文档中一致,否则会加载失败format: options.format?options.format:"tiles",   // 图片格式wrapX: true,tileGrid: new WMTSTileGrid({// 投影坐标系origin: getTopLeft(projections.getExtent()),resolutions: res.resolutions,matrixIds: res.matrixIds,}),projection: projections // 投影坐标系}),})
}
function getXYZLayer(options) {const projections = options.projection?options.projection:projection4326;return new TileLayer({title: '泾阳',source:  new XYZ({url: options.url,projection: projections})})
}
const key ='b9031f80391e6b65bd1dd80dcde1b097';
/**\* 矢量底图 + 矢量注记*/
export function vec_c() {return [getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/vec_c/wmts?tk=' + key, "layer":'vec',"projection":projection4490}),getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cva_c/wmts?tk=' + key, "layer":'cva',"projection":projection4490}),]
}/**\* 影像底图 + 影像注记*/
export function img_c() {return [//  getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/img_c/wmts?tk=' + key, "layer":'img',"projection":projection4490}), getXYZLayer({"url":'https://xxxx/jingyang/imgyx/jyx/{z}/{x}/{y}.png',"projection":projection3857}),getWMTSLayer({"url":'http://xxxx:6080/arcgis/rest/services/jingyang/jingyang1/MapServer/WMTS?',"layer":'jingyang_jingyang1',"projection":projection4490}),getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cia_c/wmts?tk=' + key, "layer":'cia'}),//  getXYZLayer({"url":'http://xxxx:6080/arcgis/rest/services/jingyang/jingyang1/MapServer/tiles/{z}/{x}/{y}.png',"projection":projection4490}),]
}
/**\* 地形底图 + 地形注记*/
export function ter_c() {return [getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/ter_c/wmts?tk=' + key, "layer":'ter',"projection":projection4490}),getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cta_c/wmts?tk=' + key, "layer":'cta',"projection":projection4490}),]
}

7.其他

7.1 Layer分类

  • TitleLayer: 切片图层,用于加载切片数据。切片是指利用网格将一幅地图切成大小相等的小正方形。切片尺寸一般是256*256或者512*512
  • ImageLayer:图片图层,主要用于服务器渲染的图像,
  • VectorLayer:矢量图层,是指在客户端渲染的图层类型
  • VectorTileLayer:矢量切片图层,和栅格切片一样的思路。

7.2 source类型

source 是 Layer 的重要组成部分,表示图层的来源,也就是服务地址。除了在构造函数中制定外,可以使用 layer.setSource(source) 稍后指定。

基类(不能被实例化,只负责被继承):

  • ol.source.Image,提供单一图片数据的类型,直接继承自 ol.source.Source;
  • ol.source.Tile,提供被切分为网格切片的图片数据,继承自 ol.source.Source;
  • ol.source.Vector,提供矢量图层数据,继承自 ol.source.Source;

可以实例化的类:

  • ol.source.BingMaps ,必应地图的切片数据,继承自ol.source.TileImage;
  • ol.source.Cluster,聚簇矢量数据,继承自ol.source.Vector;
  • ol.source.ImageCanvas,数据来源是一个 canvas 元素,其中的数据是图片,继承自 ol.source.Image;
  • ol.source.ImageMapGuide,Mapguide 服务器提供的图片地图数据,继承自 ol.source.Image,fire ol.source.ImageEvent;
  • ol.source.ImageStatic,提供单一的静态图片地图,继承自ol.source.Image;
  • ol.source.ImageVector,数据来源是一个 canvas 元素,但是其中的数据是矢量来源 ol.source.Vector,继承自 ol.source.ImageCanvas;
  • ol.source.ImageWMS,WMS 服务提供的单一的图片数据,继承自 ol.source.Image,触发 ol.source.ImageEvent;
  • ol.source.MapQuest,MapQuest 提供的切片数据,继承自 ol.source.XYZ;
  • ol.source.OSM,OpenStreetMap 提供的切片数据,继承自 ol.source.XYZ;
  • ol.source.Stamen,Stamen 提供的地图切片数据,继承自 ol.source.XYZ;
  • ol.source.TileVector,被切分为网格的矢量数据,继承自 ol.source.Vector;
  • ol.source.TileDebug,并不从服务器获取数据,而是为切片渲染一个网格,继承自 ol.source.Tile;
  • ol.source.TileImage,提供切分成切片的图片数据,继承自 ol.source.Tile,触发 ol.source.TileEvent;
  • ol.source.TileUTFGrid,TileJSON 格式 的 UTFGrid 交互数据,继承自 ol.source.Tile;
  • ol.source.TileJSON,TileJSON 格式的切片数据,继承自 ol.source.TileImage;
  • ol.source.TileArcGISRest,ArcGIS Rest 服务提供的切片数据,继承自 ol.source.TileImage;
  • ol.source.WMTS,WMTS 服务提供的切片数据。继承自 ol.source.TileImage;
  • ol.source.XYZ,XYZ 格式的切片数据,继承自 ol.source.TileImage;
  • ol.source.Zoomify,Zoomify 格式的切片数据,继承自 ol.source.TileImage。

7.3 proj常见方法

(1)ol.proj.addCoordinateTransforms(source, destination, forward, inverse)
注册坐标转换函数来转换源投影和目标投影之间的坐标。正、反函数转换坐标对;此函数将这些转换为内部使用的处理区段和坐标数组的函数

source:源投影
destination:目标投影
forward:接受ol的正向变换函数(即从源投影到目标投影)。作为参数,并返回转换后的ol.Coordinate
inverse:接受ol的逆变换函数(即从目标投影到源投影)。作为参数,并返回转换后的ol.Coordinate
(2)ol.proj.addEquivalentProjections(projections)
注册不改变坐标的转换函数。它们允许在具有相同含义的投影之间进行转换。

(3)ol.proj.addProjection(projection)
将投影对象添加到受支持的投影列表中,这些投影可以通过它们的SRS码进行查找。

(4)ol.proj.equivalent(projection1, projection2)
检查两个投影是否相同,即一个投影中的每个坐标确实表示另一个投影中的相同地理点。

(5)ol.proj.fromLonLat(coordinate, opt_projection)
将经纬度坐标转换为不同的投影

coordinate:经纬度数组,经度在前,纬度在后
projection:目标投影。默认是Web Mercator,即“EPSG: 3857”
(6)ol.proj.get(projectionLike)
获取指定代码的投影对象。

(7)ol.proj.getTransform(source, destination)
给定类似于投影的对象,搜索转换函数将坐标数组从源投影转换为目标投影。

(8)ol.proj.setProj4(proj4)
proj4注册。如果没有显式注册,则假定proj4js将加载在全局名称空间中

ol.proj.setProj4(proj4);
(9)ol.proj.toLonLat(coordinate, opt_projection)
将坐标转换为经度/纬度

coordinate:投影坐标
projection:坐标的投影,默认是Web Mercator,即“EPSG: 3857”
(10)ol.proj.transform(coordinate, source, destination)
将坐标从源投影转换为目标投影,这将返回一个新的坐标(并且不修改原始坐标)。

coordinate:坐标
source:源投影
destination:目标投影
(11)ol.proj.transformExtent
将范围从源投影转换为目标投影,这将返回一个新范围(并且不修改原始范围)。

(12)ol.proj.Units{string}
投影单位:'degrees', 'ft', 'm', 'pixels', 'tile-pixels' or 'us-ft'

8. 参考文章

开源GIS(二)——openlayers加载Arcgis和geoserver在线离线切片 - 灰信网(软件开发博客聚合)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/8026.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot Demo工程搭建

SpringBoot Demo工程搭建 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://ma…

【C#】并行编程实战:使用 Visual Studio 调试任务

并行编程可以提高应用程序的性能&#xff0c;但是调试起来会更困难&#xff0c;这一点在之前的章节中我们已经有了很直观的感受。对于程序而言&#xff0c;保证程序的正确性和保证性能同样重要。 本章将介绍可以在 Visual Studio 中的调试工具&#xff08;包括 Thread 窗口、Ta…

Vue中TodoList案例_编辑

nextTick: MyItem.vue 加一个编辑按钮&#xff0c;input框&#xff1a;blur失去焦点时触发事件handleBlur&#xff0c;ref获取真实dom&#xff1a; <inputtype"text"v-show"todo.isEdit":value"todo.title"blur"handleBlur(todo,$even…

服务器中了360后缀勒索病毒,360后缀勒索病毒介绍解密数据恢复

360后缀勒索病毒&#xff0c;是BeijingCrypt勒索家族中的一种勒索软件病毒&#xff0c;这种恶意软件一旦攻击了企业的服务器就会利用自身独特的加密技术来全盘扫描系统文件&#xff0c;并对用户的全部文件进行加密&#xff0c;并要求用户支付赎金以解锁文件。近期&#xff0c;我…

命名约定~

1.变量的命名约定 JavaScript 变量名称是区分大小写的&#xff0c;大写和小写字母是不同的。比如&#xff1a; let DogName Scooby-Doo; let dogName Droopy; let DOGNAME Odie; console.log(DogName); // "Scooby-Doo" console.log(dogName); // "Dro…

Hadoop教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下&#xff0c;开发分布式程序。充分利用集群的威力进行高速运算和存储。Hadoop实现了一个分布式文件系统&#xff08; Distributed File System&#xff09;&#xff0…

训练营day6-7:数组篇

目录 1、LeetCode &#xff1a;242.有效的字母异位词 2、349. 两个数组的交集 3、202. 快乐数 4、1. 两数之和 5、454. 四数相加 II 6、383. 赎金信 7、15. 三数之和 8、18. 四数之和 1、LeetCode &#xff1a;242.有效的字母异位词 还是比较简单的&#xff0c;直接统计…

SystemVerilog 第2章:数据类型

在 Verilog中,初学者经常分不清reg和wire两者的区别。应该使用它们中哪一个来驱动端口?连接不同模块时又该如何做? Systemverilog对经典的reg数据类型进行了改进,使得它除了作为一个变量以外,还可以被连续赋值、门单元和模块所驱动。为了与寄存器类型相区别,这种改进的数据类…

Python封装:提升代码质量的秘诀

在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;封装是一种将数据和操作数据的方法绑定在一起的机制&#xff0c;以隐藏内部实现的细节&#xff0c;使代码更简洁、更安全。在Python中&#xff0c;我们通过定义类来实现封装。在本文中&#xff0c;我们将介绍Python封装…

常微分方程建模R包ecode(一)——构建常微分方程系统

常微分方程在诸多研究领域中有着广泛应用&#xff0c;本文希望向大家介绍笔者于近期开发的R包ecode&#xff0c;该包采用简洁易懂的语法帮助大家在R环境中构建常微分方程&#xff0c;并便利地调用R图形接口&#xff0c;研究常微分方程系统的相速矢量场、平衡点、稳定点等解析性…

AI面试官:LINQ和Lambda表达式(三)

AI面试官&#xff1a;LINQ和Lambda表达式&#xff08;三&#xff09; 当面试官面对C#中关于LINQ和Lambda表达式的面试题时&#xff0c;通常会涉及这两个主题的基本概念、用法、实际应用以及与其他相关技术的对比等。以下是一些可能的面试题目&#xff0c;附带简要解答和相关案…

视频内存过大如何压缩变小?这个压缩方法了解一下

在日常生活中&#xff0c;不管是日常随手拍的视频还是在工作中遇到的视频文件&#xff0c;在编辑处理的时候&#xff0c;如果视频的内存过大&#xff0c;不仅会占用很大的内存&#xff0c;在传送的时候也会花费很长时间&#xff0c;这时候将视频给压缩一下就可以很好的解决这一…

Feign远程调用如何携带form url

这是一个需要携带参数在form url上的请求&#xff0c;正常调用方式是这样的 响应&#xff1a; 在Feign中&#xff0c;应该怎么调用呢?? 定义OpenFeignClient接口 FeignClient(value "client-service", url "http://127.0.0.1/api") public interface…

代理模式来啦

一、代理模式 代理模式是我们工作中比较常用的设计模式之一了&#xff0c;主要用于隐藏具体实现类的实现细节或者对实现类的行为进行增强&#xff0c;即对具体实现的前后做些特殊逻辑。 既然说是代理&#xff0c;那就要对客户端隐藏真实实现&#xff0c;由代理来负责客户端的所…

Unity游戏源码分享-3d机器人推箱子游戏

Unity游戏源码分享-3d机器人推箱子游戏 一个非常意思的3D游戏 工程地址&#xff1a;https://download.csdn.net/download/Highning0007/88098014

STM32CUBEMX配置 定时器中断 和 上升沿中断(实现检测1s以内的脉冲个数)

———————————————————————————————————— ⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子&#xff0c;使用STM32CUBEMX做了很多驱动&#x…

Redis简介、常用命令

目录 一、​​关系数据库​​与非关系型数据库概述 1.1 关系型数据库 1.2 非关系型数据库 二、关系数据库与非关系型数据库区别 2.1 数据存储方式不同 2.2 扩展方式不同 2.3 对事务性的支持不同 三、非关系型数据库产生背景 四、Redis简介 4.1 Redis的单线程模式 4.…

评论管理功能

后端 bp.get("/comment/list") def comment_list():comments CommentModel.query.order_by(CommentModel.create_time.desc()).all()comment_list []for comment in comments:comment_dict comment.to_dict()comment_list.append(comment_dict)return restful.ok…

网络超时导致namenode被kill的定位

交换机升级导致部分网络通信超时, 集群的namenode主从切换后,主namenode进程被杀死。 网络问题导致namenode与zk间的连接超时触发了hadoop集群的防脑裂机制而主动kill掉了超时的namenode进程。 日志分析发现zk和namenode之间的网络连接超时: 超时触发了namenode切换,并将超时…

linux 无桌面运行 GUI 程序(electron、arm)

操作 开发板事先连接好屏幕&#xff0c;并用串口连接开发板 apt install xorg dpkg-reconfigure x11-common # 允许任何用户连接到X11服务器 startx # 会在屏幕启动一个命令行终端将键盘连接到开发板&#xff0c;并在开发板上执行命令运行 GUI 应用即可 ./your_program如果是…