官网demo地址:
Immediate Rendering (Geographic)
首先先创建1000个随机点,创建点对象。
const n = 1000;
const geometries = new Array(n);
for (let i = 0; i < n; ++i) {
const lon = 360 * Math.random() - 180;
const lat = 180 * Math.random() - 90;
geometries[i] = new Point([lon, lat]);
}
因为创建的点坐标是地理坐标,而地图默认是3857投影展示,所以使用 useGeographic()让所有坐标都直接使用地理坐标系(EPSG:4326)
import { useGeographic } from "ol/proj.js";
useGeographic();
等同于在view中设置projection为"EPSG:4326"
view: new View({
center: [0, 0],
zoom: 2,
projection: "EPSG:4326",
}),
然后利用postrender在地图上绘制动画效果,每次随机生成一个点,push进geometries数组中,同时将数组的第一个删除,使地图上的点动态的出现消失。
layer.on("postrender", function (event) {
const vectorContext = getVectorContext(event);
for (let i = 0; i < n; ++i) {
const importance = upAndDown(Math.pow((n - i) / n, 0.15));
if (importance < 0.1) {
continue;
}
style.getImage().setOpacity(importance);
style.getImage().setScale(importance);
vectorContext.setStyle(style);
vectorContext.drawGeometry(geometries[i]);
}
const lon = 360 * Math.random() - 180;
const lat = 180 * Math.random() - 90;
geometries.push(new Point([lon, lat]));
geometries.shift();
map.render();
});
其中upAndDown
是openlayers提供的缓动函数,创建动画效果。定义了动画的进度和速度曲线,使得动画效果更加平滑和自然。调整点的透明度和缩放比例,从而实现点的渐显渐隐效果。
const importance = upAndDown(Math.pow((n - i) / n, 0.15));
计算了每个点的重要性,Math.pow((n - i) / n, 0.15)
计算了一个缩放值,upAndDown
函数应用了缓动效果,使得这个缩放值先增加后减少。
如果不喜欢点,也可以换成星星图形。
const star = new RegularShape({
radius: 10,
radius2: 3,
points: 5,
angle: Math.PI,
fill: new Fill({
color: "rgba(255, 153, 0, 0.8)",
}),
});
const style = new Style({
// image: image,
image: star,
});
完整代码:
<template>
<div class="box">
<h1>Immediate Rendering (Geographic)</h1>
<div id="map" class="map"></div>
</div>
</template>
<script>
import StadiaMaps from "ol/source/StadiaMaps.js";
import TileLayer from "ol/layer/Tile.js";
import { Circle, Fill, Style, Icon, RegularShape } from "ol/style.js";
import { Map, View } from "ol/index.js";
import { Point } from "ol/geom.js";
import { getVectorContext } from "ol/render.js";
import { upAndDown } from "ol/easing.js";
import { useGeographic } from "ol/proj.js";
export default {
name: "",
components: {},
data() {
return {
map: null,
};
},
computed: {},
created() {},
mounted() {
useGeographic();
const layer = new TileLayer({
source: new StadiaMaps({
layer: "stamen_toner",
}),
});
const map = new Map({
layers: [layer],
target: "map",
view: new View({
center: [0, 0],
zoom: 2,
projection: "EPSG:4326",
}),
});
const image = new Circle({
radius: 8,
fill: new Fill({ color: "rgba(255, 153, 0, 0.8)" }),
});
const star = new RegularShape({
radius: 10,
radius2: 3,
points: 5,
angle: Math.PI,
fill: new Fill({
color: "rgba(255, 153, 0, 0.8)",
}),
});
const style = new Style({
// image: image,
image: star,
});
const n = 1000;
const geometries = new Array(n);
for (let i = 0; i < n; ++i) {
const lon = 360 * Math.random() - 180;
const lat = 180 * Math.random() - 90;
geometries[i] = new Point([lon, lat]);
}
layer.on("postrender", function (event) {
const vectorContext = getVectorContext(event);
for (let i = 0; i < n; ++i) {
const importance = upAndDown(Math.pow((n - i) / n, 0.15));
if (importance < 0.1) {
continue;
}
style.getImage().setOpacity(importance);
style.getImage().setScale(importance);
vectorContext.setStyle(style);
vectorContext.drawGeometry(geometries[i]);
}
const lon = 360 * Math.random() - 180;
const lat = 180 * Math.random() - 90;
geometries.push(new Point([lon, lat]));
geometries.shift();
map.render();
});
},
methods: {},
};
</script>
<style lang="scss" scoped>
#map {
width: 100%;
height: 500px;
}
.box {
height: 100%;
}
#popup {
width: 160px;
height: 80px;
border-radius: 10px;
background: #fff;
position: absolute;
padding: 10px;
box-sizing: border-box;
}
.triangle {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -20px;
border-top: 10px solid #fff;
border-bottom: 10px solid transparent;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
}
</style>