cola ui ajax,打开组后的新布局不基于最后一个cola.js布局

本文介绍了一个用于图形布局的JS库cola.js,它支持部队布局和小组支援。作者在尝试实现开放组功能时遇到了问题:当打开一个组时,预期的布局调整并未发生,而是重新布局了所有节点。作者通过官方示例和自己的演示代码进行了分析,但未能找到满意的解决方案。文中展示了cola.js的使用示例代码,并详细描述了遇到的问题和期望的行为,为读者提供了一个深入理解cola.js和图形布局动态调整的案例。
摘要由CSDN通过智能技术生成

我最近了解了一个优秀的JS库cola.js。它可以进行部队布局和支援小组。在此了解更多信息:

Cola.js

我创建了一个简单的演示来展示一个带有开放组功能的强制布局。但我对这种开放的行为感到困惑。

我认为当打开一个组时,新的布局应该是基于最后一个布局的微小调整。但现在它重新传输所有节点。为什么?

我从这个环节学到了一些理念:

Offical Demo : Online Graph Exploration

这看起来很复杂。新节点动态添加到图形的坐标应设置为打开组的坐标。不幸的是,它也不能解决我的问题。

以下是我的演示:

var w = 480, h = 420, cola;

var data = {

"nodes": [

{"name": "Top","width": 60,"height": 60},

{"name": "A","width": 60,"height": 60},

{"name": "B","width": 60,"height": 60},

{"name": "C","width": 60,"height": 60},

{"name": "D","width": 60,"height": 60},

{"name": "E","width": 60,"height": 60},

{"name": "F","width": 60,"height": 60},

{"name": "G","width": 60,"height": 60},

{"name": "H","width": 60,"height": 60},

{"name": "I","width": 60,"height": 60}

],

"links": [

{"source": 0,"target": 6},

{"source": 0,"target": 4},

{"source": 0,"target": 3},

{"source": 0,"target": 7},

{"source": 0,"target": 8},

{"source": 6,"target": 0},

{"source": 6,"target": 7},

{"source": 4,"target": 0},

{"source": 4,"target": 3},

{"source": 3,"target": 0},

{"source": 3,"target": 4},

{"source": 7,"target": 0},

{"source": 7,"target": 6},

{"source": 7,"target": 4},

{"source": 8,"target": 0},

{"source": 8,"target": 7}

],

"groups": [

{"leaves": [0,1,2],"groups": [1],"name": "Product"},

{"leaves": [7],"name": "Businness"},

{"leaves": [3,4,6,8,9],"name": "Tech"}

]

};

cola = cola.d3adaptor()

.linkDistance(150)

.avoidOverlaps(true)

.handleDisconnected(true)

.size([w, h]);

svg = d3.select("body").append("svg")

.attr("width", w)

.attr("height", h)

.on("dblclick.zoom", null);

svg.append('rect')

.attr("width", w)

.attr("height", h)

.style("fill", "none")

.style("pointer-events", "all");

svg = svg.append('g');

update(data);

cola.on("tick", function () {

svg.selectAll(".link")

.attr("x1", function (d) { return d.source.x; })

.attr("y1", function (d) { return d.source.y; })

.attr("x2", function (d) { return d.target.x; })

.attr("y2", function (d) { return d.target.y; });

svg.selectAll(".nodeimage").attr("x", function(d){ return d.x - 25 / 2 }).attr("y", function(d){ return d.y - 25 / 2 });

svg.selectAll(".group")

.attr("x", function (d) { return d.bounds.x; })

.attr("y", function (d) { return d.bounds.y; })

.attr("width", function (d) { return d.bounds.width(); })

.attr("height", function (d) { return d.bounds.height(); });

svg.selectAll(".label").attr("x", function (d) {

var w = this.getBBox().width;

return d.x - w/2;

})

.attr("y", function (d) {

var h = this.getBBox().height;

return d.y + 25;

});

svg.selectAll('.groupclosebutton')

.attr("x", function (d) { return d.bounds.x + d.bounds.width() - 20; })

.attr("y", function (d) { return d.bounds.y + 2; });

svg.selectAll('.groupname')

.attr("x", function (d) { return d.bounds.x + 5; })

.attr("y", function (d) { return d.bounds.y + 15; });

});

function update(data){

//data.groups.forEach(function (g) { g.padding = 15; });

cola.nodes(data.nodes).links(data.links).groups(data.groups).start();

var color = ['#d3d4e5', '#f7e0c8', '#dee8f2', '#cbe5c4', '#ededeb'];

var group = svg.selectAll(".group").data(data.groups, function(d) { return d.name;});

group.enter().append("rect")//, ":last-child"

.attr("rx", 8).attr("ry", 8)

.attr("class", "group")

.style("fill", function (d, i) { return color[i%5]; })

.call(cola.drag);

group.exit().remove();

var groupName = svg.selectAll(".groupname").data(data.groups, function(d) { return d.name;});

groupName.enter().append("text")

.attr("class", "groupname")

.attr("width", "40px")

.attr("height", "13px")

.text(function (d) { return d.name; });

groupName.exit().remove();

var link = svg.selectAll(".link").data(data.links, function(d) { return d.source.name+'-'+d.target.name;});

link.enter().append("line").attr("class", "link").style("stroke", "rgb(168, 168, 168)");

link.exit().remove();

var nodes = svg.selectAll('.nodeimage').data(data.nodes, function(d) { return d.name;});

nodes.enter().append('svg:image')

.attr("class", "nodeimage")

.call(cola.drag)

.attr("xlink:href", function(d){

var img = "http://icons.iconarchive.com/icons/hopstarter/sleek-xp-basic/24/Folder-icon.png";

return img;

})

.attr('temp', function(d){

var self = d3.select(this);

self.attr("width", 25);

self.attr("height", 25);

})

.on("dblclick", function(node, index, selection){

d3.event.preventDefault();

openGroup(node);

});

nodes.exit().transition().attr("width", 0).attr("width", 0).remove();

var label = svg.selectAll(".label").data(data.nodes, function(d) { return d.name;});

label.enter().append("text")

.attr("class", "label")

.attr("width", "40")

.attr("height", 15)

.text(function (d) { return d.name; })

.call(cola.drag);

label.exit().remove();

}

function openGroup(node){

var i,j, flag,maxnodes = 3, groupDeletedIndex = -1;

// Delete the node

for(i = 0; i < this.data.nodes.length; i++){

if(this.data.nodes[i].name == node.name){

this.data.nodes.splice(i, 1);

break;

}

}

// Delete old links linked to the node

for(i = this.data.links.length - 1; i >= 0; i--){

if(this.data.links[i].source.name == node.name

|| this.data.links[i].target.name == node.name){

this.data.links.splice(i, 1);

}

}

// Delete the relationship of the node

flag = false;

for(i = 0; i < this.data.groups.length; i++){

for(j = 0; j < this.data.groups[i].leaves.length; j++){

if(this.data.groups[i].leaves[j].name == node.name){

this.data.groups[i].leaves.splice(j, 1);

flag = true;

groupDeletedIndex = i;

break;

}

}

if(flag)break;

}

// Create new nodes belong to openning group

for(var i = 0; i < maxnodes; i++){

var obj = {

name : node.name+'child'+i ,

width : 100,

height : 100,

x:node.x,

y:node.y,

px:node.px,

py:node.py

};

this.data.nodes.push(obj);

if(i%3!=0){

this.data.links.push({// Create demo links

source : this.data.nodes.length-1,

target : Math.floor(Math.random(this.data.nodes.length-1))

});

}

}

// Create a group to contain the new nodes and push to groups

this.data.groups.push({

leaves : [],

name : node.name,

bounds : {x:node.x, y:node.y, X:node.x+100, Y:node.y+100},

padding : 15

});

var begin = this.data.nodes.length - maxnodes;

for(var i = 0; i < maxnodes; i++){

this.data.groups[this.data.groups.length-1].leaves.push(begin+i);

}

if(groupDeletedIndex > -1){

if(!this.data.groups[groupDeletedIndex].groups){

this.data.groups[groupDeletedIndex].groups = [];

}

this.data.groups[groupDeletedIndex].groups.push(this.data.groups.length-1);

}

update(this.data);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值