Javascript 无法在D3强制定向图中渲染图像
我有一个共享边界的国家的武力导向图。我想在每个节点上显示该国国旗。我可以看到生成的HTML中的图像,也可以看到它占用了窗口中的空间,但它不可见Javascript 无法在D3强制定向图中渲染图像,javascript,html,d3.js,svg,Javascript,Html,D3.js,Svg,我有一个共享边界的国家的武力导向图。我想在每个节点上显示该国国旗。我可以看到生成的HTML中的图像,也可以看到它占用了窗口中的空间,但它不可见 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="flags/flags.css">
<link rel="stylesheet" href="index.css">
<title>National Contiguity Visualization</title>
</head>
<body>
<div class="details">National Contiguity</div>
<svg class="plot"></svg>
<div class="tooltip hidden"></div>
<svg width="100" height="100">
<foreignobject class="node" >
<img class="flag flag-cz" alt="Czech Republic" src="flags/blank.png"/>
</foreignobject>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="index.js"></script>
</body>
</html>
尝试了svg图像元素和foreignobject方法。直接用HTML编写的代码被正确呈现。在过去的3/4天内无法解决此问题
回购:
提前感谢。- 在foreignObject标记上需要宽度和高度属性
- foreignObject用大写字母O拼写,尽管HTML标记不区分大小写,但元素的DOM创建,因此d3区分大小写
- d3希望HTML标记以xhtml为前缀:
const-apirl=”https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json';
常量工具提示=document.getElementsByClassName('tooltip')[0];
常数dragstarted=d=>{
如果(!d3.event.active)simulation.alphaTarget(0.3.restart();
d、 fx=d.x;
d、 fy=d.y;
}
常数=d=>{
d、 fx=d3.event.x;
d、 fy=d3.event.y;
}
常数d=d=>{
如果(!d3.event.active)simulation.alphaTarget(0);
d、 fx=null;
d、 fy=null;
}
常数图=(数据)=>{
data.nodes=data.nodes.map((d,索引)=>{
d['id']=索引;
返回d;
});
常量边距={
前20名,
右:20,,
底部:10,
左:100
};
常量宽度=数学最大值(((window.innerWidth/100)*80)-margin.right-margin.left),700);
常量高度=((window.innerHeight/100)*80)-margin.bottom-margin.top;
const svg=d3.select('svg')
.attr('width',width+margin.left+margin.right+100)
.attr('height',height+margin.top+margin.bottom+100)
.append('g')
.attr('transform',
`翻译(${margin.left},${margin.top})`);
常量模拟=d3.forceSimulation()
.force('link',d3.forceLink().id(函数(d){return d.id;}).distance(100).strength(1))
.force('charge',d3.forceManyBody())
.力(“中心”,d3.力中心(宽度/2,高度/2));
常数dragstarted=d=>{
如果(!d3.event.active)simulation.alphaTarget(0.3.restart();
d、 fx=d.x;
d、 fy=d.y;
}
常数=d=>{
d、 fx=d3.event.x;
d、 fy=d3.event.y;
}
常数d=d=>{
如果(!d3.event.active)simulation.alphaTarget(0);
d、 fx=null;
d、 fy=null;
}
常量勾选=()=>{
链接
.attr(“x1”,d=>d.source.x)
.attr(“y1”,d=>d.source.y)
.attr(“x2”,d=>d.target.x)
.attr(“y2”,d=>d.target.y);
节点
.attr(“x”,函数(d){return d.x=Math.max(5,Math.min(width-5,d.x));}
.attr(“y”,函数(d){返回d.y=Math.max(5,Math.min(height-5,d.y));};
}
const link=svg.append('g')
.attr('class','links'))
.selectAll('行')
.数据(数据链接)
.enter().append('行')
.attr('stroke-width',函数(d){return Math.sqrt(d.value);});
const node=svg.append('g')
.attr('类','节点')
.selectAll(“.flag”)
.data(data.nodes)
.输入()
.append('foreignObject')
.attr('width','100')
.attr('height','100')
.append('xhtml:img')
.attr('src','https://flaglane.com/download/british-flag/british-flag-small.gif')
.attr('class',d=>`flag-flag-cz`)
.call(d3.drag()
.on('start',dragstarted)
.on('拖动',拖动)
.在('结束',拖行));
node.append(“标题”)
.text(函数(d){返回d.country;})
.exit();
模拟
.nodes(数据.nodes)
。在(勾选)上;
模拟力(“链接”)
.链接(数据链接);
}
常量fetchData=()=>{
返回获取(APIRL)
。然后(响应=>{
返回response.json();
});
};
const fetchAndPlot=async()=>{
试一试{
const response=等待获取数据();
情节(反应);
}捕获(e){
控制台错误(e);
}
}
fetchAndPlot()代码>
民族邻接可视化
民族毗连
1。不要使用foreingObject
。2.如果仍要使用它,请设置宽度和高度:.attr(“宽度”,无论什么)。attr(“高度”,无论什么)
。尝试将宽度和高度属性添加到foreignObject标记,或者只使用SVG标记。foreignObject的宽度和高度?但我不确定这将如何解决渲染问题。我尝试了svg图像元素,但同样的事情也发生在那。。。图像未被渲染。@DhanushuUzumaki假设您要渲染一个矩形。不设置宽度和高度可以吗?它们是SVG1.1中的强制属性。SVG1.1规范说,如果省略它们,则不渲染任何内容。SVG 2改变了这一点,但我认为只有Chrome实现了这一点。我认为,foreignObject
区分大小写的问题不是因为D3,因为D3是不区分渲染的。如果我错了,请纠正我,但是foreignObject
应该有大写字母O,因为它是一个SVG元素,XML(与HTML不同)区分大小写。SVG作为标记嵌入HTML时不区分大小写。当您通过DOM创建它时,它是区分大小写的,无论是XML还是HTML,所以我认为它实际上是DOM而不是d3。我已经解释得更详细了。如果您查看D3append()
方法的源代码,您将看到它使用了document.createElements
。。。所以,这就解释了为什么它是区分大小写的。谢谢,@Robert和Gerardo现在图像被正确渲染了。如果我可以再请求一个帮助,x和y坐标将应用于最后附加的元素(本例中为img)。。有没有办法将其应用于foreignObject?@DhanushuUzumaki这很容易修复。但是,不要在评论中提出新问题:相反,发布新的问题
const apiUrl = 'https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json';
const tooltip = document.getElementsByClassName('tooltip')[0];
const dragstarted = d => {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
const dragged = d => {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
const dragended = d => {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
const plot = (data) => {
data.nodes = data.nodes.map((d, index) => {
d['id'] = index;
return d;
});
const margin = {
top: 20,
right: 20,
bottom: 10,
left: 100
};
const width = Math.max((((window.innerWidth / 100) * 80) - margin.right - margin.left), 700);
const height = ((window.innerHeight / 100) * 80) - margin.bottom - margin.top;
const svg = d3.select('svg')
.attr('width', width + margin.left + margin.right + 100)
.attr('height', height + margin.top + margin.bottom + 100)
.append('g')
.attr('transform',
`translate(${margin.left}, ${margin.top})`);
const simulation = d3.forceSimulation()
.force('link', d3.forceLink().id(function (d) { return d.id; }).distance(100).strength(1))
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter(width / 2, height / 2));
const dragstarted = d => {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
const dragged = d => {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
const dragended = d => {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
const ticked = () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("x", function (d) { return d.x = Math.max(5, Math.min(width - 5, d.x)); })
.attr("y", function (d) { return d.y = Math.max(5, Math.min(height - 5, d.y)); });
}
const link = svg.append('g')
.attr('class', 'links')
.selectAll('line')
.data(data.links)
.enter().append('line')
.attr('stroke-width', function (d) { return Math.sqrt(d.value); });
const node = svg.append('g')
.attr('class', 'nodes')
.selectAll('.flag')
.data(data.nodes)
.enter()
.append('foreignobject')
.append('img')
.attr('src', 'flags/blank.png')
.attr('class', d => `flag flag-cz`)
.attr('width', '5px')
.attr('height', '5px')
.attr("x", -8)
.attr("y", -8)
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended));
node.append("title")
.text(function (d) { return d.country; })
.exit();
simulation
.nodes(data.nodes)
.on("tick", ticked);
simulation.force("link")
.links(data.links);
}
const fetchData = () => {
return fetch(apiUrl)
.then(response => {
return response.json();
});
};
const fetchAndPlot = async () => {
try {
const response = await fetchData();
console.log(response);
plot(response);
} catch (e) {
console.error(e);
}
}
fetchAndPlot();