65

フレックスボックスからアイテムを削除すると、残りのアイテムはアニメーションではなく、新しい位置にすぐに「スナップ」します。

概念的には、アイテムの位置が変化しているため、トランジションが適用されると思います。

関連するすべての要素(フレックスボックスと子)に遷移プロパティを設定しました

フレックスボックスへの編集 (追加と削除) をアニメーション化する方法はありますか? これは実際には私にとってショーストッパーであり、フレックスボックスに欠けている部分の 1 つです。

4

7 に答える 7

27

Treehouseのこの例に基づいて @skyline3000 のデモを修正しました。ブラウザが変更された場合にこれが再び壊れるかどうかはわかりませんが、これはフレックスサイズの変更をアニメーション化する意図された方法のようです:

http://jsfiddle.net/2gbPg/2/

また、jQuery を使用しましたが、技術的には必要ありません。

.flexed {
    background: grey;
    /* The border seems to cause drawing artifacts on transition. Probably a browser bug. */
    /* border: 1px solid black; */
    margin: 5px;
    height: 100px;
    flex-grow: 1;
    transition: flex-grow 1000ms linear;
}

.removed {
    /* Setting this to zero breaks the transition */
    flex-grow: 0.00001;
}

CSS について注意すべきことの 1 つは、0 の a に遷移できないことですflex-grow。遷移しません。消えるだけです。非常に小さな値を入力するだけです。また、境界線を描画するときにアーティファクトのバグがあるように見えるので、この場合は背景を使用しました。

于 2014-07-26T22:33:53.983 に答える
14

フレキシブル ボックス モデルとグリッド レイアウトの仕様は、プロパティや有効な値も含めて常に変更されていることに注意してください。ブラウザの実装も完全には程遠いです。そうは言っても、要素がスムーズに移行するようにプロパティを移行し、最終的に DOM ツリーからノードを削除するのをflexリッスンすることができます。TransitionEnd

Chrome 21 で実行されている JSFiddle の例を次に示します: http://jsfiddle.net/5kJjM/ (中央の div をクリック)

var node = document.querySelector('#remove-me');

node.addEventListener('click', function(evt) {
  this.classList.add('clicked');
}, false);

node.addEventListener('webkitTransitionEnd', function(evt) {
  document.querySelector('#flexbox').removeChild(this);
}, false);
#flexbox {
  display: -webkit-flex;
  -webkit-flex-flow: row;
}

.flexed {
  border: 1px solid black;
  height: 100px;
  -webkit-flex: 1 0 auto;
  -webkit-transition: -webkit-flex 250ms linear;
}

.clicked {
  -webkit-flex: 0 0 auto;
}
<div id="flexbox">
  <div class="flexed"></div>
  <div class="flexed" id="remove-me"></div>
  <div class="flexed"></div>
</div>

編集:さらに明確にするために、ノードを削除するときは、そのフレックスを0に設定してからDOMから削除する必要があります。ノードを追加するときは、flex:0 で追加してから、flex:1 に移行します。

于 2012-07-03T16:07:37.383 に答える
7

要素を削除したときに要素をアニメーション化するコードペンを作成しました

HTML

<div class="container">
    <div></div>
    <div></div>
    ... more elements ...
</div>

CSS

.container{
    display: flex;
    flex-wrap: wrap;
}
.container > * {
    transform-origin: left top;
}

TypeScript

JavaScript が必要な場合は: Anything、関数のシグネチャと上部のインターフェイスから を削除するだけです。

interface FlexItemInfo {
  element: Element

  x: number
  y: number
  width: number
  height: number
}

const container = document.querySelector('.container')
for (const item of container.children) {
  item.addEventListener('click', () => {
    removeFlexItem(container, item)
  })
}

function removeFlexItem(container: Element, item: Element): void {
  const oldFlexItemsInfo = getFlexItemsInfo(container)
  container.removeChild(item)
  const newFlexItemsInfo = getFlexItemsInfo(container)

  aminateFlexItems(oldFlexItemsInfo, newFlexItemsInfo)
}

function getFlexItemsInfo(container: Element): FlexItemInfo[] {
  return Array.from(container.children).map((item) => {
    const rect = item.getBoundingClientRect()
    return {
      element: item,
      x: rect.left,
      y: rect.top,
      width: rect.right - rect.left,
      height: rect.bottom - rect.top,
    }
  })
}

function aminateFlexItems(
  oldFlexItemsInfo: FlexItemInfo[],
  newFlexItemsInfo: FlexItemInfo[]
): void {
  for (const newFlexItemInfo of newFlexItemsInfo) {
    const oldFlexItemInfo = oldFlexItemsInfo.find(
      (itemInfo) => itemInfo.element === newFlexItemInfo.element
    )

    const translateX = oldFlexItemInfo.x - newFlexItemInfo.x
    const translateY = oldFlexItemInfo.y - newFlexItemInfo.y
    const scaleX = oldFlexItemInfo.width / newFlexItemInfo.width
    const scaleY = oldFlexItemInfo.height / newFlexItemInfo.height

    newFlexItemInfo.element.animate(
      [
        {
          transform: `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`,
        },
        { transform: 'none' },
      ],
      {
        duration: 250,
        easing: 'ease-out',
      }
    )
  }
}
于 2018-12-04T17:35:39.183 に答える