openlayers浅入(了解框架逻辑以及简单使用)

news2024/11/18 4:28:04

openlayers浅入(了解框架逻辑以及简单使用)

项目需求,使用openlayers替换天地图api开发,记录openlayer的使用

简介

OpenLayers是一个用于开发WebGIS客户端的JavaScript包,最初基于BSD许可发行。OpenLayers是一个开源的项目,其设计之意是为互联网客户端提供强大的地图展示功能,包括地图数据显示与相关操作,并具有灵活的扩展机制。目前OpenLayers已经成为一个拥有众多开发者和帮助社区的成熟、流行的框架。最新版本的OpenLayers采用纯面向对象的ECMA Script 6进行开发,可以说,在OpenLayers中万物皆对象

OpenLayers的官方网站

openlayers框架逻辑简单分析

在最新版本OpenLayers中万物皆对象,Map、Layer、Source和View是OpenLayers框架体系中的核心类,几乎所有的动作都围绕这几个核心类展开,以实现地图加载和相关操作。在OpenLayers的体系框架中:把整个地图看作一个容器(Map),核心为地图图层(Layer),每个图层有对应的数据源(Source),并由地图视图(View)进行地图表现。地图容器上还支持一些与用户交互的控件(Control和Interaction),另外,OpenLayers还支持事件机制

在这里插入图片描述

openlayers中常使用的坐标系统

使用WGS84(EPSG:4326) 存储数据,使用伪墨卡托(EPSG:3857)显示数据

使用openlayers

1.引入方式

写的demo使用的cdn方式引入openlayers,项目中使用npm导入openlayers依赖包

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>openlayer</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.1.0/ol.css">
  <link rel="stylesheet" href="./index.css">
</head>
<body>
  <div id="map"></div>
  <div id="mouse-position" class="mouse-position-wrapper">
		<div class="custom-mouse-position"></div>
	</div>
  <script src="https://cdn.jsdelivr.net/npm/ol@v7.1.0/dist/ol.js"></script>
  <script type="module" src="./app.js"></script>
</body>
</html>

2.具体js实现代码(app.js)

const url = 'http://服务器地址/tiles/{z}/{x}/{y}.png'
const epsg = 'EPSG:3857';
const projection = ol.proj.get(epsg);

new出map对象,部分参数使用

const map = new ol.Map({
  target: 'map',
  view: new ol.View({
    center: ol.proj.transform([105.255396, 33.642909], 'EPSG:4326', epsg),
    zoom: 4,
    projection,
    // minZoom: 3,
    // 限制拖拽范围
    extent: [
      // ...ol.proj.fromLonLat([66.539576, 56.602398]),
      // ...ol.proj.fromLonLat([139.137232, 9.785853]),
      // 添加这个范围 经度-最小,纬度-最小,经度-最大,纬度-最大
      ...ol.proj.fromLonLat([73.32783475401652, 19.4243521114706]),
      ...ol.proj.fromLonLat([135.16017906160056, 53.83501005646246]),
    ], //长度为4的数组, 传入地图对角投影坐标
    /* 
      `
      lt:60.646255, 54.099069,
      rt:141.628437, 55.359014,
      rb:138.233974, 11.404207,
      lb:72.284413, 12.590013
      `
    */
    showFullExtent: true,
  }),
});

显示经纬度信息

map.addControl(ol.control.defaults.defaults().extend([
  // 鼠标位置经纬度显示
  new ol.control.MousePosition({
    coordinateFormat: ol.coordinate.createStringXY(6),
    projection: ol.proj.get('EPSG:4326'),
    className: 'custom-mouse-position',
    target: document.getElementById('mouse-position')
  }),
]))

使用addLayer方法加载离线图层

*注:addLayer 方法添加层时 如果没有设置zIndex,根据添加顺序 后面添加的会覆盖前面添加的同位置的覆盖层

// 离线图层
map.addLayer(new ol.layer.Tile({
  title: "tileLayer",
  baseLayer: true,
  willReadFrequently: true,
  source: new ol.source.XYZ({
    attributions: 'cdwx',
    minZoom: 1,
    maxZoom: 19,
    projection: projection,
    tileSize: 256,
    url
  })
}));

添加点Point,并设置点的样式图片等(注释代码是多种可设置样式的方式)

// 添加点
const iconFeature1 = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.transform([104.13689, 33.96498], 'EPSG:4326', epsg)),
  id: 9527,
  // style: new ol.style.Style({
  //   image: new ol.style.Icon({
  //     anchor: [0.5, 50],
  //     anchorXUnits: 'fraction',
  //     anchorYUnits: 'pixels',
  //     src: "img/station_0_1.png",
  //     scale: .4
  //   })
  // })
});
iconFeature1.setStyle(new ol.style.Style({
  image: new ol.style.Icon({
    anchor: [0.5, 50],
    anchorXUnits: 'fraction',
    anchorYUnits: 'pixels',
    src: "img/station_0_1.png",
    scale: .4
  })
}))
const iconFeature2 = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.transform([118.344251, 32.015470], 'EPSG:4326', epsg)),
  id: 4388,
  // style: new ol.style.Style({
  //   image: new ol.style.Icon({
  //     anchor: [0.5, 50],
  //     anchorXUnits: 'fraction',
  //     anchorYUnits: 'pixels',
  //     src: "img/station_0_1.png",
  //     scale: .4
  //   })
  // })
});
iconFeature2.setStyle(new ol.style.Style({
  image: new ol.style.Icon({
    anchor: [0.5, 50],
    anchorXUnits: 'fraction',
    anchorYUnits: 'pixels',
    src: "img/station_6_0.png",
    scale: .3
  })
}))
const tilerVectorSource = new ol.source.Vector({
  features: [iconFeature1, iconFeature2]
});
/* 
1.feature通过setStyle设置样式 layer通过 function (f) {return f.getStyle()} 设置样式 (能够在后期使用feature.setStyle(undefined)来隐藏feature)
2.
feature通过ObjectWithGeometry中设置style样式如下
new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.transform([118.344251, 32.015470], 'EPSG:4326', epsg)),
  id: 4388,
  style: new ol.style.Style({
    image: new ol.style.Icon({
      anchor: [0.5, 50],
      anchorXUnits: 'fraction',
      anchorYUnits: 'pixels',
      src: "img/station_0_1.png",
      scale: .4
    })
  })
})
layer通过 function (f) {return f.get('style')} 设置样式
3.feature不设置样式, layer通过属性设置样式
*/
map.addLayer(new ol.layer.VectorImage({
  title: 'siteLayer',
  source: tilerVectorSource,
  zIndex: 1,
  style: function (f) {
    return f.getStyle()
    // return f.get("style")
  }
  // style: new ol.style.Style({
  //   image: new ol.style.Icon({
  //     anchor: [0.5, 50],
  //     anchorXUnits: 'fraction',
  //     anchorYUnits: 'pixels',
  //     src: "img/station_0_1.png",
  //     scale: .4
  //   })
  // })
}));

添加Polygon多边形,并设置点的样式图片等(注释代码是多种可设置样式的方式)

// Polygon多边形
let pointArr1 = [[115.668,25.811],[115.746,25.769],[116.533,25.2],[116.621,25.123],[117.275,24.448],[117.348,24.357],[117.774,23.783],[118.125,23.127],[118.248,22.775],[118.351,22.478],[118.474,21.836],[118.501,21.2],[118.484,21.016],[118.441,20.57],[118.283,19.945],[118.041,19.401],[118.003,19.326],[117.563,18.713],[117.494,18.639],[116.912,18.16],[116.823,18.108],[116.311,17.839],[115.692,17.64],[115.059,17.544],[114.41,17.54],[113.744,17.629],[113.059,17.811],[112.349,18.111],[112.202,18.193],[111.605,18.563],[111.253,18.834],[110.807,19.246],[110.585,19.474],[110.063,20.115],[109.906,20.354],[109.646,20.758],[109.348,21.403],[109.155,22.05],[109.052,22.699],[109.049,23.35],[109.129,23.853],[109.156,24.002],[109.41,24.654],[109.583,24.939],[109.865,25.305],[110.144,25.594],[110.62,25.952],[110.757,26.04],[111.409,26.324],[112.089,26.484],[112.788,26.544],[113.505,26.513],[114.236,26.384],[114.982,26.146],[115.668,25.811]]
let pointArr2 = [[120.55,24.385],[120.657,24.325],[121.259,23.72],[121.417,23.41],[121.55,23.067],[121.547,22.425],[121.531,22.384],[121.135,21.792],[120.971,21.663],[120.35,21.51],[119.702,21.571],[119.106,21.825],[119.019,21.886],[118.542,22.475],[118.367,23.122],[118.498,23.769],[118.715,24.116],[119.032,24.412],[119.311,24.563],[119.966,24.596],[120.55,24.385]]
const corrds1 = [pointArr1]
const corrds2 = [pointArr2]

const sourcePolygon = new ol.source.Vector()   // 1.创建数据源
const layerPolygon = new ol.layer.Vector({     // 2.创建图层
  zIndex: 1,   // 图层的层级
  // style: {
  //   'fill-color': 'rgba(255, 0, 0, 0.3)',
  //   'stroke-color': 'rgba(255, 0, 0, 0.9)',
  //   'stroke-width': 1,
  // },

  // style: new ol.style.Style({
  //   stroke: new ol.style.Stroke({
  //     color: 'rgba(255, 0, 0, 0.9)',
  //     width: 1
  //   }),
  //   fill: new ol.style.Fill({
  //     color: 'rgba(255, 0, 0, 0.3)'
  //   })
  // }),

  style: function (f) {
    return f.getStyle()
  },
  title: 'beamLayer'
})
const featureCollection = new ol.Collection()
const polygon1 = new ol.geom.Polygon(corrds1)
polygon1.applyTransform(ol.proj.getTransform('EPSG:4326', 'EPSG:3857'));
const polygon2 = new ol.geom.Polygon(corrds2)
polygon2.applyTransform(ol.proj.getTransform('EPSG:4326', 'EPSG:3857'));

const feature1 = new ol.Feature({
  title: 'beam1',
  geometry: polygon1,
})
feature1.setStyle(new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: 'rgba(255, 0, 0, 0.9)',
    width: 1
  }),
  fill: new ol.style.Fill({
    color: 'rgba(255, 0, 0, 0.3)'
  })
}))
const feature2 = new ol.Feature({
  title: 'beam2',
  geometry: polygon2
})
feature2.setStyle(new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: 'rgba(255, 0, 0, 0.9)',
    width: 1
  }),
  fill: new ol.style.Fill({
    color: 'rgba(255, 0, 0, 0.3)'
  })
}))
featureCollection.push(feature1)
featureCollection.push(feature2)
sourcePolygon.addFeatures(featureCollection.getArray())
layerPolygon.setSource(sourcePolygon)  // 3.把数据源绑定到图层上面

map.addLayer(layerPolygon) // 4.图层通过addlayer添加到map对象上在界面显示

获取所有添加的layer图层,进行操作

*注:map.getPixelFromCoordinate 必须在map加载生成完毕后使用 否则会返回null

// 控制图标隐藏显示
map.getAllLayers().forEach(item => {
  // console.log(item)
  if (item.get('title') === 'siteLayer') {
    console.log(item.getSource().getFeatures())
    // console.log(item.getSource().getFeatures()[0].getStyle())
    item.getSource().getFeatures()[1].setStyle()
    
    // item.getSource().getFeatures()[1].setStyle(null)
    // item.getSource().getFeatures()[1].setGeometry(null)
    setTimeout(() => {
      // map.getPixelFromCoordinate 必须在map加载生成完毕后使用 否则会返回null
      console.log(map.getFeaturesAtPixel(map.getPixelFromCoordinate([118.344251, 32.015470])))
      
      // const { style, geometry } = showOneSite(0, 1, [118.344251, 32.015470])
      // item.getSource().getFeatures()[1].setStyle(style)
      // item.getSource().getFeatures()[1].setGeometry(geometry)
    }, 5000)
    // item.setVisible(false) // 根据状态显示隐藏可以使用setVisible方法
  }
  if (item.get('title') === 'beamLayer') {
    // console.log('----------')
    // console.log(item.getSource().getFeatures(), '1')
    // console.log(item.getSource().getFeatures()[0].get('title'))
    item.getSource().getFeatures()[0].setStyle()
  }
})

相比天地图api,openlayer的使用感觉功能更全面,api调用更方便,可扩展性更强,并且openlayer可以很方便的支持离线开发,离线图层等;因为自己使用cesium多处理的是3d界面数据显示,而openlayer使用不多并且是2d界面的数据展示。所以不好对比cesium,只是感觉openlayer的api调用更方便,cesium中Viewer类就是一切API的入口,代码过重。例如在cesium处理地图切换时监听事件代码如下:

viewer.sceneModePicker.viewModel.morphToColumbusView.beforeExecute.addEventListener(function(a) {
  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(105, 33, 10000000)
  });
});

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

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

相关文章

1575_AURIX_TC275_MTU简介以及部分寄存器

全部学习汇总&#xff1a; GitHub - GreyZhang/g_TC275: happy hacking for TC275! 从今天开始看一个全新的模块介绍MTU&#xff0c;存储测试单元。 TC275中所有的ECC、内置测试以及存储冗余等都有一个统一的接口规范。MTU负责管理所有的存储测试功能。MTU主要有两套寄存器&am…

【iOS】系统框架

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言熟悉系统框架多用块枚举&#xff0c;少用for循环for循环使用Objective-C 1.0的NSEnumerator遍历快速遍历基于块的遍历方式对自定义其内存管理语义的collection使…

Wechaty API 方法 文档整理

背景&#xff1a;刚使用wechaty的时候&#xff0c;对一个不熟悉初学者来说&#xff0c;看官方文档比较费时间&#xff0c;所以把方法和描述集合在一张表上&#xff0c;再使用的时候找对应的方法会比较直观。 中文文档&#xff1a; 介绍 - Wechatyhttps://wechaty.gitbook.io/…

【docker15】docker网络

1.docker网络是什么 docker不启动&#xff0c;默认网络情况 ens33lovirbr0 在CentOS7安装过程中&#xff0c;如果有选择相关虚拟化的服务安装系统后&#xff0c;启动网卡时会发现有一个网桥连接的私网地址的virbr0网卡&#xff08;virbr0网卡&#xff1a;它还有一个固定的默认…

【蓝桥杯】历届真题 魔方旋转问题(高职组) Java

问题描述 魔方可以对它的6个面自由旋转。   我们来操作一个2阶魔方&#xff0c;如图&#xff1a; 为了描述方便&#xff0c;我们为它建立了坐标系。   各个面的初始状态如下&#xff1a;   x轴正向&#xff1a;绿   x轴反向&#xff1a;蓝   y轴正向&#xff1a;红  …

Hudi系列8:Hudi集成Flink

文章目录一. 相关配置1.1 拷贝编译好的jar包到Flink的lib目录1.2 拷贝guava包&#xff0c;解决依赖冲突1.3 配置环境变量二. YARN Session模式下启动Flink SQL2.1 解决依赖问题2.2 启动yarn-session2.3 在yarn session模式下启动flink sql三. 测试四. 异常问题汇总一. 相关配置…

荣誉+1,龙蜥社区荣登 CSDN 2022 中国开发者影响力年度榜单

近日&#xff0c;CSDN 在北京成功举行 “2022 中国开发者影响力盛典暨 CSDN 企业生态汇”活动&#xff0c;同时正式发布 2022 中国开发者影响力年度榜单。凭借本年度在开源领域的卓越贡献和技术实力&#xff0c;龙蜥社区荣登 CSDN 2022 “年度开发者社区” 榜单。&#xff08;图…

python基础篇之文件操作

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a;lqj_本人的博客_CSDN博客-微信小程序,前端,vue领域博主lqj_本人擅长微信小程序,前端,vue,等方面的知识https://blog.csdn.net/lbcyllqj?spm1000.2115.3001.5343 哔哩哔哩欢迎关注&…

Why Can GPT Learn In-Context?

Why Can GPT Learn In-Context? Language Models Secretly Perform Gradient Descent as Meta-Optimizers 为什么GPT能够在In-context的环境中进行学习呢&#xff1f;Language Models能够像Meta-Optimizer一样秘密地执行梯度下降。 这篇文章的作者来自清华、北大&#xff0c;代…

Silane-PEG-COOH,硅烷-聚乙二醇-羧基结构式及相关应用介绍

英文名称&#xff1a;Silane-PEG-acid&#xff1b;Silane-PEG-COOH 中文名称&#xff1a;硅烷-聚乙二醇-羧基 分子量&#xff1a;1k&#xff0c;2k&#xff0c;3.4k&#xff0c;5k&#xff0c;10k&#xff0c;20k。。。 存储条件&#xff1a;-20C&#xff0c;避光&#xff0…

AI入门| 机器学习和深度学习傻傻分不清?

&#xff08;本文阅读时间&#xff1a;5分钟&#xff09;目前&#xff0c;人工智能主流的支持技术是机器学习和深度学习。二者有什么异同呢&#xff1f;文末为你揭晓&#xff01;在了解机器是怎么学习之前&#xff0c;我们先来回顾一下人类自己的学习过程。人类是如何学习的&am…

二叉树的基本操作

目录 一、二叉树遍历 1、前序遍历&#xff1a; 动态图解析&#xff1a; 2、中序遍历&#xff1a; 3、后序遍历&#xff1a; 4、层序遍历 &#xff08;利用队列&#xff09; 动态图解析&#xff1a; 二、统计二叉树的节点个数&#xff1a; 1、二叉树总节点…

【OpenAI】基于 Gym-CarRacing 的自动驾驶项目 | 车道检测功能的实现 | 边缘检测与分配 | 样条拟合

限时开放&#xff0c;猛戳订阅&#xff01; &#x1f449; 《一起玩蛇》&#x1f40d; &#x1f4ad; 写在前面&#xff1a; 本篇是关于多伦多大学自动驾驶专业项目的博客。GYM-Box2D CarRacing 是一种在 OpenAI Gym 平台上开发和比较强化学习算法的模拟环境。它是流行的 Box2D…

【High 翻天】Higer-order Networks with Battiston Federico (7)

目录传播与社会动力学&#xff08;1&#xff09;传播simplicial complexeshypergraphs传播与社会动力学&#xff08;1&#xff09; 模拟人类行为的动态过程一直是许多研究的焦点&#xff0c;其中社会关系和交互通常被认为是一种潜在结构&#xff0c;是高阶方法的天然试验场。 …

广告业务系统 之 框架沉淀 —— “数据消费型服务框架”

文章目录广告业务系统 之 框架沉淀 —— “数据消费型服务框架”数据消费型服务统一框架主流程Plugin 构建广告业务系统 之 框架沉淀 —— “数据消费型服务框架” 数据消费型服务统一框架 由于 ADX 系统中&#xff0c;大量数据以流式涌动&#xff0c;整个链路中出现了 “多处…

MMCME4_ADV与PLL4_ADV原语

MMCM与PLL ​ UltraScale器件中时钟管理模块(CMT)包含mixed-mode clock manager (MMCM) 和phase-locked loops (PLLs) 。PLL主要用来生成I/O时钟&#xff0c;也包含一部分MMCM的功能。 ​ 其中MMCM输出时钟相位调整语VCO频率相关。 MMCME4_ADV原语 ​ MMCM原语包含MMCME3_B…

2023年最新版Java入门教程,一套很哇塞的Java基础课

所谓天道好轮回&#xff0c;鬼畜饶过谁。最近B站学习区也沦陷了&#xff0c;由此诞生出了一种让人闻所未闻的冷概念&#xff1a;鬼畜教学法!这种奇怪的组合让人匪夷所思&#xff0c;但架不住网友们的推荐!!!爱嘤嘤嘤斯坦&#xff1a;早看到这些视频&#xff0c;妈妈就再也不用担…

东南亚跨境电商迅猛发展,商机转瞬即逝!

2022年中国跨境电商进入了转型调整期&#xff0c;前几年高歌猛进的发展势头似乎有所减弱。回顾2022年&#xff0c;跨境电商卖家们都表示心情复杂&#xff0c;过去一年&#xff0c;卖家们经历许多大事件&#xff0c;比如9月份拼多多强势推出Temu奔向北美市场&#xff0c;10月份字…

Linux权限和粘滞位

目录 一.权限概念 二.用户分类 三.文件权限 1.执行操作的人的分类 2.文件类型和访问权限&#xff08;事物属性&#xff09; 03.文件权限值的表示方法 四.目录权限与粘滞位 一.权限概念 操作系统用来限制对资源访问的机制&#xff0c;一件事情是否可以被“谁”做&#x…

【观察】浪潮信息龙蜥联合实验室:打造下一代操作系统,筑牢基础软件创新根基...

毫无疑问&#xff0c;在当今世界日益复杂的竞争环境下&#xff0c;随着中国企业数字化转型的加速和自主创新进程的加快&#xff0c;再加上开源和云计算已成为行业发展的大趋势之下&#xff0c;如何在“变局中开新局”&#xff1f;如何解决中国在核心基础软件领域面临的各种挑战…