3

ご覧いただきありがとうございます。jQ UI の addClass / remove Class メソッドを使用して、前の兄弟 div をクリックしたときに hr 要素を展開しようとしています。jQ UI エフェクト コアにより、2 つのクラス間のスムーズなアニメーション遷移が可能になります: http://jqueryui.com/demos/removeClass/。さらに、より広範なサイト デザインを実現するには、$ を使用して hr を動的に追加する必要があります。

パズルのピースは次のとおりです。

  1. 私のコードは、4 つの 100x100px 兄弟 div の行をレンダリングします。これらの div にはクラスがありませんが、必要に応じて自由に追加してください。各 div には最終的に一意のクラスがあります。4 番目の div ごとに、動的に追加された hr があります。
  2. 任意の div をクリックすると、すぐ次の hr がクラス「open」に切り替わる必要があります。これにより、行が展開されます。この div を再度クリックすると、hr からクラス「open」をトグル/削除する必要があり、hr が元のサイズに縮小されます。
  3. 1 つの div をクリックして 1 時間を展開し、次に別の div をクリックした場合、2 つのアニメーションをトリガーする必要があります。まず、「開いている」クラスを削除して行を縮小し、次にクラスを再度追加する必要があります。行を再開します。ただし、たとえば、div をクリックして 2 番目の行を開き、次に最初の hr の前にある 2 番目の div をクリックした場合、このアクションではまず 2 番目の hr を閉じてから、2 番目の div の対応する hr を開く必要があります。

私は立ち往生しています。多くの jQ 関数の組み合わせを試しましたが、結果は奇抜です。あなたが見るものは、私が得た最も近いものです。これを試してくれてありがとう。これを機能させるために、コードに自由に追加してください。

<!--HTML...the children divs of ".main" can have their own unique classes if that helps-->
<div class="main">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

/*CSS-some of this creates other events not mentioned above. These are simplified versions of what I need for my final site design*/

.main  {
    width: 450px;
}
.main div {
    height: 100px;
    width: 100px;
    background-color: #000;
    margin: 3px;
    float:left;
}
div.select   {
    background-color: #f00;
    border: 2px solid #00F;
    margin: 3px;
    float:left;
    display: block;
}
div.active   {
    background-color: #f00;
    margin: 3px;
    float:left;
    display: block;
}
hr  {
    background-color: #FF0;
    float: left;
    display: block;
    height: 20px;
    width: 450px;
}
hr.open {
    float: left;
    display: block;
    height: 300px;
    width: 450px;

}

/*the JS - sorry about the double quotes.  I'm using Dreamweaver, which seems to add them to everything*/

$(document).ready(function() {
//dynamcally adds the <hr> after every 4th div.
    $(".main div:nth-child(4n)").after('<hr class="closed"></hr>');
//puts a blue border on the squares
    $('.main div').hover(function()  {
        $(this).addClass('select');
    },
    function() {
        $(this).removeClass('select')
    });
//changes the color of the active square to red and "deactivates" the previous one.
    $('.main div').click(function()  {
        $(this).toggleClass('active').siblings().removeClass('active');
    });
//here in lies the problem...???
    $('.main div').click(function()  {
        $('hr').removeClass('open', 1000);
        $(this).toggle
        (function() {
            $(this).nextAll("hr").first().addClass('open', 500);
        },
        function()  {
            $(this).nextAll("hr").first().removeClass('open', 500)
        });

    });
});
4

2 に答える 2

2

私はこれがあなたが望むものであると確信しています。私はhttp://makr.comから一般的なHTMLレイアウトをコピーしました(あなたはそれがあなたが望むものであるとあなたは言いました):

デモ: http: //jsfiddle.net/SO_AMK/xm7Sk/

jQuery:

$(".main article:nth-child(4n)").after('<hr class="split"></hr>');
$(".main > article .slidedown").click(function(e) {
        e.stopPropagation();
}); // If you click on the slidedown, it won't collapse

var canAnimate = true,
    slideIsOpen = false,
    animateSpeed = 1000;

$(".main > article").hover(function() {
    $(this).addClass("hover");
}, function() {
    $(this).removeClass("hover");
}).click(function() {
    if (canAnimate) {
        canAnimate = false;
        var article = $(this),
            isThisOpen = article.hasClass("active");
        if (isThisOpen) {
            $(".main").queue(function () {
                hideSlide($(this))
            });
        }
        else {
            if (slideIsOpen) {
                $(".main").queue(function () {
                    hideSlide($(this));
                }).queue(function () {
                    positionPage(article, $(this));
                }).queue(function () {
                    showSlide(article, $(this));
                }).queue(function () {
                    positionPage(article, $(this));
                });
            }
            else {
                $(".main").queue(function () {
                    positionPage(article, $(this));
                }).queue(function () {
                    showSlide(article, $(this));
                }).queue(function () {
                    positionPage(article, $(this));
                });
            }
        }
    }
});

function showSlide(elm, main) {
        canAnimate = false;
        slideIsOpen = true;
        elm.nextAll("hr.split").first().addClass("active", animateSpeed);

        elm.children(".slidedown").css("top", (elm.offset().top + 114)).addClass("active").slideToggle(animateSpeed);

        elm.addClass("active");
        main.dequeue();
        canAnimate = true;
}

function hideSlide(main) {
        canAnimate = false;
        $(".main article.active").nextAll("hr.split.active").removeClass("active", animateSpeed);

        $(".main article.active").children(".slidedown").removeClass("active").slideToggle(animateSpeed);

        $(".main article.active").removeClass("active");
        $(main).dequeue();
        canAnimate = true;
        slideIsOpen = false;
}

function positionPage(elm, main) {
    canAnimate = false;
    var body;
    if ($.browser.safari) {
        body = $("body");
    }
    else {
        body = $("html");
    }
    var elmTop = elm.offset().top,
        bodyScroll = body.scrollTop();
    if (bodyScroll - elmTop == 0) {
        var speed = 0;
    }
    else {
        var speed = animateSpeed;
    }
    body.animate({
        scrollTop: elmTop
    }, speed, function () {
        main.dequeue();
        canAnimate = true;
    })
}​

これは非常に小さなものの大きなスクリプトのように見えるかもしれませんが、いくつかのフェイルセーフがあります。唯一のバグは、トランジション中にすばやくクリックを開始すると、キューが間違った順序で終了することがあることです。しかし、平均的なユーザーはアニメーション中にすばやくクリックしません:D

于 2012-09-20T17:34:46.747 に答える
1

サイズを試してみてください:http://jsfiddle.net/Bv57T/3/

主な変更点:

  1. 同じ selector に 2 つの .click バインディングがありました$('.main div')。これは技術的にサポートされていると思いますが、その理由はなく、コードを理解するのが非常に難しくなります。
  2. .toggle()関数をパラメーターとして取りません。ドキュメントを確認してください。それは好きではありませんhover()
  3. 追加と削除に別々の関数を用意する理由はありません。また、クラスを 2 回削除しています。次の HR をオープンにアニメーション化して、オープンのままにしておきたいと思っていましたか? または、すぐに開閉したいですか?後者の場合、この行の理由はありません$('hr').removeClass('open', 1000);。前者の場合、2 番目の function() を含める理由はありません$(this).nextAll("hr").first().removeClass('open', 500)

フィドルで使用したJavaScriptは次のとおりです

$(document).ready(function() {
    //dynamcally adds the <hr> after every 4th div.
    $(".main div:nth-child(4n)").after('<hr class="closed"></hr>');
    //puts a blue border on the squares
    $('.main div').hover(
        function()  {
            $(this).addClass('select');
        },
        function() {
            $(this).removeClass('select')
    });
    //changes the color of the active square to red and "deactivates" the previous one.
    $('.main div').click(function()  {
        $('hr.open').removeClass('open', 1000);
        if(!$(this).hasClass('active')) {
           $(this).nextAll("hr").first().addClass('open', 500);
        }
        $(this).toggleClass('active').siblings().removeClass('active');
    });
});​

それがまさにあなたが望むものではなく、ここから理解できない場合は、先に進んで投稿してください。私はそれをもう一度クラックします.

新しく改善されたバージョンを編集: http://jsfiddle.net/Bv57T/4/ 上記の js も更新しました。

アニメーションの進行中に 2 番目の div をクリックすると、偽装することができます。アニメーションの期間中 (グローバル) bool を true に設定し、次のアニメーションを開始する前にチェックすることで、これを回避できます。

しかし、問題の根源は、UI (つまり DOM) の状態をアプリケーションの状態として倍増させようとしていることにあります。これは、単純な操作でも非常に複雑になる可能性があります (ご覧のとおり)。このような場合に私が好むアプローチは、UI をアプリケーションから分離するライブラリを使用することです。これらは通常、MVC (model-view-controller) または MVVM (model-view-viewmodel - 意図的に紛らわしく感じるので嫌いなモニカ) と呼ばれます。私のお気に入りはknockout.jsです。jQuery および jQuery UI と完全に互換性があります。この例をチェックしてください:アニメーション化されたトランジション.

そのようなライブラリは他にもあります。Backbone.js は 1 つ、knockback.js はノックアウトとバックボーンを組み合わせたものです。私は他のいくつかの人気のある良いものを忘れていることを知っています...

于 2012-09-19T14:57:52.077 に答える