与其他 React FLIP 库的比较
功能 | react-flip-move | react-overdrive | react-flip-toolkit |
---|---|---|---|
位置动画 | ✅ | ✅ | ✅ |
缩放动画 | ❌ | ✅ | ✅ |
透明度动画 | ❌ | ✅ | ✅ |
父元素大小变化时不扭曲子元素 | ❌ | ❌ | ✅ |
使用真正的 FLIP 而非克隆和交叉淡化 | ✅ | ❌ | ✅ |
使用弹簧效果进行动画 | ❌ | ❌ | ✅ |
支持基于弹簧的交错效果 | ❌ | ❌ | ✅ |
可与 React 以外的框架一起使用 | ❌ | ❌ | ✅ |
npm install react-flip-toolkit
或 yarn add react-flip-toolkit
用单个 Flipper
组件包裹所有需要动画的子元素,该组件有一个 flipKey
属性,每当需要触发动画时该属性都会变化。
用 Flipped
组件包裹需要动画的元素,这些组件应该有一个在不同渲染间匹配的 flipId
属性。
import React, { useState } from 'react' import { Flipper, Flipped } from 'react-flip-toolkit' const AnimatedSquare = () => { const [fullScreen, setFullScreen] = useState(false) const toggleFullScreen = () => setFullScreen(prevState => !prevState) return ( <Flipper flipKey={fullScreen}> <Flipped flipId="square"> <div className={fullScreen ? 'full-screen-square' : 'square'} onClick={toggleFullScreen} /> </Flipped> </Flipper> ) }
import React, { useState } from 'react' import { Flipper, Flipped } from 'react-flip-toolkit' const Square = ({ toggleFullScreen }) => ( <Flipped flipId="square"> <div className="square" onClick={toggleFullScreen} /> </Flipped> ) const FullScreenSquare = ({ toggleFullScreen }) => ( <Flipped flipId="square"> <div className="full-screen-square" onClick={toggleFullScreen} /> </Flipped> ) const AnimatedSquare = () => { const [fullScreen, setFullScreen] = useState(false) const toggleFullScreen = () => setFullScreen(prevState => !prevState) return ( <Flipper flipKey={fullScreen}> {fullScreen ? ( <FullScreenSquare toggleFullScreen={toggleFullScreen} /> ) : ( <Square toggleFullScreen={toggleFullScreen} /> )} </Flipper> ) }
import React, { useState } from 'react' import { Flipper, Flipped } from 'react-flip-toolkit' import shuffle from 'lodash.shuffle' const ListShuffler = () => { const [data, setData] = useState([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) const shuffleList = () => setData(shuffle(data)) return ( <Flipper flipKey={data.join('')}> <button onClick={shuffleList}> 随机排序</button> <ul className="list"> {data.map(d => ( <Flipped key={d} flipId={d}> <li>{d}</li> </Flipped> ))} </ul> </Flipper> ) }
通过为卡片的大小和位置变化添加动画,为动态卡片列表增添趣味。
<a href="https://codesandbox.io/s/list-transitions-ju549"> <img src="https://yellow-cdn.veclightyear.com/835a84d5/be14d762-e751-43ef-8c16-f5c43b92e2e0.gif" height="200px" alt='动画列表' /> </a>react-flip-toolkit
库提供了基于弹簧的交错配置,让你能够实现复杂的序列效果。
对于最基本的交错效果,你只需要在 Flipped
元素上添加一个 stagger
布尔属性:
<a href="https://codesandbox.io/s/wnnxl223n8"> <img src="https://yellow-cdn.veclightyear.com/835a84d5/79061692-85c9-48ba-9922-0c8ed205e7e3.gif" height="300px" alt='列表项选中状态的动画' /> </a><Flipped flipId={`element-${i}`} stagger> <AnimatedListItem/> </Flipped>
react-flip-toolkit
使用弹簧动画。要自定义弹簧效果,你可以传入一个预设名称:
// 弹簧预设可以是以下之一: "stiff", "noWobble", "gentle", "veryGentle", 或 "wobbly" <Flipper flipKey='foo' spring='wobbly'> {/* 放置 Flipped 组件 */} </Flipper>
或者自定义弹簧配置:
<Flipper flipKey='foo' spring={{ stiffness: 280, damping: 22 }} > {/* 放置 Flipped 组件 */} </Flipper>
有趣的动画通常除了简单的平移变换外还包含缩放变换。缩放动画的问题在于子元素 — 如果你将一个 div 放大 2 倍,它的任何子元素也会被放大,从而创建一个看起来很奇怪的动画。这就是为什么这个库允许你用一个带有 inverseFlipId
的 Flipped
组件包裹子元素,以抵消父元素的变换:
<Flipped flipId={id}> <div> <Flipped inverseFlipId={id} scale> <div>不会被扭曲的文本</div> </Flipped> </div> </Flipped>
默认情况下,父元素的缩放和平移变换都会被抵消(这允许子组件进行自己的 FLIP 动画而不受父元素影响)。
但在许多使用场景中,你还需要额外指定 scale
属性来限制调整为仅缩放,并允许定位随父元素移动。
注意: 具有反向变换的 DOM 元素应该紧贴其父容器,以实现最无缝的动画效果。
这意味着任何布局样式 — 内边距、弹性盒子等 — 应该应用于反转容器(用带有 inverseFlipId
的 Flipped
组件包裹的元素)而不是父 Flipped
容器。
react-flip-toolkit
可以很好地与客户端路由器配合使用,提供路由驱动的过渡效果:
<Route render={({ location, search }) => { return ( <Flipper flipKey={`${location.pathname}-${location.search}`} > {/* 包含 Flipped 组件的子路由放在这里 */} </Flipper> ) }} />
Flipper
包含所有需要动画的元素的父包装组件。通常每个页面只需要一个,但有时在页面的不同区域使用多个 Flipper
来处理不同的过渡效果会更方便。
<Flipper flipKey={someKeyThatChanges}>{/* 子元素 */}</Flipper>
属性 | 默认值 | 类型 | 详情 |
---|---|---|---|
flipKey (必填) | - | string , number , bool | 改变这个值会告诉 react-flip-toolkit 对包裹在 Flipped 组件中的子元素进行过渡。 |
children (必填) | - | node | 一个或多个元素子节点 |
spring | noWobble | string 或 object | 提供一个字符串引用预设弹簧之一 — noWobble (默认), veryGentle , gentle , wobbly , 或 stiff , 或者提供一个包含 stiffness 和 damping 参数的对象。在这里探索弹簧设置选项。这里提供的属性将作为默认弹簧设置,可以在 Flipped 组件上针对每个元素进行覆盖。 |
applyTransformOrigin | true | bool | react-flip-toolkit 是否应该为动画子元素应用 "0 0" 的 transform-origin (这通常但并不总是适用于 FLIP 动画) |
element | div | string | 如果你想让 Flipped 容器创建的包装元素是 div 以外的其他元素,可以在这里指定。 |
className | - | string | 应用于包装元素的类名,有助于样式设置。 |
staggerConfig | - | object | 为交错的 Flipped 子元素提供配置。配置对象可能看起来像下面的代码片段: |
staggerConfig={{ // "default" 配置将应用于没有显式键的交错元素 default: { // 默认方向是正向 reverse: true, // 默认为 .1, 0 < n < 1 speed: .5 }, // 这将应用于具有 stagger='namedStagger' 属性的 Flipped 元素 namedStagger : { speed: .2 } }}
属性 | 默认值 | 类型 | 详情 |
---|---|---|---|
decisionData | - | any | 有时,你可能希望 Flipper 的动画子元素根据状态转换表现不同 — 也许只有某些 Flipped 元素应该响应特定的变化进行动画。通过为 Flipper 组件提供 decisionData 属性,你可以使该数据在每个子 Flipped 组件的 shouldFlip 和 shouldInvert 方法中可用,这样它们可以自行决定是否进行动画。 |
debug | false | boolean | 这个实验性属性会在 FLIP 样式初始应用时暂停你的动画。这允许你在动画开始时检查状态,此时应该看起来与动画开始前的 UI 相似或相同。 |
portalKey | - | string | 通常,Flipper 组件只会对其后代应用过渡效果。这允许多个 Flipper 元素在同一页面上共存,但如果你使用 portals,它会阻止动画工作。你可以为 Flipper 提供一个唯一的 portalKey 属性,告诉它将元素选择范围扩大到整个文档,而不仅限于其子元素,这样 portals 中的元素也可以进行过渡。 |
onStart | - | function | 这个回调属性会在任何单独的 FLIP 动画开始之前被调用。它接收 Flipper 的 HTMLElement 和前面描述的 decisionData 对象作为参数。 |
onComplete | - | function | 这个回调属性会在所有单独的 FLIP 动画完成时被调用。它的唯一参数是在动画过程中被激活的 Flipped 组件的 flipId 列表。如果动画被中断,onComplete 仍会在正在进行的动画终止之前被调用。 |
handleEnterUpdateDelete | - | function | 默认情况下,react-flip-toolkit 会在动画新元素之前完成退出元素的动画,同时更新元素会立即变换。你可能想要对过渡序列有更多控制 — 比如,你想隐藏元素,暂停,更新元素,再次暂停,最后动画显示新元素。或者你可能希望过渡同时发生。如果是这样,请提供 handleEnterUpdateDelete 函数作为属性。理解其工作原理的最佳方式是查看这个交互式示例。 每次发生过渡时,handleEnterUpdateDelete 都会接收以下参数: |
handleEnterUpdateDelete({ // 该函数将进入元素的不透明度设为0,以便后续淡入效果 // 应该立即调用 hideEnteringElements, // 为所有 进入的元素调用 `onAppear` animateEnteringElements, // 为所有退出的元素调用 `onExit` // 返回一个 Promise,在所有元素退出后解析 animateExitingElements, // 主要事件:对更新的元素执行 `FLIP` 动画 // 同样返回一个 Promise,在动画完成时解析 animateFlippedElements })
Flipped
包装一个需要动画效果的元素。
例如,在一个组件中你可以有:
<Flipped flipId="coolDiv"> <div className="small" /> </Flipped>
在另一个组件的其他地方你可以有:
<Flipped flipId="coolDiv"> <div className="big" /> </Flipped>
它们将通过 react-flip-toolkit
进行过渡动画。
Flipped
组件不会生成任何标记,它只是将一些属性传递给其包装的子元素。
如果你想包装 React 组件而不是像 div
这样的 JSX 元素,你可以提供一个渲染属性,然后在你的组件中将 flippedProps
直接应用到被包装的元素上:
<Flipped> {flippedProps => <MyCoolComponent flippedProps={flippedProps} />} </Flipped> const MyCoolComponent = ({ flippedProps }) => <div {...flippedProps} />
你也可以简单地提供一个普通的 React 组件,只要该组件将未识别的属性直接传递给包装的元素(这种技术适用于包装样式化组件):
<Flipped> <MyCoolComponent /> </Flipped> const MyCoolComponent = ({ knownProp, ...rest }) => <div {...rest} />
属性 | 默认值 | 类型 | 详情 |
---|---|---|---|
children (必需) | - | node 或 function | 用 Flipped 组件包装单个元素、React 组件或渲染属性子元素 |
flipId (除非提供 inverseFlipId,否则为必需) | - | string | 用于告诉 react-flip-toolkit 如何在渲染之间匹配元素,以便进行动画处理。 |
inverseFlipId | - | string | 引用父 Flipped 容器的 id,其变换你想要抵消。如果提供此属性,Flipped 组件将成为其有限版本,仅负责抵消其父变换。它将读取任何提供的 transform 属性,并忽略所有其他属性(除了 inverseFlipId )。在此处阅读更多关于抵消父变换的信息。 |
transformOrigin | "0 0" | string | 这是一个便捷方法,用于将正确的 CSS transform-origin 应用于被 FLIP 的元素。如果作为属性提供,这将覆盖 react-flip-toolkit 默认应用的 transform-origin: 0 0; 。 |
spring | noWobble | string 或 object | 提供一个字符串引用预设的弹簧之一 — noWobble (默认)、veryGentle 、gentle 、wobbly 或 stiff ,或者提供一个包含 stiffness 和 damping 参数的对象。在此处探索弹簧设置选项。 |
stagger | false | boolean 或 string | 提供一个自然的、基于弹簧的错开效果,其中每个项目的弹簧缓动都固定在前一个的移动上。提供 true 以将元素与所有其他错开的元素错开。如果你想更精细地控制,可以提供一个字符串键,元素将与具有相同键的其他元素错开。 |
delayUntil | false | string (flipId) | 通过提供对另一个 Flipped 组件的引用来延迟动画,它应该等待该组件后再开始动画(另一个 Flipped 组件应该有错开延迟,因为这是唯一需要此属性的用例。) |
上面的动画使用 onAppear
和 onExit
回调来实现淡入和淡出动画。
属性 | 参数 | 详情 |
---|---|---|
onAppear | element , index , {previous: decisionData, current: decisionData } | 当元素首次出现在 DOM 中时调用。第一个参数提供正在过渡的 DOM 元素的引用,第二个参数是元素相对于所有出现元素的索引。注意:如果你提供 onAppear 属性,元素的默认不透明度将 被设置为 0,以允许你将其动画化而不会有任何初始闪烁。如果你不想要任何不透明度动画,只需在 onAppear 函数中立即将元素的不透明度设置为 1。 |
onStart | element , {previous: decisionData, current: decisionData } | 当元素的 FLIP 动画开始时调用。第一个参数提供正在过渡的 DOM 元素的引用。 |
onStartImmediate | element , {previous: decisionData, current: decisionData } | 类似于 onStart ,但保证在 FLIP 动画的初始刻度上为所有 FLIP 元素运行,在下一帧渲染之前,即使元素有错开延迟。第一个参数提供正在过渡的 DOM 元素的引用。 |
onSpringUpdate | springValue | 使用当前的弹簧值调用(通常在 0 - 1 之间,但可能根据弹簧的"弹性"程度短暂超出或低于该范围)。如果你想要与 FLIP 过渡同时调整其他非 FLIP 动画,这个属性很有用。 |
onComplete | element ,{previous: decisionData, current: decisionData } | 当 FLIP 动画完成时调用。第一个参数提供正在过渡的 DOM 元素的引用。(如果过渡被新的过渡打断,onComplete 仍会被调用。) |
onExit | element , index , removeElement , {previous: decisionData, current: decisionData } | 当元素从 DOM 中移除时调用。它必须在退出过渡完成时调用 removeElement 函数。 |
默认情况下,FLIP 元素的 translate、scale 和 opacity 属性都会被变换。但是,某些效果需要更多控制,所以如果你指定了以下任何属性,只有指定的属性会被缓动:
属性 | 类型 | 详情 |
---|---|---|
translate | bool | 缓动 translateX 和 translateY |
scale | bool | 缓动 scaleX 和 scaleY |
opacity | bool |
控制 FLIP 何时发生的函数
属性 | 参数 | 详情 |
---|---|---|
shouldFlip | previousDecisionData , currentDecisionData | 一个函数,提供由 Flipper 组件传递的当前和之前的 decisionData 属性。返回一个 boolean 值,表示 Flipped 组件在特定时刻是否应该动画化。 |
shouldInvert | previousDecisionData , currentDecisionData | 一个函数,提供由 Flipper 组件传递的当前和之前的 decisionData 属性。返回一个 boolean 值,表示是否对所有通过 inverseFlipId 请求的 Flipped 子元素应用反转变换。 |
Spring
为了方便,react-flip-toolkit
导出了一个小函数,用于访问用于创建 FLIP 过渡的相同弹簧系统。
<a href="https://codesandbox.io/s/react-flip-toolkit-spring-example-e6pyc"> <img src="https://yellow-cdn.veclightyear.com/835a84d5/c69e11b9-f3c2-4b8b-b9f8-e42ea58bd6b6.gif" alt="弹簧示例" width="200px"/> </a>import { spring } from 'react-flip-toolkit' spring({ config: "wobbly", values: { translateY: [-15, 0], opacity: [0, 1] }, onUpdate: ({ translateY, opacity }) => { el.style.opacity = opacity; el.style.transform = `translateY(${translateY}px)`; }, delay: i * 25, onComplete: () => console.log('完成') });
如果需要在所有地方禁用(或重新启用)FLIP动画,可以通过编程方式调用以下函数。
disableFlip()
全局开关,用于禁用所有Flipper
容器中的所有动画。
enableFlip()
全局开关,用于(重新)启用所有Flipper
容器中的所有动画。默认情况下,动画是启用的。只有在之前使用disableFlip()
禁用了动画时,才需要调用此函数。
isFlipEnabled()
返回一个布尔值,指示动画是全局启用还是禁用。
Flipper
组件的flipKey
属性。Flipped
组件包裹的是另一个React组件而不是DOM元素,使用渲染属性获取Flipped属性并传递给必要的DOM元素。Flipped
属性的元素是否在DOM中可见?react-flip-toolkit
会尝试优化性能,不会对屏幕外的元素或没有宽度和高度的元素进行动画处理。display:inline
元素无法进行动画。如果你想让inline
元素产生动画效果,请设置display:inline-block
。flipId
是唯一的。 在任何时候,页面上只能有一个元素具有指定的flipId
。如果页面上有多个具有相同id的Flipped
元素,动画将会出错。div
中,实际上你是在为div添加动画,这可能会在某些时候导致宽度比预期的要大得多,从而影响动画效果。检查是否需要给动画元素添加inline-block
样式。debug
属性。如果你仍然无法找出问题所在,可以直接在Flipper
组件上添加debug
属性来暂停过渡的开始。React-flip-toolkit
在底层做了很多工作来尝试最大化你的动画性能 —— 例如,不会对屏幕外的元素进行动画处理,并且样式更新会被批量处理以防止布局抖动。
然而,如果你正在构建特别复杂的动画 —— 涉及数十个元素或大型图片的动画 —— 还有一些额外的策略可以用来确保动画的性能。
记忆化
当你使用react-flip-toolkit
触发复杂的FLIP动画时,React
可能会在允许动画开始之前花费宝贵的毫秒时间进行不必要的协调工作。如果你注意到动画触发和开始之间有轻微的延迟,这可能就是原因。为了绕过这种可能不必要的工作,尝试使用React.memo
或PureComponent
对你的动画元素进行记忆化,并看看是否可以重构你的代码,以在动画即将发生时最小化对动画子元素的属性更新。
will-change:transform
.box { will-change: transform; }
这个CSS属性告诉浏览器预期元素将发生变化。应谨慎使用,因为它可能会增加浏览器资源的使用。如果你注意到动画中存在渲染问题,可以尝试看看它是否能提高动画的性能。
字节跳动发布的AI编程神器IDE
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语 言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供 便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的 高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。
openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。