尝试使用add
函数向现有图表添加新节点,最后使用所有新图表。这是我的code:
function Graph(elementId) {
var svg;
var simulation;
var mNodesData = [];
var mEdgesData = [];
var mNode = null;
var mLink = null;
var elementId;
var heightDelta = 100;
var width = window.innerWidth;
var height = window.innerHeight - heightDelta;
return {
init: function () {
svg = d3.select('#' + elementId)
.append("svg")
.attr("width", width)
.attr("height", height);
simulation = d3.forceSimulation()
.force(".edge", d3.forceLink())
.force("charge", d3.forceManyBody().strength(-600))
.force("center", d3.forceCenter(width / 2, height / 2));
},
clearGraph: function () {
$('#' + this.elementId).empty();
},
getNodes: function () {
return mNodesData;
},
getEdges: function () {
return mEdgesData;
},
addNodes: function (nodes) {
mNodesData = mNodesData.concat(nodes);
},
addEdges: function (edges) {
mEdgesData = mEdgesData.concat(edges);
},
draw: function () {
mLink = svg.selectAll(".edge")
.data(mEdgesData)
.enter()
.append("line")
.attr("class", "edge")
.style("stroke", "#ccc")
.style("stroke-width", function (e) {
return 1
/* e.width*/
});
mNode = svg.selectAll(".node")
.data(mNodesData)
.enter()
.append("g")
.attr("class", "node")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
mNode.on('mouseover', function (d) {
function removePopup() {
$("#nodePopup").remove();
}
function showPopup(d) {
removePopup();
if (!d['data']) {
return;
}
var data = d['data'];
var htmlStr = '';
htmlStr += '<div id="nodePopup" >';
htmlStr += ' <div><button id="nodePopupCloseButton" type="button" class="close" data-dismiss="alert"><span class="glyphicon glyphicon-remove" style="font-size: 13px;"> </span> </div>';
htmlStr += ' <div class="nodePopupName">' + data['name'] + '</div>';
if (data['desc']) {
if (data['desc'].startsWith("http")) {
htmlStr += ' <a class="nodePopupLink" href="' + data['desc'] + '" target="_blank">Go to post..</a>';
}
else {
htmlStr += ' <div class="nodePopupDesc">' + data['desc'] + '</div>';
}
}
htmlStr += ' <div class="nodePopupGroup">GROUP: ' + data['groupId'] + '</div>';
htmlStr += ' <div class="nodePopupLeader">LEADER: ' + data['leaderId'] + '</div>';
htmlStr += ' <div class="nodePopupImage"><img src="' + d['image'] + '" style="width: 130px;" /></div>';
htmlStr += '</div>';
$("body").append(htmlStr);
$("#nodePopupCloseButton").click(removePopup);
}
showPopup(d);
mNode.filter(function (d1) {
return (d !== d1 && d1.adjacents.indexOf(d.id) == -1);
}).select("image").style("opacity", 0.2);
mNode.filter(function (d1) {
return (d !== d1 && d1.adjacents.indexOf(d.id) == -1);
}).select("circle").style("stroke", "#f6f6f6");
mLink.filter(function (d1) {
return (d !== d1.source && d !== d1.target);
}).style("opacity", 0.2);
mNode.filter(function (d1) {
return (d == d1 || d1.adjacents.indexOf(d.id) !== -1);
}).select("image").style("opacity", 1);
mNode.filter(function (d1) {
return (d == d1 || d1.adjacents.indexOf(d.id) !== -1);
}).select("circle").style("stroke", "gray");
mLink.filter(function (d1) {
return (d == d1.source || d == d1.target);
}).style("opacity", 1);
})
.on('mouseout', function () {
// removePopup();
mNode.select("image").style("opacity", 1);
mNode.select("circle").style("stroke", "gray");
mLink.style("opacity", 1);
});
var nodeCircle = mNode.append("circle")
.attr("r", function (d) {
return 0.5 * Math.max(d.width, d.height)
})
.attr("stroke", "gray")
.attr("stroke-width", "2px")
.attr("fill", "white");
var nodeImage = mNode.append("image")
.attr("xlink:href", function (d) {
return d.image
})
.attr("height", function (d) {
return d.height + ""
})
.attr("width", function (d) {
return d.width + ""
})
.attr("x", function (d) {
return -0.5 * d.width
})
.attr("y", function (d) {
return -0.5 * d.height
})
.attr("clip-path", function (d) {
return "circle(" + (0.48 * Math.max(d.width, d.height)) + "px)"
});
simulation.nodes(mNodesData);
simulation.force(".edge").links(mEdgesData);
simulation.on("tick", function () {
mLink.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;
})
mNode.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")"
});
mNode.attr("cx", function (d) {
return d.x = Math.max(d.width, Math.min(width - d.width, d.x));
})
.attr("cy", function (d) {
return d.y = Math.max(d.height, Math.min(height - heightDelta - d.height, d.y));
});
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
}
}
}
function getData() {
return $.ajax({
url: 'api/v1/data.json',
type: "GET",
});
}
var graph = Graph('d3Graph');
graph.init();
$.when(getData()).then(function (data) {
graph.addNodes(data.nodes);
graph.addEdges(data.edges);
graph.draw();
});
function add() {
graph.addNodes([{
"id": 4,
"image": "images/4.jpeg",
"height": 20,
"width": 20,
"adjacents": [0],
"data": {
"name": "Number4",
"groupId": "Bla4",
"desc": "Desc4",
"leaderId": "1234-1234"
}
}]);
graph.addEdges([{
"source": 4,
"target": 3,
"width": 1
}])
graph.draw();
// graph.draw();
}
如果我在页面上调用add
原始图形堆栈,而在另一个边缘调用新的图形堆栈。节点已添加。我该如何做到这一点? (更新旧版本而不创建全新的..
答案 0 :(得分:0)
您目前拥有的内容:
mLink = svg.selectAll("link")
.data(mEdgesData)
.enter()
.append("line")
通常selectAll("link")
表示您选择所有链接的html元素。但是您附加了line
而不是link
。因此,附加元素不是selectAll
的一部分。没有可能知道你只想将数据添加到已经存在的东西中。
答案 1 :(得分:0)
解决方案是将merge
添加到两个链接&amp;节点:
mLink = svg.selectAll(".edge")
.data(mEdgesData)
.enter()
.append("line")
.attr("class", "edge")
.style("stroke", "#ccc")
.style("stroke-width", function (e) {
return 1
/* e.width*/
}).merge(mLink);
mNode = svg.selectAll(".node")
.data(mNodesData)
.enter()
.append("g")
.attr("class", "node").merge(mNode);
答案 2 :(得分:0)
当我尝试为具有动态数据的图形创建常规更新过程时,我遇到了类似的问题。在更新节点或链接时,将触发select address
from tab
where address like '%VIA%BOEZIO%6%'
函数。
这个想法的工作原理如下;重新绘制图形时(即数据更改时),所有旧节点和链接都将被删除并重新绘制。使用redraw
,节点保持在原位。
这是我的工作示例:
.join()
在我的redraw = () => {
simulation.nodes(nodes);
simulation.force('link')
.links(links)
.initialize(nodes);
d3.selectAll('g.node').remove(); // remove all old nodes
d3.selectAll('g.node').data(nodes).join();
d3.selectAll("line").data(links).join();
draw();
simulation.alpha(0.1)
simulation.restart();
}
函数中,将相应地创建节点和链接:
draw()
draw = () => {
container.selectAll('line').data(links).join('line');
// creates nodes with rectangles that contain text
container.selectAll('g.node').raise()
.data(nodes).join("g")
.each(function (d, i) {
d3.select(this).append("rect");
var text = d3.select(this).append("text").text(d => d.name)
// calculate text width for function tick() to adapt rect x position
d.width = text.filter(t => t.index == d.index).node()
.getBBox().width;
})
.call(drag(simulation));
}
是可缩放和可拖动的SVG元素:
container
为完整起见,这是我的container = svg.append('g');
svg.call(d3.zoom()
.on('zoom', () => this.container.attr('transform', d3.event.transform))
.scaleExtent([0.25, 2]))
函数:
tick()
如果有时间,我稍后再发布一个JSFiddle。