web-dev-qa-db-ja.com

flexbox挿入と削除をアニメーション化できますか?

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

概念的には、アイテムの位置が変わっているため、移行が適用されると予想されます。

関係するすべての要素に遷移プロパティを設定しました(flexboxおよび子)

フレックスボックスへの編集(追加と削除)をアニメーション化する方法はありますか?これは実際に私にとっては最高の存在であり、フレックスボックスの欠品です。

40
mmaclaurin

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つは、ゼロのflex-growに移行することはできず、移行しないだけで消えることです。非常に小さな値を設定する必要があります。また、境界線を描画するときにアーティファクトのバグがあるようですので、この場合は背景を使用しました。

24
Chris Nicola

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

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>

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

11
skyline3000

誤って簡単な方法で動作するようになりました。基本的に、width:0;flex-grow:1そしてもちろんtransition:all 2s; 以上です。好奇心盛なハックです。

動作を確認

2

要素を削除するときに要素をアニメーション化するコードペンを実行しました。見てみましょう: https://codepen.io/MauriciAbad/pen/eQoQbK

最適化できますが、機能します。 ; D

HTML

<div class="container">
    <div id="0"></div>
    <div id="1"></div>
    ... more divs ...
</div>

CSS

.container{
    display: flex;
    flex-wrap: wrap;
}
.container > div{
    flex-grow: 1;
    transform-Origin: left top;
}

JavaScript

var cards = document.querySelectorAll('.container > div');
cards.forEach((card) => {
    card.addEventListener('click', () => {removeCard(card);});
});

var cardsOldInfo = //example content
    {"cardId": {
        "x": 100,
        "y": 200,
        "width": 100
        }
    };
var cardsNewInfo = cardsOldInfo;

function removeCard(card){
    cardsOldInfo = getCardsInfo();
    card.parentNode.removeChild(card);
    cardsNewInfo = getCardsInfo();
    moveCards();
}

function getCardsInfo(){
    updateCards();
    let cardsInfo = {};
    cards.forEach((card) => {
        var rect = card.getBoundingClientRect();
        cardsInfo[card.id] = {
            "x": rect.left,
            "y": rect.top,
            "width": (rect.right - rect.left)
        };
    });
    return cardsInfo;
}

function moveCards(){
    updateCards();
    cards.forEach((card) => {
        card.animate([ 
            {
                transform: `translate(${cardsOldInfo[card.id].x - cardsNewInfo[card.id].x}px, ${cardsOldInfo[card.id].y -cardsNewInfo[card.id].y}px) scaleX(${cardsOldInfo[card.id].width/cardsNewInfo[card.id].width})`
            }, 
            {
                transform: 'none'
            }
        ], { 
            duration: 250,
            easing: 'ease-out'
        });
        });
}

function updateCards(){
  cards = document.querySelectorAll('.container > div');
}

フレックスボックスの行をアニメーション化しようとしています。これはcssだけでは不可能でした。だから私は少しのjavascriptと私のflexbox行のための余分な親でそれをしました。

HTML

<div class="outer-container">
  <div class="inner-container">
    <div class="row">Row number 1</div>
  </div>
</div>

<button id="add">Add one more item</button>

CSS

.row{
  height : 40px;
  width : 200px;
  border: 1px solid #cecece;
  text-align : center;
  padding-top : 20px;
}

.outer-container {
  height : 500px;
  border : 1px solid blue;
  width : 250px;
  display: flex;
  justify-content : center;
  align-items: center;
}

.inner-container { 
  height : 42px;
  transition : height 0.3s;
 }

button {
  width : 200px;
  height: 30px;
  margin-left : 80px;
  margin-top : 10px;
}

Javascript:

(() => {
    let count = 1;
    document.querySelector("#add").addEventListener('click', () => {
        const template = document.createElement('div');
        count += 1;
        template.textContent = `Row number ${count}`;
        template.className = 'row';

        const innerContainer = document.querySelector('.inner-container');
        innerContainer.appendChild(template);
        innerContainer.style.height = `${innerContainer.clientHeight + 42}px`;
    })
})();

動作デモ: https://jsfiddle.net/crapbox/dnx654eo/1/

0
crapbox