概要
Cytoscape.js の Tips を紹介します
環境
- macOS 10.14
- Chrome 70.0.3538.77
- Cytoscape.js 3.2.19
四角形のノードを作成する
style: [
{
selector: 'node',
style: {
'shape': 'rectangle',
'background-color': '#666',
'label': 'data(id)'
}
}
]
style
で 'shape': 'rectangle'
を指定する
丸と四角のノードを混在させる方法
elements: {
nodes: [
{
data: {
id: 'a',
},
classes: 'foo'
},
{
data: { id: 'b' }
}
],
edges: [
{
data: { id: 'ab', source: 'a', target: 'b' }
}
]
}
nodes で classes
属性を追加します
そして style
の selector
でクラスを指定します
style: [
{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},
{
selector: '.foo',
style: {
'shape': 'rectangle',
'background-color': '#BD4343',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}
]
selector: 'node'
がデフォルトで selector: '.foo'
が classes
属性を追加したスタイルになります
マウスオーバー時のイベントをハンドリングする
cy.on('mouseover', 'node', function(event) );
ノードに背景画像を設定する
{
selector: '.host',
style: {
'shape': 'rectangle',
'label': 'data(id)',
'background-fit': 'cover',
'background-image': 'https://farm8.staticflickr.com/7272/7633179468_3e19e45a0c_b.jpg'
}
}
ノードのボーダ線を表示する
{
selector: '.host',
style: {
'shape': 'rectangle',
'label': 'data(id)',
'border-color': '#BD4343',
'border-width': 3,
'border-opacity': 0.5
}
}
ノードをタップしたら接続しているノードを削除する
cy.on('tap', 'node', function() {
console.log('hoge');
if (this.scratch().restData == null) {
this.scratch({
restData: this.successors().targets().remove()
});
} else {
this.scratch().restData.restore();
this.scratch({
restData: null
});
}
});
source 側をタップすると target 側のノードが消えます
アニメーションを追加する
cy.nodes('.host').animate({
position: {
x: cy.nodes('.host').position('x') + 100,
y: cy.nodes('.host').position('y')
},
style: {
backgroundColor: 'red',
'opacity': 0.0
},
duration: 1000,
complete: function() {
console.log("done");
}
});
画面描画時に nodes('.host')
が水平方向に右側に +100 動きます
またアニメーション時にノードの背景を赤に透明度を 0 にしています
つまりアニメーションが終了するとノードが見えなくなります (実際にはある)
また complete
を指定するとアニメーション終了後に関数を呼び出すことができます
ノードを削除したい場合はここで remove()
すれば OK です
応用: タップしたらアニメーションしてノードの削除を行う
cy.on('tap', '.router', function() {
var tappedNode = this;
var targetNode = this.successors().targets();
if (tappedNode.scratch().restData == null) {
var orgX = targetNode.position('x');
targetNode.animate({
position: {
x: tappedNode.position('x') + 100,
y: tappedNode.position('y')
},
style: {
'opacity': 0.1
},
complete: function() {
tappedNode.scratch({
targetNode: targetNode,
orgX: orgX,
restData: targetNode.remove()
});
}
});
} else {
tappedNode.scratch().restData.restore();
tappedNode.scratch().targetNode.animate({
position: {
x: tappedNode.scratch().orgX,
y: tappedNode.scratch().targetNode.position('y')
},
style: {
'opacity': 1.0
},
complete: function() {
console.log("restore");
}
});
tappedNode.scratch({
restData: null
})
}
});
restore
は remove()
した状態に戻すだけなのでアニメーションした後の位置でノードは復活します
なので restore
したあとでノードを元の位置に戻してあげる必要があります
orgX
は元の位置を保存するための scratch
でこれを使って元の位置に戻します
少し長いですがやっていることは単純です
データを外出しする
elements と style の JSON データは外出しておくと便利です
Promise.all([
fetch('../json/data.json', {mode: 'no-cors'})
.then(function(res) {
return res.json()
}),
fetch('../json/style.json', {mode: 'no-cors'})
.then(function(res) {
return res.json()
})
])
.then(function(dataArray) {
var cy = cytoscape({
container: $('#cy'),
elements: dataArray[0],
style: dataArray[1],
layout: {
name: 'cose',
}
});
});
ただし json ファイルはローカルファイルは参照できないのでご注意を
Web アプリケーション化すれば問題ないです
Promiss.all
を使うとキレイに書けます
応用: マウスオーバー時に子ノードをすべてハイライトする
またそれ以外のノードはローライトします
cy.on('mouseover', 'node', function(evt){
var sel = evt.target;
cy.elements().difference(sel.successors()).not(sel).addClass('semitransp');
sel.addClass('highlight').successors().addClass('highlight');
});
cy.on('mouseout', 'node', function(evt){
var sel = evt.target;
cy.elements().removeClass('semitransp');
sel.removeClass('highlight').successors().removeClass('highlight');
});
スタイルの json の定義は以下の通りです
色や透明度は好きな値に変更してください
{
"selector": "node.highlight",
"style": {
"border-color": "#000",
"border-width": "2px"
}
},
{
"selector": "node.semitransp",
"style":{
"opacity": "0.2"
}
},
{
"selector": "edge.highlight",
"style": {
"mid-target-arrow-color": "#000"
}
},
{
"selector": "edge.semitransp",
"style":{
"opacity": "0.2"
}
}
ちなみに successors
を outgoers
に変更すると 1 階層だけハイライトすることができます
filter を使って特定の data を含むノードだけを取得する
例えば name 属性を部分一致で検索して特定の文字列が含まれる場合のノードを取得します
var nodes = cy.nodes().filter(function(ele) {
if (ele.data('name').indexOf(name) > -1) {
return ele
}
});
特定のノード以外のノードたちを取得する
cy.nodes().difference(nodes).addClass('semitransp');
上記の場合 nodes
以外に対してクラスを追加します