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矢量图块和其他格式的矢量数据。
<!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>
将文件解压到本地,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>
新建一个测试文件夹,在里面下载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
$ 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
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/
修改如下的文件的内容:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.sayHello),
url(r'^gethtml$', views.gethtml),
]
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')
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',
],
},
},
]
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
<!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'
});
<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'});
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 //缩放级别
});
import TileLayer from 'ol/layer/Tile';
var osmLayer = new TileLayer({source: osmSource});
map.addLayer(osmLayer);
import OSM from 'ol/source/OSM';
var osmSource = OSM();
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 );
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);
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}'
})
})
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);
// 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,
}),
});
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);
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
})
});
// 创建基础矢量图层
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: []
});
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]),
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()
]),
});
// 创建鹰眼控件
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
])
});
<!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>
<!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: ' '
});
//标准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>
本地瓦片数据:
浏览器显示加载:
<!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:
<!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??? 谢谢各位童鞋们啦( ´ ▽´ )ノ ( ´ ▽´)っ!!!
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩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
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
最近在学习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总线个人知识总
深度学习部署: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