天天看點

Cytoscape.js 網絡圖

這是基于vue架構的網絡圖案例,隻實作了一部分功能,要想深入了解參考:Cytoscape.js

1、安裝cytoscape.js      
npm : npm install cytoscape
npm : npm install cytoscape-panzoom

2、在main.js裡面配置:
  import cytoscape from 'cytoscape'
  import panzoom from 'cytoscape-panzoom'
  panzoom(cytoscape)
           

一、建立一個展示網絡圖的視窗,html代碼。

// html頁面
<div :id='this.id' :style="idBackground"></div>
// 網絡圖資料
data() {
  return {
  id:'netWorkId',
  idBackground: {backgroundColor: "white", height: "650px"},
  filter:0.5, //  edge資料展示的控制
  clusterInfo:{},
  networkData:{},
  cy: {},
   }
}
           

二、資料的擷取

1、假資料的格式

let NetWorkData = {
	data:{
		"clusterInfo":['1','2'],
		"nodes":[{ "id": "1", "name": "TCGA-CN-6022-01", "cluster": "2" }, { "id": "2", "name": "TCGA-CQ-5327-01", "cluster": "1" }],
		"edges":[{ "id": "1_2", "source": "1", "target": "2", "edge_weight": "1" }, { "id": "1_2", "source": "1", "target": "2", "edge_weight": "1" },]
	}
}
           

2、資料的擷取和指派

// 初始化這個方法
show(){
	this.networkData = {nodes: NetWorkData.data.nodes, edges: NetWorkData.data.edges};
	this.clusterInfo = NetWorkData.data.clusterInfo;
	this.drawNetwork();
}
           

二、網絡圖建立的必要方法

drawNetwork(){
	var elements = this.formatCoexpression(this.filter)
    this.cy = this.generateCyto(elements, this.id);
    // 圖注的添加。樣式的設定是設定classes,位置的設定是position
    this.cy.add([{
          group: "nodes",
          data: {id: 'legend1', name: 'Cluster1', width: 30},
          position: {x: 50, y: 50},
          classes: 'legend1',
          locked: true,
          grabbable: false,
        },{
          group: "nodes",
          data: {id: 'legend2', name: 'Cluster2', width: 30},
          position: {x: 50, y: 100},
          classes: 'legend2',
          locked: true,
          grabbable: false,
        }]);
        // A panzoom UI widget
	this.cy.panzoom({
         zoomFactor: 0.05, // zoom factor per zoom tick
         zoomDelay: 45, // how many ms between zoom ticks
         minZoom: 0.1, // min zoom level
         maxZoom: 10, // max zoom level
         fitPadding: 50, // padding when fitting
         panSpeed: 10, // how many ms in between pan ticks
         panDistance: 10, // max pan distance per tick
         panDragAreaSize: 75, // the length of the pan drag box in which the vector for panning is calculated (bigger = finer control of pan speed and direction)
         panMinPercentSpeed: 0.25, // the slowest speed we can pan by (as a percent of panSpeed)
         panInactiveArea: 8, // radius of inactive area in pan drag box
         panIndicatorMinOpacity: 0.5, // min opacity of pan indicator (the draggable nib); scales from this to 1.0
         zoomOnly: false, // a minimal version of the ui only with zooming (useful on systems with bad mousewheel resolution)
         fitSelector: undefined, // selector of elements to fit
         animateOnFit: function () { // whether to animate on fit
           return false;
         },
         fitAnimationDuration: 1000, // duration of animation on fit

         // icon class names
         //sliderHandleIcon: 'fa fa-minus',
         sliderHandleIcon: 'ivu-icon ivu-icon-ios-remove',
         zoomInIcon: 'ivu-icon ivu-icon-ios-add',
         //zoomOutIcon: 'fa fa-minus',
         zoomOutIcon: 'ivu-icon ivu-icon-ios-remove"',
         //resetIcon: 'fa fa-expand'
         resetIcon: 'ivu-icon ivu-icon-ios-resize'
       })
}
           

generateCyto()方法:

generateCyto(elements, containerId) {
        return cytoscape({
          container: document.getElementById(containerId),
          style: cytoscape.stylesheet().selector('node').css({
            'content': 'data(name)'
          }).selector('node').css({
            'height': 'data(width)',
            'width': 'data(width)',
            'text-halign': "center",
            'text-valign': "center",
            'font-size':'12px',
            'text-opacity':1,
            'background-fit': 'cover'
          }).selector('node.cluster1').css({
            'background-color': '#ff9f03',
            'cursor': 'pointer'
          }).selector('node.cluster2').css({
            'background-color': '#0075b0',
          }).selector('node.legend1').css({
            'background-color': '#ff9f03',
          }).selector('node.legend2').css({
            'background-color': '#0075b0',
          }).selector('node.positiveNodeSelect').css({
            'background-color': '#00FF00'
          }).selector('node.negativeNodeSelect').css({
            'background-color': '#FF0000'
          }).selector('edge').css({
            'target-arrow-shape': 'none',
            'curve-style': 'bezier',
            'control-point-step-size': 20,
            'line-color': '#B2B2B2',
            'width': 'data(weight)'
          }),
          elements: elements,
          layout: {
            name: cose, // 算法的不同展示方法
            padding: 20,
            boundingBox: {x1: 0, y1: 0, w: 550, h: 650},
            fit: true,
          },
          // zoomingEnabled:false,
          zoom: 1,
          minZoom: 0.5,
          maxZoom: 2,
          ready: function () {
          }
        })
      },
           

要是需要處理資料,執行例一,不需要處理資料直接把數值指派element就可以了。

下面是處理資料的方法。 formatCoexpression()方法:

//例一
formatCoexpression() {
        let elements = [];
        var tempObj = {}
        // 對node的處理,包括複合節點的動态添加,就是下面父節點和子節點的代碼片段
        if (this.networkData.nodes[0].node_number) {//自己加的判斷,沒有用可以删除
          this.networkData.nodes.forEach(item => {
            tempObj = {
              id: item["id"],
              name: item["name"],
              cluster: item["cluster"],
              node_number: item["node_number"],
              width: item["node_number"] / 5,
            }
            elements.push({
              data: tempObj,
              classes: "cluster" + item["cluster"]
            })
          })
        } else {
          //父節點
          this.clusterInfo.forEach(clusterItem=>{
            tempObj = {
              id: `cluster${clusterItem}`,
              name: clusterNameMap[clusterItem],
              width: 30,
              height: 50
            }
            elements.push({
              data: tempObj,
              classes: "clusterParent" + clusterItem
            })
          });
          //子節點
          this.networkData.nodes.forEach(item => {
            tempObj = {
              id: item["id"],
              name: item["name"],
              //cluster: item["cluster"],
              parent: `cluster${item["cluster"]}`,
              width: 30
            };
            elements.push({
              data: tempObj,
              classes: "cluster" + item["cluster"]
            })
          })
        }
        // 對edge的處理,根據filter控制線顯示的資料多少。
        this.networkData.edges.forEach(item => {
          let tempObj = {
            id: item["source"] + "_" + item["target"],
            source: item["source"],
            target: item["target"],
            weight: item["edge_weight"] * 2,
            edgeWeight: item['edge_weight'],
          }
          if (item["edge_weight"] > this.filter) {
            elements.push({
              data: tempObj,
              //classes:"cluster"+item["cluster"]
            })
          }
        })
        return elements
      },
           

結果展示:

紅色框内展示的是panzoom的執行個體

Cytoscape.js 網絡圖

以上是完整的網絡圖執行個體,下面介紹下關于網絡圖自己用過的其他方法。

//擷取視口的範圍,這是模型坐标中的一個邊界框,它允許您知道在視口中可見的模型位置。

1、this.cy.extent();

// node的點選事件

2、this.cy.nodes().on(‘click’, e => {});

//重構網絡圖頁面的方法,得到一個新的布局,它可以用來在圖中對節點進行算法定位

3、this.cy.layout({

name: cose, //資料的排列算法

boundingBox: {x1: 0, y1: 0, w: 550, h: 650}, //限制視圖的展示範圍。

}).run();

//對edge資料的處理

4、this.cy.edges();

//對點的樣式的處理方法

5、this.cy.nodes(’.’ + this.classes).style({

‘background-color’: red;

});

//擷取node樣式

this.cy.nodes(’.’ + this.classes).style();

// 線的樣式的處理

6、this.cy.edges().style({

// 樣式

})

//擷取edge樣式

this.cy.edges().style();

git位址:https://github.com/Li-gm/cytoscape_Test

參考網址:https://js.cytoscape.org/