四十九、openlayers官网示例Immediate Rendering (Geographic)——在地图上绘制星空动画效果

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

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值