css实现气泡随机漂浮效果

  • 实现效果
  • React代码
  • css代码
  • 总结

实现效果

React代码

// 泡泡随机漂浮
// 这里的封装逻辑是基于每个泡泡大小一样进行封装的import React,{FC,useState,useEffect,useRef} from 'react'
import styles from './index.less'// 泡泡的背景图
import bubble1 from '../../img/bubblefloat/bubble1.png'
import bubble2 from '../../img/bubblefloat/bubble2.png'
import bubble3 from '../../img/bubblefloat/bubble3.png'
import bubble4 from '../../img/bubblefloat/bubble4.png'
import bubble5 from '../../img/bubblefloat/bubble5.png'
import bubble6 from '../../img/bubblefloat/bubble6.png'
import bubble7 from '../../img/bubblefloat/bubble7.png'const Bubble:FC<any>  = (props)=>{useEffect(()=>{document.documentElement.style.fontSize=(document.documentElement.clientWidth/750)*100+'px';},[])const mainRef = useRef<any>()const BubblesRef = useRef<any>([])const getBubbles = (dom: any) => {if(!dom) return;BubblesRef.current.push(dom)}const bubblesArr = [{key:1,bgImg:bubble1},{key:2,bgImg:bubble2},{key:3,bgImg:bubble3},{key:4,bgImg:bubble4},{key:5,bgImg:bubble5},{key:6,bgImg:bubble6},{key:7,bgImg:bubble7},]// 气泡运动的函数const bubbleMovement = ()=>{// 气泡运动区域const main  = mainRef.current//  气泡数组const  circles =  BubblesRef.current//初始化运动的最大宽和高, 为了让气泡不卡在屏幕边缘,因此要减去自身的宽高const maxW = main.clientWidth- circles[0].clientWidth; const  maxH = main.clientHeight - circles[0].clientHeight; const container:any = []; //存放气泡的具体信息,包括坐标,速度等值const cwidth = circles[0].clientWidth; //小球的直径let arr;//数组对象的初始化for (let i = 0; i < circles.length; i++) {arr = {};arr.x = Math.floor(Math.random() * (maxW + 1)); //初始x坐标arr.y = Math.floor(Math.random() * (maxH + 1)); //初始y坐标arr.cx = arr.x + circles[0].clientWidth / 2; //圆心x坐标arr.cy = arr.y + circles[0].clientHeight / 2; //圆心y坐标arr.movex = Math.floor(Math.random() * 2); //x轴移动方向 1:右 0:左arr.movey = Math.floor(Math.random() * 2); //y轴移动方向 1:下 0:上arr.speed = 1 + Math.floor(Math.random() ); //随机移动距离arr.timer = null; //计时器arr.index = i; //索引值container.push(arr); //存放全部的属性值// 气泡位置初始化circles[i].style.left = arr.x + 'px'; circles[i].style.top = arr.y + 'px';}// 碰撞检测函数const crash = (a) => {const bubble1x = container[a].cx; //在数组中任意球的圆心坐标const bubble1y = container[a].cy; for (let i = 0; i < container.length; i++) {if (i !== a) { //判断取出来的气泡是不是本身,才能和其余球进行距离判断const bubble2x = container[i].cx; //将其余气泡的圆心坐标赋值给气泡2const bubble2y = container[i].cy;//圆心距 求两个点之间的距离,开平方const distence = Math.sqrt((bubble1x - bubble2x) * (bubble1x - bubble2x) + (bubble1y - bubble2y) * (bubble1y - bubble2y));// //球心距离和求直径比较 碰撞if (distence <= cwidth) { //气泡1位于气泡2的右方if (bubble1x > bubble2x) { //气泡1位于气泡2的下方(右下)if (bubble1y > bubble2y) { container[a].movex = 1; //1表示为正值,对应的右和下container[a].movey = 1; //0表示为负值,对应的左和上} //气泡1位于气泡2的上方(右上)else if (bubble1y < bubble2y) {container[a].movex = 1;container[a].movey = 0;} //气泡1气泡2的垂直位置相同(水平)else {container[a].movex = 1;}}//气泡1位于气泡2的左方else if (bubble1x < bubble2x) {//气泡1位于气泡2的下方(左下)if (bubble1y > bubble2y) {container[a].movex = 0;container[a].movey = 0;}//气泡1位于气泡2的上方(左上)else if (bubble1y < bubble2y) {container[a].movex = 0;container[a].movey = 1;} //气泡1气泡2的垂直位置相同(水平)else {container[a].movex = 0;}}//气泡1和气泡2的水平方位位置相同(垂直)else {//  气泡1在气泡2正下方if (bubble1y > bubble2y) {container[a].movey = 1;}//  气泡1在气泡2正上方else if (bubble1y < bubble2y) {container[a].movey = 0;}}}}}}//移动函数const move = (bubble)=> { //每一个球单独有定时器bubble.timer = setInterval(()=>{//若是往右跑,则一直加速度,碰到边界,改成反方向运动if (bubble.movex === 1) {bubble.x += bubble.speed;if (bubble.x + bubble.speed >= maxW) { //防止小球出界bubble.x = maxW;bubble.movex = 0; //小球运动方向发生改变}} else {bubble.x -= bubble.speed; if (bubble.x - bubble.speed <= 0) {bubble.x = 0;bubble.movex = 1;}}//若是往下跑,则一直加速度,碰到边界,改成反方向运动if (bubble.movey === 1) {bubble.y += bubble.speed;if (bubble.y + bubble.speed >= maxH) {bubble.y = maxH;bubble.movey = 0;}} else {bubble.y -= bubble.speed;if (bubble.y - bubble.speed <= 0) {bubble.y = 0;bubble.movey = 1;}}// 计算坐标圆心是为了判断气泡和气泡之间是否碰撞bubble.cx = bubble.x + circles[0].clientWidth / 2; //圆心等于:运动中x的值加上自身的半径bubble.cy = bubble.y + circles[0].clientHeight / 2;circles[bubble.index].style.left = bubble.x + 'px'; circles[bubble.index].style.top = bubble.y + 'px';crash(bubble.index); //每一个小球进行碰撞检测}, 30); //改变定时器的数值可以修改小球运动速度}// //对每个小球绑定计时器,让小球动起来for (let i = 0; i < container.length; i++) {move(container[i]);}}useEffect(()=>{bubbleMovement()},[])return(<div className={styles.bubbles} ref={mainRef}>{bubblesArr.map((item)=>{return <div key={item.key} className={styles.bubble}  style={{  backgroundImage:`url(${item.bgImg})`}}ref={getBubbles}/>})}</div>)
}export default Bubble;

css代码

.bubbles{width: 100vw;height: 95vh;position: relative;.bubble{position: absolute;background-repeat: no-repeat;background-size: contain;width: 1rem;height: 1rem;}
}

总结

1、实现方式:定位+随机改变x值和y值
2、需要注意的是:这里的实现逻辑是基于每个气泡的大小都一样的前提下实现的
3、具体的实现逻辑在bubbleMovement函数
(1)初始化,设置每个气泡的随机位置,移动距离、移动方向
(2)增加setInterval函数让每个气泡动起来 运动起来具体逻辑看move函数,大概的实现逻辑就是根据初始化的方向,往左或右或上或下以初始化时给定的速度走,走的时候需要监听是否到达边界,如果到达,继续往反方向走,走的时候并且需要监听是否碰撞
(3)监听碰撞:具体看这个函数 crash(bubble.index);这个函数大概的逻辑就是判断一下有没有碰撞到别的气泡,如果碰撞了,就判断一下当前气泡处于这个气泡的哪个方位,如果在左上方,那就继续往这个左上方走(既然碰撞了 并且气泡1位于气泡2的左上方,就说明之前气泡1运动的方向是右下才会导致碰撞)

css动效:气泡在屏幕上随机漂浮相关推荐

  1. 01超精美渐变色动态背景完整示例【CSS动效实战(纯CSS与JS动效)】

    若是大一学子或者是真心想学习刚入门的小伙伴可以私聊我,若你是真心学习可以送你书籍,指导你学习,给予你目标方向的学习路线,无套路,博客为证. 本节案例如下(其他动效篇幅原因逐步讲解,欢迎三连): 一.线 ...

  2. div旋转 vue_详细解析:uniapp项目|vue组件形式实现的水珠晃动loading纯CSS动效

    前言 上一篇文件给大家分享了一个颇具科技感的loading动效,[→传送门]这篇文章,小凡再来跟大家分享一个很酷的水珠晃动loading动效,依然是纯CSS实现的哦! 一.效果展示及思路分析 1.效果 ...

  3. 详细解析:uni-app|vue组件实现茶杯中茶水浮动loading纯CSS动效

    前言 前面我已经跟大家分享了[科技感Loading动效]和[水珠晃动Loading动效]两篇文章了,如果大家没有读过,建议大家花一点点时间去看一下,有了前两篇文章的基础后,这次,小凡给大家再分享一个茶 ...

  4. vue3使用swiper+animate.css动效

    场景:现在好多推广翻页的h5都会添加一些动效,大部分结合的是animate.css这个效果,参考 把夏日回忆 藏进自然笔记 animate.css动效是比较多样化并且很容易上手的css模板 那么swi ...

  5. python基础编程:Python实现鼠标自动在屏幕上随机移动功能

    这篇文章主要介绍了Python实现鼠标自动在屏幕上随机移动功能,具有很好的参考价值,希望对大家有所帮助.还等什么?一起跟随小编过来看看吧 本来想控制鼠标自动移动防止公司电脑自动休眠的策略,然而,实现了 ...

  6. vue项目调用通用组件_详细解析:uniapp项目|vue组件形式实现的科技感loading纯CSS动效...

    前言 本人是一枚并不安分守己的后端程序猿,一直对前端开发"垂涎三尺",所以,一有机会就会"不务正业"一番.最近,发现了一个非常好的学习资料,于是乎,我的老毛病又 ...

  7. 怎么实现hover_写CSS动效的常用套路(附demo的效果实现与源码)

    作者:alphardex https://juejin.im/post/5e070cd9f265da33f8653f0 前言 本文是笔者写CSS时常用的套路.不论效果再怎么华丽,万变不离其宗. 1.交 ...

  8. html与css结合动效案例,写CSS动效的常用套路(附demo的效果实现与源码)

    作者:alphardex https://juejin.im/post/5e070cd9f265da33f8653f0 前言 本文是笔者写CSS时常用的套路.不论效果再怎么华丽,万变不离其宗. 1.交 ...

  9. 干货分享|巧用CSS滤镜绘制安卓手机充电动效(uni-app|view组件版)

    前言 CSS3的滤镜真的是一个非常强大的功能,如果我们能够很好的利用它,并充分发挥我们的想象力,想要制作出非常惊艳的动效也是没有问题的哦.比如:接下来我要跟大家分享的一个巧妙使用CSS滤镜绘制出来的a ...

最新文章

  1. 潜移默化学会WPF--绘图 学习(一)
  2. PAXOS/RAFT理解
  3. RUP概述与实际应用的例子
  4. python模块使用_一文让你学会所有的python模块使用
  5. Java——集合(Map集合的两种迭代)
  6. 基于Java+SpringMvc+vue+element实现驾校管理系统详细设计
  7. java httpget 设置参数_java 模拟HTTP doPost请求 设置参数 | 学步园
  8. 快捷笔记应用Side Notes Mac
  9. 类的多态性:成员变量与成员方法访问特点(C++、Java)
  10. 华为最新解bl解锁码计算工具_黔隆科技刷机教程红米note4X低配版忘记密码刷机解锁降级救砖解屏幕锁账户锁教程...
  11. Wireshark网络抓包
  12. C语言 递归实现指数函数
  13. 【华为机试真题 Python实现】竖直四子棋
  14. ASM磁盘状态为forcing
  15. 中国菜刀使用教程--ctf 文件上传
  16. 【Bootstrap】007-全局样式:按钮
  17. gdb arm linux 下载,月光软件站 - 编程文档 - 其他语言 - 关于ARM Linux下的GDBServer
  18. 魔兽地图编辑器插件YDWE的使用与基本设置5 触发编辑器3 单位组选择多个单位
  19. null 和空值““
  20. JDBC(本质,配置环境变量,JDBC编程六步,类加载注册,sql注入,事务问题,封装工具类,悲观锁,乐观锁)

热门文章

  1. POJ 1511 Invitation Cards(最短路径,dijkstra 模板题)
  2. input 只能输入正整数,包括 0
  3. java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook] with root cause
  4. 产品:《人人都是产品经理》读书笔记
  5. 2021年全球医用气体压力调节器收入大约180.9百万美元,预计2028年达到226.3百万美元
  6. 明星2,3亿年收入,其实也合情合理
  7. linux 下使用百度云盘
  8. 互联网数字营销广告管理平台应用
  9. java zip 字符串_java字符串的压缩解压
  10. java基于ssm的洗衣店管理系统