アニメーションをよりシンプルにするFLIPテクノロジー

6919 ワード

あるとき、次のアニメーション効果をどのように実現するかを尋ねられました.
いくつかの要素カードが上から下に並べられ、あるカードを追加または削除すると、残りのカードはtransitionアニメーションの形で適切な位置に移動し、硬く現れるのではなく、適切な位置に移動します.
当時私はちょうどVueの中の内蔵コンポーネントtransitionの実現を見たことがあり、transitionコンポーネントの一部の原理でこの効果を完全に達成できることに気づいたが、なぜそうなのか深く探究したことがなく、表面にとどまっているだけで、それを知っているがなぜか分からないので、私はこの効果をどのように実現するか知っているが、なぜそうなのか説明するのは難しい.言語組織が比較的困難である
それから私は何気なく1篇の文章FLIP技術がWebレイアウトにもたらした変化を見て、すぐにはっと悟って、もとはこれはFLIPと呼ばれています
FLIP
FLIPは、FirstLastInvertPlayの4つの単語の頭文字の略であるFirstとは、何かが起こる前に(移行する前に)、現在の要素の位置とサイズ、すなわちアニメーションが始まる前の要素の位置とサイズ情報を記録することを意味し、getBoundingClientRect()というAPIを使用して処理することができる(ほとんどの場合、実際にはoffsetLeftoffsetTopも可能である)Last:エレメントが変化するようにコードを実行し、アニメーションの最後の状態におけるエレメントの位置と寸法、すなわちアニメーションが終了した後のエレメントの位置と寸法情報を記録するInvert:要素の最初の位置(First)と最後の位置(Last)との間の位置変化(必要に応じて2つの状態間の寸法の大きさの変化も計算できる)を計算し、これらの数字を用いて一定の計算を行い、要素を移動させる(transformによって要素の位置と寸法を変更する)、最初の位置(初期位置)にある錯覚を作成します
すなわち、要素を直接アニメーションの終了状態にし、transform属性を使用して要素をアニメーションの開始状態に戻す(この状態の情報はFirstステップで取得される)Play:要素を反転(firstの位置を装う)、transformnoneに設定することができます.transformの制約を失ったため、要素は必ずこの位置(つまりアニメーションの終了時の状態)に移動します.つまりlastの位置です.要素にtransitionの属性を加えると、この過程は自然にアニメーションの形で起こります
私の理解によって、アニメーションの要素に対して状態の1つの量子化を始めて、1つの公式に量子化して、ほとんどの連続するアニメーションはすべてこの公式を套用することによって完成することができて、アニメーションの開発の効率を高めて、更に詳しいのは自分でFLIP技術を参照してWebのレイアウトに持ってくる変化
カードカードカードの削除を実現FLIPという概念を理解してから、冒頭のアニメの効果を実現するのは簡単です.
First
アニメーション開始前の各カードの位置とサイズ情報を記録します.ここでは、カードのサイズはアニメーション中に実際には変化しないので、このステップを省略して、カードの位置情報のみを記録することができます.
また、全てのカードのサイズが同一であれば、全てのカードの位置情報を記録する必要はない.カード挿入や削除にかかわらず、位置座標が変化するカード座標の後ろに位置するカードのみが影響を受け、前のカードは変化しない
// First
activeList.forEach((itemEle, index) => {
  rectInfo = itemEle.getBoundingClientRect()
  transArr[index + stepIndex][0] = rectInfo.left
  transArr[index + stepIndex][1] = rectInfo.top
})

Last
アニメーションの終了状態は、カードを追加または削除した後、残りのカードの状態です.
if (updateStatus === 0) {
  //     
  newListData = this.state.listData.slice(0, activeIndex).concat({
    index: cardIndex++
  }, this.state.listData.slice(activeIndex))
} else {
  //     
  newListData = this.state.listData.filter((value, index) => index !== activeIndex)
}

この時点でカードにtransitionの属性が付加されていないため、カード数の更新という過程は、実は一瞬のことであり、人の目には何の変化も感じられないが、ページ上の要素は確かに変化しており、その時にカードの位置情報であるLastに必要なデータを測定する
Invert
アニメーションの開始段階で影響を受けるカードの位置情報を取得すると、transform属性で要素の位置を反転することができます.
// Last + Invert
const stepIndex = updateStatus === 0 ? 1 : 0
activeList.forEach((itemEle, index) => {
  rectInfo = itemEle.getBoundingClientRect()
  transArr[index + stepIndex][0] = transArr[index + stepIndex][0] - rectInfo.left
  transArr[index + stepIndex][1] = transArr[index + stepIndex][1] - rectInfo.top
}

Play
準備フェーズが完了すると、最後のステップPlayが実行されます.このステップの鍵は、要素にtransitionのプロパティを追加し、transformが要素に与える位置の変化を除去することです.
// Play
//   
transArr = getArrByLen(this.state.listData.length)
setTimeout(() => {
  this.setState({
    animateStatus: 3
  })
}, 0)

ブラウザはページのDOMの変化を統合して最適化するので、視覚的に所望のアニメーション効果を示すためには、ここでこの最適化を中断しなければならない.setTimeoutはよく使われる方法である.
ここまでで、冒頭のアニメ効果が完成したので、Live Demoを作りました.興味があれば自分で試してみてください.また、コードもGithubにアップロードできます.
画像の拡大/復元を実現
微信appのチャットインタフェースでプレビュー画像をクリックすると、画像がダイアログボックスから全画面にプレビューされるこの過程は、移行したアニメーションを使って、画像が小さい図から大きい図へと回復し、大きい図から小さい図へと回復する全過程を示しています.スケーリング過程は以下のように似ています.
これも連続動画ですが、もちろんFLIPで簡単に実現できます
First
ここでは、画像の位置とサイズの変化に関し、画像はFirstの小図原位置と小図サイズから、Lastの状態における大図位置と大図サイズとなっているので、この2つのデータを同時に取得する必要があるが、いずれも一度にgetBoundingClientRectを呼び出すことで完了することができる
Last
画像がプレビューされた状態のサイズと位置情報を取得し、getBoundingClientRectを使用して完了します.
また、transformのアニメーションをよりよく利用するために、ここでは、ピクチャの2つの状態における寸法変化をscale値の変化に変換し、FirstLastの状態における幅または高さの割合がこのscaleの取るべき値である(ピクチャ幅比例を変更しない前提で)
scaleValue = rectInfo.width / lastRectInfo.width

Invert transformを使用して位置と寸法の反転(すなわちscale値の変更)を行う
ここで注意すべき点は、transformのアニメーションのデフォルトのtransform-originが要素の中心である50% 50%であるが、算出されたlefttopは、スケーリングされていないピクチャに対して、scaleの値が一意でない場合、ピクチャアニメーションのFirstの状態がずれるため、このようなばらつきを解消するために、transform0 0とする必要がある
Play
画像にtransitionプロパティを追加し、関連するtransformプロパティを削除すると、アニメーションが開始されます.FLIPを適用した後、もともと厄介に見えたアニメーションが、簡単にモード化されて実現されたことがわかります.
拡大した画像が小図に戻る段階については、別のFLIPアニメーションと見なすことができ、引き続き適用すればよいが、このアニメーションは前の拡大アニメーションの逆方向であり、必要なサイズと位置情報はすでに入手されており、getBoundingClientRectを呼び出す過程を省くことができる.
同じLive Demoを作ったので、興味があれば自分で試してみてください.また、コードもGithubにアップロードできます.
小結
多くの前端の学友はアニメーションをあまり気にかけないようで、これはただ1つの補助能力だと思って、業務のロジックは最も重要で、その他はすべて後ろの駅に頼って、たとえ時間があっても気持ちを見てからやるかどうかを決めます
私の見方は、ビジネスロジックはもちろんトップに置かなければならないが、他の枝葉末節を軽視してはいけない.例えば、アニメーション、体験の良い動効はユーザーのより多くの滞在を引き付けることができ、共通の方法で側面からビジネスの転化効果を向上させ、特定のシーンでは、その役割は、ビジネスの目標と並ぶこともできます.