React实战中的bug-滑动动画与遮罩层,以及点击bug

✊不积跬步,无以至千里;不积小流,无以成江海

需求描述

要实现如图需求的动画,点击左上角图标召唤菜单栏,菜单栏滑动进入,主页面用黑色遮罩层遮挡。

使用react spring库实现遮罩层和主页层的遮罩动画。基础代码长这样。

ini 复制代码
const maskStyles = useSpring({opacity: visible ? 1 : 0})
const menuStyles = useSpring({
    opacity: visible ? 1 : 0,
    transform: visible ? 'translateX(0%)' : 'translateX(-100%)',
  })
  
......

<animated.div fixed top-0 left-0 w="100%" h="100%" className="bg-black:75"
        style={maskStyles} z="[calc(var(--z-menu)-1)]" onClick={onClickMask}/>
     ......
<animated.div fixed top-0 left-0 w="70vw" max-w-20em h-screen flex flex-col
        style={menuStyles}/>
        
 ......

但是这样运行的时候会发现有个问题,鼠标根本没法点击左上角图触发发菜单栏。检查了一下发现是有一个fix的div把整个页面盖住了,相当于有一个透明的浮在所有的上面。于是尝试开始解决。

首先删掉遮罩层的div,发现页面能够正常点击,但由于删掉了遮盖层,导致召唤菜单栏之后背景为白色。如下图:

可以得到结论,说明由于遮罩层并没有位移,看不见的时候在页面正上方,那么通过给遮罩层加上位移可以解决这个问题吗?即代码中加入:

php 复制代码
const maskStyles = useSpring({opacity: visible ? 1 : 0,
//加入位移代码
    transform: visible ? 'translateX(0%)' : 'translateX(-100%)'})

const menuStyles = useSpring({
    opacity: visible ? 1 : 0,
    transform: visible ? 'translateX(0%)' : 'translateX(-100%)',
  })
  
...

发现页面长这样:

虽然能动起来了,但是动画非常丑,是从左到右滑动的。黑色遮罩需要时从当前位置慢慢浮现,而不是滑动的。

解决思路

已知,我们期待黑色遮罩从背景中慢慢浮现,即不透明度从0到1,但当不透明度为0的时候,又会挡住点击图标导致无法触发操作。

解决思路:能否一开始将遮罩藏起来,等点击时再将遮罩召唤出来。

ini 复制代码
//添加状态
const [maskVisible, setMaskVisible] = useState(false)

const maskStyles = useSpring({opacity: visible ? 1 : 0})
const menuStyles = useSpring({
    opacity: visible ? 1 : 0,
    transform: visible ? 'translateX(0%)' : 'translateX(-100%)',
  })
  
......

<animated.div fixed top-0 left-0 w="100%" h="100%" className="bg-black:75"

//给style同时添加状态
        style={...maskStyles, visibility: (maskVisible ? 'visible' : 'hidden') as 'visible' | 'hidden'} 
        
        z="[calc(var(--z-menu)-1)]" onClick={onClickMask}/>
     ......
<animated.div fixed top-0 left-0 w="70vw" max-w-20em h-screen flex flex-col
        style={menuStyles}/>
        
 ......

但用这样的方法会发现,遮罩还是不见了,如下图所示。

出现这个问题的原因是因为遮罩层一直被hidden。

(opacity是0时,对象看不见可以点击;visiblity是hidden时,对象看不见也无法点击;display是none时,对象看不见也无法点击;display: none 会将元素从文档流中删除,元素不会占用任何空间,也不会响应鼠标事件。visibility: hidden 会将元素隐藏,元素仍然会占用空间,并会响应鼠标事件。)

不能让遮罩层一直被hidden,它需要将遮罩在某个时刻被再被召唤回visible的状态,并让它们在两种状态间自由切换。

因此,

可以选择一些回调函数来表示状态的切换。

javascript 复制代码
const [maskVisible, setMaskVisible] = useState(false)

const maskStyles = useSpring({opacity: visible ? 1 : 0})
const menuStyles = useSpring({
    opacity: visible ? 1 : 0,
    
    //添加回调函数表示状态
    //因为动画其实有两个:
    //1.打开动画 0->1
    //2.关闭动画 1->0
    //所以我们需要依据当前的状态做判断,传入一个状态值命名为value
    onStart: ({ value }) => {
        //如果当前的opacity < 0.1,就让遮罩被看见
    if (value.opacity < 0.1) { setMaskVisible(true) }
  },
  onRest: ({ value }) => {
      //如果当前的opacity < 0.1,就让遮罩被关闭
    if (value.opacity < 0.1) { setMaskVisible(false) }
  }
  })
  
......

加入状态切换后如图所示:

bug解决,得到了想要的动画~

相关推荐
2601_949593656 小时前
基础入门 React Native 鸿蒙跨平台开发:模拟智能音响
react native·react.js·harmonyos
xiaoqi9227 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233228 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头88219 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
xiaoqi92211 小时前
React Native鸿蒙跨平台如何实现分类页面组件通过searchQuery状态变量管理搜索输入,实现了分类的实时过滤功能
javascript·react native·react.js·ecmascript·harmonyos
打小就很皮...11 小时前
Tesseract.js OCR 中文识别
前端·react.js·ocr
qq_1777673712 小时前
React Native鸿蒙跨平台实现应用介绍页,实现了应用信息卡片展示、特色功能网格布局、权限/联系信息陈列、评分展示、模态框详情交互等通用场景
javascript·react native·react.js·ecmascript·交互·harmonyos
jin12332213 小时前
基于React Native鸿蒙跨平台地址管理是许多电商、外卖、物流等应用的重要功能模块,实现了地址的添加、编辑、删除和设置默认等功能
javascript·react native·react.js·ecmascript·harmonyos
2501_9209317013 小时前
React Native鸿蒙跨平台医疗健康类的血压记录,包括收缩压、舒张压、心率、日期、时间、备注和状态
javascript·react native·react.js·ecmascript·harmonyos
落霞的思绪14 小时前
配置React和React-dom为CDN引入
前端·react.js·前端框架