先上官网的实现效果:官网
实现的大概思路:
- 对加载在最上层图层进行监听
- 监听的事件类型是RenderEvent渲染事件;渲染事件有好几种:这里用到了prerender和postrender
- 使用input标签来控制卷帘操作,input标签的type类型属性值为range,可以实现一个滑块的效果。input标签其实有很多类型。可见:类型
- input标签绑定input事件类型,监听值的变化来控制地图的重新渲染。
以下是代码,使用vue框架
ol.css文件在mainjs文件引入即可
<template>
<div class="container">
<div id="map"></div>
<input type="range" ref="swipe" style="width: 100%" @input="handleInput" />
</div>
</template>
<script>
import Map from "ol/Map";
import View from "ol/View";
// 添加图层
import Tilelayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import XYZ from "ol/source/XYZ";
import { getRenderPixel } from "ol/render";
export default {
name: "LayerSwipe",
data() {
return {
map: null,
};
},
mounted() {
this.init();
},
methods: {
init() {
const osm = new Tilelayer({
source: new OSM(),
});
//这里是添加天地图的影像图,key填自己的
const xyz = new Tilelayer({
source: new XYZ({
url: "http://t4.tianditu.com/DataServer?T=ter_w&tk=key&x&x={x}&y={y}&l={z}",
}),
});
this.map = new Map({
target: "map",
//这里注意图层顺序,数组最后一个是最上层的图层
layers: [osm, xyz],
view: new View({
center: [0, 0],
zoom: 2,
}),
});
// handleSwipe
const swipe = this.$refs.swipe;
let that = this;
xyz.on("prerender", function (e) {
const ctx = e.context;
const mapSize = that.map.getSize();
const width = mapSize[0] * (swipe.value / 100);
const tl = getRenderPixel(e, [width, 0]);
const tr = getRenderPixel(e, [mapSize[0], 0]);
const bl = getRenderPixel(e, [width, mapSize[1]]);
const br = getRenderPixel(e, mapSize);
ctx.save();
ctx.beginPath();
ctx.moveTo(tl[0], tl[1]);
ctx.lineTo(bl[0], bl[1]);
ctx.lineTo(br[0], br[1]);
ctx.lineTo(tr[0], tr[1]);
ctx.closePath();
ctx.clip();
});
xyz.on("postrender", function (e) {
const ctx = e.context;
ctx.restore();
});
},
handleInput() {
this.map.render();
},
},
};
</script>
<style lang="scss" scoped>
#map {
width: 100%;
height: 80vh;
}
</style>