浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【React】「@viselect/react」ライブラリを使ってドラッグして要素を選択する機能を実装する

今回は Web のプロジェクトに実装したライブラリについてです。
「@viselect/react」というライブラリで、マウスでドラッグした範囲の要素を複数選択することができます。
既存のレイアウトと合わせるのには苦労しましたが、実装自体はそこまで難しくはありませんでした。

GitHub のページはこちらから。

Simonwep/selection: ✨ Viselect – A simple and lightweight library to add a visual way of selecting elements, just like on your Desktop. Zero dependencies, super small. Support for major frameworks.
https://github.com/Simonwep/selection

なお、React で記述されているプロジェクトに実装する場合は、下記のリンクをご参照ください。
https://github.com/Simonwep/selection/tree/master/packages/react

 

さて、まずライブラリのインストールは下記コマンドで行います。

npm install @viselect/react

上記の実行が完了したら、プロジェクトに組み込んでいきます。
下記のサンプルコードは、GitHub のページに掲載されていたものをまるっとコピーさせて頂いています。

import SelectionArea, {SelectionEvent} from '@viselect/react';
import React, {FunctionComponent, useState} from 'react';

const App: FunctionComponent = () => {
    const [selected, setSelected] = useState<Set<number>>(() => new Set());
    const extractIds = (els: Element[]): number[] =>
        els.map(v => v.getAttribute('data-key'))
            .filter(Boolean)
            .map(Number);

    const onStart = ({event, selection}: SelectionEvent) => {
        if (!event?.ctrlKey && !event?.metaKey) {
            selection.clearSelection();
            setSelected(() => new Set());
        }
    };

    const onMove = ({store: {changed: {added, removed}}}: SelectionEvent) => {
        setSelected(prev => {
            const next = new Set(prev);
            extractIds(added).forEach(id => next.add(id));
            extractIds(removed).forEach(id => next.delete(id));
            return next;
        });
    };

    return (
        <>
            <SelectionArea className="container"
                           onStart={onStart}
                           onMove={onMove}
                           selectables=".selectable">
                {new Array(42).fill(0).map((_, index) => (
                    <div className={selected.has(index) ? 'selected selectable' : 'selectable'}
                         data-key={index}
                         key={index}/>
                ))}
            </SelectionArea>
        </>
    );
}

state の設定や、onStartonDrag などのマウスドラッグの開始時やマウスドラッグ中の処理については、まずはそのままコピー&ペーストしてきて問題ないと思います。

で、私が間違えたのが、下記の2点です。

  1. <SelectionArea> コンポーネントの下に子要素を入れ、その中でドラッグして選択したい要素を入れた
  2. data-key に文字列を指定した

まず、1 についてはそのままで、必ず <SelectionArea> コンポーネントの直下に、ドラッグで選択したい要素を記述するようにしてください。
サンプルコードで言うと、33行目からの .map()<div> などのコンポーネントで囲わないようにしてください。

2 については、サンプルコード 5行目の selected StateSet に格納できる値を Number で指定されており、ここには data-key で指定した値が配列形式で格納されるのですが、35行目で指定している data-key に文字列を指定するというミスをやらかしました。
こちらについてはエディターのコードチェックで引っ掛かり、実行はしなかったのですが…うっかりミスにもほどがある…。
上記は data-key に格納する値を数値にするか、Set に格納するデータの型を string に変更してください。

個人的に間違えやすそうな点は以上です。
特に 1 にはお気を付けください。

 

以上、React で要素をドラッグして複数選択する機能を実装できるライブラリ「@viselect/react」のご紹介でした。
ご参考になれば幸いです。

  • この記事いいね! (0)