前端開發框架總結之利用Jtopo實現網路拓撲功能(四)
前端開發框架總結之利用Jtopo實現網路拓撲功能(四)
上文我們講了拓撲容器相關的互動設計和實現思路以及一些關鍵技術細節。至此,我們已經覆蓋了結點建立、連線建立、容器建立、結點新增等常用場景,本文我們繼續我們的拓撲管理開發之旅。
- 拓撲元素序列化
拓撲元素建立好了,位置也擺好了,結點關聯關係也建立了,容器分組關係也明確了。接下來就是如何把這些‘辛苦’佈局的場景儲存下來以便下次就來的時候還能完完整整的看到呢。這時我們就用到了拓撲元素的序列化了。
官網的API中有現成的序列化和反序列方法,我們不妨拿來試下效果。what?序列化方法直接報錯?原來是因為我的scene中只設置了backgroundColor,好吧,製作圖片,設定backgroud屬性,然後再試。what?反序列化後我的容器和連線全不見了。好吧讓我們分析下,序列化後的資料。結果發現序列化後的資料中竟然都沒有記錄連線和結點的關聯關係。還有其他好多重要關聯資料都沒有,怪不得沒法反序列化出我們想要的結果呢。好吧,只能實現我們自己的序列化方法了。
首先是確定序列化資料的格式。我採用了官方使用json格式的資料。(js中操作json資料還是很方便的)
然後是確定具體json內容。這個根據各個人的需求確認自己要儲存哪些資訊。但是大致的層次是不會錯的。我這裡採用了三大層。第一層為stage的資訊,第二層為scene的資訊,第三次為拓撲元素的資訊,包括node,textnode,link,container。拓撲關係,比如連線、容器等與結點的關係,是使用node的virtualId屬性進行關聯的。這裡有一些小細節要主要處理,但大體思路不難。比如,container的資料結構中就要把為了固定容器四個角的結點和普通結點進行區分開來儲存。
js片段,具體屬性可以自己豐富。
function getJsonData() { var data = new Object(); data.stage = new Object(); data.stage.scene = new Object(); data.stage.scene.nodes = []; data.stage.scene.textNodes = []; data.stage.scene.links = []; data.stage.scene.containers = []; data.stage.wheelZoom = stage.wheelZoom; var nodeList = scene.find('node'); nodeList.forEach(function (item) { var node = new Object(); node.bound = item.getBound(); node.type = item.type; node.fontColor = item.fontColor; node.text = item.text; node.deviceId = item.deviceId; node.elementType = item.elementType; node.alpha = item.alpha; node.virtualId = item.virtualId; data.stage.scene.nodes.push(node); }); var textNodeList = scene.find('TextNode'); textNodeList.forEach(function (item) { var textNode = new Object(); textNode.bound = item.getBound(); textNode.font = item.font; textNode.fontColor = item.fontColor; textNode.text = item.text; textNode.elementType = item.elementType; textNode.alpha = item.alpha; textNode.virtualId = item.virtualId; data.stage.scene.textNodes.push(textNode); }); var linkList = scene.find('link'); linkList.forEach(function (item) { if(item.nodeA.virtualId && item.nodeZ.virtualId){ var link = new Object(); link.startId = item.nodeA.virtualId; link.endId = item.nodeZ.virtualId; link.strokeColor = item.strokeColor; link.lineWidth = item.lineWidth; data.stage.scene.links.push(link); } }); var containerList = scene.find('container'); containerList.forEach(function (item) { var container = new Object(); container.text = item.text; container.bound = item.getBound(); container.borderColor = item.borderColor; container.borderWidth = item.borderWidth; container.borderRadius = item.borderRadius; // 圓角 container.fillColor = item.fillColor; container.alpha = item.alpha; container.virtualId = item.virtualId; container.elementType = item.elementType; container.childs = []; container.corners = []; item.childs.forEach(function (child) { if(child.virtualId == item.virtualId){ var corner = new Object(); corner.bound = child.getBound(); corner.virtualId = item.virtualId; container.corners.push(corner); } else{ var childNode = scene.findElements(function (childNode) { return childNode.virtualId == child.virtualId; }); if(childNode && childNode.length > 0){ container.childs.push(child.virtualId); } } }); data.stage.scene.containers.push(container); }); return JSON.stringify(data); }
- 拓撲元素反序列化
反序列化的過程主要是Json格式資料協議的解析和拓撲元素的建立。
這裡會用到scene查詢拓撲結點的方法,另外就是要注意建立順序就能很好的把之前建立的拓撲圖給還原出來。按照Node、Link、Container的順序來建立就可以了。
直接上程式碼js
function createTopoFromJson(jsonStr) {
var data = JSON.parse(jsonStr);
if(data){
//設定滾輪縮放比例。
stage.wheelZoom = data.stage.wheelZoom;
//建立Node。
if(data.stage.scene.nodes){
data.stage.scene.nodes.forEach(function (item) {
var node = new JTopo.Node(item.text);
node.setLocation(item.bound.left, item.bound.top);
node.setImage(getImageByType(item.type));
node.setSize(item.bound.width,item.bound.height);
node.fontColor = item.fontColor;
node.addEventListener('mousedrag',nodeMouseDrag);
node.addEventListener('mouseup',nodeMouseUp);
node.addEventListener('dbclick',nodeDbClick);
node.addEventListener('click',nodeClick);
node.deviceId = item.deviceId;
node.type = item.type;
node.virtualId = item.virtualId;
scene.add(node);
});
}
//建立TextNode。
if(data.stage.scene.textNodes){
data.stage.scene.textNodes.forEach(function (item) {
var textNode = new JTopo.TextNode(item.text);
textNode.setLocation(item.bound.left, item.bound.top);
textNode.fontColor = item.fontColor;
textNode.font = item.font;
textNode.alpha = item.alpha;
textNode.virtualId = item.virtualId;
textNode.addEventListener('mousedrag',nodeMouseDrag);
textNode.addEventListener('dbclick',textDbClick);
textNode.addEventListener('mouseup',linkMouseUp);
scene.add(textNode);
});
}
//建立Link。
if(data.stage.scene.links){
data.stage.scene.links.forEach(function (item) {
//查詢起點
var nodeA = scene.findElements(function (node) {
return node.virtualId == item.startId;
});
var nodeZ = scene.findElements(function (node) {
return node.virtualId == item.endId;
});
if(nodeA && nodeA.length >0 && nodeZ && nodeZ.length >0){
var link = new JTopo.Link(nodeA[0], nodeZ[0]);
link.lineWidth = item.lineWidth;
link.strokeColor = item.strokeColor;
scene.add(link);
link.addEventListener('mouseup',linkMouseUp);
}
});
}
//建立container。
if(data.stage.scene.containers){
data.stage.scene.containers.forEach(function (item) {
var container = new JTopo.Container(item.text);
container.borderColor = item.borderColor;
container.borderWidth = item.borderWidth;
container.borderRadius = item.borderRadius;
container.fillColor = item.fillColor;
container.alpha = item.alpha;
container.virtualId = item.virtualId;
container.setLocation(item.bound.left, item.bound.top);
item.corners.forEach(function (corner) {
var node = new JTopo.Node();
node.setLocation(corner.bound.left,corner.bound.top);
node.virtualId = corner.virtualId;
container.add(node);
});
scene.add(container);
item.childs.forEach(function (child) {
var node = scene.findElements(function (node) {
return node.virtualId == child;
});
if(node && node.length > 0){
container.add(node[0]);
node[0].removeEventListener('mousedrag');
};
});
container.addEventListener('mouseover',containerMouseOver);
container.addEventListener('mouseup',containerMouseUp);
container.addEventListener('mouseup',linkMouseUp);
});
}
}
}