jQuery: Cytoscape.js お試せた7.5 (ラベル(再)、background-image)

Cytoscape.js の公式ドキュメントは「えれー読みにくい」だけの話で、「書かれてない」とは限らないんだよね。

jQuery: Cytoscape.js お試せた7 (multiline label とかダブルタップとか色んなレイアウトとかとにかく色々)」のそのまま続きだけれど、「まだイケてないとこややりたいこと多数」でやり残したこととは別のことを先にやろうかと。

2つだけ。「エッジのラベル」と、「画像背景」。後者は「ワタシのヤツだとゴテゴテしてあんまし嬉しかないかなぁ、でも何か他のではすぐにやりたくなりそうだな」と思ってやってみたんだけど、やってみたら案外いい塩梅の見た目と使い勝手になったんで、もうこれを正にしちゃおうかと。前者はこれで済んだつもりになってたんだけれど、気付いたことがあったので改めて。

「エッジのラベル」、「画像背景」のどっちにも共通の話に「気付いた」話から。これ書いた時点では、「(cssに対応する)class を付けて css でスタイル付けする」というやり方にしか気付いていなかったのね。けど、個々のノード・エッジそれぞれに対して「style」を指定出来るのね。html のエレメントに直接指定する style と、class と css の関係そのまんまだね。滅茶苦茶わかりにくいけど。アタシのコードは少し基礎から外れだしてるんでわかりにくいかもしらんので、単純化すればこんな:

 1 var cy = window.cy = cytoscape({
 2   container: document.getElementById('cy'),
 3 
 4   boxSelectionEnabled: false,
 5   autounselectify: true,
 6 
 7   layout: {
 8     name: 'preset'
 9   },
10   elements: {
11     "nodes": [
12       /* ... snip ... */
13       {
14         "position": { "y": -7110.4598, "x": 27955.9998 }, 
15         "data": { "iata": "HND", "id": 2359 },
16         style {
17              label: "HND",
18         },
19       }, 
20       {
21         "position": { "y": -6885.459899902344, "x": 27048.800659179688 }, 
22         "data": { "iata": "KIX", "id": 3992 },
23          style: {
24              label: "KIX",
25          },
26       }, 
27       /* ... snip ... */
28     ], 
29     "edges": [
30       /* ... snip ... */
31       {
32         "data": { "source": 2305, "target": 2359, "id": "rt0", "airline": "STARFLYER" },
33          style: {
34              label: "STARFLYER",
35              "source-label": "HND",
36              // "target-label": "..."
37          },
38       }, 
39       /* ... snip ... */
40     ]
41   },
42 
43 });

souce-label と target-label の使い方が「センス」だよなぁと思ったりはする。「source⇒target」のまんまラベル付けしてしまうと「役に立たないラベル」になりがちだもんねぇ。(ノードが遠く離れてるからこそ価値があるラベル、にするなら、逆に付けるのがいい、普通は。)

画像背景については、なんかドキュメントが気合入ってる。わかりにくいのは相変わらずだけれど。共通の画像背景にしたいなら class (classes) と css を使うのが良いけれど、ワタシの例の場合「全ノードで画像が違う」ので class によるアプローチは無理がある、というわけで、上の例にそのまま画像背景を使うとしたら、

 1 var cy = window.cy = cytoscape({
 2   container: document.getElementById('cy'),
 3 
 4   boxSelectionEnabled: false,
 5   autounselectify: true,
 6 
 7   layout: {
 8     name: 'preset'
 9   },
10   elements: {
11     "nodes": [
12       /* ... snip ... */
13       {
14         "position": { "y": -7110.4598, "x": 27955.9998 }, 
15         "data": { "iata": "HND", "id": 2359 },
16         style {
17              label: "HND",
18              "background-image": ["/path/to/image"], // Array でないと動かないみたい。
19              "background-fit": "contain", // or "cover",
20         },
21       }, 
22       {
23         "position": { "y": -6885.459899902344, "x": 27048.800659179688 }, 
24         "data": { "iata": "KIX", "id": 3992 },
25          style: {
26              label: "KIX",
27              "background-image": ["/path/to/image"],
28              "background-fit": "contain", // or "cover",
29          },
30       }, 
31       /* ... snip ... */
32     ], 
33     "edges": [
34       /* ... snip ... */
35       {
36         "data": { "source": 2305, "target": 2359, "id": "rt0", "airline": "STARFLYER" },
37          style: {
38              label: "STARFLYER",
39              "source-label": "HND",
40              // "target-label": "..."
41          },
42       }, 
43       /* ... snip ... */
44     ]
45   },
46 
47 });

でいい、と言いたいところだがなぜかここだけ気合入ってるドキュメントにも書かれている通りで「クロスドメイン問題」が普通は起こる。ワタシは未だにこれの完全な意味がわかってないんだけれど、とにかく「cors なプロキシかましちまえや」相手にするならば、"background-image-crossorigin": "anonymous", でいいみたい。(てのと、ワタシが相手にしてるヤツの場合、「プロキシを通しつつ、なおかつ crossorigin 指定も必要」だった。)てわけで例えばこんな感じなのだ:

 1 var cy = window.cy = cytoscape({
 2   container: document.getElementById('cy'),
 3 
 4   boxSelectionEnabled: false,
 5   autounselectify: true,
 6 
 7   layout: {
 8     name: 'preset'
 9   },
10   elements: {
11     "nodes": [
12       /* ... snip ... */
13       {
14         "position": { "y": -7110.4598, "x": 27955.9998 }, 
15         "data": { "iata": "HND", "id": 2359 },
16         style {
17              label: "HND",
18              "background-image-crossorigin": "anonymous",
19              "background-image": ["https://cors-anywhere.herokuapp.com/" + "/path/to/image"],
20              "background-fit": "contain", // or "cover",
21         },
22       }, 
23       {
24         "position": { "y": -6885.459899902344, "x": 27048.800659179688 }, 
25         "data": { "iata": "KIX", "id": 3992 },
26          style: {
27              label: "KIX",
28              "background-image-crossorigin": "anonymous",
29              "background-image": ["https://cors-anywhere.herokuapp.com/" + "/path/to/image"],
30              "background-fit": "contain", // or "cover",
31          },
32       }, 
33       /* ... snip ... */
34     ], 
35     "edges": [
36       /* ... snip ... */
37       {
38         "data": { "source": 2305, "target": 2359, "id": "rt0", "airline": "STARFLYER" },
39          style: {
40              label: "STARFLYER",
41              "source-label": "HND",
42              // "target-label": "..."
43          },
44       }, 
45       /* ... snip ... */
46     ]
47   },
48 
49 });

(2018-01-23追記: ノード背景に複数イメージを使う例を書いておいた。)

というわけでこの2点においての進化版:



06:10追記:
少し進化させたが新たな技術的なネタは何もないのでシンプルに追記の形で。こんなもんは「イタチごっこ」なアレなんだけれど、データの欠落で死ぬパターンが結構あったので直しつつ、ついでに検索結果リストを「大きく」しつつ collapse 出来るようにして「広々」させてみた:




Related Posts