一、openlayers官网示例Accessible Map解析

120 阅读3分钟

官网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

  <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>

页面长这样

e45932ab11f84eb0745760e51996ac94.gif 二、加载第一个地图 加载地图首先需要一个容器,并且这个容器必须有宽高。

接下来初始化一个地图实例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

      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,
        }),
      });
    },

11.png 加两个放大缩小的按钮事件

      <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);
    },

2.gif FirstMap.vue完整代码

  <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>