jquery ui draggableの配置について困っております。


ピース画像をdraggableにし、別の大きな画像に配置するという
福笑いのパズルのようなサイトを作成しようとしています。
ピースの数が多いため縦一列に配置しようと思うのですが
ピースをドラッグすると他のピースが上に詰まるようにしたいと考えております。

※参考サイト
http://www.openspc2.org/JavaScript/Ajax/jQuery_study/ver1.2.6/chapter06/001/sample02/index.html

この参考サイトでも実現可能なのですが、最新のjsファイルを使うと上に詰まる動作が出来なくなったため
別の方法で考えております。ちょうどSortableでピースを縦に並べて、そこからdragして別の画像の任意の場所へドロップするようなイメージです。

プラグインなどではドラッグ&ドロップでレイアウトを変更できるようなものもあるのですが
別の画像にピースを当てはめたいという動作が実現できません。

何か良いアイデアや参考になるサイトがございましたらご教授下さい。
大変お手数おかけいたしますがよろしくお願いいたします。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2013/09/08 10:51:25
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。
id:hossiiii

説明が分かりずらいようでしたのでもう一度要件を整理しました。

①ドラッグ対象の要素が縦一列に整列可能な事

②ドラッグ対象の要素がドラッグされた時、空いたスペースを埋めるように

 他の要素で再度縦一列に整列可能な事

③ドラッグされた要素は福笑いのように1ピクセル単位で画面上の

 自由な位置にドロップ出来る事

ちょうど福笑いのようなパズルを作りたいと思っています

よろしくお願いいたします。

ベストアンサー

id:Lhankor_Mhy No.2

回答回数814ベストアンサー獲得回数232

ポイント168pt

コメント欄の思いつきどおりやってみました。
うーん、なんかあれですねえ。
http://jsfiddle.net/TWfq2/

他10件のコメントを見る
id:Lhankor_Mhy

インラインでスタイルが書いているのですが、動作しませんでしたでしょうか。
一応、書き直しておきますが、動作しない原因はCSSではないような気がしますね。
http://jsfiddle.net/TWfq2/3/

2013/09/08 09:11:15
id:hossiiii

Lhankor_Mhy 様
書き直して頂いたもので動きました!ありがとうございます。
2番目の方でも動作するのですね。私の確認のしかたが良くなかったのだと思います。
誠にありがとう御座いました。

2013/09/08 10:45:15

その他の回答2件)

id:gatchan No.1

回答回数9ベストアンサー獲得回数1

ポイント166pt

Sortable | jQuery UI
http://jqueryui.com/sortable/
---
普通にUIの.jsを読み込んで、単純に、

$( "#sortable" ).sortable();
$( "#sortable" ).disableSelection(); //おまけ:テキスト選択を無効にする

で標準的にできると思いますが、これでは違いますか?
アイテム群のliタグを含んだラッパーのulタグに対して、sortable()メソッド。

HTML

<ul id="sortable">
  <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 1</li>
  <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 2</li>
  <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 3</li>
  <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 4</li>
  <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 5</li>
  <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 6</li>
  <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 7</li>
</ul>

すみません、ソースはそのままですw

他7件のコメントを見る
id:hossiiii

gatchan様 ありがとうございます。
こちらも私の実現したい要件をすべて叶えて頂けております。
ドラッグの要素がゆっくり上に詰まっていく感じがすごくいいですね。
参考にさせて頂きます。

2013/09/08 10:43:13
id:gatchan

animate(propaerties, duration) のdurationには1500にしてますが、わかりやすいようにしただけですので、適宜変えてもらえれば。
参考になれば幸いです。

あと、基本的なTipsとして、どの場合でもそうですが、DOMの操作というのは本来(無視できる程度ですが)重いものになります。DOMの追加、削除など。なのでスクリプトの設計時にまずそれらを避ける、あるいは、できるだけキャッシュを使いまわす、CSSのプロパティで動かす/変える、と言った具合です。
ましてや、何万回のループは顕著になります。まあちょっとしたアプリケーションでない限りそこまでしないと思いますが...。
今はモバイル対応も考えることも多く、その場合割りとJSの動作は多少というか、結構落ちます。特にアニメーション周り(まあ元々負荷が高い処理です)。
という感じですw
ありがとうございました:D

2013/09/08 13:03:04
id:hossiiii

質問文を編集しました。詳細はこちら

id:Lhankor_Mhy No.2

回答回数814ベストアンサー獲得回数232ここでベストアンサー

ポイント168pt

コメント欄の思いつきどおりやってみました。
うーん、なんかあれですねえ。
http://jsfiddle.net/TWfq2/

他10件のコメントを見る
id:Lhankor_Mhy

インラインでスタイルが書いているのですが、動作しませんでしたでしょうか。
一応、書き直しておきますが、動作しない原因はCSSではないような気がしますね。
http://jsfiddle.net/TWfq2/3/

2013/09/08 09:11:15
id:hossiiii

Lhankor_Mhy 様
書き直して頂いたもので動きました!ありがとうございます。
2番目の方でも動作するのですね。私の確認のしかたが良くなかったのだと思います。
誠にありがとう御座いました。

2013/09/08 10:45:15
id:a-kuma3 No.3

回答回数4973ベストアンサー獲得回数2154

ポイント166pt

かなり力技のような気もしますが、それっぽい動きになってます。
jsFiddle で、動作確認をしたのがこちら。
http://jsfiddle.net/a_kuma3/2wc9t/1/embedded/result/

こんな感じのソースです。

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>

<script>
$(function(){
    var element_from = $("#from").get()[0];
    var element_to   = $("#to").get()[0];
    var diff_top = element_from.offsetTop - element_to.offsetTop;
    var diff_left = element_from.offsetLeft - element_to.offsetLeft;
    var opt = {
            stop: function(event, ui) {
                        $(".dArea").draggable("destroy");
                        var t = ui.helper.get()[0];
                        if (t.parentNode === element_from) {
                            prev_top = t.offsetTop;
                            prev_left = t.offsetLeft;
                            t.parentNode.removeChild(t);
                            t.style.position = "absolute";
                            element_to.appendChild(t);
                            t.style.top = prev_top + diff_top + "px";
                            t.style.left = prev_left + diff_left + "px";
                        }
                        $("#from > .dArea").css("position", "static")
                        $(".dArea").draggable(opt);
                    }
        }
    $(".dArea").draggable(opt);
});
</script>
<style>
.dArea {
    background-color: greenyellow;
    border: 2px solid limegreen;
    width:140px;
    height:50px;
}
div#from {
    position: absolute;
    width: 200px;
    border: solid 1px green;
    top: 3em;
    height: 300px;
}
div#to {
    position: absolute;
    width: 200px;
    border: solid 1px red;
    top: 3em;
    left: 300px;
    height: 300px;
}
</style>
</head>
<body>

<br><br>

<div id="from">
<div class="dArea">(1) ここがドラッグできます</div>
<div class="dArea">(2) ここがドラッグできます</div>
<div class="dArea">(3) ここがドラッグできます</div>
<div class="dArea">(4) ここがドラッグできます</div>
</div>
<div id="to">
</div>

</body>
</html>

Draggable な要素を動かし終わったときに、

  1. 一旦、Draggable を破棄
  2. 動かした要素を、別の要素の下にぶら下げる
  3. まだ動かしていない Draggable な要素の position を static にする(これで、詰まる)
  4. あらためて、Draggable を指定する

という処理をしています。

id:hossiiii

a-kuma3様 動作確認しました。
こちらもまさしく期待している動きでした。
更に内容の説明もありがとうございます。
分かりやすいコードで不慣れな自分でも理解出来ました。
ベストアンサーはタッチの差で投稿頂いたのと
シンプルなコードからLhankor_Mhy 様にしようと思うのですが
今後作成していく中で不具合があった場合の
バックアップ用のコードとして利用させて頂きます。

前回の質問に引き続き誠にありがとう御座いました。

2013/09/07 16:28:18
  • id:a-kuma3
    質問に挙げられてる ui.draggable.js って、すんごい古い実装なんですね。
    jquery ui v1.5.2 (Google がホストしてくれてる中の一番古いやつ) でも、最新のと同じ動きで Draggable な要素の位置は変わらないです。

    前の質問の回答に書いた svn だと、1.0.1a から 1.5 の間がぽっかり空いているのですけれど、1.0 が質問に挙げられてるのと同じ実装で。
    う~ん...
  • id:hossiiii
    a-kuma3様 コメントありがとう御座います。
    そうだったのですね。
    今後の拡張なども考えると、やはりサンプルで使っている
    ui.draggable.jsは使わない方がよさそうですね。

    できればサンプルで提示しているような
    シンプルなコードで実現出来れば非常に嬉しい所ですが
    なかなかうまくいかないものですね。
  • id:Lhankor_Mhy
    うーん、こういう感じのものでしょうか。
    http://gridster.net/
  • id:hossiiii
    Lhankor_Mhy様 ありがとう御座います。
    はい、このような感じです。
    このようにドラッグ後に自動整列させて
    ドラッグした要素をパズルのピースとして
    別の領域上にドロップしたいです。

    http://tcb.core-tech.jp/javascript/jquerygridster/

    ちょうどこのサイトでレイアウトされている枠の外側に
    福笑いのような感じでドロップしたいと考えています
  • id:Lhankor_Mhy
    あ、配置先では整列しなくていいんですね。
  • id:hossiiii
    配置先では整列させない動きをさせたいです。質問文にこの事が入って無かったので混乱させてしまいもうしわけありませんでした。
  • id:Lhankor_Mhy
    draggableがCSSをposition:relativeにしているので、ドラッグ終了イベントを拾ってDOM構造を変えてしまえばいいと思ったんですが、なんか上手く行かないです。
    もうちょっと考えてみます。
  • id:a-kuma3
    >なんか上手く行かないです。
    ドラッグされた要素の位置が、うまく制御できない?
  • id:hossiiii
    Lhankor_Mhy様
    お世話になっております。
    頂いたヒントをもとに検索したところ
    想定した動作に近いサイトが見つかりました。

    http://black-flag.net/jquery/20120425-3777.html

    このサイトのドロップエリア(下側の領域)の動作で
    枠の外に整列せずに配置出来ればいいのですが。。
  • id:hossiiii
    gatchan 様
    a-kuma3 様
    Lhankor_Mhy 様

    この度は本当にありがとうございました。
    私の周りにはWEB系で話を出来る人がおらず
    本当に困っていたところでした。

    説明も不備がある中でとても丁寧に親切に教えて下さり
    みなさんとこの人力はてなにとても感謝しております。

    ベストアンサーとポイントの配分ですが考えた結果
    ベストアンサーは一番最初に実現可能なコードを提示くださったLhankor_Mhy 様に
    ポイント配分はみなさんに均等に分配させて頂きたいと思います。

    また別の事で質問を登録する事があると思いますが
    その時はまた是非よろしくお願いいたします。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません