Skip to content

动画效果

TIP

点击按钮触发动画效果。

代码如下:

点我查看代码
vue
<template>
  <div class="btns">
    <el-button type="primary" @click="handleSpin">旋转定位到沈阳</el-button>
    <el-button type="primary" @click="handleElastic">弹性定位到北京</el-button>
    <el-button type="primary" @click="handleBounce">反弹定位到上海</el-button>
    <el-button type="primary" @click="handleRotate">围绕武汉旋转</el-button>
    <el-button type="primary" @click="handleFly">飞行定位到广州</el-button>
  </div>
  <div id="map"></div>
</template>

<script lang="ts" setup>
import { onMounted, onBeforeUnmount } from "vue";
import { Map, View } from "ol";
import { Tile as TileLayer } from "ol/layer";
import { fromLonLat } from "ol/proj";
import { easeIn, easeOut } from "ol/easing";
import { MAPURL, ATTRIBUTIONS } from "../../../constants";
import XYZ from "ol/source/XYZ";

let map: Map | null = null;

const raster = new TileLayer({
  source: new XYZ({
    attributions: ATTRIBUTIONS,
    url: MAPURL,
    maxZoom: 20,
  }),
});

const view = new View({
  //地图初始中心点
  center: [12950000, 4860000],
  //地图初始显示级别
  zoom: 11,
});

const initMap = () => {
  map = new Map({
    //初始化map
    target: "map",
    //地图容器中加载的图层
    layers: [
      //加载瓦片图层数据
      raster,
    ],
    view,
  });
};

//各定位点(中国省会城市)
const shenyang = fromLonLat([123.24, 41.5]);
const beijing = fromLonLat([116.28, 39.54]);
const shanghai = fromLonLat([121.29, 31.14]);
const wuhan = fromLonLat([114.21, 30.37]);
const guangzhou = fromLonLat([113.15, 23.08]);

// 获取反弹值
function bounce(t) {
  let s = 7.5625,
    p = 2.75,
    l;
  if (t < 1 / p) {
    l = s * t * t;
  } else {
    if (t < 2 / p) {
      t -= 1.5 / p;
      l = s * t * t + 0.75;
    } else {
      if (t < 2.5 / p) {
        t -= 2.25 / p;
        l = s * t * t + 0.9375;
      } else {
        t -= 2.625 / p;
        l = s * t * t + 0.984375;
      }
    }
  }
  return l;
}
// 获取弹性伸缩值
function elastic(t) {
  return (
    Math.pow(2, -10 * t) * Math.sin(((t - 0.075) * (2 * Math.PI)) / 0.3) + 1
  );
}

// 旋转定位到沈阳
const handleSpin = () => {
  const center = view.getCenter();
  if (!center) return;
  view.animate(
    //第一个过程
    {
      //动画结束时的视图中心,即当前视图中心同目标视图中心连线的中心点
      center: [
        center[0] + (shenyang[0] - shenyang[0]) / 2,
        center[1] + (shenyang[1] - shenyang[1]) / 2,
      ],
      rotation: Math.PI, //动画结束时的旋转角度,即180度
      easing: easeIn, //按每一帧动画控制的动画速度,即开始缓慢并逐渐加快速度
    },
    //第二个过程
    {
      center: shenyang, //动画结束时的视图中心
      rotation: 2 * Math.PI, //动画结束时的旋转角度,即360度回正
      easing: easeOut, //按每一帧动画控制的动画速度,即开始快速并逐渐减速
    }
  );
};

// 弹性定位到北京
const handleElastic = () => {
  view.animate({
    center: beijing, ///动画结束时的视图中心
    duration: 2000, //动画的持续时间(以毫秒为单位)
    easing: elastic, //按每一帧动画控制的动画持续时间函数
  });
};

// 反弹定位到上海
const handleBounce = () => {
  view.animate({
    center: shanghai, ///动画结束时的视图中心
    duration: 2000, //动画的持续时间(以毫秒为单位)
    easing: bounce, //按每一帧动画控制的动画持续时间函数
  });
};

// 围绕武汉旋转
const handleRotate = () => {
  const rotation = view.getRotation();
  view.animate(
    //第一个过程
    {
      rotation: rotation + Math.PI, //第一次动画旋转角度
      anchor: wuhan, //自旋的中心点,即武汉
      easing: easeIn, ////按每一帧动画控制的动画速度,即开始缓慢并逐渐加快速度
    },
    //第二个过程
    {
      rotation: rotation + 2 * Math.PI, //动画结束时的旋转角度,即360度回正
      anchor: wuhan, // 旋转中心点
      easing: easeOut, ///按每一帧动画控制的动画速度,即开始快速并逐渐减速
    }
  );
};

// handleFly
const handleFly = () => {
  const duration = 2000; //动画的持续时间(以毫秒为单位)
  const zoom = view.getZoom();
  if (!zoom) return;
  //第一个动画
  view.animate({
    center: guangzhou,
    duration: duration,
  });
  //第二个动画
  view.animate(
    {
      zoom: zoom - 1,
      duration: duration / 2,
    },
    {
      zoom: zoom,
      duration: duration / 2,
    }
  );
};

onMounted(() => {
  initMap();
});

onBeforeUnmount(() => {
  if (map) {
    map.dispose();
    map = null;
  }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#map {
  width: 100%;
  height: 650px;
}

.btns {
  display: flex;
  justify-content: space-around;
  align-items: center;
  height: 50px;
}
</style>

如有转载或 CV 的请标注本站原文地址