9

このフィドルを見てください:http://jsfiddle.net/dhcyA/

ブロックをクリックしてみてください。私が欲しいのは、他の要素が消えたときに、選択したブロックが、今のようにジャンプするのではなく、与えられた位置にアニメーション化/緩和することです。次に、ボックスをもう一度クリックすると同じアニメーションが繰り返されますが、元の場所に戻ります。

覚えておくべきかもしれませんが、
私は応答性の高いデザインを使用しています。つまり、ウィンドウを拡大縮小した後、これらのブロックを垂直方向と水平方向に配置できます。

フィドルや提案に関する再定義は素晴らしいでしょう!

4

5 に答える 5

7

これが私の解決策です。

既存のマークアップに、ラッパー内のボックスの位置を計算するラッパー分割を追加しました。このような

<div id="wrapper">
    <div class="block">
        <h2>I'm block 1</h2>
    </div>
    ....
</div>

ブロックの流動性を維持するために、ブロックをラッパーに配置する関数を作成しました。ブロックの位置の関数は次のとおりです。

var reposition = function() {
    wrapper = $("#wrapper");
    console.log(wrapper.innerWidth());
    pLeft = 0;
    pTop = 0;
    maxRowHeight = 0;
    $(".block").each(function(){
        if($(this).data('active')) {
            $(this).data('top', pTop);
            $(this).data('left', pLeft);
        } else {
            $(this).stop(0,0).animate({
              'top' : pTop + 'px',
              'left' : pLeft + 'px'
            });
        }
            pLeft += $(this).outerWidth() + parseInt($(this).css('marginLeft'));
            if($(this).height() > maxRowHeight) maxRowHeight = $(this).outerHeight() + parseInt($(this).css('marginTop')); //Find out the longest block on the row

            if(pLeft + $(this).next().outerWidth() + parseInt($(this).next().css('marginLeft')) >= wrapper.innerWidth()) {
               pLeft = 0;
               pTop += maxRowHeight;
               maxRowHeight = 0;
            }

    });    
};

最後に、ブロックを切り替えるスクリプト

$(".block").click(function() {

    $(this).siblings().slideToggle('slow'); //Toggle other blocks

    if(!$(this).data('active')){ //if the block is not active
        $(this).data('left', $(this).position().left); //sets its left
        $(this).data('top', $(this).position().top);   // and top position
        $(this).animate({ //animate at the top and bottom
            top:0,
            left:0
        },'slow');

        $(this).data('active',true);

    }else{

        $(this).animate({ //animate to its last known position
            top:$(this).data('top'),
            left:$(this).data('left')
        },'slow');

        $(this).data('active',false);
    }
});

デモ

  • Demo [Full] (サイズを変更して、流動性が維持されていることを確認してください)
  • Demo [Full] (可変高さを示すバージョン)

このソリューションが提供するものは次のとおりです。

  • 最後の位置を記憶し、この位置に/から徐々にアニメーション化します
  • ブロックの位置は、読み込み時とサイズ変更のたびに計算され、アニメーション化されます
  • 再配置が行われるため、絶対位置を使用しているにもかかわらず、ブロックの流動的な性質が維持さ$(window).resize()れます。
  • 可変高さをサポート
  • 既存のマークアップと CSS のマイナー チェンジ

また、Gaby によって拡張された 2 つの問題を修正しました

  • 各ブロックマージンを個別に計上
  • サイズ変更後に要素の位置を再計算します
于 2012-10-29T03:03:55.747 に答える
5

最終更新

これは、 JSを使用して、残りの位置(単純な計算)とCSS遷移を設定するための完全に機能するソリューション(私の意見では非常に簡単です)です。

http://jsfiddle.net/gaby/pYdKB/3/でのデモ

流動性を維持し、float:left任意の数の要素で機能します。また:nth-child、スタイリングを維持できます。また、複数の要素を表示したままにする場合にも機能します。

javascript

var wrapper = $('.wrapper'),
    boxes = wrapper.children(),
    boxWidth = boxes.first().outerWidth(true),
    boxHeight = boxes.first().outerHeight(true); 

function rePosition(){
    var w = wrapper.width(),
        breakat = Math.floor( w / boxWidth ); // calculate fluid layout, just like float:left

    boxes
        .filter(':not(.go)')
        .each(function(i){
            var matrixX = ((i)%breakat)+1,
                matrixY = Math.ceil((i+1)/breakat);

            $(this).css({
                left:(matrixX-1) * boxWidth ,
                top: (matrixY-1) * boxHeight
            });
        });
}

$('.box').click(function(){
    $(this)
        .siblings()
        .toggleClass('go');// just add the go class, and let CSS handle the rest

    rePosition(); // recalculate final positions and let CSS animate the boxes
});

$(window).resize(rePosition);
$(window).trigger('resize');

CSS

.wrapper{
    position:relative;
}

.box{
    width:200px;
    height:100px;
    position:absolute;
    margin:5px;
    cursor:pointer;
    overflow:hidden;
    text-align: center;
    line-height: 100px;

        -moz-transition-property: top,left,width,height;
     -webkit-transition-property: top,left,width,height;
         -ms-transition-property: top,left,width,height;
          -o-transition-property: top,left,width,height;
             transition-property: top,left,width,height;

        -moz-transition-duration: 1s;
     -webkit-transition-duration: 1s;
         -ms-transition-duration: 1s;
          -o-transition-duration: 1s;
             transition-duration: 1s;
}

.go{
    height:0;
    width:0;
}

:@Athariがコメントで正しく言及されているように、最も幅広いサポートのためにすべてのブラウザープレフィックスを含める必要があります。(私の最初の答えには、moz / webkitと標準のみが含まれていました)


元の回答

現在のHTML構造で直接行うことはできません。フロートコンセプトはそれをサポートしていません。

しかし、追加のラッパーを購入できるのであれば、問題はありません。

追加のラッパー要素の内容をスライドするだけです。

floatラッパー要素にコードを配置し、

$(document).ready(function() {

    $(".block-wrapper").click(function() {
        $(this).siblings().find('.block').slideToggle("slow");
    });

});

http://jsfiddle.net/gaby/t8GNP/でのデモ


アップデート#1

クリックした要素を左上と後ろに移動する必要がある場合、CSSでは実際には移動できません。

それらを手動で(JSを介して)配置し、CSSトランジション(またはjquery)を設定し、クリックしたら新しい位置を適用する必要があります。

後で、複数を表示したままにして、位置を変更したい場合があります。

したがって、これと、より多くの状況/レイアウトを処理できる優れたIsotopeプラグインを確認することをお勧めします。

于 2012-10-28T21:31:59.127 に答える
3

これが私のバージョンです: http://jsfiddle.net/selbh/dhcyA/92/ (javascriptのみが変更され、応答性があります)

$(document).ready(function() {

    $(".block").click(function() {
        var $this = $(this);
        var pos = $this.offset();
        var $siblings = $(this).siblings().add(this);
        var marginTop = $this.css('marginTop').replace(/[^-\d\.]/g, '');
        var marginLeft = $this.css('marginLeft').replace(/[^-\d\.]/g, ''); 

        var $clone = $this.clone();

        $siblings.slideToggle("slow");

        $clone.css({
            position: 'absolute',
            left: pos.left - marginLeft,
            top: pos.top - marginTop,
            'background-color': $this.css('background-color')
        });

        $('body').append($clone);

        $this.css('opacity', 0);

        $clone.animate({
            'left': 0,
            'top': 0
        });


        $clone.click(function() {
            $siblings.slideToggle("slow", function() {
                $clone.remove();
                $this.css('opacity', 1);
            });

            $clone.animate({
                left: pos.left - marginLeft,
                top: pos.top - marginTop
            });
        });


    });

});​
于 2012-11-03T22:44:04.163 に答える
2

ちょっと眠いので(ここは午前2時30分です)、アイデアを提供するために半分完成した回答をここに残します(30分で完了したので、さらに30分あれば本当に素晴らしいものが得られると思います)

http://jsfiddle.net/LuL2s/2/

トリックは、アニメーションを容易にし、出現と消滅の違いを生み出すブロックホルダーによってもたらされます

JS

$(document).ready(function() {
    var open = true;
    $(".block").click(function() {
            var $this = $(this);
            var count = 0;
        if (open) {
            $this.parent().siblings().children().slideToggle("slow", function(){
                if (count++ == 2) {                 
                    $this.parent().siblings().animate({width: 'toggle', height:'toggle'});
                }
            });
        } else {
            $this.parent().siblings().animate({width: 'toggle', height:'toggle'}, function(){
                if (count++ == 2) {                 
                    $this.parent().siblings().children().slideToggle("slow");                
                }
            });

        }
        open = !open;                      
    });

});

HTML

<div class="block-holder">
    <div class="block">
        <h2>I'm block 1</h2>
    </div>
</div>

<div class="block-holder">
    <div class="block">
        <h2>I'm block 2</h2>
    </div>
</div>

<div class="block-holder">
    <div class="block">
        <h2>I'm block 3</h2>
    </div>
</div>

<div class="block-holder">
    <div class="block">
        <h2>I'm block 4</h2>
    </div>
</div>

CSS

.block {
    width: 100%;
    height: 100%;
    text-align: center;
    line-height: 100px;
    cursor: pointer;
}
.block-holder:nth-child(1) .block {
    background: green;
}
.block-holder:nth-child(2) .block {
    background: red;
}
.block-holder:nth-child(3) .block {
    background: orange;
}
.block-holder:nth-child(4) .block {
    background: pink;
}

.block-holder {
    width: 200px;
    height: 100px;
    float: left;
    margin: 20px;
}
于 2012-10-29T01:33:09.573 に答える
2

グレートチャレンジ!

新しいバージョン:

これは、ブロックが行にとどまるようにするため、はるかに優れたバージョンです。行にもスタイルを適用できるようcssに機能を追加しました。nth-child同じ HTML 構造も維持します。

デモ: http://jsfiddle.net/MadLittleMods/fDDZB/23/

この新しいリビジョンの jQuery は次のようになります。

$('.block').on('click', function() {
    var block = $(this);

    // Keep the blocks in line
    makeRows($('body'));

    $('.block').not(this).each(function() {

        // If sibling on the same level, horizontal toggle
        // We also want ignore the toggleMethod if it is shown because we might need to reassign
        if (($(this).position().top == block.position().top && (($(this).data('toggle') == -1) || $(this).data('toggle') == null)) || ($(this).data('toggle') != -1 && $(this).data('toggleMethod') == 'side'))
        {
            $(this).data('toggleMethod', 'side');

            // Hide block
            if ($(this).data('toggle') == -1 || $(this).data('toggle') == null)
            {
                // Set properties for later use in show block
                $(this).data('overflowBefore', $(this).css('overflow'));
                $(this).css('overflow', 'hidden');
                $(this).data('marginBefore', $(this).css('margin'));

                var width = $(this).width();
                $(this).animate({
                    width: 0,
                    margin: 0
                }, function() {
                    $(this).data('toggle', width);
                });
            }
            // Show block
            else
            {
                $(this).css('overflow', $(this).data('overflowBefore'));

                $(this).animate({
                    width: $(this).data('toggle'),
                    margin: $(this).data('marginBefore')
                }, function() {
                    $(this).data('toggle', -1);
                });
            }
        }
        // Do a normal vertical toggle
        else 
        {
            $(this).data('toggleMethod', 'top');
            $(this).slideToggle('slow');
        }
    });

});

// Make rows to make the blocks in line
function makeRows(container)
{
    // Make rows so that the elements stay where they should
    var containerWidth = container.width();
    var currentRowWidth = 0;

    // Add styles first so nothing gets messed up
    container.children().each(function() {
        var itemCSS = css($(this));
        $(this).css(itemCSS);
    });

    // Now assemble the rows
    container.children().each(function() {

        var blockWidth = $(this).outerWidth() + parseInt($(this).css('margin-left')) + parseInt($(this).css('margin-right'));

        if((currentRowWidth + blockWidth) < containerWidth)
        {
            currentRowWidth += blockWidth;
        }
        else
        {
            Array.prototype.reverse.call($(this).prevUntil('.row')).wrapAll('<div class="row"></div>');
            $(this).prev().append('<div class="row_clear" style="clear: both;"></div>');

            currentRowWidth = 0;
        } 
    });    
}

// Remove the rows added
function deleteRows()
{
    var content = $('.row').contents()
    $('.row').replaceWith(content);

    $('.row_clear').remove();
}

$(window).resize(function() {
    deleteRows();
});



// Functions courtesy of marknadal
// https://stackoverflow.com/a/5830517/796832
function css(a)
{
    var sheets = document.styleSheets, o = {};
    for(var i in sheets) {
        var rules = sheets[i].rules || sheets[i].cssRules;
        for(var r in rules) {
            if(a.is(rules[r].selectorText)) {
                o = $.extend(o, css2json(rules[r].style), css2json(a.attr('style')));
            }
        }
    }
    return o;
}

function css2json(css)
{
    var s = {};
    if(!css) return s;
    if(css instanceof CSSStyleDeclaration) {
        for(var i in css) {
            if((css[i]).toLowerCase) {
                s[(css[i]).toLowerCase()] = (css[css[i]]);
            }
        }
    } else if(typeof css == "string") {
        css = css.split("; ");          
        for (var i in css) {
            var l = css[i].split(": ");
            s[l[0].toLowerCase()] = (l[1]);
        };
    }
    return s;
}

makeRowsと関数を追加しdeleteRowsて、ブロックが小さくなって上の行に移動するのではなく、行にとどまるようにしました。deleteRowsレスポンシブなレイアウトを維持できるように、ウィンドウのサイズが変更されるたびに呼び出します。次に、ブロックを切り替える必要がある場合は、行を再作成します。

csscss2json関数はmarknadalの厚意によるものです



古いバージョン:

.animate水平方向に緩和できるように、 で解決策を考え出しました。

ここにデモがあります: http://jsfiddle.net/MadLittleMods/fDDZB/8/

jQuery は次のようになります。

$('.block').on('click', function() {
    var block = $(this);
    $(this).siblings().each(function() {
        // If sibling on the same level, horizontal toggle
        // We also want ignore the toggleMethod if it is shown because we might need to reassign
        if (($(this).position().top == block.position().top && ($(this).data('toggle') == -1) || $(this).data('toggle') == null) || ($(this).data('toggle') != -1 && $(this).data('toggleMethod') == 'side'))
        {
            $(this).data('toggleMethod', 'side');

            // Hide block
            if ($(this).data('toggle') == -1 || $(this).data('toggle') == null)
            {
                // Set properties for later use in show block
                $(this).data('overflowBefore', $(this).css('overflow'));
                $(this).css('overflow', 'hidden');
                $(this).data('marginBefore', $(this).css('margin'));

                var width = $(this).width();
                $(this).animate({
                    width: 0,
                    margin: 0
                }, function() {
                    $(this).data('toggle', width);
                });
            }
            // Show block
            else
            {
                $(this).css('overflow', $(this).data('overflowBefore'));

                $(this).animate({
                    width: $(this).data('toggle'),
                    margin: $(this).data('marginBefore')
                }, function() {
                    $(this).data('toggle', -1);
                });
            }
        }
        // Do a normal vertical toggle
        else 
        {
            $(this).data('toggleMethod', 'top');
            $(this).slideToggle('slow');
        }
    });
});​

鍵は、トグルされたブロックを分離することで.slideToggleあり.animate、表示と非表示のときに同じものを適用する必要があるためです.

于 2012-10-28T22:37:16.927 に答える