官网demo地址:
openlayers官网的demo根本不适合小白,于是写了一系列解析文章。
很多人打开openlayers官网第一个demo,兴致冲冲的copy下来代码,运行起来却发现,嗯?地图咋出不来?代码也看不太懂,这是啥情况?别慌,俺来带你解析一下~
一、准备工作
首先咱们起一个vue2的架子
vue create openlayers_demo
下载一些依赖
npm install ol
npm install ol-ext
npm i element-ui -S
main.js里面引入一下elementui和配置的路由
import Vue from 'vue'
import App from './App.vue'
import router from "./router";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import "ol/ol.css";
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
router,
render: h => h(App),
}).$mount('#app')
我在views目录下写了一个List页面,使用动态组件的方式加载右边的地图,左侧目录绑定点击事件切换组件,方便点击查看不同示例。
List.vue
<template>
<div class="list">
<div class="left">
<h3>目录</h3>
<div
class="item"
@click="setMapView(item)"
v-for="(item, index) in list"
:key="index"
:style="{
color: item.name == mapviewCom ? 'rgb(192, 126, 247)' : '#000',
}"
>
{{ item.text }}
</div>
</div>
<div class="right">
<component :is="mapviewCom"></component>
</div>
</div>
</template>
<script>
import FirstMap from "./components/FirstMap.vue";
import VectorTiles from "./components/VectorTiles.vue";
export default {
name: "",
components: {
FirstMap,
VectorTiles
},
data() {
return {
mapviewCom: "VectorTiles",
list: [
{
name: "FirstMap",
text: "加载第一个地图",
},
{
name: "VectorTiles",
text: "加载第二个地图",
},
],
};
},
computed: {},
created() {},
methods: {
setMapView(item) {
this.mapviewCom = item.name;
},
},
};
</script>
<style scoped>
.list {
display: flex;
}
.left {
width: 30%;
}
.right {
flex: 1;
border: 1px solid #666;
height: 600px;
}
.item {
cursor: pointer;
margin-bottom: 10px;
}
</style>
页面长这样
二、加载第一个地图
加载地图首先需要一个容器,并且这个容器必须有宽高。
接下来初始化一个地图实例new Map,传递一个对象作为Map类的参数,其中layers是图层数组,同一个地图上可以叠加多个图层,图层的层级通过zIndex设置。只有一个图层时可以不写。
TileLayer是openlayers定义好的一个切片图层,图层下都有一个source表示图层源是什么。
target为绑定的地图容器的id,view是地图的视图,zoom是缩放层级,center为视角中心点,这里我写的是北京的坐标。
openlayers默认是3857的坐标系,我们通常使用的是4326的坐标系,可以通过 projection: "EPSG:4326"来指定坐标系,此时北京的坐标就是 center: [116.389, 39.903]。
FirstMap.vue
initOSMLayer() {
this.map = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
],
target: "map",
view: new View({
center:[12961431, 4836415], //坐标系3857下的北京的坐标
zoom: 8,
}),
});
},
官网这里展示的是一个源source为OSM的瓦片图层TileLayer,地图没出来的原因是OSM源的地图在国内有时候会出不来,有vpn的可以挂个vpn,没有vpn的换个地图源,这样写:
// 初始化地图
initXYZMap() {
let osmLayer = new TileLayer({
source: new XYZ({
url: "http://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png",
}),
zIndex: 1,
});
this.map = new Map({
target: "map",
layers: [osmLayer],
view: new View({
projection: "EPSG:4326",
center: [116.389, 39.903],
zoom: 8,
}),
});
},
效果:
加两个放大缩小的按钮事件
<div class="btn">
<el-button type="primary" @click="magnify">放大</el-button>
<el-button type="primary" @click="reduce">缩小</el-button>
</div>
getView()方法可以获取地图上的View,再从view里面使用getZoom()获取当前的放大层级,打印zoom将得到一个数字,就是当前的层级。使用setZoom()方法将获取到zoom加一就可以实现放大地图效果了。 缩小反之。
//放大
magnify() {
const view = this.map.getView();
const zoom = view.getZoom();
view.setZoom(zoom + 1);
},
最终效果:
FirstMap.vue完整代码
<template>
<div class="box">
<h1>第一个地图</h1>
<div id="map"></div>
<div class="btn">
<el-button type="primary" @click="magnify">放大</el-button>
<el-button type="primary" @click="reduce">缩小</el-button>
</div>
</div>
</template>
<script>
import Map from "ol/Map.js";
import OSM from "ol/source/OSM.js";
import TileLayer from "ol/layer/Tile.js";
import View from "ol/View.js";
import { XYZ } from "ol/source";
export default {
name: "",
components: {},
data() {
return {
map: null,
};
},
computed: {},
created() {},
mounted() {
this.initOSMLayer()
// this.initXYZMap()
},
methods: {
initOSMLayer() {
this.map = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
],
target: "map",
view: new View({
center:[12961431, 4836415], //坐标系3857下的北京的坐标
zoom: 8,
}),
});
},
// 初始化地图
initXYZMap() {
let osmLayer = new TileLayer({
source: new XYZ({
url: "http://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png",
}),
zIndex: 1,
});
this.map = new Map({
target: "map",
layers: [osmLayer],
view: new View({
projection: "EPSG:4326",
center: [116.389, 39.903],
zoom: 8,
}),
});
},
//放大
magnify() {
const view = this.map.getView();
const zoom = view.getZoom();
view.setZoom(zoom + 1);
},
//缩小
reduce() {
const view = this.map.getView();
const zoom = view.getZoom();
view.setZoom(zoom - 1);
},
},
};
</script>
<style lang="scss" scoped>
#map {
width: 100%;
height: 100%;
}
.box {
height: 100%;
}
</style>