官网demo地址:
Layer Spy
这篇实现了鼠标跟随望远镜效果,鼠标移动时绘制一个圆形的剪裁区剪裁上层图层。
container.addEventListener("mousemove", function (event) {
mousePosition = map.getEventPixel(event);
map.render();
});
container.addEventListener("mouseout", function () {
mousePosition = null;
map.render();
});
通过map.render()触发prerender,postrender两个函数来完成裁剪,其原理和上篇的卷帘效果一样。
上篇地址:
完整代码:
<template>
<div class="box">
<h1>Layer Spy</h1>
<div id="map" class="map"></div>
</div>
</template>
<script>
import StadiaMaps from "ol/source/StadiaMaps.js";
import Map from "ol/Map.js";
import TileLayer from "ol/layer/Tile.js";
import View from "ol/View.js";
import XYZ from "ol/source/XYZ.js";
import { fromLonLat } from "ol/proj.js";
import { getRenderPixel } from "ol/render.js";
export default {
name: "",
components: {},
data() {
return {
map: null,
};
},
computed: {},
created() {},
mounted() {
const container = document.getElementById("map");
const layer = new TileLayer({
source: new StadiaMaps({
layer: "stamen_terrain_background",
}),
zIndex: 2,
});
const map = new Map({
layers: [
layer,
new TileLayer({
source: new StadiaMaps({
layer: "outdoors",
}),
}),
],
target: "map",
view: new View({
center: [0, 0],
zoom: 2,
projection: "EPSG:4326",
}),
});
let radius = 75;
document.addEventListener("keydown", function (evt) {
if (evt.key === "ArrowUp") {
radius = Math.min(radius + 5, 150);
map.render();
evt.preventDefault();
} else if (evt.key === "ArrowDown") {
radius = Math.max(radius - 5, 25);
map.render();
evt.preventDefault();
}
});
let mousePosition = null;
container.addEventListener("mousemove", function (event) {
mousePosition = map.getEventPixel(event);
map.render();
});
container.addEventListener("mouseout", function () {
mousePosition = null;
map.render();
});
layer.on("prerender", function (event) {
const ctx = event.context;
ctx.save();
ctx.beginPath();
if (mousePosition) {
const pixel = getRenderPixel(event, mousePosition);
const offset = getRenderPixel(event, [
mousePosition[0] + radius,
mousePosition[1],
]);
const canvasRadius = Math.sqrt(
Math.pow(offset[0] - pixel[0], 2) + Math.pow(offset[1] - pixel[1], 2)
);
ctx.arc(pixel[0], pixel[1], canvasRadius, 0, 2 * Math.PI);
ctx.lineWidth = (5 * canvasRadius) / radius;
ctx.strokeStyle = "rgba(0,0,0,0.5)";
ctx.stroke();
}
ctx.clip();
});
layer.on("postrender", function (event) {
const ctx = event.context;
ctx.restore();
});
},
methods: {},
};
</script>
<style lang="scss" scoped>
#map {
width: 100%;
height: 500px;
}
.box {
height: 100%;
}
</style>