草庐IT

【GIS开发】OpenLayers入门学习(JavaScript库)

爱看书的小沐 2023-03-28 原文

1、简介

官网地址: https://openlayers.org/ 源码地址: https://github.com/openlayers/openlayers

OpenLayers是一个高性能、功能丰富的库,用于在 Web 上创建交互式地图。它可以在任何网页上显示从任何来源加载的地图瓦片、矢量数据和标记。OpenLayers 的开发旨在进一步使用各种地理信息。它是完全免费的开源 JavaScript,在BSD 2-Clause License下发布。

OpenLayers is a high-performance, feature-packed library for creating interactive maps on the web. It can display map tiles, vector data and markers loaded from any source on any web page. OpenLayers has been developed to further the use of geographic information of all kinds. It is completely free, Open Source JavaScript, released under the BSD 2-Clause License.

OpenLayers 在所有支持HTML5和ECMAScript 5的现代浏览器上运行。这包括 Chrome、Firefox、Safari 和 Edge。对于较旧的浏览器和平台(Internet Explorer、Android 4.x、iOS v12 和更早版本、Safari v12 和更早版本),以下浏览器功能可能需要 polyfill。

支持平铺层:从OSM,Bing,MapBox,Stamen和您可以找到的任何其他XYZ源中拉出图块。还支持OGC映射服务和分层图层。 支持矢量层:渲染来自GeoJSON,TopoJSON,KML,GML,Mapbox矢量图块和其他格式的矢量数据。

  • 平铺层 从 OSM、Bing、MapBox、Stamen 和您可以找到的任何其他 XYZ 源中提取图块。还支持 OGC 映射服务和直到层。

  • 矢量图层 渲染来自 GeoJSON、TopoJSON、KML、GML、Mapbox 矢量切片和其他格式的矢量数据。

  • 尖端、快速和移动就绪 利用 Canvas 2D、WebGL 和 HTML5 的所有最新优势。开箱即用的移动支持。仅使用您需要的组件构建轻量级自定义配置文件。

  • 易于定制和扩展 使用简单的 CSS 设置地图控件的样式。连接到不同级别的 API 或使用3rd 方库来自定义和扩展功能。

2、快速入门

<font color=blue>github网页上显示当前OpenLayers库的最新版本是6.13.0。

2.1 在线库快速入门

我们打开vscode,将如下代码复制进去,保存为一个新的.html文件(Untitled-1.html)。然后可以直接在浏览器里运行查看结果。

相关代码可以参考官网的代码: https://openlayers.org/en/latest/doc/quickstart.html

Untitled-1.html:

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css" type="text/css"> <style> .map { height: 45rem; width: 100%; } </style> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script> <title>OpenLayers example</title> </head> <body> <h2>爱看书的小沐的地图</h2> <div id="map" class="map"></div> <script type="text/javascript"> var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([104.1, 30.6]), zoom: 10 }) }); </script> </body> </html> <font color=blue>注意: 以下两行代码说明了上面的测试用例中使用的是在线访问的OpenLayers功能库文件(ol.css和ol.js)以及它的版本号。当然为了优化加载速度,我们也可以将它下载到本地或自己建设的服务器里,再引用,请查看下一小节《本地库快速入门》的说明。

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css" type="text/css"> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>

2.2 本地库快速入门

官网下载地址: https://openlayers.org/download/ 将文件解压到本地,ol.css和ol.js在文件夹内。 新建一个文件Untitled-2.html:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Simple Map</title> <link rel="stylesheet" href="../v6.13.0-dist/ol.css" /> <script src="../v6.13.0-dist/ol.js"></script> <style> #map { height: 400px; width: 100%; } </style> </head> <body> <div id="map"></div> <script> let map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ projection: 'EPSG:4326', center: [104.1, 30.6], zoom: 11 }) }); </script> </body> </html>

2.3 nodejs快速入门

官网地址: https://nodejs.org/en/

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时。 Node.js 是一个开源和跨平台的 JavaScript 运行时环境。 它几乎是任何类型项目的流行工具! Node.js 在浏览器之外运行 V8 JavaScript 引擎(Google Chrome 的内核)。 这使得 Node.js 的性能非常好。

下面我们开始安装nodejs开发环境。 新建一个测试文件夹,在里面下载nodejs环境里的OpenLayers库(node_modules)。

cd C:\Users\tomcat mkdir test cd test npm init npm install ol npm install --save-dev parcel-bundler openlayers库安装完之后的文件夹如下图所示: 在测试主文件夹“C:\Users\tomcat\Desktop\test”里新建文件“index.js”:

//index.js import 'ol/ol.css'; import {Map ,View} from 'ol'; import TileLayer from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; const map = new Map({ target:'map', layers:[ new TileLayer({ source:new OSM() }) ], view:new View({ center:[0,0], zoom:0 }) }); 在测试主文件夹“C:\Users\tomcat\Desktop\test”里新建文件“index.html”:

<!--index.html--> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Using Parcel with OpenLayers</title> <style> #map{ width: 100%; height: 250px; } </style> </head> <body> <div id="map"></div> <script src="./index.js"></script> </body> </html> 修改文件package.json的内容中script子项如下:

{ "name": "test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start":"parcel index.html", "build":"parcel build --public-url . index.html" }, "author": "", "license": "ISC", "dependencies": { "ol": "^6.13.0" }, "devDependencies": { "parcel-bundler": "^1.12.5" } } 或者

{ "name": "mapbox-vector-tiles-advanced", "dependencies": { "ol": "6.13.0" }, "devDependencies": { "parcel": "^2.0.0" }, "scripts": { "start": "parcel index.html", "build": "parcel build --public-url . index.html" } } 执行如下命令进行打包操作,这样打包后可以将dist文件夹复制到服务器中。

npm run build

执行如下命令进行开启临时web服务器功能,浏览器通过网址可以访问网页内容操作。(按快捷键ctrl+c可停止运行应用)

npm start

2.4 vue快速入门

http://vuejs-templates.github.io/webpack/

To use this template, scaffold a project with vue-cli. It is recommended to use npm 3+ for a more efficient dependency tree.

$ npm install -g vue-cli $ vue init webpack my-project $ cd my-project $ npm install $ npm run dev 由于 npm 安装速度慢,本教程使用了淘宝的镜像及其命令 cnpm。

# 查看版本 $ npm -v # 升级或安装 cnpm npm install cnpm -g 或 npm install -g cnpm --registry=https://registry.npm.taobao.org # 查看cnpm版本命令查看是否安装成功 cnpm -v # 更换包管理器 npm config set registry https://registry.npm.taobao.org # 检测cnpm是否成功替换npm npm config get registry Vue.js 提供一个官方命令行工具,可用于快速搭建大型单页应用。

# 全局安装 vue-cli $ cnpm install --global vue-cli

# 创建用户测试文件夹 $ cd C:\Users\tomcat\Desktop $ md test3 $ cd test3 # 创建一个基于 webpack 模板的新项目 $ vue init webpack my-project # 这里需要进行一些配置,默认回车即可

$ cd my-project $ cnpm install $ cnpm run dev 然后在浏览器中输入网址:

http://localhost:8080 用VSCode打开刚刚创建的项目,打开文件夹my-project(或者直接拖拽文件夹到VsCode也可以) 在左边的文件树上的components鼠标右键新建文件“MapView.vue”,它的代码如下:

<template> <div id="mapDiv"></div> </template> <script> import "ol/ol.css"; import { Map, View } from "ol"; import TileLayer from "ol/layer/Tile"; import OSM from "ol/source/OSM"; import {fromLonLat} from 'ol/proj'; export default { mounted() { const map = new Map({ target: "mapDiv", layers: [ new TileLayer({ source: new OSM(), }), ], view: new View({ center: fromLonLat([114.41, 32.82]), zoom: 9, }), }); }, }; </script> <style scoped> #mapDiv { width: 100%; height: 100%; } </style> App.vue文件的代码如下:

<template> <div id="app"> <img src="./assets/logo.png"> <HelloWorld/> <MapView/> </div> </template> <script> import HelloWorld from './components/HelloWorld' import MapView from './components/MapView' export default { name: 'App', components: { HelloWorld, MapView } } </script> <style> html,body{ padding: 0; margin: 0; width: 100%; height: 100%; } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 40px; width: 100%; height: 100%; } </style> 在VSCode的NPM Script窗口中,点击dev那一行后面的三角形按钮,编译运行项目,或者直接按下快捷键Ctrl+S也可以。 然后在浏览器中输入网址:

http://localhost:8081

2.5 python快速入门

pip install django==3.0.6 -i https://pypi.tuna.tsinghua.edu.cn/simple

django-admin

django-admin startproject HelloWorld

cd C:\Users\tomcat\HelloWorld python manage.py runserver 0.0.0.0:5000 在浏览器输入:

http://127.0.0.1:5000/ 修改如下的文件的内容:

  • urls.py:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.sayHello), url(r'^gethtml$', views.gethtml), ]
  • views.py:
from django.http import HttpResponse from django.shortcuts import render import datetime def hello(request): return HttpResponse("Hello world ! 2022") def sayHello(request): s = 'Hello World!' current_time = datetime.datetime.now() html = '<html><head></head><body> %s <p> %s </p></body></html>' % (s, current_time) return HttpResponse(html) def gethtml(request): return render(request, 'ol.html')
  • settings.py: 修改其中的TEMPLATES的子项DIRS的内容如下:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
  • 放置自己编辑的的openlayers文件ol.html
新建文件夹templates,并在里面放置自己的openlayers网页文件ol.html。 ol.html:

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css" type="text/css"> <style> .map { height: 45rem; width: 100%; } </style> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script> <title>OpenLayers example</title> </head> <body> <h2>爱看书的小沐的地图</h2> <div id="map" class="map"></div> <script type="text/javascript"> var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([104.1, 30.6]), zoom: 10 }) }); </script> </body> </html>
  • 在浏览器输入:
http://127.0.0.1:5000/

http://127.0.0.1:5000/gethtml

3、基本概念

在页面上放置地图,您将在下面找到一个完整的工作示例。创建一个新文件,复制下面的内容,然后在浏览器中打开:

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css" type="text/css"> <style> .map { height: 400px; width: 100%; } </style> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script> <title>OpenLayers example</title> </head> <body> <h2>My Map</h2> <div id="map" class="map"></div> <script type="text/javascript"> var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 4 }) }); </script> </body> </html> 或者 一个更简单代码片段脚本,用一个瓦片层渲染地图,如下所示:

import Map from 'ol/Map'; import View from 'ol/View'; import OSM from 'ol/source/OSM'; import TileLayer from 'ol/layer/Tile'; new Map({ layers: [ new TileLayer({source: new OSM()}) ], view: new View({ center: [0, 0], zoom: 2 }), target: 'map' });

3.1 ol.map

OpenLayers 的核心组件是地图 ( ol/Map)。它被渲染到一个target容器(例如div网页上包含地图的元素)。所有地图属性都可以在构建时进行配置,也可以使用 setter 方法进行配置,例如setTarget().

下面的标记可用于创建div包含您的地图的标记。

<div id="map" style="width: 100%, height: 400px"></div> <style> #map { height: 100%; width: 100%; position: absolute; } </style> <style> #map { height: 400px; width: 100%; } #map .ol-zoom-in, #map .ol-zoom-out { background-color: white; color: black; } #map .ol-zoom-extent button { color: blue; } #map .ol-zoomslider { background-color: gray; } #map .ol-zoomslider button{ background-color: black; } </style> 下面的脚本使用元素的 id 作为选择器来构造一个在div上面渲染的地图map。

import Map from 'ol/Map'; var map = new Map({target: 'map'});

3.2 ol.view

视图。它主要就是控制地图显示的位置以及层级等功能。地图不负责地图的中心、缩放级别和投影等事项。相反,这些是ol/View实例的属性。

import View from 'ol/View'; map.setView(new View({ center: [0, 0], zoom: 2 })); A View also has a projection. The projection determines the coordinate system of the center and the units for map resolution calculations. If not specified (like in the above snippet), the default projection is Spherical Mercator (EPSG:3857), with meters as map units.

The zoom option is a convenient way to specify the map resolution. The available zoom levels are determined by maxZoom (default: 28), zoomFactor (default: 2) and maxResolution (default is calculated in such a way that the projection's validity extent fits in a 256x256 pixel tile). Starting at zoom level 0 with a resolution of maxResolution units per pixel, subsequent zoom levels are calculated by dividing the previous zoom level's resolution by zoomFactor, until zoom level maxZoom is reached.

// 创建墨卡托投影坐标系 const projection = get("EPSG:3857"); const view = new View({ center: fromLonLat([105.14805, 35.26971]), projection: projection, zoom: 5, maxZoom: 14, minZoom: 4 }); const projection = get("EPSG:3857"); const view = new View({ // 设置成都为地图中心 center: [104.06, 30.67], // 指定投影使用EPSG:4326一个等同于WGS84坐标系 projection: 'EPSG:4326', // 投影确定center用于地图分辨率计算的单位和单位的坐标系 zoom: 0, }); view: new ol.View({ center: [13380880,3535823],// 设置地图中心坐标点 zoom: 8, // 设置初始化显示层级 minZoom: 7, // 最小显示层级 maxZoom: 14 // 最大显示层级 }) this.map.setView(new ol.View({ center: [114.064839,22.548857], //深圳 zoom: 15, projection: 'EPSG:4326' //使用的坐标,这里是 WGS84 坐标系 })) view: new ol.View({ center: ol.proj.transform([104, 30], 'EPSG:4326', 'EPSG:3857'), zoom: 10 }), 默认 是Web Mercator的 EPSG:3857 坐标系(伪墨卡托投影,也被称为球体墨卡托),所以我们可以不写。但是我们用到的 center 数据值格式 是 EPSG:4326格式(常见的数据源),所以我们需要使用 fromLonLat() 方法把 EPSG:4326格式数据转换为 EPSG:3857 数据格式。 (1)EPSG:3857(投影):数据的可读性差和数值大存储比较占用内存。 (2)EPSG:4326(地理):使用此坐标系会导致页面变形。

let view = new View({ // projection: "EPSG:3857", //使用这个坐标系,默认为 3857,可以不写 center: fromLonLat([104.912777, 34.730746]), // 数据格式4326转为3857 zoom: 6.5 //缩放级别 });

3.3 ol.layer

图层。在openlayers中针对不同业务有着多种多样的图层类提供,而ol.layer相当于一个管理者,有效处理地图数据来源的多样性和复杂性问题。

图层是来自source. OpenLayers 有四种基本类型的层:

  • ol/layer/Tile- 渲染在按特定分辨率的缩放级别组织的网格中提供平铺图像的源。
  • ol/layer/Image- 渲染以任意范围和分辨率提供地图图像的源。
  • ol/layer/Vector- 在客户端渲染矢量数据。
  • ol/layer/VectorTile- 渲染作为矢量图块提供的数据。
import TileLayer from 'ol/layer/Tile'; var osmLayer = new TileLayer({source: osmSource}); map.addLayer(osmLayer);

3.4 ol.source

数据源。它是整个地图背后的核心部分,如果没有数据,地图是渲染不出来。它与图层一一对应,针对不同的图层也会有不同的数据来源。

openlayers 默认使用的墨卡托投影坐标系,当然我们也是可以使用 WGS84 坐标系的。

为了获取层的远程数据,OpenLayers 使用ol/source/Source子类。这些可用于 OpenStreetMap 或 Bing 等免费和商业地图图块服务、WMS 或 WMTS 等 OGC 源,以及 GeoJSON 或 KML 等格式的矢量数据。

import OSM from 'ol/source/OSM'; var osmSource = OSM();

3.5 ol.control

控件。

3.6 ol.interaction

交互。

4、ol.source分析

4.1 OpenStreetMap

var map = new ol.Map({ target: 'map', layers: [], // 创建图层容器,但不添加图层数据 view: new ol.View({ center: [0, 0], //center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 2, }) }); var tileLayer = new ol.layer.Tile({ source: new ol.source.OSM(), }); // 创建图层数据 map.addLayer(tileLayer); // 图层添加至地图 或者

var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: [0, 0], //center: [13380880,3535823],// 设置地图中心坐标点 zoom: 2, maxZoom: 14, minZoom: 0 }), }) 或者

// 使用内置的OSM const tileLayer = new TileLayer({ source: new OSM() }) map.addLayer(tileLayer );

4.2 Thunderforest

https://openlayers.org/en/latest/examples/xyz.html

https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=<insert-your-apikey-here> const tileLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: "https://{a-c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=a5dd6a2f1c934394bce6b0fb077203eb", attributions: "test" }) }); map.addLayer(tileLayer);

4.3 ArcGIS

https://openlayers.org/en/latest/examples/vector-esri.html

const raster = new ol.layer.Tile({ source: new ol.source.XYZ({ attributions: 'Tiles © <a rel="nofollow" href="https://services.arcgisonline.com/ArcGIS/' + 'rest/services/World_Topo_Map/MapServer">ArcGIS</a>', url: 'https://server.arcgisonline.com/ArcGIS/rest/services/' + 'World_Topo_Map/MapServer/tile/{z}/{y}/{x}', }), }); map.addLayer(raster); const arcgisLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}' }) })

4.4 Bing

https://openlayers.org/en/latest/examples/bing-maps.html

const raster_bing = new ol.layer.Tile({ visible: true, preload: Infinity, source: new ol.source.BingMaps({ key: 'Your Bing Maps Key from https://www.bingmapsportal.com/ here', imagerySet: 'RoadOnDemand', // use maxZoom 19 to see stretched tiles instead of the BingMaps // "no photos at this zoom level" tiles // maxZoom: 19 }), }) map.addLayer(raster_bing);

4.5 Stamen

// https://stamen.com/ const map = new Map({ layers: [ new TileLayer({ source: new Stamen({ layer: 'watercolor', }), }), new TileLayer({ source: new Stamen({ layer: 'terrain-labels', }), }), ], target: 'map', view: new View({ center: fromLonLat([-122.416667, 37.783333]), zoom: 12, }), });

4.6 高德地图

const tileLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}' }) }) map.addLayer(tileLayer);

4.7 天地图

TiandituKey = "***********************"; var cityPos = ol.proj.fromLonLat([116.28, 39.54]); //实例化Map对象加载地图,默认底图加载天地图 var map = new ol.Map({ layers: [ new ol.layer.Tile({ title: "天地图矢量图层", source: new ol.source.XYZ({ url: "http://t0.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=" + TiandituKey,//parent.TiandituKey()为天地图密钥 wrapX: false }) }), new ol.layer.Tile({ title: "天地图矢量注记图层", source: new ol.source.XYZ({ url: "http://t0.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=" + TiandituKey,//parent.TiandituKey()为天地图密钥 wrapX: false }) }) ], //地图容器div的ID target: 'mapCon', view: new ol.View({ //地图初始中心点 center: cityPos, minZoom: 1, zoom: 6 }) });

4.8 自定义

// 创建基础矢量图层 const baseLayer = new TileLayer({ source: new TileWMS({ url: 'http://127.0.0.1:8080/services/Map/MapService/WMS', params: {LAYERS: 'Map', CRS: projection}, projection: projection }) }); const map = new Map({ layers: [baseLayer], target: "sceneControlDiv", view: view, overlays: [popup], controls: [] });

5、ol.control分析

5.1 全屏

var fullScreen = new ol.control.FullScreen(); let map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ projection: 'EPSG:4326', center: [104.1, 30.6], zoom: 11 }), controls: ol.control.defaults().extend([fullScreen]), }); 主要是通过上面的两行代码实现全屏功能: <font color=blue>var fullScreen = new ol.control.FullScreen(); controls: ol.control.defaults().extend([fullScreen]),

5.2 比例尺

let map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ projection: 'EPSG:4326', center: [104.1, 30.6], zoom: 11 }), controls: ol.control.defaults().extend([ new ol.control.FullScreen(), new ol.control.MousePosition(), new ol.control.OverviewMap(), new ol.control.ScaleLine(), new ol.control.ZoomSlider(), new ol.control.ZoomToExtent() ]), });

5.3 鹰眼

// 创建鹰眼控件 let overviewMapControl = new ol.control.OverviewMap({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ] }); let map = new ol.Map({ target: 'map', layers: [...], view: ..., controls: ol.control.defaults().extend([ // 添加鹰眼控件 overviewMapControl ]) });

5.4 框选

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="../v6.13.0-dist/ol.css" /> <script src="../v6.13.0-dist/ol.js"></script> <script src="http://lib.sinaapp.com/js/jquery/2.2.4/jquery-2.2.4.min.js"></script> <style type="text/css"> body, html { width: 100%; height: 100%; } #map, #info { width: 100%; height: 80%; } </style> </head> <body> <div id="map"></div> <div id="info"> <table> <tr> <td>左上角:</td> <td>经度:<input id="lon1" readonly=“readonly”/>纬度:<input id="lat1" readonly=“readonly”/></td> </tr> <tr> <td>右下角:</td> <td>经度:<input id="lon2" readonly=“readonly”/>纬度:<input id="lat2" readonly=“readonly”/></td> </tr> <tr><button id="btnclick" onclick="clickHandler()">开始框选</button></tr> </table> </div> <script> var style = new ol.style.Style({ fill: new ol.style.Fill({ color: 'rgba(96,96,96, 0.3)' }), stroke: new ol.style.Stroke({ color: 'rgba(96,96,96, 0.3)', width: 2 }), image: new ol.style.Circle({ radius: 5, stroke: new ol.style.Stroke({ color: 'rgba(96,96,96, 0.3)' }), fill: new ol.style.Fill({ color: 'rgba(96,96,96, 0.3)' }) }) }); map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.transform([104.1, 30.6], 'EPSG:4326', 'EPSG:3857'), zoom: 9 }) }); var layer = new ol.layer.Vector({ source: new ol.source.Vector(), style: style }); var draw = new ol.interaction.Draw({ source: layer.getSource(), type: 'Circle', style: style, geometryFunction: ol.interaction.Draw.createBox() }); function clickHandler(e1) { $('#map').bind("click", function (e) { var pointermove = $('#map').bind("pointermove", function (e2) { var coordinate = ol.proj.transform(map.getEventCoordinate(e2), 'EPSG:3857', 'EPSG:4326'); $("#lon2").attr("value", coordinate[0].toFixed(6)); $("#lat2").attr("value", coordinate[1].toFixed(6)); }).bind("click", function () { $("#map").off('pointermove'); $("#map").off('click'); }); if ($("#lon1").val() == "" && $("#lat1").val() == "") { var coordinate = ol.proj.transform(map.getEventCoordinate(e), 'EPSG:3857', 'EPSG:4326'); $("#lon1").attr("value", coordinate[0].toFixed(6)); $("#lat1").attr("value", coordinate[1].toFixed(6)); } }); if ("取消框选" == ($("#btnclick").text())) { $("#btnclick").text("开始框选"); $("input").attr("value", ""); layer.getSource().clear(); map.removeLayer(layer); } else { $("#btnclick").text("取消框选"); map.addInteraction(draw); } } draw.on('drawend', function () { map.addLayer(layer); map.removeInteraction(draw); }); </script> </body> </html>

6、其他

6.1 加载本地瓦片数据

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>本地瓦片数据测试</title> <link rel="stylesheet" href="../v6.13.0-dist/ol.css" /> <style> #map { width: 100%; height: 400px; } #myposition, #myproj { float: left; position: relative; bottom: 0px; width: 400px; height: 10px; z-index: 1000; } .mousePosition { color: red; font-size: 20px; } </style> <script src="../v6.13.0-dist/ol.js"></script> </head> <body> <div id="map"> </div> <div id="myposition"></div> <form id='myproj'> <label>Projection</label> <select id="projection"> <option value="EPSG:4326">EPSG:4326</option> <option value="EPSG:3857">EPSG:3857</option> </select> <label>Precision</label> <input id="precision" type="number" min="0" max="12" value="6" /> </form> <script type="text/javascript"> // 选取投影的控件 var projectionSelect = document.getElementById("projection"); projectionSelect.addEventListener('change', function (event) { // 使mousePositionControl控件的投影与选取投影控件选取的投影一致 mousePositionControl.setProjection(event.target.value); }); var precisionInput = document.getElementById('precision'); precisionInput.addEventListener('change', function (event) { // 设置mousePositionControl控件的坐标格式 var format = ol.coordinate.createStringXY(event.target.valueAsNumber); mousePositionControl.setCoordinateFormat(format); }); //定义坐标系 let projParam = 'EPSG:4326' //EPSG:3857 //定义鼠标位置控件对象 var mousePositionControl = new ol.control.MousePosition({ className: 'mousePosition', coordinateFormat: ol.coordinate.createStringXY(6), projection: 'EPSG:4326', target: document.getElementById('myposition'), undefinedHTML: '&nbsp;' }); //标准TMS切片加载方式 var offlineSource = new ol.source.XYZ({ tileUrlFunction: function (coordinate) { console.log(coordinate[0], coordinate[1], coordinate[2]); var z = coordinate[0]; var x = coordinate[1]; var y = Math.pow(2, z - 1) + coordinate[2]; return "file:///D:/maps/" + z + "/" + x + "/" + y + ".png"; }, maxZoom: 19, minZoom: 0, projection: projParam }); //定义图层:地图 var offlineMapLayer = new ol.layer.Tile({ source: offlineSource }); //定义图层:瓦片网格线 var tileGridLayer = new ol.layer.Tile({ source: new ol.source.TileDebug({ projection: projParam, tileGrid: offlineSource.getTileGrid(), }) }); //定义地图对象 var map = new ol.Map({ view: new ol.View({ center: [104.1, 30.6], projection: projParam, zoom: 7 }), controls: ol.control.defaults().extend([mousePositionControl]), target: 'map', layers: [], }); //将两个图层添加到地图对象里 map.addLayer(offlineMapLayer); map.addLayer(tileGridLayer); </script> </body> </html> 本地瓦片数据: 浏览器显示加载:

6.2 加载geojson文件

nodejs搭建服务器,加载如下网页。

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css" type="text/css"> <style> .map { height: 45rem; width: 100%; } </style> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script> <title>OpenLayers example</title> </head> <body> <h2>爱看书的小沐的地图</h2> <div id="map" class="map"></div> <script type="text/javascript"> var pointGeoJsonLayer = new ol.layer.Vector({ title: 'points', source: new ol.source.Vector({ projection: 'EPSG:4326', url: 'http://localhost:9000/china.json', format: new ol.format.GeoJSON() }) }); var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), pointGeoJsonLayer ], view: new ol.View({ center: ol.proj.fromLonLat([104.1, 21.6]), zoom: 3 }) }); </script> </body> </html> china.json:

6.3 路径动画

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css" type="text/css"> <style> .map { height: 45rem; width: 100%; } </style> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.min.js"></script> <title>OpenLayers example</title> </head> <body> <h2>爱看书的小沐的地图</h2> <div id="map" class="map"></div> <button id="btnStart">显示轨迹</button> <script type="text/javascript"> //生成随机轨迹点 var points = [ [114.1, 22.6] ]; var x = 114.1; var y = 22.6; for (i = 0; i < 100; i++) { var flag = 1; if (Math.random() < 0.5) flag = -1; x += Math.floor(Math.random() * 10) * 0.005; y += Math.floor(Math.random() * 10) * 0.02 * flag; points.push([x, y]) } // 创建文字图层 var createLabelStyle = function (feature) { return new ol.style.Style({ text: new ol.style.Text({ //位置 textAlign: 'center', //基准线 textBaseline: 'middle', //文字样式 font: 'normal 14px arial', //文本内容 text: feature.get('name'), //文本填充样式(即文字颜色) fill: new ol.style.Fill({ color: '#000000' }), stroke: new ol.style.Stroke({ color: '#ffcc33', width: 12 }) }) }); } var iconFeature = new ol.Feature({ }); iconFeature.setStyle(createLabelStyle(iconFeature)); //矢量标注的数据源 var vectorSource = new ol.source.Vector({ features: [iconFeature] }); //矢量标注图层 var textLayer = new ol.layer.Vector({ source: vectorSource }); //map.addLayer(textLayer); // 创建瓦片图层 var tileLayer = new ol.layer.Tile({ source: new ol.source.OSM() }); // 创建轨迹点图层 var markerLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: new ol.style.Style({ image: new ol.style.Circle({ radius: 10, fill: new ol.style.Fill({ color: 'red' }) }) }) }); // 创建轨迹线图层 var lineLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: new ol.style.Style({ stroke: new ol.style.Stroke({ width: 3, color: 'blue' }) }) }); var map = new ol.Map({ target: 'map', layers: [ tileLayer, lineLayer, markerLayer, textLayer ], view: new ol.View({ center: [114.064839, 22.548857], zoom: 8, projection: 'EPSG:4326' }) }); var timer1; var index = 0; $('#btnStart').click(function () { // 清除定时器 if (timer1 != undefined) { clearInterval(timer1); } // 清空要素图层 markerLayer.getSource().clear(); lineLayer.getSource().clear(); index = 0; // 绘制轨迹线 if (points.length > 1) { var lineFeature = new ol.Feature({ geometry: new ol.geom.LineString(points) }); lineLayer.getSource().addFeature(lineFeature); } // 创建定时器 timer1 = setInterval(function () { if (index < points.length) { var currentPoint = points[index]; //绘制点数据 markerLayer.getSource().clear(); markerFeature = new ol.Feature({ geometry: new ol.geom.Point(currentPoint) }); markerLayer.getSource().addFeature(markerFeature); //绘制文字数据 var inputText = currentPoint[0].toFixed(3).toString() + ", "+ currentPoint[1].toFixed(3).toString(); vectorSource.clear(); var newFeature = new ol.Feature({ geometry: new ol.geom.Point(currentPoint), name: inputText === "" ? '标注点' : inputText }); newFeature.setStyle(createLabelStyle(newFeature)); vectorSource.addFeature(newFeature); index++; } else { clearInterval(timer1); index = 0; } }, 100); }); </script> </body> </html>

后记

如果你觉得该方法或代码有一点点用处,可以给作者点个赞、赏杯咖啡;╮( ̄▽ ̄)╭ 如果你感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O??? 谢谢各位童鞋们啦( ´ ▽´ )ノ ( ´ ▽´)っ!!!

有关【GIS开发】OpenLayers入门学习(JavaScript库)的更多相关文章

  1. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  2. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  3. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  5. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  9. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  10. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

随机推荐