css3实现椭圆轨迹旋转加闪烁

1,889 阅读1分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

背景需求

实现效果如下图:开发一个沿椭圆轨迹旋转的动效

CgFBIl8eeoKAVpZFAABrEKZrOqk754.gif

设计拆解

div块叠加的方式,以下图图标为底图,叠加一个沿椭圆轨迹移动的小球和一个闪烁的小球。

02004.png

代码

首先我们了解下动画animation的语法(截图来自w3cschool)

image.png

闪烁的小圆球

首先实现一个简单的小圆点闪烁,rem是项目需要,copy代码可以直接乘100转为px。

关键代码animation: animOpa 0.5s infinite linear;

infinite表示无限次播放,此处可以填集体的次数值(其他参数可参考w3cschool)

linear 表示动画从头到尾的速度是相同的

0.5s 表示动画播放一个周期设定的时间

animOpa 是自定义的keyframs,0%表示开始,100%表示结束。

此处opacity表示透明度从0到1匀速变化,这个过程在0.5秒内执行一次结束,且无限次重复执行。

其余css主要实现小圆球样式

<template>
  <div class="areaNamePanel">
    <div class="opacityBall"></div>
  </div>
</template>
<script>
export default {
  name: 'MapMarkerAnim',
  data() {
    return {}
  }
}
</script>
<style lang="less" scoped>
@keyframes animOpa {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
.areaNamePanel {
  height: 0.144rem;
  width: 0.4416rem;
  transform: translate(-50%, -0.3072rem);
  .opacityBall {
    position: absolute;
    width: 0.048rem;
    height: 0.048rem;
    left: 0.0432rem;
    top: 0.12rem;
    box-shadow: 0px 0px 8px #ff6000;
    border-radius: 8px;
    background-color: #f8cc03;
    animation: animOpa 0.5s infinite linear;
  }
}
</style>

沿椭圆轨迹移动的小圆球

关键代码

animation: animX 2s cubic-bezier(0.36, 0, 0.64, 1) -1s infinite alternate,
      animY 2s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate,
      scale 4s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate;

image.png 椭圆用到的为:cubic-bezier(0.36, 0, 0.64, 1)

椭圆构成三要素:三次贝塞尔曲线+左右移动延迟负一秒+scale为x+y的总时长。 scale主要是为了视觉上更有立体感,近大远小。

完整代码

<template>
  <div class="areaNamePanel">
    <div class="animatianBall"></div>
    <div class="opacityBall"></div>
  </div>
</template>
<script>
export default {
  name: 'MapMarkerAnim',
  data() {
    return {}
  }
}
</script>
<style lang="less" scoped>
@keyframes animX {
  0% {
    left: 0px;
  }
  100% {
    left: 0.4416rem;
  }
}
@keyframes animY {
  0% {
    top: 0px;
  }
  100% {
    top: 0.144rem;
  }
}
@keyframes scale {
  0% {
    opacity: 0.1;
    transform: scale(0.7);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0.1;
    transform: scale(0.7);
  }
}
@keyframes animOpa {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
.areaNamePanel {
  height: 0.144rem;
  width: 0.4416rem;
  transform: translate(-50%, -0.3072rem);
  .animatianBall {
    position: absolute;
    width: 0.048rem;
    height: 0.048rem;
    box-shadow: 0px 0px 8px #ff6000;
    border-radius: 0.064rem;
    background-color: #f8cc03;
    animation: animX 2s cubic-bezier(0.36, 0, 0.64, 1) -1s infinite alternate,
      animY 2s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate,
      scale 4s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate;
  }
  .opacityBall {
    position: absolute;
    width: 0.048rem;
    height: 0.048rem;
    left: 0.0432rem;
    top: 0.12rem;
    box-shadow: 0px 0px 8px #ff6000;
    border-radius: 8px;
    background-color: #f8cc03;
    animation: animOpa 0.5s infinite linear;
  }
}
</style>