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

推薦する

ウェブサイトを構築するときは、UTF-8 または GB2312 エンコードを使用する必要がありますか?

外国のウェブサイトを開くと文字化けした文字が表示されることが多く、また、英語以外の外国のウェブサイト...

docker の実行に必要な権限の分析

Docker を実行するには root 権限が必要です。非 root ユーザーに docker コマ...

MySQL 8.0.13 解凍版のインストールと設定方法のグラフィックチュートリアル

1. インストール1. MySQLをダウンロードするダウンロードアドレス: リンクアドレスブラウザで...

Vueカスケードドロップダウンボックスの設計と実装

目次1. データベース設計2. フロントエンドページ3. 完全なデモフロントエンド開発では、カスケー...

Vueでデータ例を定義する方法

序文開発プロセスにおいて、変数の定義は非常に頻繁かつ基本的なタスクです。変数の使用シナリオと範囲に応...

1 つの記事で Nginx の現在の制限を理解する (簡単な実装)

Nginx は現在、最も人気のあるロード バランサーの 1 つです。インターネット トラフィックの...

iframe タグの使用方法の詳細な説明 (属性、透明度、適応高さ)

1. iframe の定義と使用法iframe 要素は、別のドキュメントを含むインライン フレーム...

W3C組織はHTML4のスタイルに関する推奨事項を提供しています

これは、W3C 組織が HTML4 に対して提示したスタイル推奨事項です。残念ながら、ブラウザが独自...

HTML 名 ID とクラスの違い_PowerNode Java アカデミー

名前タグの名前を指定します。形式 <input type="text" n...

kindとDockerを使用してローカルKubernetes環境を起動する

導入Kubernetes を使い始めるのに丸一日を費やしたことはありませんか?最近登場したいくつかの...

擬似分散グラフィックを実現するための VMware 構成 Hadoop チュートリアル

1. 実験環境シリアルナンバープロジェクトソフトウェアとバージョン1オペレーティング·システムCen...

JavaScript Canvas で三目並べゲームを実装

この記事では、JavaScript Canvasで三目並べゲームを実装するための具体的なコードを参考...

MySQL 5.7.18 zip バージョンのインストール チュートリアル

MySQL の mysql 5.7.18 zip バージョンは、クリックして次のステップをクリックし...

TypeScript の条件型に関する詳細な読書と実践記録

目次ジェネリック型での条件型の使用ツールタイプ脱出ポッド矢印関数で条件型を使用する型推論による条件型...

Vue バインディング オブジェクト、配列データを動的にレンダリングできないケースの詳細な説明

プロジェクトシナリオ: Dark Horse Vueプロジェクト管理の実践、製品分類の取得、拡張バー...