我在D3中有一个强制定向图,可以在Web套接字上正确呈现。我的任务是根据后续的Web套接字消息在此图表中添加或删除链接和节点。我遇到的问题是,当我平移或缩放图形时,会应用变换。我不知道如何将该转换应用于新添加的链接或节点。因此,添加的链接取决于源节点和目标节点的原始cx cy位置。以下是其中的代码。希望有人可以告诉我如何将转换应用于新添加的链接。
代码为了简洁而按要求编辑:
var DataPlane = (function() {
//This method gets called when a link is either added or removed from the svg via web socket.
var remapDataPlane = function(data) {
var dpData = $.parseJSON(data);
...
if (dpData.addedLinks.length > 0) {
//get the svg
var parentSvg = d3.select("#app_dataPlane svg").select("g")
var svg = parentSvg.select("g");
//this portion gets the transform that has been applied to the svg group element.
var trans = svg.attr("transform");
//get a list of switches from svg
var svgSwitches = d3.selectAll(".switch");
//Process unidirectional and bidirectional links -- BEGIN
var bidLinks = [];
var uniLinks = [];
var pairs = [];
var idx = 0;
function hasMatchingNode(element, index, array) {
return (element.src.dpid !== this.src.dpid && element.src.dpid === this.dst.dpid && element.dst.dpid === this.src.dpid);
}
function parseLinks(element, index, array) {
var node = array.filter(hasMatchingNode, element);
if (node.length > 0) {
var match = array.indexOf(node.pop());
array.splice(match, 1);
} else {
uniLinks.push(element);
array.splice(index, 1);
}
}
dpData.addedLinks.map(parseLinks);
if (dpData.addedLinks != undefined) {
dpData.addedLinks.forEach(function(item) {
item["nature"] = "bidirectional";
});
uniLinks.forEach(function(item) {
item["nature"] = "unidirectional";
});
//Links are added in pairs to represent bidirectional nature. I elminate duplicate links from the data and merge them with unidirectional links here.
$.merge(dpData.addedLinks, uniLinks);
}
//For each link being added to the graph
for (var i = 0; i <= dpData.addedLinks.length - 1; i++) {
//Get the name of the source node for the link and it's corresponding coordinates
var srcName = 'switch_' + dpData.addedLinks[i].src.dpid;
var srcC = document.getElementById(srcName);
var srcCx = +srcC.getAttribute('cx');
var srcCy = +srcC.getAttribute('cy');
var srcCtm = srcC.getCTM();
var srcCoords = getScreenCoords(srcCx, srcCy, srcCtm);
//Get the name of the destination node for the link and it's corresponding coordinates
var dstName = 'switch_' + dpData.addedLinks[i].dst.dpid;
var dstC = document.getElementById(dstName);
var dstCx = +dstC.getAttribute('cx');
var dstCy = +dstC.getAttribute('cy');
var dstCtm = dstC.getCTM();
var dstCoords = getScreenCoords(dstCx, dstCy, dstCtm);
//Append the line to the graph using the coordinates derived from the Cx & Cy coordinates
var link = svg.append("line")
.attr("x1", srcCoords.x)
.attr("y1", srcCoords.y)
.attr("x2", dstCoords.x)
.attr("y2", dstCoords.y)
.attr("class", "link")
.attr("id", function(d) {
return "name_" + dpData.addedLinks[i].dst.dpid + dpData.addedLinks[i].src.dpid;
})
.style("stroke-width", 2)
//Set Style for unidirectional otherwise grey
.style("stroke", function(d) {
if (d != undefined && d.nature == "unidirectional") {
return "green";
}
})
// **** This is where I try and apply the transform to the link ****
.attr("transform", trans)
}
}
function getScreenCoords(x, y, ctm) {
var xn = ctm.e + x * ctm.a;
var yn = ctm.f + y * ctm.d;
return {
x: xn,
y: yn
};
}
};
// Initial code omitted for brevity as requested
return {
drawDataPlane: drawDataPlane,
remapDataPlane: remapDataPlane
};
})();
SVG Elements的样本:
<svg width="814" height="305" pointer-events="all">
<g>
<g transform="translate(6.568073042618323,138.38858706474264) scale(0.8420541187522115)">
<rect width="1628" height="610" fill="white"></rect>
<line class="link" id="name_00:00:00:00:00:00:00:0100:00:00:00:00:00:00:03" x1="427.59429499296965" y1="125.07073054436019" x2="375.8732495447546" y2="138.7148361886131" style="stroke-width: 2px;"></line>
<line class="link" id="name_00:00:00:00:00:00:00:0200:00:00:00:00:00:00:01" x1="375.8732495447546" y1="138.7148361886131" x2="400.55190412548484" y2="186.17410516927373" style="stroke-width: 2px;"></line>
<circle r="6" id="switch_00:00:00:00:00:00:00:02" class="switch" fill="#15a9ff" cx="400.55190412548484" cy="186.17410516927373"></circle>
<circle r="6" id="switch_00:00:00:00:00:00:00:03" class="switch" fill="#15a9ff" cx="427.59429499296965" cy="125.07073054436019"></circle>
<circle r="6" id="switch_00:00:00:00:00:00:00:01" class="switch selectedSwitch" fill="#15a9ff" cx="375.8732495447546" cy="138.7148361886131"></circle>
</g>
</g>
平移/缩放功能:
function redraw() {
svg.attr("transform",
"translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); /* skewX(30) */
}