CSS动效合集之实现气泡发散动画

2023-09-18 13:37:42

前言

👏CSS动效合集之实现气泡发散动画,速速来Get吧~
🥇文末分享源代码。记得点赞+关注+收藏!

1.实现效果

在这里插入图片描述

2.实现步骤

  • 定义一个数组bubbles,用来存储气泡列表的基本新,w表示宽高,x表示绝对定位中left的百分比
  • 注:以下代码基于vue
const bubbles = ref([
  {
    w: 8,
    x: 10,
  },
  {
    w: 9,
    x: 50,
  },
  {
    w: 4,
    x: 30,
  },
  {
    w: 5,
    x: 80,
  },
  {
    w: 4,
    x: 30,
  },
  {
    w: 4,
    x: 70,
  },
  {
    w: 6,
    x: 20,
  },
  {
    w: 8,
    x: 50,
  },
  {
    w: 4,
    x: 60,
  },
  {
    w: 6,
    x: 65,
  },
]);
  • 绘制父元素section,设置宽高为300px,相对定位

在这里插入图片描述

section {
  height: 300px;
  width: 300px;
  margin: 50px auto;
  position: relative;
  z-index: 1;
  border-radius: 20px;
  box-shadow: 0px 9px 17px 4px rgba(0, 0, 0, 0.5);
}
  • section内添加子元素bubbles标签,设置宽高与父元素一致,绝对定位
  • 在bubbles用span标签循环展示气泡列表
<div class="bubbles">
  <span
    class="bubble"
    v-for="(item, index) in bubbles"
    :key="index"
     }"
  ></span>
</div>
  • 为span标签添加css变量,设置–w表示元素的宽高,–x表示绝对定位中left的百分比
<span
 class="bubble"
 v-for="(item, index) in bubbles"
 :key="index"
 :style="{
   '--w': item.w,
   '--x': item.x,
 }"
  • 气泡设置绝对定位,初始位置居于父元素的底部10%,水平居中,并设置宽高为–w,默认设置背景色为粉色

在这里插入图片描述

.bubble {
  position: absolute;
  width: calc(1px * var(--w));
  height: calc(1px * var(--w));  border-radius: 50%;
  left: calc(50% - calc(1px * calc(var(--w) / 2)));
  bottom: 10%;
  background: pink;
}
  • 为气泡添加发散动画
.bubble {
	+     animation: rise 3s infinite linear;
}
  • 实现气泡left由水平居中到对应列表中–x的变化,bottom位置由10%到100%的改变,opacity透明度由刚开始的0到中间0.8,最后0的变化

在这里插入图片描述



@keyframes rise {
  0% {
    left: calc(50% - calc(1px * calc(var(--w) / 2)));
    opacity: 0;
    bottom: 10%;
  }
  50% {
    opacity: 0.8;
  }
  100% {
    left: calc(1% * var(--x));
    bottom: 90%;
    opacity: 0;
  }
}
  • 给每个气泡设置不同的动画延迟,实现错落的效果,在span标签上添加–d,表示当前标签动画延迟时间

在这里插入图片描述

<span
	class="bubble"
	v-for="(item, index) in bubbles"
	:key="index"
	:style="{
	'--w': item.w,
	'--x': item.x,
	'--d':
	parseInt(bubbles.length / 2) +
	1 -
	Math.abs(index - parseInt(bubbles.length / 2)),
	}"
></span>
.bubble {
	+  animation-delay: calc(600ms * var(--d));
}
  • 可以发现,设置了动画延迟,在初始阶段,会出现固定的气泡展示在中心位置,这不是我们想要的效果,修改span标签样式,设置其默认的透明度为0

在这里插入图片描述

.bubble {
	+  opacity: 0;
}
  • 当前动画时长是3s,动画延迟为间隔600ms * 延长单位,气泡列表长度为10个,我们尝试将动画延迟为间隔设置100ms,会发生什么呢?
    在这里插入图片描述
  • 可以发现,气泡发散效果变的不连贯,延迟的时间间隔不够大,如果想要气泡发散是比较连贯的效果,就需要去平衡动画总时长和延迟间隔
  • 为每个气泡设置不同的颜色,定义一个颜色数组colors
 colors: {
    type: Array,
    default: () => ["#00BABC", "#009FA4", "#00FFC0"],
  },
  • 每个气泡的颜色根据当前数据的索引从colors中获取
bubbles.value.forEach((i, index) => {
  i.c = props.colors[index]
});
  • 那么随之而来一个问题,当bubbles数据过多,colors不够用怎么解决?

  • 当colors不够用时候,就从colors的第一项继续赋值

  • 定义一个循环取值的方法

/**
 * 根据索引循环取数值的值,取模运算符(%)来实现循环取数组的值
 * @param {*} array
 * @param {*} sort
 * @returns
 */
export const forArrayValue = (array, sort) => {
  return array[sort % array.length];
};
  • bubbles重新赋值
bubbles.value.forEach((i, index) => {
  i.c = forArrayValue(props.colors, index);
});
  • 为每个气泡span标签添加–c变量,表示当前背景颜色

在这里插入图片描述

<span
	class="bubble"
	v-for="(item, index) in bubbles"
	:key="index"
	:style="{
	'--w': item.w,
	'--c': item.c,
	'--x': item.x,
	'--d':
	 parseInt(bubbles.length / 2) +
	 1 -
	 Math.abs(index - parseInt(bubbles.length / 2)),
	}"
></span>
.bubble {
 + background: var(--c);
}
  • 为其父元素bubbles设置溢出隐藏,以防left位置变化超出当前容器,设置z-index为-1,以防遮挡到父元素其他内容
.bubbles {
 + z-index: -1;
 + overflow: hidden;
}
  • 这样就完整的实现啦~

在这里插入图片描述

  • 当然,你可以可以通过代码,动态的去生成气泡列表,使用Math.random生成其位置和大小,实现原理与上述一致~,这里就不在赘述了

3.实现代码

<template>
  <section>
    <div class="bubbles">
      <span
        class="bubble"
        v-for="(item, index) in bubbles"
        :key="index"
        :style="{
          '--w': item.w,
          '--c': item.c,
          '--x': item.x,
          '--d':
            parseInt(bubbles.length / 2) +
            1 -
            Math.abs(index - parseInt(bubbles.length / 2)),
        }"
      ></span>
    </div>
  </section>
</template>
<script setup>
import { ref } from "vue";
import { forArrayValue } from "@/utils/tools";
const props = defineProps({
  colors: {
    type: Array,
    default: () => ["#00BABC", "#009FA4", "#00FFC0"],
  },
});
const bubbles = ref([
  {
    w: 8,
    x: 10,
  },
  {
    w: 9,
    x: 50,
  },
  {
    w: 4,
    x: 30,
  },
  {
    w: 5,
    x: 80,
  },
  {
    w: 4,
    x: 30,
  },
  {
    w: 4,
    x: 70,
  },
  {
    w: 6,
    x: 20,
  },
  {
    w: 8,
    x: 50,
  },
  {
    w: 4,
    x: 60,
  },
  {
    w: 6,
    x: 65,
  },
]);
bubbles.value.forEach((i, index) => {
  i.c = forArrayValue(props.colors, index);
});
</script>
<style lang="less" scoped>
section {
  height: 300px;
  width: 300px;
  margin: 50px auto;
  position: relative;
  z-index: 1;
  border-radius: 20px;
  box-shadow: 0px 9px 17px 4px rgba(0, 0, 0, 0.5);
}
.bubbles {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  z-index: -1;
  overflow: hidden;
}
.bubble {
  position: absolute;
  width: calc(1px * var(--w));
  height: calc(1px * var(--w));
  background: var(--c);
  border-radius: 50%;
  left: calc(50% - calc(1px * calc(var(--w) / 2)));
  opacity: 0;
  bottom: 10%;
  animation: rise 3s infinite linear;
  animation-delay: calc(600ms * var(--d));
}
@keyframes rise {
  0% {
    left: calc(50% - calc(1px * calc(var(--w) / 2)));
    opacity: 0;
    bottom: 10%;
  }
  50% {
    opacity: 0.8;
  }
  100% {
    left: calc(1% * var(--x));
    bottom: 90%;
    opacity: 0;
  }
}
</style>

4.写在最后🍒

看完本文如果觉得对你有一丢丢帮助,记得点赞+关注+收藏鸭 🍕
更多相关内容,关注🍥苏苏的bug,🍡苏苏的github,🍪苏苏的码云~
更多推荐

面试题四:请解释一下watch,computed和filter之间的区别

watch与computed、filter:watch:监控已有属性,一旦属性发生了改变就去自动调用对应的方法computed:监控已有的属性,一旦属性的依赖发生了改变,就去自动调用对应的方法.computed有详细的介绍,移步computed的使用filter:js中为我们提供的一个方法,用来帮助我们对数据进行筛选,

容器内也能运行图形化应用?Distrobox 为容器注入生命 | 开源日报 No.35

JetBrains/compose-multiplatformStars:13.3kLicense:Apache-2.0ComposeMultiplatform是一个使用Kotlin在多个平台上共享UI的声明性框架。它基于JetpackCompose,由JetBrains和开源贡献者开发。您可以选择使用ComposeM

django和celery的项目,nginx和uwsgi协议,在通过api端口进行deeplearning任务的训练和排队

问题汇总redis安装django和celery的安装nginx和uwsgi的安装一.Django的项目,有个runserver直接起了一个webserver,为什么还要Nginx包一层,起一个webserver呢?Nginx的性能比Django自带的Webserver的性能要好,python写的程序,deeplab想

怎样提高redis的命中率

要提高Redis缓存命中率,可以考虑以下几个方面:合理设置缓存过期时间:根据业务需求和数据更新频率,设置适当的缓存过期时间。过长的过期时间可能导致数据不及时更新,而过短的过期时间则可能导致频繁的缓存失效。选择合适的数据结构:根据具体业务场景选择合适的Redis数据结构。例如,使用Hash类型来存储对象,使用Sorted

DEM格式转换:转换NSDTF-DEM国标数据格式为通用格式,使用ArcGIS工具转换NSDTF-DEM国标.dem文件为通用.tif格式。

DEM格式转换:转换NSDTF-DEM国标数据格式为通用格式,使用ArcGIS工具转换NSDTF-DEM国标.dem文件为通用.tif格式。*.dem是一种比较常见的DEM数据格式,其有两种文件组织方式,即NSDTF-DEM和USGS-DEM。(1)NSDTF-DEM是一种明码的中国国家标准空间数据的交换格式,遵从国家

浅谈消防设备电源监控系统在高层民用建筑内的应用

【摘要】:当高层民用建筑内火灾发生时,各类消防设备能否正常运行、能否发挥作用是初期火灾扑救是否成功的重要条件之一,而稳定可靠的消防设备电源则是消防设备正常工作的保障。因此针对高层民用建筑内消防设备电源的监测系统至关重要。【关键词】:消防设备电源;AFPM100/B1;电压/电流传感器;高层民用建筑0前言为扎实推进高层民

【全志V3s】SPI NAND Flash 驱动开发

文章目录一、硬件介绍V3s的启动顺序二、驱动支持U-Boot驱动主线Linux驱动已经支持三、烧录工具xfel四、构建U-Boot(官方的Uboot)先编译一下开始spinandflash代码层面的适配修改menuconfig配置ARMarchitecture配置SupportforSPINandFlashonAllw

MySQL远程登录提示Access denied的场景

厂商给的某个MySQL库,通过客户端远程登录,提示这个错误,Accessdeniedforuser'用户名'@'IP'(usingpassword:YES)确认输入的账号密码都是正确的,出现这个错误说明端口是通的。此时可以检索mysql.user,如果待登录账号的记录host字段是localhost,说明仅允许本地登录

Hbuilder本地调试微信H5项目(一)

摘要通过内网穿透,访问本地Hbuilder创建的Vue项目前置准备下载并安装【HBuilder】,本文用的是HBuilder3.8.12版本,下载地址下载并安装【微信开发者工具】,本文用的是1.06版本,下载地址下载并安装【natapp】,下载地址实现逻辑本地使用Hbuilder进行开发并运行起来(配置为80端口)使用

【golang】深入理解GMP调度模型

GoroutineGo中,协程被称为goroutine,它非常轻量,一个goroutine只占几KB,并且这几KB就足够goroutine运行完,这就能在有限的内存空间内支持大量goroutine,支持了更多的并发,虽然一个goroutine的栈只占几KB(Go语言官方说明为4~5KB),但实际是可伸缩的,如果需要更多

性能测试 —— Jmeter定时器

固定定时器如果你需要让每个线程在请求之前按相同的指定时间停顿,那么可以使用这个定时器;需要注意的是,固定定时器的延时不会计入单个sampler的响应时间,但会计入事务控制器的时间1、使用固定定时器位置在http请求中;每次http请求前延迟3秒;配置路径——定时器——固定定时器;如下图:2、线程组循环3次,通过表格查看

热文推荐