ドラッグアンドドロップによる並べ替えの詳細を実現する 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の紹介とインストール

推薦する

MySQL マルチバージョン同時実行制御 MVCC の基本原理の分析

目次1 トランザクションの同時実行で発生する問題1.1 ダーティリード1.2 繰り返し不可能な読み取...

MySQL CHARとVARCHARの選択方法

目次VARCHAR 型と CHAR 型結論: VARCHAR 型と CHAR 型VARCHAR と ...

MySQL 8.0.15 のインストールと設定のグラフィックチュートリアルと Linux でのパスワード変更

このブログは、MySQL8.0.15 を正常にインストールしたことを思い出すために書きました。以前は...

nginx で第 3 レベルドメイン名を設定する方法の例

問題の説明nginx を設定することで、異なるポートを介して異なる Web アプリケーションにアクセ...

CSS を解析して画像のテーマカラー機能を抽出する (ヒント)

背景すべては、WeChat 技術グループのクラスメートが「写真の主な色を取得する方法はあるか」と尋ね...

Linuxファイルを表示するコマンドの詳細な説明

Linuxファイルを表示する方法ファイルの内容を表示するコマンド: catは最初の行からコンテンツを...

JavaScript でのプロキシの使用を理解するための記事

目次エージェントとは何かプロキシの基礎知識ハンドラオブジェクトのメソッドプロキシでできること参考文献...

WindowsにOpenSSLをインストールし、OpenSSLを使用して公開鍵と秘密鍵を生成します。

1. OpenSSL公式サイト公式ダウンロードアドレス: https://www.openssl....

Linux システムに Zookeeper サービスをインストールする方法

1. /usr/local/services/zookeeper フォルダを作成します。 mkdir...

Postman に基づく HTTP インターフェース テスト プロセスの分析

偶然、素晴らしい人工知能のチュートリアルを発見したので、みんなと共有せずにはいられませんでした。この...

Antd+vueは円形属性フォームの動的検証のアイデアを実現します

必要な項目をループして検証するために、クエリ フォームのいくつかのプロパティを実装したいと考えていま...

DockerでEurekaを設定する方法

ユーレカ: 1. JDKイメージを構築するEurekaコンテナを起動するjdkフォルダと必要なファイ...

1つの記事でNavicat for MySQLの基本を理解する

目次1. データベース操作2. データ型3. バックアップとリカバリ3. 操作4. 上級5. 知識補...

Vue が 4 レベルのナビゲーションと検証コードを実装する方法の例

効果: まず5つのVueインターフェースを作成する1.home.vueページ <テンプレート&...

CSS 動的読み込みバー効果のサンプルコード

CSS変数の知識を使って、追加したコードとコメントを直接投稿します <!DOCTYPE htm...