环保网站建设公司,公司介绍页面设计,南通网站建设系统电话,中国建筑app免费下载https://www.freesion.com/article/1751396517/
1.背景
有个项目需要使用openlayer加载各种服务上发布的数据#xff0c;坐标系也不同#xff0c;我们都知道openalyer默认可以加载EPAG:3857,要加载4490的坐标系的数据需要重新定义一下#xff0c;之后再加载。一想起要重新…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 (2epsg EPSG.io: Coordinate Systems Worldwide 了解有关各种投影的参数定义 (3proj4js 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,projlonglat ellpsGRS80 no_defs typecrs);
//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,projlonglat ellpsGRS80 no_defs typecrs);是从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
});
5.控制图层显示影藏
//获取某一图层
const getLayerInfo (map,name) {const layers map?.getAllLayers();if (layers) {return layers.find((item) item?.getProperties().title name);}
};//在某一视域范围内显示
function change(map){
// 定义指定区域的边界坐标经度、纬度//var extent transformExtent([westLongitude, southLatitude, eastLongitude, northLatitude], EPSG:4326, EPSG:3857);var extent transformExtent([108.495435118675, 34.4888700423221,108.952496945858, 34.7379809617996], EPSG:4326, EPSG:3857);// 监听视图变化事件map.getView().on(change, function() {var view map.getView();var currentExtent view.calculateExtent(map.getSize());// 判断当前视图的范围是否在指定区域内var isWithinBounds containsExtent(extent, currentExtent);let layer getLayerInfo(map,cia)console.log(layer)if (isWithinBounds) {console.log(当前视域在指定区域内);layer?.setVisible(false);} else {console.log(当前视域不在指定区域内);layer?.setVisible(true);}});
}
6.整体demo
openalyer.vue
template langpug
#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 langless
#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,projlonglat ellpsGRS80 no_defs typecrs);
//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*512ImageLayer:图片图层主要用于服务器渲染的图像VectorLayer:矢量图层是指在客户端渲染的图层类型VectorTileLayer:矢量切片图层和栅格切片一样的思路。
7.2 source类型
source 是 Layer 的重要组成部分表示图层的来源也就是服务地址。除了在构造函数中制定外可以使用 layer.setSource(source) 稍后指定。
基类(不能被实例化只负责被继承)
ol.source.Image提供单一图片数据的类型直接继承自 ol.source.Sourceol.source.Tile提供被切分为网格切片的图片数据继承自 ol.source.Sourceol.source.Vector提供矢量图层数据继承自 ol.source.Source
可以实例化的类:
ol.source.BingMaps 必应地图的切片数据继承自ol.source.TileImageol.source.Cluster聚簇矢量数据继承自ol.source.Vectorol.source.ImageCanvas数据来源是一个 canvas 元素其中的数据是图片继承自 ol.source.Imageol.source.ImageMapGuideMapguide 服务器提供的图片地图数据继承自 ol.source.Imagefire ol.source.ImageEventol.source.ImageStatic提供单一的静态图片地图继承自ol.source.Imageol.source.ImageVector数据来源是一个 canvas 元素但是其中的数据是矢量来源 ol.source.Vector继承自 ol.source.ImageCanvasol.source.ImageWMSWMS 服务提供的单一的图片数据继承自 ol.source.Image触发 ol.source.ImageEventol.source.MapQuestMapQuest 提供的切片数据继承自 ol.source.XYZol.source.OSMOpenStreetMap 提供的切片数据继承自 ol.source.XYZol.source.StamenStamen 提供的地图切片数据继承自 ol.source.XYZol.source.TileVector被切分为网格的矢量数据继承自 ol.source.Vectorol.source.TileDebug并不从服务器获取数据而是为切片渲染一个网格继承自 ol.source.Tileol.source.TileImage提供切分成切片的图片数据继承自 ol.source.Tile触发 ol.source.TileEventol.source.TileUTFGridTileJSON 格式 的 UTFGrid 交互数据继承自 ol.source.Tileol.source.TileJSONTileJSON 格式的切片数据继承自 ol.source.TileImageol.source.TileArcGISRestArcGIS Rest 服务提供的切片数据继承自 ol.source.TileImageol.source.WMTSWMTS 服务提供的切片数据。继承自 ol.source.TileImageol.source.XYZXYZ 格式的切片数据继承自 ol.source.TileImageol.source.ZoomifyZoomify 格式的切片数据继承自 ol.source.TileImage。
7.3 proj常见方法
1ol.proj.addCoordinateTransforms(source, destination, forward, inverse) 注册坐标转换函数来转换源投影和目标投影之间的坐标。正、反函数转换坐标对;此函数将这些转换为内部使用的处理区段和坐标数组的函数
source源投影 destination目标投影 forward接受ol的正向变换函数(即从源投影到目标投影)。作为参数并返回转换后的ol.Coordinate inverse接受ol的逆变换函数(即从目标投影到源投影)。作为参数并返回转换后的ol.Coordinate 2ol.proj.addEquivalentProjections(projections) 注册不改变坐标的转换函数。它们允许在具有相同含义的投影之间进行转换。
3ol.proj.addProjection(projection) 将投影对象添加到受支持的投影列表中这些投影可以通过它们的SRS码进行查找。
4ol.proj.equivalent(projection1, projection2) 检查两个投影是否相同即一个投影中的每个坐标确实表示另一个投影中的相同地理点。
5ol.proj.fromLonLat(coordinate, opt_projection) 将经纬度坐标转换为不同的投影
coordinate经纬度数组经度在前纬度在后 projection目标投影。默认是Web Mercator即“EPSG: 3857” 6ol.proj.get(projectionLike) 获取指定代码的投影对象。
7ol.proj.getTransform(source, destination) 给定类似于投影的对象搜索转换函数将坐标数组从源投影转换为目标投影。
8ol.proj.setProj4(proj4) proj4注册。如果没有显式注册则假定proj4js将加载在全局名称空间中
ol.proj.setProj4(proj4); 9ol.proj.toLonLat(coordinate, opt_projection) 将坐标转换为经度/纬度
coordinate投影坐标 projection坐标的投影默认是Web Mercator即“EPSG: 3857” 10ol.proj.transform(coordinate, source, destination) 将坐标从源投影转换为目标投影这将返回一个新的坐标(并且不修改原始坐标)。
coordinate坐标 source源投影 destination目标投影 11ol.proj.transformExtent 将范围从源投影转换为目标投影这将返回一个新范围(并且不修改原始范围)。
12ol.proj.Units{string} 投影单位degrees, ft, m, pixels, tile-pixels or us-ft
8. 参考文章
开源GIS二——openlayers加载Arcgis和geoserver在线离线切片 - 灰信网软件开发博客聚合