概要
Webページ内の情報を線で結ぶことがしたいので該当技術を色々探していた。
Webページ内の情報全てをSVGにしてしまう方法などが考えられたが、設定すべきパラメータが多くなることが考えられたので、こちらも辞めた。
SVGを埋め込むようなことが出来るらしいが、調査していくと新しく理解することが多くなったので、既存のライブラリ(LeaderLine)で簡単に実現することにした。
以下では、自分が実装した範囲での実用例を中心に示していきます。
前置き
普段は自然言語処理を少しやる大学院生で、必要に応じてTypeScript, JavaScript, Reactを使用しているため誤用や実装上の不備が多く見られるかもしれません。この記事に有用性を感じて、それらについてご指摘を頂いた場合には出来る限り更新するよう考えています。
本記事は初学者の立場として、参考に出来るものが少なかったのでメモとして残しています。
LeaderLineについて
TypeScriptで利用するためにTypeが必要になるのですが、leader-lineでは対応していなく、leader-line-newという方を用いる必要があります。
要素を線で結べるらしい方法はいくつかまとめられていたので、こちらの記事で問題が解決できなかった場合には参照してみて下さい。
参照:JSで要素間を線で繋いだり動かしたりライブラリ調査@202002 - Qiita
とりあえず使ってみる(JavaScript)
JavaScriptでとりあえず使ってみる。
<!DOCTYPE html>
<head>
<script src="anseki-leader-line-fc2bfda\leader-line.min.js"></script>
<style type="text/css">
html{
margin: auto;
}
.main_comment{
display: inline-block;
}
.comments{
display: inline-block;
}
.main_comment{
width: auto;
margin: 5rem;
border: 5px solid tomato;
}
.comment{
width: auto;
margin: 1rem;
border: 5px solid turquoise
}
</style>
</head>
<body>
<div class="map">
<div class="main_comment" id="mc1">メインコメント</div>
<div class="comments">
<div class="comment" id="c1">コメント1</div>
<div class="comment" id="c2">コメント2</div>
</div>
</div>
<script>
new LeaderLine(
document.getElementById("mc1"),
document.getElementById("c1")
);
new LeaderLine(
document.getElementById("mc1"),
document.getElementById("c2")
)
</script>
</body>
表示すると下記画像のようなものができます。
htmlファイルを表示したものをデベロッパーツールなどで見ていただくとsvgで色々やってくれているのが分かるかと思います。
React × TypeScriptでやってみる
まず、Reactのプロジェクトを雛形を利用して作成する。
参照:create-react-appで React + Typescript な環境を構築する - Qiita
実行環境
node
: v14.5.0
create-react-app
: 3.4.1
create-react-app {プロジェクト名} --typescript
プロジェクト名をll_sample
として、
create-react-app ll_sample --typescript
※もしかしたら@types/react
に欠損があるかもしれないので、import React from "react"
の部分で怒られていたら下記を実行してみてください。
npm install @types/react
上記で述べたようにleader-line-new
をライブラリとして用います。cd ll_sample
で移動してから、
npm install leader-line-new
混乱が生じないように、作成されるApp.tsx
について変更を加えて、機能を把握することを行っていきます。
import React, {useEffect, useState} from 'react';
import './App.css';
import LeaderLine from "leader-line-new";
const App: React.FC = () => {
// initialLinksで初期化
const initialLinks: LeaderLine[] = [];
const [links, setLinks] = useState(initialLinks);
const [link_number, setLinknumber] = useState(0);
const [num, setNum] = useState(3);
useEffect(() =>{
// removeしなければリンク表示が残ったままである
if (links.length > 0){
links.filter(l => {
l.remove();
})
}
let link_id: number = Math.floor(link_number % num);
let start = document.getElementById("mc_0");
let end = document.getElementById(String(link_id));
if (start && end){
let link = [];
link.push(new LeaderLine(start, end, {startSocket:"right", endSocket:"left"}));
setLinks(link);
}
},[link_number]);
// クリックされたら動くfunction
// setLinknumberでリンク先を変更する
const handleOnclick = () =>{
setLinknumber(link_number+1);
}
return(
<div>
<div className="area">
<div className="main_comment_area">
<div className="main_comment" id="mc_0">
メインコメント
</div>
<button onClick={handleOnclick}>リンク先変更</button>
</div>
<div className="comments">
{
(()=>{
let comments = [];
for (let i=0; i<num; i++){
comments.push(
<div className="comment" id={String(i)}>
コメント{i}
</div>
)
}
return comments;
})()
}
</div>
</div>
</div>
);
}
export default App;
これに伴って、LeaderLineの矢印の表示が見やすくなるように簡単にApp.css
を整えます。
.area{
display: flex;
}
.main_comment_area{
margin: 0 20rem 0 0;
}
.main_comment{
border: 5px solid tomato;
margin: 5rem;
}
.comment{
margin: 1rem;
border: 5px solid turquoise;
}
この2つを変更することに加えて、index.tsx
においてimport "./index.css"
をコメントアウト等で無効にしておいてください。
ここまで終えたらnpm start
等で実行して表示を確認してみて下さい。
初期状態では下記画像のようになっているかと思います。以降ボタン押すことによってhandleOnclick
が作動し、その中でlink_number
が変更されることでuseEffect
が動きLeaderLine
による描画の変更が行われます。
LeaderLineが関係する部分のプログラムの説明
-
l.remove()
について
remove()
をしないと、new LeaderLine()
で生成された描画が残った状態で引き継がれてしまうので注意が必要。 -
LeaderLine(start, end, {startSocket:"right", endSocket:"left"})
について
startSocket
,endSocket
はそれぞれ要素のどの位置(top
,bottom
,right
,left
)にリンクは接続するのかということをオプションとして設定できるようになっています。
詳しくは公式ドキュメントを参照してください。
これで、LeaderLine
のReact×TypeScriptでの機能確認は終了となります。
最後に
本記事内で「コメント」という単語を使っている通り、レビューコメントに対して処理を施すということを実験的にやりたくてLeaderLine
を使用しました。下記リンク先でもLeaderLine
をとりあえず使いましたが、表示は今後いろいろ弄る予定です。
レビューコメントを収集してマップ化する機能(いつか公開したい)- GitHub
(早く就活終わらしていろいろやりたい・・・)