阅读 59

【思考】FLIP 关键流程

FLIP 是什么呢?

已经有很多文章介绍过 FLIP,大名鼎鼎的 vue 里面的 transition-group,使用的也是 FLIP

参考 Github 地址:https://github.com/googlearchive/flipjs

通过官方文档,我们大概了解了 FLIP 的流程

主要概括为 四个步骤:

  1. First(元素初始状态)
  2. Last(元素完成状态 - Layout Change)
  3. Invert(状态反转操作)
  4. Play(播放动画)

通过上述四个步骤,可以帮助开发者轻松实现过渡效果,几乎不用额外代码的情况下,可以实现复杂的过渡动画效果

主要疑问

第二个步骤,即 Layout Change 以后,还能继续显示动画吗?

例如,一辆车已经到达了目的地以后,再去显示一次这辆车从 出发地 到 目的地 的动画

像上面的描述那样操作元素,我们看到的动画就会很奇怪:车闪现到了目的地,然后再闪回起点,再从起点 以动画的方式去到 目的地

带着这个疑问去看相关的源码

源码地址:https://github.com/davidkpiano/flipping

查看源码后发现,果然是 车 已经到达目的地后,再把 车 重新从 出发地 到 目的地的过程绘制出来

如上图,当车到达目的地,layout 更新后,还没刷新到屏幕前,把 车 设置回出发地,然后再把 车 从出发地 到 目的 的运动过程 绘制出来

做个实验

修改 FLIP 源码,在接口 wrap 方法中,this.flip 的流程上,添加个 setTimeout 或者 requestAnimationFrame 处理,看看会出现什么情况

修改前:

修改后:

“汽车” 先出现在了 目的地,然后瞬间被搬回 出发地,然后再出发 至 目的地

总结关键流程

元素样式更新后,立刻 同步 进行 layout 更新(通知浏览器,让浏览器更新元素的位置信息,但由于还没释放 js 线程,浏览器还不会把 元素 的新位置 更新到屏幕上)

layout 更新后,即可获得各元素新的表现信息(位置,宽高等)(获得车在终点的位置信息)

同步执行 再一次更新元素的样式表现(把车放回原点)

拓展思考

活用 浏览器重排(reflow 更新 layout 信息),我们可以实现 类似 “预渲染” 的能力

在 FLIP 中,通过 getBoundingClientRect 接口,完成了一次 layout 的更新

在同一次的 task 中,layout 的更新只会实际执行一次,所以 FLIP 源码中的多次使用 getBoundingClientRect 并不会引起多次 reflow 从而导致页面性能下降的问题

FLIP 无法实现元素 删除前后(卸载)的过渡效果

目前前端主流的 过渡方案 有两种:

  1. 过渡模式
  2. FLIP

FLIP 主要用于 layout 更新时的自动过渡

过渡模式(before-enter、enter-active、active、before-leave、leave-active)则可以实现单个元素在声明周期中的细节过渡

相比之下,

FLIP 可以实现 layout 的自动过渡,而过渡模式则不行

过渡模式支持 元素生命周期过渡效果,而 FLIP 则不行

如果想要实现 支持 元素生命周期过渡 以及 layout 更新自动过渡的效果,就有必要考虑将 过渡模式 以及 FLIP 合并一起使用

Vue 的过渡方案 transition-group 就实现了合并的效果

如有错误,欢迎斧正