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