1、Source 的分类
1、ol.source.Tile对应的是瓦片数据源,现在网页地图服务中,绝大多数都是使用的瓦片地图,而OpenLayers 3作为一个WebGIS引擎,理所当然应该支持瓦片。
2、ol.source.Image对应的是一整张图,而不像瓦片那样很多张图,从而无需切片,也可以加载一些地图,适用于一些小场景地图。
3、ol.source.Vector对应的是矢量地图源,点,线,面等等常用的地图元素(Feature),就囊括到这里面了。这样看来,只要这两种Source就可以搞定80%的需求了。
我们已经通过第一种Source源的方式加载过一个OSM瓦片地图了。针对第一种ol.source.Tile 加载地图的方式其内部具体划分还有如下的格式。
2、ol.source.Tile 瓦片地图
瓦片地图 就像名字一样,有一张很大的地图,分别切割成无数的小的固定地图,由各个小的地图拼接到页面上形成一张完整的地图。
2-1、通过 ol.source.Tile 加载一张基本的地图 Open Street Map 也就是实现我们前面 示例中的地图
import Map from "ol/Map";
import View from "ol/View";
import Tile from "ol/layer/Tile";
import OSM from "ol/source/OSM";
export default class customMap {
constructor(options) {
this.mapUrl = options.mapUrl || "";
this.target = options.target;
this.map = null;
}
/**
* @description: 初始化地图实例
*/
init() {
// 已经初始化就不需要再次初始化了
if (this.map) return;
// Map 地图实例用来承载我们的配置
this.map = new Map({
// 让id为map的div作为地图的容器
target: this.target,
// 图层容器: 图层会有很多个 类似于我们吃的千层饼 一层一层叠在一起 这样可以让我们看到更多丰富的内容.
layers: [
// 创建一个使用Open Street Map地图源的瓦片图层
// Tile 加载一个瓦片地图 也就是我们底图
new Tile({ source: new OSM() }),
],
// 设置显示地图的视图: 对我们的地图进行一些配置
view: new View({
center: [0, 0], // 定义地图显示中心于经度0度,纬度0度处
zoom: 2, // 并且定义地图显示层级为2
}),
});
}
}
除了Open Street Map openlayers内部还集成了 微软的Bing地图,Stamen地图。他们的调用方式别为
import Map from "ol/Map";
import View from "ol/View";
import Tile from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import Layer from "ol/layer/Layer";
import * as olSource from "ol/source";
export default class customMap {
constructor(options) {
this.mapUrl = options.mapUrl || "";
this.target = options.target;
this.map = null;
this.openStreetMapLayer = null;
this.bingMapLayer = null;
this.stamenLayer = null;
}
// Open Street Map 地图层
initOpenStreetMapLayer() {
this.openStreetMapLayer = new Tile({
source: new olSource.OSM(),
});
}
// 初始化bing图层
initBingMapLayer() {
this.bingMapLayer = new Tile({
source: new olSource.BingMaps({
key: "AkjzA7OhS4MIBjutL21bkAop7dc41HSE0CNTR5c6HJy8JKc7U9U9RveWJrylD3XJ",
imagerySet: "Road",
}),
});
}
// 初始化stamenLayer图层
initStamenLayer() {
this.stamenLayer = new Tile({
source: new olSource.Stamen({
layer: "watercolor",
}),
});
}
/**
* @description: 初始化地图实例
*/
init() {
this.initOpenStreetMapLayer();
this.initBingMapLayer();
this.initStamenLayer();
// 已经初始化就不需要再次初始化了
if (this.map) return;
// Map 地图实例用来承载我们的配置
this.map = new Map({
// 让id为map的div作为地图的容器
target: this.target,
// 图层容器: 图层会有很多个 类似于我们吃的千层饼 一层一层叠在一起 这样可以让我们看到更多丰富的内容.
layers: [this.stamenLayer],
// 设置显示地图的视图: 对我们的地图进行一些配置
view: new View({
center: [0, 0], // 定义地图显示中心于经度0度,纬度0度处
zoom: 2, // 并且定义地图显示层级为2
}),
});
}
}
2-2、图层切换
customMap.js
import Map from "ol/Map";
import View from "ol/View";
import Tile from "ol/layer/Tile";
import * as olSource from "ol/source";
export default class customMap {
constructor(options) {
this.mapUrl = options.mapUrl || "";
this.target = options.target;
this.map = null;
this.openStreetMapLayer = null;
this.bingMapLayer = null;
this.stamenLayer = null;
}
// Open Street Map 地图层
initOpenStreetMapLayer() {
this.openStreetMapLayer = new Tile({
source: new olSource.OSM(),
});
}
// 初始化bing图层
initBingMapLayer() {
this.bingMapLayer = new Tile({
source: new olSource.BingMaps({
key: "AkjzA7OhS4MIBjutL21bkAop7dc41HSE0CNTR5c6HJy8JKc7U9U9RveWJrylD3XJ",
imagerySet: "Road",
}),
});
}
// 初始化stamenLayer图层
initStamenLayer() {
this.stamenLayer = new Tile({
source: new olSource.Stamen({
layer: "watercolor",
}),
});
}
/**
* @description: 初始化地图实例
*/
init() {
this.initOpenStreetMapLayer();
this.initBingMapLayer();
this.initStamenLayer();
// 已经初始化就不需要再次初始化了
if (this.map) return;
// Map 地图实例用来承载我们的配置
this.map = new Map({
// 让id为map的div作为地图的容器
target: this.target,
// 图层容器: 图层会有很多个 类似于我们吃的千层饼 一层一层叠在一起 这样可以让我们看到更多丰富的内容.
layers: [this.stamenLayer],
// 设置显示地图的视图: 对我们的地图进行一些配置
view: new View({
center: [0, 0], // 定义地图显示中心于经度0度,纬度0度处
zoom: 2, // 并且定义地图显示层级为2
}),
});
}
}
index.jsx
import React, { useEffect } from "react";
import customMap from "./libs/customMap";
import "./index.less";
const SourceComponent = () => {
/**
* @description: 初始化地图
*/
let newCustomMap = null;
const init = () => {
newCustomMap = new customMap({
url: "",
target: "map",
});
newCustomMap.init();
};
useEffect(() => {
init();
}, []);
/**
* @description: 切换showOpenStreetMap 图层
*/
const showOpenStreetMap = () => {
const map = newCustomMap.map;
// 通过map 实例 获取所有图层 找到第一个图层 删除图层 然后添加我们的新图层
// 这边会用到 map实例的两个api removeLayer,addLayer
const AllLayers = map.getLayers();
// 删除图层
map.removeLayer(AllLayers.item(0));
// 添加新图层
map.addLayer(newCustomMap.openStreetMapLayer);
};
/**
* @description: 切换showBingMapLayer 图层
*/
const showBingMapLayer = () => {
const map = newCustomMap.map;
// 通过map 实例 获取所有图层 找到第一个图层 删除图层 然后添加我们的新图层
// 这边会用到 map实例的两个api removeLayer,addLayer
const AllLayers = map.getLayers();
// 删除图层
map.removeLayer(AllLayers.item(0));
// 添加新图层
map.addLayer(newCustomMap.bingMapLayer);
};
/**
* @description: 切换StamenLayer 图
*/
const showStamenLayer = () => {
const map = newCustomMap.map;
// 通过map 实例 获取所有图层 找到第一个图层 删除图层 然后添加我们的新图层
// 这边会用到 map实例的两个api removeLayer,addLayer
const AllLayers = map.getLayers();
// 删除图层
map.removeLayer(AllLayers.item(0));
// 添加新图层
map.addLayer(newCustomMap.stamenLayer);
};
return (
<div className="warp">
<div id="map"></div>
<button onClick={showOpenStreetMap}>加载Open Street Map 地图</button>
<button onClick={showBingMapLayer}>加载Bing地图层</button>
<button onClick={showStamenLayer}>加载Stamen地图层</button>
</div>
);
};
export default SourceComponent;
这样我们就实现了一个最近基本的图层切换功能,可能看到这里会有一些疑问,对于这些操作地图的api我们是在哪里找到呢?
1、第一个办法 我们可以打印我们实例化的map实例 通过原型上进行查看 当前的实例具体有那些方法。
2、在官网上进行查看直接搜索我们要操作的对象
3、进一步了解瓦片地图
在我们日常工作中,经常会用到百度地图、高德地图,其实他们的地图源都归属为瓦片地图,甚至我们想做某个精细化地区,地级市的业务时我们可能还会根据自己的地图服务器生成我们更加个性化的地图。那么这种情况下我们还能够使用我们上面说的三种地图源 进行业务开发吗?显示是不能的,所以openlayers 为了应对这种情况 提供了更加通用的加载地图的api。
// 我们通过 ol.source.XYZ 来 加载通用地图资源。
ol.source.XYZ
1、通过ol.source.XYZ 的形式加载我们OMS地图
// Open Street Map 地图层
initOpenStreetMapLayer() {
this.openStreetMapLayer = new Tile({
source: new olSource.XYZ({
url: 'http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
}),
});
}
2、使用我们的图层
init() {
this.initOpenStreetMapLayer();
this.initBingMapLayer();
this.initStamenLayer();
// 已经初始化就不需要再次初始化了
if (this.map) return;
// Map 地图实例用来承载我们的配置
this.map = new Map({
// 让id为map的div作为地图的容器
target: this.target,
// 图层容器: 图层会有很多个 类似于我们吃的千层饼 一层一层叠在一起 这样可以让我们看到更多丰富的内容.
layers: [this.openStreetMapLayer],
// 设置显示地图的视图: 对我们的地图进行一些配置
view: new View({
center: [0, 0], // 定义地图显示中心于经度0度,纬度0度处
zoom: 2, // 并且定义地图显示层级为2
}),
});
}
3、让我们观察一下这个url http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png,其中的x,y,z分别代表什么意思的呢?
这张图就是对我们的瓦片地图的实现原理的讲解,我们通过图中可以看出,x,y分别代表一个瓦片地图的坐标位置,Z代表当前瓦片在图层中的层级。
3-1、加载高德瓦片地图
/**
* @description: 初始化高德图层
*/
initGaodeMap() {
this.gaodeMap = new Tile({
source: new olSource.XYZ({
url: "http://webst0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
}),
});
}
3-2、加载雅虎瓦片地图
/**
* @description: 初始化yahu地图
*/
initYahuMap() {
this.yahuMap = new Tile({
source: new olSource.XYZ({
tileSize: 512,
url: "https://{0-3}.base.maps.api.here.com/maptile/2.1/maptile/newest/normal.day/{z}/{x}/{y}/512/png8?lg=ENG&ppi=250&token=TrLJuXVK62IQk0vuXFzaig%3D%3D&requestid=yahoo.prod&app_id=eAdkWGYRoc4RfxVo0Z4B",
}),
});
}