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. python3 类字符串名实例化对象
  2. Titanium Developer
  3. 组件中props参数的应用
  4. 【Java每日一题】20170309
  5. 单点登录(SSO)—简介 1
  6. python计算小数点后有几位_python的数字类型
  7. HTML CSS JS(一)
  8. apache2.4.7 make报错[exports.lo] Error 1 解决方法
  9. Drawbot赋能商家: 智能助手主打上新详情
  10. Dev C++中编译问题
  11. U盘提示''这张磁盘有写保护''修复工具
  12. 什么是区块链,可能是史上最简单易懂的讲解
  13. Maya v1.0.7.0 类似Rolan简洁小巧简单易用的快速启动工具
  14. linux树莓派扩容,树莓派OpenWrt扩容磁盘分区大小
  15. 何俊谈阿里巴巴前端性能优化最佳实践-笔记
  16. 河流水质动态分段精细化制图
  17. 必读 | 深入理解 Flutter 的布局约束
  18. Cocos2dx游戏开发系列笔记10:解刨《战神传说》
  19. m基于ID3决策树算法的能量管理系统matlab仿真
  20. 沉入海底 2 年的微软数据中心浮出水面:故障率只有陆地上的 1/8,除了长点贝类和藻类完全没问题...

热门文章

  1. 八旗旗主,八大贝勒(亦称人王)
  2. java 数据库工资管理系统设计_数据库课程设计—企业工资管理系统(java版完整代码)...
  3. HDU - 5984 Pocky(数学推导)
  4. web开发学习,HTML标签语义化
  5. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java后台投票网站系统9h37l
  6. 机器学习:KNN完成英文手语分类
  7. 垃圾收集之Remember Set(CardTable)
  8. hdu 1824 Let's go home(2-sat 基础题)
  9. 搜款网新接口的展示过程
  10. SOTA 激光相机标定velo2cam_calibration(待完成)