今回は 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 の設定や、onStart、onDrag などのマウスドラッグの開始時やマウスドラッグ中の処理については、まずはそのままコピー&ペーストしてきて問題ないと思います。
で、私が間違えたのが、下記の2点です。
- <SelectionArea> コンポーネントの下に子要素を入れ、その中でドラッグして選択したい要素を入れた
- data-key に文字列を指定した
まず、1 についてはそのままで、必ず <SelectionArea> コンポーネントの直下に、ドラッグで選択したい要素を記述するようにしてください。
サンプルコードで言うと、33行目からの .map() を <div> などのコンポーネントで囲わないようにしてください。
2 については、サンプルコード 5行目の selected State で Set に格納できる値を Number で指定されており、ここには data-key で指定した値が配列形式で格納されるのですが、35行目で指定している data-key に文字列を指定するというミスをやらかしました。
こちらについてはエディターのコードチェックで引っ掛かり、実行はしなかったのですが…うっかりミスにもほどがある…。
上記は data-key に格納する値を数値にするか、Set に格納するデータの型を string に変更してください。
個人的に間違えやすそうな点は以上です。
特に 1 にはお気を付けください。
以上、React で要素をドラッグして複数選択する機能を実装できるライブラリ「@viselect/react」のご紹介でした。
ご参考になれば幸いです。