【发布时间】:2016-12-07 00:42:53
【问题描述】:
我正在努力为我的 d3 图表添加过滤器功能。当用户根据标签或 id 搜索特定节点时,我想重新渲染图形并再次显示整个图形,但我希望过滤后的节点位于 svg 元素的中心。
这是我帮助它居中的原因:
// I get the width and height of the SVG element:
var svgWidth = parseInt(svg.style("width").replace(/px/, ""), 10);
var svgHeight = parseInt(svg.style("height").replace(/px/, ""), 10);
// I get the center of the svg:
var centerX = svgWidth / 2;
var centerY = svgHeight / 2;
_.forEach(nodes, function(e) {
// get the full node (with x and y coordinates) based on the id
var nodeObject = g.node(nodeId);
// I look for matches between the nodeId or label and search word
if (searchInput) {
if (nodeObject.id === parseInt(searchInput, 10) || nodeObject.label.toUpperCase().indexOf(searchInput.toUpperCase()) > -1) {
searchedNodes.push(nodeObject);
console.log(searchedNodes);
}
}
}
// after looping through all the nodes rendered
if (searchedNodes.length > 0) {
//var width = searchedNodes[0].elem.getBBox().width;
//var height = searchedNodes[0].elem.getBBox().height;
ctrl.selectedNode = searchedNodes[0];
var offsetX = centerX - searchedNodes[0].x;
var offsetY = centerY - searchedNodes[0].y;
svgGroup.attr("transform", "translate(" + offsetX + "," + offsetY + ")" + "scale(" + 3 + ")");
// this line here is incorrect syntax and breaks the build, essentially stopping the script from running
// the graph renders correctly when this line is here
svgGroup.attr("transform", "translate(" + offsetX + "," + offsetY + ")").scale(2).event;
}
这就是图表的样子,上面的行打破了包含的脚本。
当我删除那条线时,它没有居中,几乎看起来像是过度渲染了图表。显然我需要删除上面不正确的代码行,但有人不知道为什么在这种情况下图表不能正确呈现吗?:
// get the user input and re-render the graph
elem.find(".search").bind("keyup", function (e:any) {
var searchInput;
if (e["keyCode"] === 13) {
searchedNodes = [];
searchInput = scope["searchInput"];
currentFilteredNode = null;
enterKeyPressed = true;
renderGraph(searchInput);
}
if (e["keyCode"] === 8) {
searchedNodes = [];
searchInput = scope["searchInput"];
currentFilteredNode = null;
renderGraph(searchInput);
}
});
// if there is searchInput and at least one matching node sort the nodes
// by id and then select and center the first matching one
if (searchInput && searchedNodes.length > 0) {
searchedNodes.sort(function (node1:any, node2:any) {
return node1.id - node2.id;
});
// make sure the noResultsMessage does not get shown on the screen if there are matching results
scope.$apply(function() {
scope["noResultsMessage"] = false;
});
ctrl.selectedNode = searchedNodes[0];
offsetX = centerX - searchedNodes[0].x;
offsetY = centerY - searchedNodes[0].y;
svgGroup.attr("transform", "translate(" + offsetX + "," + offsetY + ")" + "scale(" + 3 + ")");
}
// the only other zoom and this runs just on page load
zoom = d3.behavior.zoom();
zoom.on("zoom", function() {
svgGroup.attr("transform", "translate(" + (<any>d3.event).translate + ")" + "scale(" + (<any>d3.event).scale + ")");
// this scales the graph - it runs on page load and whenever the user enters a search input, which re-renders the whole graph
var scaleGraph = function(useAnimation:any) {
var graphWidth = g.graph().width + 4;
var graphHeight = g.graph().height + 4;
var width = parseInt(svg.style("width").replace(/px/, ""), 10);
var height = parseInt(svg.style("height").replace(/px/, ""), 10);
var zoomScale = originalZoomScale;
// Zoom and scale to fit
if (ctrl.autoResizeGraph === "disabled") {
zoomScale = 1;
} else {
// always scale to canvas if set to fill or if auto (when larger than canvas)
if (ctrl.autoResizeGraph === "fill" || (graphWidth > width || graphHeight > height)) {
zoomScale = Math.min(width / graphWidth, height / graphHeight);
}
}
var translate;
if (direction.toUpperCase() === "TB") {
// Center horizontal + align top (offset 1px)
translate = [(width / 2) - ((graphWidth * zoomScale) / 2) + 2, 1];
} else if (direction.toUpperCase() === "BT") {
// Center horizontal + align top (offset 1px)
translate = [(width / 2) - ((graphWidth * zoomScale) / 4) + 2, 1];
} else if (direction.toUpperCase() === "LR") {
// Center vertical (offset 1px)
translate = [1, (height / 2) - ((graphHeight * zoomScale) / 2)];
} else if (direction.toUpperCase() === "RL") {
// Center vertical (offset 1px)
translate = [1, (height / 2) - ((graphHeight * zoomScale) / 4)];
} else {
// Center horizontal and vertical
translate = [(width / 2) - ((graphWidth * zoomScale) / 2), (height / 2) - ((graphHeight * zoomScale) / 2)];
}
zoom.center([width / 2, height / 2]);
zoom.size([width, height]);
zoom.translate(translate);
zoom.scale(zoomScale);
// If rendering the first time, then don't use animation
zoom.event(useAnimation ? svg.transition().duration(500) : svg);
};
过滤节点的代码:
// move to the left of the searchedNodes array when the left arrow is clicked
scope["filterNodesLeft"] = function () {
filterNodesIndex--;
if (filterNodesIndex < 0) {
filterNodesIndex = searchedNodes.length - 1;
}
currentFilteredNode = searchedNodes[filterNodesIndex];
runScaleGraph = true;
number = 1;
renderGraph();
};
// move to the right of the searchNodes array when the right arrow is clicked
scope["filterNodesRight"] = function () {
filterNodesIndex++;
if (filterNodesIndex > searchedNodes.length - 1) {
filterNodesIndex = 0;
}
currentFilteredNode = searchedNodes[filterNodesIndex];
runScaleGraph = true;
number = 1;
renderGraph();
};
// get the current filteredNode in the searchNodes array and center it
// when the graph is re-rendered
if (currentFilteredNode) {
ctrl.selectedNode = currentFilteredNode;
offsetX = centerX - currentFilteredNode.x;
offsetY = centerY - currentFilteredNode.y;
svgGroup.attr("transform", "translate(" + offsetX + "," + offsetY + ")");
runScaleGraph = false;
}
【问题讨论】:
-
是的,所有节点都位于 g.nodes 中,然后每个节点都有 g.node 类。我确实具有 subGraph 功能,因此新的节点集位于容器节点内。我正在寻找与上图中的搜索输入匹配的任何节点居中。我也在上图中包含了 DOM 布局。这可能吗?感谢您的帮助
-
当您的脚本抛出错误(如在第一个屏幕截图中)时,视觉输出是您期望的吗?你有其他代码调整 svgGroup 的变换吗?如果您注释掉导致空指针/引用的行,如果您在调试器中单步执行代码会发生什么?
-
是的,脚本抛出错误的第一个屏幕截图是预期的输出。我只希望每个选定的节点居中。然后,我可以选择是否有多个匹配的搜索结果,用户可以单击以查看匹配结果。这段代码是一个大角度组件的一部分,但我已经添加了主要代码,包括调用其他缩放的区域。
-
从我在调试器中可以看出,当用户输入搜索输入并再次调用 renderGraph 时,匹配的节点被推入“searchedNodes”数组,然后首先按最低 id 排序,然后第一个节点被选中并且应该在 svg 中居中。它似乎运行了一次。我似乎无法判断 scaleGraph 是否导致 svgGroup translate 属性调用不正确?我在原始代码中添加了一些额外的代码post.再次感谢
-
我认为这个错误是一个红鲱鱼。您在出错之前立即从转换中删除“比例”。编辑答案如下。
标签: javascript jquery angularjs d3.js svg