jQuery: Cytoscape.js お…、う、cy.center は意図と違い、cy.panBy は何かヘン

現在進行形の「うまくいってない」メモ。

とにかく「ダメな状態」なのでソースコード管理としてリビジョン管理してるけどコミットは出来ない「試行錯誤」を、メモの形で貼り付けときたいな、という読者には迷惑な話。

とにかく全然意味不明なんだけれど、今のところわかっていること:

  1. cy.center() は最も一般的なニーズの振る舞いとは違うらしい。
    • cy.fit() と限りなく似た振る舞いをする。
    • ふつーはノードを中心に持ってくんではねーの?
  2. となれば、と、仕方なく cy.panBy()cy.extent() で動かそうとするも…。なんか凄くヘン。

1つ目を「そういうもんだ」と諦めるつもりで「許容出来る」として忘れることが出来るとしても、その代替実装をすんなり書けないのが困っているんであるよ。

こういうコードを書いた:

1 var target_ele = ...;  // ターゲットのノード (実際は cy.elements("node") で取って来たノード一つ)
2 var pos = target_ele.position();
3 var extent = cy.extent();
4 var center = {
5     x: extent.x1 + extent.w / 2,
6     y: extent.y1 + extent.h / 2
7 };
8 var vec = {x: center.x - pos.x, y: center.y - pos.y};  // pos -> center のベクトル
9 cy.panBy(vec);

最初「全くダメじゃん」なちょっとというにはズレ過ぎの位置に移動して、うーん、と思ってしばらく操作してて、あることに気付いた。

「何度も上のコードを実行し続ける(つまり作った UI のボタンを押し続ける)と、少しずつ正しい位置に収束していく」。なんぢゃそりゃぁ、ということなのだが、それだけでもないのが困っておってな。どうもレイアウト依存なの。「実行し続ければ収束する」のは grid、random、spread (と多分 preset も) で、ほかは「ぶっ飛んだまま返ってくることはない(永遠に収束しない)ということで、なので「だったら繰り返せばええんか」:

 1 var target_ele = ...;  // ターゲットのノード (実際は cy.elements("node") で取って来たノード一つ)
 2 var pos = target_ele.position();
 3 for (var _i = 0; _i < 1000; ++_i) {
 4     var extent = cy.extent();
 5     var center = {
 6         x: extent.x1 + extent.w / 2,
 7         y: extent.y1 + extent.h / 2
 8     };
 9     var vec = {x: center.x - pos.x, y: center.y - pos.y};  // pos -> center のベクトル
10     cy.panBy(vec);
11 }

なこれは、grid、random、spread (と多分 preset も) にしか通用しない、ということ。

なんなんだそれ。

ほかの pan 系もこないだ試して全然言うこと効いてなかったし zoom 系も同様なんだけど、それらの「どううまくいってないか」はまだ整理出来てない。

うーん、解決出来るんであろうか、これ。


03:50追記:
「節穴だった、解決した」と言えれば良かったんだけれど、解決には至らず。が、節穴は節穴に違いない。

#notation/position に model position と renderd position について説明されてることを見落としていた。間違いなくこれが関係している、ということだけはわかった。でもね…、わからんのよ、要するに両座標系の変換を cy.zoom() を参照して計算するとか node.renderedPosition() を使え、とかそういうことなはずなんだけどね、そこは多分そうなんだけどね、頭こんがらがっちゃって。


2018-01-23追記:
やっと解決した。本当はめちゃくちゃ単純な話だった、ということが読めばわかる…、がちょっと長いか? 正しくしたコードを引用しとく:

1 var target_ele = ...;  // ターゲットのノード (実際は cy.elements("node") で取って来たノード一つ)
2 var pos = target_ele.renderedPosition();
3 var center = {
4     x: $(cy.container()).width() / 2,
5     y: $(cy.container()).height() / 2
6 };
7 var vec = {x: center.x - pos.x, y: center.y - pos.y};  // pos -> center のベクトル
8 cy.panBy(vec);


Related Posts