cytoscape.js進階篇
- 系列文章
- 前言
- cytoscape依賴參考
- cytoscape擴展依賴參考
- 升級Cytoscape組件
- 擴展Cytoscape組件模板容器
- 擴展Cytoscape組件方法
- 完善Cytoscape組件高亮樣式
- 完善Cytoscape組件中圓形選單中的高亮鄰居指令
- Cytoscape組件中完善內容方法詳解
- 放大縮小
- 合適大小
- 重繪布局
- 高亮鄰居
- 完整的Cytoscape組件代碼
- Cytoscape組件的使用
- 創建Cytoscape測驗模板
- Cytoscape組件參考
- Cytoscape測驗模板方法
- 完整的Cytoscape測驗模板代碼
- 完整截圖
- 注意事項
很久之前寫過一篇cytoscape.js基礎篇, 地址是https://blog.csdn.net/dahaiaixiaohai/article/details/89669526. 可以適當的參考一下其內容.
很久之前寫過一篇cytoscape.js初級篇, 地址是https://blog.csdn.net/dahaiaixiaohai/article/details/108862390. 可以適當的參考一下其內容.
很久之前寫過一篇cytoscape.js Cxtmenu圓形選單篇, 地址是https://blog.csdn.net/dahaiaixiaohai/article/details/108867486. 可以適當的參考一下其內容.
本篇章, 正式使用cytoscape.js實作一些簡單的節點操作, 并加上左上角的操作工具列. 所提供的工具列功能有: 放大, 縮小, 自由布局, 方形布局, 圓形布局, 高亮鄰居. 實作這些功能后, 開發者可以自由實作其他功能. 擴展功能將會在后期繼續更新發布.


本文對應的源代碼寄托于github, cytoscape.js進階篇 , 在此感謝github提供的服務.
系列文章
- cytoscape.js基礎篇CSDN博客
- cytoscape.js初級篇CSDN博客
- cytoscape.js初級篇github源代碼
- cytoscape.js Cxtmenu圓形選單篇
- cytoscape.js Cxtmenu圓形選單篇github源代碼
- cytoscape.js進階篇
- cytoscape.js進階篇github源代碼
- cytoscape.js專案篇
- cytoscape.js專案篇github源代碼
前言
本實體通過Vue開發測驗, 其他開發方式可以參考本篇章, 適當的修改后使用.
cytoscape依賴參考
- npm : npm install cytoscape --save
- bower : bower install cytoscape
- jspm : jspm install npm:cytoscape
cytoscape擴展依賴參考
- 本篇章主要依賴
cytoscape-avsdf,cytoscape-cola,cytoscape-cose-bilkent組件. 所以務必保證該些組件安裝成功.
npm 布局及擴展依賴參考
# Cytoscape.js的圓形可滑動背景關系擴展選單
npm install cytoscape-cxtmenu --save
# Cytoscape.js的布局方式
npm install cytoscape-avsdf --save
npm install cytoscape-cola --save
npm install cytoscape-cose-bilkent --save
升級Cytoscape組件
- 本篇章是在 cytoscape.js Cxtmenu圓形選單篇 的基礎上繼續完善實作的, 沒有 cytoscape.js Cxtmenu圓形選單篇 準備作業或后面代碼看起來有些吃力的小伙伴們可以先看一下cytoscape.js Cxtmenu圓形選單篇, cytoscape.js初級篇 , 甚至可以先看一下 cytoscape.js基礎篇 .
擴展Cytoscape組件模板容器
- 擴展Cytoscape模板容器后的樣式, 在左上角會多出一組工具列. 該工具列是由組件本身提供, 不需要參考者單獨開發工具列.
<style scoped>
.tools {
display: inline-block;
height: 45px;
width: 45px;
vertical-align: middle;
}
.center-center {
height: 100%;
display: flex;
align-items: center;
align-content: center;
justify-items: center;
justify-content: center;
}
</style>
<template>
<div style="position: relative; height: 100%; width: 100%; z-index: 0;">
<div id="cytoscape_id" style="height: 100%; width: 100%; z-index: 1;"></div>
<div id="cytoolbar_id" style="position: absolute; left: 5pt; top: 5pt; z-index: 2; background-color: rgba(249, 249, 249, 0.9);">
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="放大" type="ios-add-circle-outline" @click="magnifying()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="縮小" type="ios-remove-circle-outline" @click="contractible()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="合適大小" type="ios-resize" @click="resize()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="高亮鄰居" type="ios-color-wand-outline" @click="highlight()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="重繪布局" type="ios-sync" @click="refresh({name: 'cola'})"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="網格布局" type="ios-apps-outline" @click="refresh({name: 'grid'})"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="環形布局" type="ios-globe-outline" @click="refresh({name: 'circle'})"/>
</div>
</div>
</div>
</div>
</template>
擴展Cytoscape組件方法
<script>
export default {
methods: {
// ......
/***************************工具列************************/
/**
* 縮放大小.
* @param zoom 增減幅度.
*/
zoom(zoom) {
/** 獲取已選擇內容 */
let selectedEles = this.$cy.elements('node:selected');
/** 獲取已選擇內容中得第一個, 沒有選擇為null */
let selectedEle = selectedEles && selectedEles.length ? selectedEles[0] : null;
/** 獲取畫布偏移位置 */
let pan = this.$cy.pan();
/** 計算原點坐標 */
let [x, y] = selectedEle ? [selectedEle.position('x'), selectedEle.position('y')] : [pan.x, pan.y];
let level = this.$cy.zoom() + zoom;
(level > this.$cy.maxZoom) && (level = this.$cy.maxZoom);
(level < this.$cy.minZoom) && (level = this.$cy.minZoom);
this.$cy.zoom({level: level, renderedPosition: {x: x, y: y}});
},
/** 放大 */
magnifying() {
this.zoom(0.3);
},
/** 縮小 */
contractible() {
this.zoom(-0.3);
},
/** 合適大小 */
resize() {
this.$cy.fit();
},
/**
* 高亮.
* @param ele 某元素ID
*/
lightOn(ele) {
this.$cy.startBatch();
this.$cy.batch(() => {
this.$cy.elements().addClass("light-off"); //*添加樣式*/
let elements = ((Array.isArray ? Array.isArray(ele) : null != ele && ele instanceof Array) ? ele : [ele]);
elements.forEach(__ => {
this.$cy.getElementById(__).removeClass("light-off");
this.$cy.getElementById(__).neighborhood().removeClass("light-off");
});
});
this.$cy.once('click', () => this.lightOff());
this.$cy.endBatch();
},
/**
* 取消高亮.
*/
lightOff() {
this.$cy.startBatch();
this.$cy.batch(() => this.$cy.elements().removeClass("light-off") /*移除樣式*/);
this.$cy.endBatch();
},
/** 高亮鄰居 */
highlight() {
/** 獲取已選擇內容 */
let selectedEles = this.$cy.elements('node:selected');
/** 獲取已選擇內容中得第一個, 沒有選擇為null */
let selectedEle = selectedEles && selectedEles.length ? selectedEles[0] : null;
(selectedEle) && (this.lightOn(selectedEle.id()));
},
/**
* 重繪布局.
* name取值范圍:
* ['grid', 'circle', 'cola', 'avsdf', 'cose-bilkent', ]
* @param {name = 'cola......', randomize = true | false, animate = true | false}
*/
refresh({name = 'cola', randomize = false, animate = true} = {}) {
this.$cy.layout({name: name, randomize: randomize, animate: animate,}).run();
},
/***************************工具列************************/
},
}
</script>
完善Cytoscape組件高亮樣式
- 高亮樣式核心樣式配置
this.$cy.style().selector('.light-off').style({'opacity': '0.1',}).
// 通用的樣式
this.$cy.style()
/*未選擇節點樣式*/
.selector('node')
.style({'label': 'data(name)', 'font-size': '10pt', 'width': '8pt', 'height': '8pt'})
/*已選擇節點樣式*/
.selector('node:selected')
.style({'border-color': '#c84e40', 'border-width': "1px",})
/*未選擇節點樣式*/
.selector('edge')
.style({......})
/*已選擇節點樣式*/
.selector('edge:selected')
.style({......})
/*高亮樣式*/
.selector('.light-off')
.style({'opacity': '0.1',})
;
完善Cytoscape組件中圓形選單中的高亮鄰居指令
{
// fillColor: 'rgba(200, 200, 200, 0.75)', // optional: custom background color for item
content: '高亮鄰居', // html/text content to be displayed in the menu
// contentStyle: {}, // css key:value pairs to set the command's css in js if you want
select: (ele) => this.lightOn([ele.id()]), // a function to execute when the command is selected
enabled: true, // whether the command is selectable
},
Cytoscape組件中完善內容方法詳解
放大縮小
/**
* 縮放大小.
* @param zoom 增減幅度.
*/
zoom(zoom) {
/** 獲取已選擇內容 */
let selectedEles = this.$cy.elements('node:selected');
/** 獲取已選擇內容中得第一個, 沒有選擇為null */
let selectedEle = selectedEles && selectedEles.length ? selectedEles[0] : null;
/** 獲取畫布偏移位置 */
let pan = this.$cy.pan();
/** 計算原點坐標 */
let [x, y] = selectedEle ? [selectedEle.position('x'), selectedEle.position('y')] : [pan.x, pan.y];
let level = this.$cy.zoom() + zoom;
(level > this.$cy.maxZoom) && (level = this.$cy.maxZoom);
(level < this.$cy.minZoom) && (level = this.$cy.minZoom);
this.$cy.zoom({level: level, renderedPosition: {x: x, y: y}});
},
/** 放大 */
magnifying() {
this.zoom(0.3);
},
/** 縮小 */
contractible() {
this.zoom(-0.3);
},
合適大小
/** 合適大小 */
resize() {
this.$cy.fit();
},
重繪布局
- 依賴上述依賴組件:
cytoscape-avsdf,cytoscape-cola,cytoscape-cose-bilkent組件.
/**
* 重繪布局.
* name取值范圍:
* ['grid', 'circle', 'cola', 'avsdf', 'cose-bilkent', ]
* @param {name = 'cola......', randomize = true | false, animate = true | false}
*/
refresh({name = 'cola', randomize = false, animate = true} = {}) {
this.$cy.layout({name: name, randomize: randomize, animate: animate,}).run();
},
高亮鄰居
- 高亮的程序: 判斷是否有選擇節點, 多選擇節點, 只取第0個節點.
- 給所有節點添加高亮樣式, 獲取選擇節點去除高亮樣式.
- 添加一次性操作onse(‘click’, () => {}), 取消高亮樣式.
- 異步執行.
/**
* 高亮.
* @param ele 某元素ID
*/
lightOn(ele) {
this.$cy.startBatch();
this.$cy.batch(() => {
this.$cy.elements().addClass("light-off"); //*添加樣式*/
let elements = ((Array.isArray ? Array.isArray(ele) : null != ele && ele instanceof Array) ? ele : [ele]);
elements.forEach(__ => {
this.$cy.getElementById(__).removeClass("light-off");
this.$cy.getElementById(__).neighborhood().removeClass("light-off");
});
});
this.$cy.once('click', () => this.lightOff());
this.$cy.endBatch();
},
/**
* 取消高亮.
*/
lightOff() {
this.$cy.startBatch();
this.$cy.batch(() => this.$cy.elements().removeClass("light-off") /*移除樣式*/);
this.$cy.endBatch();
},
/** 高亮鄰居 */
highlight() {
/** 獲取已選擇內容 */
let selectedEles = this.$cy.elements('node:selected');
/** 獲取已選擇內容中得第一個, 沒有選擇為null */
let selectedEle = selectedEles && selectedEles.length ? selectedEles[0] : null;
(selectedEle) && (this.lightOn(selectedEle.id()));
},
完整的Cytoscape組件代碼
<style scoped>
.tools {
display: inline-block;
height: 45px;
width: 45px;
vertical-align: middle;
}
.center-center {
height: 100%;
display: flex;
align-items: center;
align-content: center;
justify-items: center;
justify-content: center;
}
</style>
<template>
<div style="position: relative; height: 100%; width: 100%; z-index: 0;">
<div id="cytoscape_id" style="height: 100%; width: 100%; z-index: 1;"></div>
<div id="cytoolbar_id" style="position: absolute; left: 5pt; top: 5pt; z-index: 2; background-color: rgba(249, 249, 249, 0.9);">
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="放大" type="ios-add-circle-outline" @click="magnifying()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="縮小" type="ios-remove-circle-outline" @click="contractible()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="合適大小" type="ios-resize" @click="resize()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="高亮鄰居" type="ios-color-wand-outline" @click="highlight()"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="重繪布局" type="ios-sync" @click="refresh({name: 'cola'})"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="網格布局" type="ios-apps-outline" @click="refresh({name: 'grid'})"/>
</div>
</div>
<div class="tools">
<div class="center-center">
<Icon style="font-size: 32px; cursor: pointer;" title="環形布局" type="ios-globe-outline" @click="refresh({name: 'circle'})"/>
</div>
</div>
</div>
</div>
</template>
<script>
import cytoscape from 'cytoscape';
import cxtmenu from 'cytoscape-cxtmenu';
import cola from 'cytoscape-cola';
import avsdf from 'cytoscape-avsdf';
import coseBilkent from 'cytoscape-cose-bilkent';
export default {
name: "CJS",
beforeCreate() {
this.$cy && this.$cy.destroyed() && this.$cy.destroy();
delete this.$cy;
},
beforeDestroy() {
this.$cy && this.$cy.destroyed() && this.$cy.destroy();
delete this.$cy;
},
watch: {},
props: {},
mounted() {
// Cxtmenu圓形選單主要依賴組件
if (!cytoscape().cxtmenu) {
cytoscape.use(cxtmenu);
cytoscape.use(cola);
cytoscape.use(avsdf);
cytoscape.use(coseBilkent);
}
this.$cy = cytoscape({
// initial viewport state:
zoom: 1, // 圖表的初始縮放級別.可以設定options.minZoom和options.maxZoom設定縮放級別的限制.
pan: {x: 0, y: 0}, // 圖表的初始平移位置.
// interaction options:
minZoom: 1e-50, // 圖表縮放級別的最小界限.視口的縮放比例不能小于此縮放級別.
maxZoom: 1e50, // 圖表縮放級別的最大界限.視口的縮放比例不能大于此縮放級別.
zoomingEnabled: true, // 是否通過用戶事件和編程方式啟用縮放圖形.
userZoomingEnabled: true, // 是否允許用戶事件(例如滑鼠滾輪,捏合縮放)縮放圖形.對此縮放的編程更改不受此選項的影響.
panningEnabled: true, // 是否通過用戶事件和編程方式啟用平移圖形.
userPanningEnabled: true, // 是否允許用戶事件(例如拖動圖形背景)平移圖形.平移的程式化更改不受此選項的影響.
boxSelectionEnabled: true, // 是否啟用了框選擇(即拖動框疊加,并將其釋放為選擇).如果啟用,則用戶必須點擊以平移圖表.
selectionType: 'single', // 一個字串,指示用戶輸入的選擇行為.對于'additive',用戶進行的新選擇將添加到當前所選元素的集合中.對于'single',用戶做出的新選擇成為當前所選元素的整個集合.
touchTapThreshold: 8, // 非負整數,分別表示用戶在輕擊手勢期間可以在觸摸設備和桌面設備上移動的最大允許距離.這使得用戶更容易點擊.
// 這些值具有合理的默認值,因此建議不要更改這些選項,除非您有充分的理由這樣做.大值幾乎肯定會產生不良后果.
desktopTapThreshold: 4, // 非負整數,分別表示用戶在輕擊手勢期間可以在觸摸設備和桌面設備上移動的最大允許距離.這使得用戶更容易點擊.
// 這些值具有合理的默認值,因此建議不要更改這些選項,除非您有充分的理由這樣做.大值幾乎肯定會產生不良后果.
autolock: false, // 默認情況下是否應鎖定節點(根本不可拖動,如果true覆寫單個節點狀態).
autoungrabify: false, // 默認情況下節點是否不允許被拾取(用戶不可抓取,如果true覆寫單個節點狀態).
autounselectify: false, // 默認情況下節點是否允許被選擇(不可變選擇狀態,如果true覆寫單個元素狀態).
// rendering options:
headless: false, // true:空運行,不顯示不需要容器容納.false:顯示需要容器容納.
styleEnabled: true, // 一個布林值,指示是否應用樣式.
hideEdgesOnViewport: true, // 渲染提示,設定為true在渲染視窗時,不渲染邊.例如,移動某個頂點時或縮放時,邊資訊會被臨時隱藏,移動結束后,邊資訊會被執行一次渲染.由于性能增強,此選項現在基本上沒有實際意義.
hideLabelsOnViewport: true, // 渲染提示,當設定為true使渲染器在平移和縮放期間使用紋理而不是繪制元素時,使大圖更具回應性.由于性能增強,此選項現在基本上沒有實際意義.
textureOnViewport: true, // 渲染提示,當設定為true使渲染器在平移和縮放期間使用紋理而不是繪制元素時,使大圖更具回應性.由于性能增強,此選項現在基本上沒有實際意義.
motionBlur: true, // 渲染提示,設定為true使渲染器使用運動模糊效果使幀之間的過渡看起來更平滑.這可以增加大圖的感知性能.由于性能增強,此選項現在基本上沒有實際意義.
motionBlurOpacity: 0.2, // 當motionBlur:true,此值控制運動模糊幀的不透明度.值越高,運動模糊效果越明顯.由于性能增強,此選項現在基本上沒有實際意義.
wheelSensitivity: 0.3, // 縮放時更改滾輪靈敏度.這是一個乘法修飾符.因此,0到1之間的值會降低靈敏度(變焦較慢),而大于1的值會增加靈敏度(變焦更快).
pixelRatio: 'auto', // 使用手動設定值覆寫螢屏像素比率(1.0建議,如果已設定).這可以通過減少需要渲染的有效區域來提高高密度顯示幕的性能,
// 盡管在最近的瀏覽器版本中這是不太必要的.如果要使用硬體的實際像素比,可以設定pixelRatio: 'auto'(默認).
// DOM容器,決定內容展示的位置,方式一(原生):document.getElementById('xx'),方式二(jQuery):$('#xx')
container: document.getElementById('cytoscape_id'),
// 一個指定布局選項的普通物件.
layout: {name: 'random'},
});
// Cxtmenu圓形選單--開始
this.$cy.cxtmenu({
menuRadius: 80, // the radius of the circular menu in pixels
selector: 'node', // elements matching this Cytoscape.js selector will trigger cxtmenus
commands: (element) => {
return [
{
fillColor: 'rgba(200, 200, 200, 0.75)', // optional: custom background color for item
content: '<span class="fa fa-flash fa-2x">操作1</span>', // html/text content to be displayed in the menu
contentStyle: {}, // css key:value pairs to set the command's css in js if you want
select: function (ele) { // a function to execute when the command is selected
alert(ele.id()); // `ele` holds the reference to the active element
},
enabled: true, // whether the command is selectable
},
{
fillColor: 'rgba(200, 200, 200, 0.75)', // optional: custom background color for item
content: '<span class="fa fa-flash fa-2x">操作2</span>', // html/text content to be displayed in the menu
contentStyle: {}, // css key:value pairs to set the command's css in js if you want
select: function (ele) { // a function to execute when the command is selected
alert(ele.id()); // `ele` holds the reference to the active element
},
enabled: true, // whether the command is selectable
},
{
// fillColor: 'rgba(200, 200, 200, 0.75)', // optional: custom background color for item
content: '高亮鄰居', // html/text content to be displayed in the menu
// contentStyle: {}, // css key:value pairs to set the command's css in js if you want
select: (ele) => this.lightOn([ele.id()]), // a function to execute when the command is selected
enabled: true, // whether the command is selectable
},
{
// fillColor: 'rgba(200, 200, 200, 0.75)', // optional: custom background color for item
content: '禁用', // html/text content to be displayed in the menu
// contentStyle: {}, // css key:value pairs to set the command's css in js if you want
select: (ele) => alert(ele.id()), // a function to execute when the command is selected
enabled: false, // whether the command is selectable
}
]
},
fillColor: 'rgba(0, 0, 0, 0.75)', // 指令默認顏色(the background colour of the menu)
activeFillColor: 'rgba(1, 105, 217, 0.75)', // 所選指令的顏色(the colour used to indicate the selected command)
activePadding: 10, // additional size in pixels for the active command
indicatorSize: 14, // the size in pixels of the pointer to the active command
separatorWidth: 4, //連續命令之間的空白間隔(以像素為單位)
spotlightPadding: 10, //元素和聚光燈之間的額外間距(以像素為單位)
minSpotlightRadius: 10, // the minimum radius in pixels of the spotlight
maxSpotlightRadius: 14, // the maximum radius in pixels of the spotlight
openMenuEvents: 'cxttapstart taphold', // space-separated cytoscape events that will open the menu; only `cxttapstart` and/or `taphold` work here
itemColor: 'white', // 各指令元素內字體顏色
itemTextShadowColor: 'red', // 各指令元素內字體陰影顏色
zIndex: 9999, // the z-index of the ui div
atMouse: true, // draw menu at mouse position
});
//Cxtmenu圓形選單--結束
// 不同節點的樣式
this.$cy
.style()
.selector('.classes-A')
.style({'background-color': '#FF0000', 'border-color': '#FF0000', 'border-width': "1px",})
.selector('.classes-B')
.style({'background-color': '#00FF00', 'border-color': '#00FF00', 'border-width': "1px",})
.selector('.classes-C')
.style({'background-color': '#0000FF', 'border-color': '#0000FF', 'border-width': "1px",})
.selector('.classes-D')
.style({'background-color': '#E0E0E0', 'border-color': '#E0E0E0', 'border-width': "1px",})
;
// 通用的樣式
this.$cy.style()
/*未選擇節點樣式*/
.selector('node')
.style({'label': 'data(name)', 'font-size': '10pt', 'width': '8pt', 'height': '8pt'})
/*已選擇節點樣式*/
.selector('node:selected')
.style({'border-color': '#c84e40', 'border-width': "1px",})
/*未選擇節點樣式*/
.selector('edge')
.style({
'label': 'data(name)',
'target-arrow-shape': 'triangle-backcurve', /*箭頭樣式*/
'target-arrow-size': '1px', /*箭頭大小*/
'target-arrow-color': '#999999', /*箭頭顏色*/
'curve-style': 'bezier', /*線條樣式曲線*/
'line-color': '#999999', /*線條顏色*/
'width': '1px', /*線條寬度*/
'font-size': '10px', /*標簽字體大小*/
'color': '#000000', /*標簽字體大小*/
'text-outline-color': 'white', /*文本輪廓顏色*/
'text-outline-width': '1px', /*文本輪廓寬度*/
'text-rotation': 'autorotate', /*標簽方向*/
})
/*已選擇節點樣式*/
.selector('edge:selected')
.style({
'color': '#3165fc', /*標簽字體大小*/
'target-arrow-color': '#61bffc', /*箭頭顏色*/
'line-color': '#61bffc', /*線條顏色*/
})
/*高亮樣式*/
.selector('.light-off')
.style({'opacity': '0.1',})
;
},
data() {
return {}
},
methods: {
/**
* eles : Array or Map.
* node_eg: {group: 'nodes', data: {id: 'nid1', name: 'name1', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
* edge_eg: {group: 'edges', data: {id: 'eid1', name: 'name1', source: 'A', target: 'B', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
* node_eg: [
* {group: 'nodes', data: {id: 'nid1', name: 'name1', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
* {group: 'nodes', data: {id: 'nid2', name: 'name2', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
* ];
* edge_eg: [
* {group: 'edges', data: {id: 'eid1', name: 'name1', source: 'nid1', target: 'nid2', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
* {group: 'edges', data: {id: 'eid2', name: 'name1', source: 'nid2', target: 'nid3', label: 'l1 l2', others: 'others'}, classes: 'like label', position: {x: 100, y: 100}};
* ];
* @param eles 元素集合.
*/
addEles(eles) {
if (eles) {
this.$cy.startBatch();
this.$cy.batch(() => {
let elements = ((Array.isArray ? Array.isArray(eles) : null != eles && eles instanceof Array) ? eles : [eles]);
let filterElements = elements.filter(__ => !this.$cy.getElementById(__.data.id).length)
this.$cy.add(filterElements);
});
this.$cy.endBatch();
}
},
/**
* 洗掉選擇的內容(可能是頂點, 也可能是關系)
*/
delEles() {
this.$cy.startBatch();
this.$cy.batch(() => {
let selectedEles = this.$cy.elements(':selected');
// 未選擇不進行操作
if (!selectedEles || 1 > selectedEles.length) {
return false;
}
selectedEles.remove();
});
this.$cy.endBatch();
},
/***************************工具列************************/
/**
* 縮放大小.
* @param zoom 增減幅度.
*/
zoom(zoom) {
/** 獲取已選擇內容 */
let selectedEles = this.$cy.elements('node:selected');
/** 獲取已選擇內容中得第一個, 沒有選擇為null */
let selectedEle = selectedEles && selectedEles.length ? selectedEles[0] : null;
/** 獲取畫布偏移位置 */
let pan = this.$cy.pan();
/** 計算原點坐標 */
let [x, y] = selectedEle ? [selectedEle.position('x'), selectedEle.position('y')] : [pan.x, pan.y];
let level = this.$cy.zoom() + zoom;
(level > this.$cy.maxZoom) && (level = this.$cy.maxZoom);
(level < this.$cy.minZoom) && (level = this.$cy.minZoom);
this.$cy.zoom({level: level, renderedPosition: {x: x, y: y}});
},
/** 放大 */
magnifying() {
this.zoom(0.3);
},
/** 縮小 */
contractible() {
this.zoom(-0.3);
},
/** 合適大小 */
resize() {
this.$cy.fit();
},
/**
* 高亮.
* @param ele 某元素ID
*/
lightOn(ele) {
this.$cy.startBatch();
this.$cy.batch(() => {
this.$cy.elements().addClass("light-off"); //*添加樣式*/
let elements = ((Array.isArray ? Array.isArray(ele) : null != ele && ele instanceof Array) ? ele : [ele]);
elements.forEach(__ => {
this.$cy.getElementById(__).removeClass("light-off");
this.$cy.getElementById(__).neighborhood().removeClass("light-off");
});
});
this.$cy.once('click', () => this.lightOff());
this.$cy.endBatch();
},
/**
* 取消高亮.
*/
lightOff() {
this.$cy.startBatch();
this.$cy.batch(() => this.$cy.elements().removeClass("light-off") /*移除樣式*/);
this.$cy.endBatch();
},
/** 高亮鄰居 */
highlight() {
/** 獲取已選擇內容 */
let selectedEles = this.$cy.elements('node:selected');
/** 獲取已選擇內容中得第一個, 沒有選擇為null */
let selectedEle = selectedEles && selectedEles.length ? selectedEles[0] : null;
(selectedEle) && (this.lightOn(selectedEle.id()));
},
/**
* 重繪布局.
* name取值范圍:
* ['grid', 'circle', 'cola', 'avsdf', 'cose-bilkent', ]
* @param {name = 'cola......', randomize = true | false, animate = true | false}
*/
refresh({name = 'cola', randomize = false, animate = true} = {}) {
this.$cy.layout({name: name, randomize: randomize, animate: animate,}).run();
},
/***************************工具列************************/
},
}
</script>
Cytoscape組件的使用
- Cytoscape測驗模板與 cytoscape.js初級篇 的Cytoscape測驗模板幾乎完全一致.
- 唯一差距在: 將添加, 洗掉按鍵下移, 給工具列騰出位置.
創建Cytoscape測驗模板
<template>
<div style="height: 100%; width: 100%; border: 1px solid #00F;">
<div style="position: fixed; left: 20pt; top: 50pt; z-index: 99999;">
<Button size="small" @click="addEles">添加</Button>
<Button size="small" @click="delEles">洗掉</Button>
</div>
<CJS ref="ref_CJS"></CJS>
</div>
</template>
- 樣式如下

Cytoscape組件參考
- 測驗模板參考Cytoscape組件, 并命名為CJS.
<script>
import CJS from './components/cjs';
export default {
name: "Test",
components: {CJS,},
// ......
}
</script>
Cytoscape測驗模板方法
methods: {
addEles() {
this.$refs['ref_CJS'].addEles([
{group: 'nodes', data: {'id': '魯A123456', 'name': '魯A123456',}, classes: 'classes-A', position: {x: 200, y: 50}},
{group: 'nodes', data: {'id': '魯B123456', 'name': '魯B123456',}, classes: 'classes-A', position: {x: 500, y: 50}},
{group: 'nodes', data: {'id': '魯C123456', 'name': '魯C123456',}, classes: 'classes-A', display: 'hide', position: {x: 200, y: 150}},
{group: 'nodes', data: {'id': '魯D123456', 'name': '魯D123456',}, classes: 'classes-A', position: {x: 500, y: 150}},
{group: 'nodes', data: {'id': '小王', 'name': '小王',}, classes: 'classes-B', position: {x: 100, y: 100}},
{group: 'nodes', data: {'id': '小趙', 'name': '小趙',}, classes: 'classes-B', position: {x: 400, y: 100}},
{group: 'nodes', data: {'id': '川川某公司', 'name': '川川某公司',}, classes: 'classes-C', display: 'hide', position: {x: 300, y: 100}},
{group: 'nodes', data: {'id': '京京某單位', 'name': '京京某單位',}, classes: 'classes-D', position: {x: 300, y: 200}},
{group: 'edges', data: {id: 'e0', name: '擁有', source: '小王', target: '魯A123456'}},
{group: 'edges', data: {id: 'e1', name: '擁有', source: '小趙', target: '魯B123456'}},
{group: 'edges', data: {id: 'e2', name: '擁有', source: '小王', target: '魯C123456'}},
{group: 'edges', data: {id: 'e3', name: '擁有', source: '小趙', target: '魯D123456'}},
{group: 'edges', data: {id: 'e4', name: '就職', source: '小王', target: '川川某公司'}},
{group: 'edges', data: {id: 'e5', name: '就職', source: '小趙', target: '川川某公司'}},
{group: 'edges', data: {id: 'e6', name: '租用', source: '川川某公司', target: '魯A123456'}},
{group: 'edges', data: {id: 'e7', name: '租用', source: '川川某公司', target: '魯B123456'}}
]);
},
delEles() {
this.$refs['ref_CJS'].delEles();
},
},
完整的Cytoscape測驗模板代碼
<template>
<div style="height: 100%; width: 100%; border: 1px solid #00F;">
<div style="position: fixed; left: 20pt; top: 20pt; z-index: 99999;">
<Button size="small" @click="addEles">添加</Button>
<Button size="small" @click="delEles">洗掉</Button>
</div>
<CJS ref="ref_CJS"></CJS>
</div>
</template>
<script>
import CJS from './components/cjs';
export default {
name: "Test",
components: {CJS,},
watch: {},
mounted() {
this.addEles();
},
methods: {
addEles() {
this.$refs['ref_CJS'].addEles([
{group: 'nodes', data: {'id': '魯A123456', 'name': '魯A123456',}, classes: 'classes-A', position: {x: 200, y: 50}},
{group: 'nodes', data: {'id': '魯B123456', 'name': '魯B123456',}, classes: 'classes-A', position: {x: 500, y: 50}},
{group: 'nodes', data: {'id': '魯C123456', 'name': '魯C123456',}, classes: 'classes-A', display: 'hide', position: {x: 200, y: 150}},
{group: 'nodes', data: {'id': '魯D123456', 'name': '魯D123456',}, classes: 'classes-A', position: {x: 500, y: 150}},
{group: 'nodes', data: {'id': '小王', 'name': '小王',}, classes: 'classes-B', position: {x: 100, y: 100}},
{group: 'nodes', data: {'id': '小趙', 'name': '小趙',}, classes: 'classes-B', position: {x: 400, y: 100}},
{group: 'nodes', data: {'id': '川川某公司', 'name': '川川某公司',}, classes: 'classes-C', display: 'hide', position: {x: 300, y: 100}},
{group: 'nodes', data: {'id': '京京某單位', 'name': '京京某單位',}, classes: 'classes-D', position: {x: 300, y: 200}},
{group: 'edges', data: {id: 'e0', name: '擁有', source: '小王', target: '魯A123456'}},
{group: 'edges', data: {id: 'e1', name: '擁有', source: '小趙', target: '魯B123456'}},
{group: 'edges', data: {id: 'e2', name: '擁有', source: '小王', target: '魯C123456'}},
{group: 'edges', data: {id: 'e3', name: '擁有', source: '小趙', target: '魯D123456'}},
{group: 'edges', data: {id: 'e4', name: '就職', source: '小王', target: '川川某公司'}},
{group: 'edges', data: {id: 'e5', name: '就職', source: '小趙', target: '川川某公司'}},
{group: 'edges', data: {id: 'e6', name: '租用', source: '川川某公司', target: '魯A123456'}},
{group: 'edges', data: {id: 'e7', name: '租用', source: '川川某公司', target: '魯B123456'}}
]);
},
delEles() {
this.$refs['ref_CJS'].delEles();
},
},
}
</script>
<style scoped>
</style>
完整截圖

注意事項
由于該專案是一系列文章, 逐步完善下來的, 所以在中間章節中, 并沒有詳細講解之前的內容, 如果需要了解之前的內容, 可以通過系列文章預覽閱讀早期內容或更新的內容.
本文到此結束, 更完善的內容還在后面, 敬請期待.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/143297.html
標籤:其他
上一篇:JavaScript基礎速通
下一篇:Vue條件和回圈陳述句
