いくらなんでも「ほんとのほんとに毎度ゼロから構築」はないよなぁ、と気になり続けていたがやっと。
jQuery: Cytoscape.js お試せた6 で cy.add で動的に追加していくのがダメだ、と言った。何が起こるかと言えば、「どんなレイアウトを選んでも全部 (0, 0) にノードが配置されてしまう」ことだった。ひとまず諦めていたんだけれど、automove のデモ内に非常に気になるコードを見つけてしまったのである:
1 // a, b, c; with mid in the middle
2 cy.$('#a, #b, #c').makeLayout({
3 name: 'circle',
4 boundingBox: {
5 x1: 0,
6 y1: 0,
7 x2: 300,
8 y2: 300
9 }
10 }).run();
うーん、これが出来るんなら、うまくいけそうな気がする…。makeLayout
なんかドキュメントされてないぞ。
とりあえずこの makeLayout
と cy.remove、cy.add、そしておそらく makeLayout
は eles
にバインドされているのであろうから cy.$() et al の3つと、あと cy.batch() も活用すれば、きっと「合理的な elements の入れ替え」が出来るんではないだろうか?
以下 makeLayout
を最初 makelayout
と書いてしまったたった一回の「試行錯誤」だけで書けてしまったヤツ:
1 <html>
2 <head jang="ja">
3 <meta charset="UTF-8">
4 <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
5 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.8/cytoscape.min.js"></script>
6 <style>
7 #outer {
8 border-style: none;
9 border-width: 3em;
10 }
11 #cy {
12 width: 100%; /* MUST */
13 height: 90%; /* MUST */
14 }
15 </style>
16 </head>
17 <body>
18 <input type="button" id="toggle" value="Toggle data!"/>
19 <div id="cy"></div>
20 <script>
21 var all_elememts = [
22 // graph 1 elements
23 [
24 { data: { id: 'a' } },
25 { data: { id: 'b' } },
26 { data: { id: 'c' } },
27 { data: { id: 'mid' }, classes: 'mid' },
28 { data: { source: 'a', target: 'mid' } },
29 { data: { source: 'b', target: 'mid' } },
30 { data: { source: 'mid', target: 'c' } },
31 { data: { id: 'd' } },
32 { data: { id: 'e' } },
33 { data: { id: 'f' } },
34 { data: { source: 'e', target: 'f' } },
35 { data: { id: 'g' } },
36 { data: { id: 'h' } },
37 { data: { id: 'i' } },
38 { data: { source: 'h', target: 'i' } }
39 ],
40
41 // graph 2 elements
42 [
43 { data: { id: 'a' } },
44 { data: { id: 'b' } },
45 { data: { id: 'c' } },
46 { data: { id: 'mid' }, classes: 'mid' },
47 { data: { source: 'a', target: 'mid' } },
48 { data: { source: 'b', target: 'mid' } },
49 { data: { source: 'c', target: 'mid' } },
50 { data: { id: 'd' } },
51 { data: { id: 'e' } },
52 { data: { id: 'mid2' }, classes: 'mid' },
53 { data: { source: 'd', target: 'mid2' } },
54 { data: { source: 'e', target: 'mid2' } },
55 { data: { source: 'mid', target: 'mid2' } }
56 ]
57 ];
58 // construct cy with neither elements nor layout
59 var cy = window.cy = cytoscape({
60 container: document.getElementById('cy'),
61 style: [
62 {
63 selector: 'node',
64 style: {
65 'content': 'data(id)',
66 }
67 },
68 ],
69 });
70 // if button is clicked, (re)set elements and makeLayout
71 var curidx = 0;
72 $('#toggle').on("click", function(evt) {
73 // elements what i want to render
74 var elems = all_elememts[curidx];
75
76 // ---------------------------------------
77 // cy.batch() et al:
78 // Allow for manipulation of elements without triggering multiple
79 // style calculations or multiple redraws.
80 cy.startBatch();
81 // first, remove all existing elements
82 cy.remove(cy.elements());
83 // add new elements
84 cy.add(elems);
85 // layout - 17:20 追記: makeLayout は endBatch() のあとの方がいいみたい。
86 cy.elements().makeLayout({
87 name: "grid",
88 }).run();
89 //
90 cy.endBatch();
91 // ---------------------------------------
92 //
93 curidx = (curidx + 1) % 2;
94 });
95 </script>
96 </body>
97 </html>
イケた…。うーん、こーーーんな大事なこと、ドキュメントしときなさいよ、まったく…。