javascript - 将外部元素添加到 d3,js 现在显示
问题描述
我正在尝试在节点中添加复选框和文本。请参阅下面的图片,了解我想要实现的目标。
我可以在元素视图中看到复选框,但无法在页面中查看。
但这就是我现在得到的。
下面是使用的代码。
(function() {
var width, height, rules, map, tasks, links, nodes, svg, tick, radius, force, link, node;
width = 960;
height = 500;
rules = [
['root', 'iot'],
['root', 'points'],
['root', 'camnative'],
['root', 'classifier'],
['points', 'classifier2'],
['camnative', 'classifier3'],
['classifier', 'consec'],
['iot', 'classifier1'],
['cloudclassif', 'schedule'],
['schedule', 'privacy'],
['privacy', 'roi'],
['roi', 'flooding'],
['classifier1', 'cloudclassif'],
['classifier2', 'cloudclassif'],
['classifier3', 'cloudclassif'],
['consec', 'cloudclassif']
];
map = d3.map();
rules.forEach(function(rule) {
map.set(rule[0], {
fixed: false
});
return map.set(rule[1], false);
});
map.set('root', {
fixed: true,
x: 100,
y: height / 2
});
// map.set('P4', {
// fixed: true,
// x: width / 2 - 100,
// y: height / 2
// });
tasks = map.keys();
links = rules.map(function(rule) {
return {
source: tasks.indexOf(rule[0]),
target: tasks.indexOf(rule[1])
};
});
nodes = tasks.map(function(k) {
var entry;
entry = {
name: k
};
if (map.get(k).fixed) {
entry.fixed = true;
entry.x = map.get(k).x;
entry.y = map.get(k).y;
}
return entry;
});
svg = d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
svg.append("svg:defs")
.append("svg:marker")
.attr("id", "arrow")
.attr("viewBox", "0 0 10 10")
.attr("refX", 0)
.attr("refY", 5)
.attr("markerUnits", "strokeWidth")
.attr("markerWidth", 8)
.attr("markerHeight", 6)
// .attr("orient", "auto")
.append("svg:path")
.attr("d", "M 0 0 L 10 5 L 0 10 z");
svg.append("line")
.attr("x1", 5)
.attr("x2", 50)
.attr("y1", 5)
.attr("y2", 50)
.style("stroke", "black")
.attr("stroke-width", 2)
.attr("marker-end", "url(#arrow)");
tick = function() {
var arrowheadLength = 8, // from markerWidth
nodeRadius = 10;
link.each(function(d) {
var x1 = d.source.x,
y1 = d.source.y,
x2 = d.target.x,
y2 = d.target.y,
angle = Math.atan2(y2 - y1, x2 - x1);
d.targetX = x2 - Math.cos(angle) * (nodeRadius + arrowheadLength);
d.targetY = y2 - Math.sin(angle) * (nodeRadius + arrowheadLength);
});
link.selectAll("line").attr("x1", function(d) {
return d.source.x;
}).attr("y1", function(d) {
return d.source.y;
}).attr("x2", function(d) {
return d.targetX;
}).attr("y2", function(d) {
return d.targetY;
}).attr("marker-end", "url(#arrow)");
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
};
radius = d3.scale.sqrt().range([0, 6]);
force = d3.layout.force().size([width / 2, height]).charge(-900).linkDistance(function(d) {
return 40;
});
force.nodes(nodes).links(links).on("tick", tick).start();
link = svg.selectAll(".link").data(links).enter().append("g").attr("class", "link");
link.append("line").style("stroke-width", 1).attr("marker-end", "url(#arrow)");
node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.call(force.drag);
node.append("rect")
.attr("class", "node")
.attr("width", 100)
.attr("height", 50);
node.append("input")
.attr("type", "checkbox")
.attr("class", "mycheck")
.attr("fill", "black");
node.append("text")
.attr("x", function(d) { return (d) - 3; })
.attr("y", 50 / 2)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
console.log("HERE2");
console.log("HERE5");
}).call(this);
我检查了D3 v3 附加复选框?,但该解决方案不起作用。
更新
添加
node.append("foreignObject")
.attr("width", 100)
.attr("height", 100)
.append("xhtml:chart")
.append("div")
.append("input")
.attr("type", "checkbox");
添加复选框被添加到节点。
解决方案
我玩弄了这个并走得更远。我发现发现了一些东西:
- 正如其他人所提到的,将复选框放在 <foreignObject>
- 在foreignObject 内的html 对象之前使用“xhtml:”前缀。
- 您的数据函数中有一些糟糕的数学运算。例如:return (d) - 3;返回 NaN。你需要类似return dx - 3;
- <g> 元素内的项目相对于组定位。在我的小提琴示例(底部链接)中,我将矩形的左上角定位在(0,-16)。
// Create the <foreignObject>:
let ddiv = node.append("foreignObject")
.attr("x", -10)
.attr("y", -34)
.attr("width", 50)
.attr("height",50)
.append("xhtml:div") // <<<---- xhtml: prefix!
.classed("roundedOne", true)
ddiv.append("xhtml:input") // <<<---- xhtml: prefix!
.attr("type", "checkbox")
.attr("id", (d) => d.name);
ddiv.append("xhtml:label") // <<<---- xhtml: prefix!
.attr("for", (d) => d.name);
查看我的 jsFiddle:https ://jsfiddle.net/visioguy/yz5tfgjm/
我添加了一些更适合您的框的精美复选框样式,这就是我在您的代码中添加额外的 <div> 和 <label> 的原因。您将不得不摆弄更多的边距、大小和偏移量,也许还有一些强制布局参数才能使布局正常工作。
推荐阅读
- node.js - 在流式渲染期间更改 http 状态 (renderToNodeStream)
- postgresql - prisma:如何将具有多个 FK 的数据库表转换为 prisma 模式?
- typescript - 在泛型中使用类类型
- autosar - 如何理解部分网络概念 (PNC) 中的“镜像回”
- django - 尝试在html中列出对象时出现Django TypeError
- python - 替换行并循环编译乳胶文件
- linux - Image Magick 源文件夹在哪里
- c# - 如何将字符串数组绑定到 DTO 类中的枚举列表 - C# WebApi
- python - 在过滤的熊猫数据框中嵌套 iloc
- java - 在 JPQL Native Query 中将查询作为查询参数传递