ドラッグアンドドロップによる並べ替えの詳細を実現する js

ドラッグアンドドロップによる並べ替えの詳細を実現する js

1. はじめに

ドラッグ アンド ドロップによる並べ替えは、誰にとっても馴染みのある操作です。通常の作業では、ニーズに合わせてSortable.jsなどのオープン ソース ライブラリを使用することもできます。しかし、要件を満たした後、ドラッグ アンド ドロップによる並べ替えを実現する方法について考えたことはありますか?私は時間をかけて調査し、今日それを皆さんと共有します。

2. 実装

 {
    マージン: 0;
    パディング: 0;
    ボックスのサイズ: 境界線ボックス;
}

.グリッド{
    ディスプレイ: フレックス;
    flex-wrap: ラップ;
    マージン: 0 -15px -15px 0;
    タッチアクション: なし;
    ユーザー選択: なし;
}

.グリッドアイテム{
    幅: 90ピクセル;
    高さ: 90px;
    行の高さ: 88px;
    テキスト配置: 中央;
    マージン: 0 15px 15px 0;
    背景: #FFF;
    境界線: 1px 実線 #d6d6d6;
    リストスタイル: なし;
}

。アクティブ {
    背景: #c8ebfb;
}

.clone-grid-item {
    位置: 固定;
    左: 0;
    上: 0;
    zインデックス: 1;
    幅: 90ピクセル;
    高さ: 90px;
    行の高さ: 88px;
    テキスト配置: 中央;
    背景: #FFF;
    境界線: 1px 実線 #d6d6d6;
    不透明度: 0.8;
    リストスタイル: なし;
}

<ul class="grid">
    <li class="grid-item">項目1</li>
    <li class="grid-item">項目2</li>
    <li class="grid-item">項目3</li>
    <li class="grid-item">項目4</li>
    <li class="grid-item">項目5</li>
    <li class="grid-item">項目6</li>
    <li class="grid-item">項目7</li>
    <li class="grid-item">項目8</li>
    <li class="grid-item">項目9</li>
    <li class="grid-item">アイテム10</li>
</ul>

ES6 クラスの記述を使用する:

クラス Draggable {
    コンストラクタ(オプション) {
        this.parent = options.element; // 親要素 this.cloneElementClassName = options.cloneElementClassName; // 複製要素のクラス名 this.isPointerdown = false;
        this.diff = { x: 0, y: 0 }; // 最後の移動に対する差異 this.drag = { element: null, index: 0, lastIndex: 0 }; // 要素をドラッグ this.drop = { element: null, index: 0, lastIndex: 0 }; // 要素を解放 this.clone = { element: null, x: 0, y: 0 };
        this.lastPointermove = { x: 0, y: 0 };
        this.rectList = []; // ドラッグアイテムのgetBoundingClientRect()メソッドによって取得されたデータを保存するために使用されます。this.init();
    }
    初期化() {
        this.getRect();
        このイベントリスナーをバインドします。
    }
    // 要素の位置情報を取得する getRect() {
        this.rectList.length = 0;
        for (this.parent.children の定数項目) {
            this.rectList.push(item.getBoundingClientRect());
        }
    }
    ハンドルポインタダウン(e) {
        // マウスクリックの場合は左ボタンにのみ反応します if (e.pointerType === 'mouse' && e.button !== 0) {
            戻る;
        }
        if (e.target === this.parent) {
            戻る;
        }
        this.isPointerdown = true;
        this.parent.setPointerCapture(e.pointerId);
        this.lastPointermove.x = e.clientX;
        this.lastPointermove.y = e.clientY;
        this.drag.element = e.target;
        this.drag.element.classList.add('active');
        this.clone.element = this.drag.element.cloneNode(true);
        this.clone.element.className = this.cloneElementClassName;
        this.clone.element.style.transition = 'なし';
        const i = [].indexOf.call(this.parent.children, this.drag.element);
        this.clone.x = this.rectList[i].left;
        this.clone.y = this.rectList[i].top;
        this.drag.index = i;
        this.drag.lastIndex = i;
        this.clone.element.style.transform = 'translate3d(' + this.clone.x + 'px, ' + this.clone.y + 'px, 0)';
        document.body.appendChild(this.clone.element);
    }
    ハンドルポインタ移動(e) {
        if (this.isPointerdown) {
            this.diff.x = e.clientX - this.lastPointermove.x;
            this.diff.y = e.clientY - this.lastPointermove.y;
            this.lastPointermove.x = e.clientX;
            this.lastPointermove.y = e.clientY;
            this.clone.x += this.diff.x;
            this.clone.y += this.diff.y;
            this.clone.element.style.transform = 'translate3d(' + this.clone.x + 'px, ' + this.clone.y + 'px, 0)';
            (i = 0 とします; i < this.rectList.length; i++) {
                // 衝突検出 if (e.clientX > this.rectList[i].left && e.clientX < this.rectList[i].right &&
                    e.clientY > this.rectList[i].top && e.clientY < this.rectList[i].bottom) {
                    this.drop.element = this.parent.children[i];
                    this.drop.lastIndex = i;
                    if (this.drag.element !== this.drop.element) {
                        if (this.drag.index < i) {
                            this.parent.insertBefore(this.drag.element、this.drop.element.nextElementSibling);
                            this.drop.index = i - 1;
                        } それ以外 {
                            this.parent.insertBefore(this.drag.element、this.drop.element);
                            this.drop.index = i + 1;
                        }
                        this.drag.index = i;
                        定数dragRect = this.rectList[this.drag.index];
                        定数 lastDragRect = this.rectList[this.drag.lastIndex];
                        定数 dropRect = this.rectList[this.drop.index];
                        定数 lastDropRect = this.rectList[this.drop.lastIndex];
                        this.drag.lastIndex = i;
                        this.drag.element.style.transition = 'なし';
                        this.drop.element.style.transition = 'なし';
                        this.drag.element.style.transform = 'translate3d(' + (lastDragRect.left - dragRect.left) + 'px, ' + (lastDragRect.top - dragRect.top) + 'px, 0)';
                        this.drop.element.style.transform = 'translate3d(' + (lastDropRect.left - dropRect.left) + 'px, ' + (lastDropRect.top - dropRect.top) + 'px, 0)';
                        this.drag.element.offsetLeft; // 再描画をトリガーします this.drag.element.style.transition = 'transform 150ms';
                        this.drop.element.style.transition = '150ms で変換';
                        this.drag.element.style.transform = 'translate3d(0px, 0px, 0px)';
                        this.drop.element.style.transform = 'translate3d(0px, 0px, 0px)';
                    }
                    壊す;
                }
            }
        }
    }
    ハンドルポインタアップ(e) {
        if (this.isPointerdown) {
            this.isPointerdown = false;
            this.drag.element.classList.remove('active');
            this.clone.element.remove();
        }
    }
    ハンドルポインタキャンセル(e) {
        if (this.isPointerdown) {
            this.isPointerdown = false;
            this.drag.element.classList.remove('active');
            this.clone.element.remove();
        }
    }
    バインドイベントリスナー() {
        this.handlePointerdown = this.handlePointerdown.bind(this);
        this.handlePointermove = this.handlePointermove.bind(this);
        this.handlePointerup = this.handlePointerup.bind(this);
        this.handlePointercancel = this.handlePointercancel.bind(this);
        this.getRect = this.getRect.bind(this);
        this.parent.addEventListener('pointerdown', this.handlePointerdown);
        this.parent.addEventListener('pointermove', this.handlePointermove);
        this.parent.addEventListener('pointerup', this.handlePointerup);
        this.parent.addEventListener('pointercancel', this.handlePointercancel);
        window.addEventListener('スクロール'、this.getRect);
        window.addEventListener('resize', this.getRect);
        window.addEventListener('orientationchange', this.getRect);
    }
    アンバインドイベントリスナー() {
        this.parent.removeEventListener('pointerdown', this.handlePointerdown);
        this.parent.removeEventListener('pointermove', this.handlePointermove);
        this.parent.removeEventListener('pointerup', this.handlePointerup);
        this.parent.removeEventListener('pointercancel', this.handlePointercancel);
        window.removeEventListener('scroll', this.getRect);
        ウィンドウのサイズ変更イベント リスナーを削除します。
        window.removeEventListener('orientationchange', this.getRect);
    }
}
// 新しい Draggable をインスタンス化します({
    要素: document.querySelector('.grid'),
    cloneElementClassName: 'clone-grid-item'
});

デモ: jsdemo.codeman.top/html/dragga…

3. HTML ドラッグ アンド ドロップ API を使用しないのはなぜですか?

ネイティブHTMLドラッグ アンド ドロップAPIモバイル デバイスでは使用できないため、 PCとモバイル デバイスの両方と互換性を持たせるために、 PointerEventイベントを使用してドラッグ ロジックを実装します。

4. まとめ

ドラッグアンドドロップによる並べ替えの基本機能は実装されていますが、まだ欠点が多くあります。ネストされたドラッグ、リスト間でのドラッグ、一番下までドラッグしたときの自動スクロールなどの機能は実装されていません。

ドラッグアンドドロップソートをjsで実装する詳細に関するこの記事はこれで終わりです。ドラッグアンドドロップソートをjsで実装することに関するより関連性の高いコンテンツについては、123WORDPRESS.COMで以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも123WORDPRESS.COMをよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Antdesign-vueとsortablejsを組み合わせて、2つのテーブルをドラッグして並べ替える機能を実現
  • js に基づく画像のドラッグ アンド ドロップによる並べ替えのソース コード例
  • React.js コンポーネントはドラッグ アンド ドロップによるソート コンポーネント機能のプロセス分析を実装します
  • Elementui テーブル コンポーネント + sortablejs を使用して行のドラッグ アンド ドロップによる並べ替えを実装するサンプル コード
  • AngularJS ドラッグ アンド ドロップ プラグイン ngDraggable.js をベースにしたドラッグ アンド ドロップ ソートの実装
  • JS ドラッグアンドドロップソートプラグイン Sortable.js の使用例分析
  • React.js コンポーネントはドラッグ アンド ドロップ コピーとソート可能なサンプル コードを実装します
  • JS は、シンプルな画像のドラッグ アンド ドロップによる並べ替えのサンプル コードを実装します。

<<:  ウェブデザインにおける円形要素の使用例 25 選

>>:  MySQL Shellの紹介とインストール

推薦する

WeChatアプレットは写真の撮影とアルバムからの写真の選択を実現します

この記事では、WeChatアプレットで写真を撮ったり、アルバムから写真を選択したりするための具体的な...

HTMLページでチェックボックスを操作する方法

チェックボックスは Web ページで非常によく使用されます。e コマースの Web サイトでもプラッ...

ページ内の検索エンジンの呼び出しはBaiduを例に挙げています

今日、突然、自分のウェブページで Google や Baidu のような強力な検索エンジンを呼び出す...

MySQL でのテーブルの作成と削除の詳細な例

テーブル作成コマンドには以下が必要です。 テーブルの名前フィールド名各フィールドを定義します(タイ...

WeChatアプレットのオーディオコンポーネントがiOSで再生できない問題の解決策

解決策:クリック イベントをオーディオ コンポーネントにバインドし、再生メソッドと一時停止メソッドを...

MySQLのネクストキーロックのロック範囲についての簡単な説明

序文ある日、突然 MySQL の次のキー ロックについて尋ねられ、私の即座の反応は次のようなものでし...

DockerのIDEA構成プロセス

IDEA は Java で最も一般的に使用されている開発ツールであり、Docker は最も人気のある...

jQuery は、画像を切り替えるための左ボタンと右ボタンのクリックを実装します。

この記事では、左ボタンと右ボタンをクリックすることで画像を切り替えるjQueryの具体的なコードを例...

JSフロントエンドモジュール化のいくつかの仕様についての簡単な説明

目次序文フロントエンドモジュール開発の価値厄介な名前の競合面倒なファイル依存関係モジュール化の利点C...

MySQL でスロークエリログを有効にする方法

1.1 はじめにスロークエリログを有効にすると、MySQL は指定された時間を超えるクエリステートメ...

Docker で ElasticSearch と Kibana をインストールするためのサンプル コード

1. はじめにElasticsearchは現在非常に人気があり、多くの企業が利用しているため、esを...

インストールされていないバージョンの MySQL を使用する手順とパスワードを忘れた場合の解決策

最初のステップは、圧縮されたパッケージを対応するディスクに解凍することです。 2 番目の手順は、cm...

Nginx のパラメータをオンにして Web パフォーマンスを 3 倍向上させる方法

1. 遭遇したいくつかの問題2008 年にパフォーマンス テストを行っていたとき、パフォーマンス テ...

Dockerがsudo操作を使用する必要がある問題を解決する

手順は以下のとおりです1. dockerグループを作成する: sudo groupadd docke...

Vue で echarts を使用してコンポーネントを視覚化する方法

echarts コンポーネントの公式ウェブサイト アドレス: https://echarts.apa...