Javascript d3部队布局中的链接图纸问题
为了绘制图形,我开始学习java脚本,我使用了几个示例来创建脚本,但我无法在节点之间绘制线条。我的猜测是,这是由于从第92行开始的属性声明造成的,但我不知道问题出在哪里。 以下是我用来创建脚本的两个主要示例: 这是我的代码:Javascript d3部队布局中的链接图纸问题,javascript,html,d3.js,Javascript,Html,D3.js,为了绘制图形,我开始学习java脚本,我使用了几个示例来创建脚本,但我无法在节点之间绘制线条。我的猜测是,这是由于从第92行开始的属性声明造成的,但我不知道问题出在哪里。 以下是我用来创建脚本的两个主要示例: 这是我的代码: <html> <head> <style type="text/css"> body { background-color: #E6E6E6; } svg { width: 1
<html>
<head>
<style type="text/css">
body {
background-color: #E6E6E6;
}
svg {
width: 100%;
height: 100%;
}
.node {
pointer-events: all;
cursor: pointer;
z-index: 1000;
}
.node text {
font: 8px sans-serif;
}
div.tooltip {
position: absolute;
background-color: white;
max-width; 200px;
height: auto;
padding: 1px;
border-style: solid;
border-radius: 4px;
border-width: 1px;
box-shadow: 3px 3px 10px rgba(0, 0, 0, .5);
pointer-events: none;
}
</style>
<script src='d3.min.js'></script>
<script src='d3-tip.js'></script>
</head>
<body style="margin: 5%">
<script type="text/javascript">
// node data
var nodes = [
{"name": "Travis", "sex": "M","size": 1983},
{"name": "Rake", "sex": "M","size": 200},
{"name": "Diana", "sex": "F","size": 15000},
{"name": "Rachel", "sex": "F","size": 1800},
{"name": "Shawn", "sex": "M","size": 1983},
{"name": "Emerald", "sex": "F","size": 10000}
]
//Create links data
var links_data = [
{"source": "Travis", "target": "Rake"},
{"source": "Diana", "target": "Rake"},
{"source": "Diana", "target": "Rachel"},
{"source": "Rachel", "target": "Rake"},
{"source": "Rachel", "target": "Shawn"},
{"source": "Emerald", "target": "Rachel"}
]
</script>
<script type="text/javascript">
//toolpit declaration
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//svg size
const width = 1000,
height = 1000;
// Allow zoom
const transform = d3.zoomIdentity;
// Find connected nodes
var linkedByIndex = {};
// Append svg info
const svg = d3.select('body').append('svg')
.call(d3.zoom().scaleExtent([1/2, 8]).on('zoom', zoomed))
.append('g')
.attr('transform', 'translate(40,0)');
// graph simulation declaration
const simulation = d3.forceSimulation()
.force('link', d3.forceLink().id(function(d) { return d.id; }))
.force('charge', d3.forceManyBody().strength(-15).distanceMax(300))
.force('center', d3.forceCenter( width/2, height/4 ))
.on('tick', ticked)
// Function to update graph informations (nodes positions, links....)
function update(nodes, links_data) {
//Extract links source and target information
link = svg
.selectAll('.links_data')
.data(links_data, function(d){ return d.source.id })
.data(links_data, function(d){ return d.target.id })
link.exit().remove()
// Custumzie links
const linkEnter = link
.enter()
.append('line')
.data(link)
.attr('class', 'link')
.style('stroke', '#000' )
.style('opacity', '0.2')
.style('stroke-width', 2)
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.source.x; })
.attr("y2", function(d) { return d.source.y; })
link = linkEnter.merge(link)
// Add nodes to svg
node = svg
.selectAll('.node')
.data(nodes, function(d){ return d.id })
node.exit().remove()
// Custumzie nodes
const nodeEnter = node
.enter()
.append('g')
.attr('class', 'node')
.attr('stroke', '#666')
.attr('stroke-width', 2)
.style('fill', color)
.on("mouseover", focus)
.on('mouseover.tooltip', function(d) {
tooltip.transition()
.duration(300)
.style("opacity", 0.9);
tooltip.html("Label:" + d.name + "<p/>Degree:" + d.size)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY + 10) + "px");
})
.on('mouseover.fade', fade(0.1))
.on("mouseout.tooltip", function() {
tooltip.transition()
.duration(100)
.style("opacity", 0);
})
.on('mouseout.fade', fade(1))
.on("mousemove", function() {
tooltip.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY + 10) + "px");
})
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended))
// Draw nodes
nodeEnter.append('circle')
.attr("r", function(d) { return Math.sqrt(d.size) / 10 || 4.5; })
.style('text-anchor', function(d){ return d.children ? 'end' : 'start'; })
.text(function(d){ return d.name })
node = nodeEnter.merge(node)
simulation.nodes(nodes)
simulation.force('link').links(link)
}
function sizeContain(num) {
num = num > 1000 ? num/1000 : num/100
if (num < 4) num = 4
return num
}
function color(d) {
return d._children ? "#51A1DC" // collapsed package
: d.children ? "#51A1DC" // expanded package
: "#F94B4C"; // leaf node
}
function radius(d) {
return d._children ? 8
: d.children ? 8
: 4
}
function ticked() {
link
.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; })
node
.attr('transform', function(d){ return `translate(${d.x}, ${d.y})`})
}
function clicked(d) {
if (!d3.event.defaultPrevented) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update()
}
}
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 flatten(root) {
const nodes = []
function recurse(node) {
if (node.children) node.children.forEach(recurse)
if (!node.id) node.id = ++i;
else ++i;
nodes.push(node)
}
recurse(root)
return nodes
}
function zoomed() {
svg.attr('transform', d3.event.transform)
}
function isConnected(a, b) {
return linkedByIndex[`${a.index},${b.index}`] || linkedByIndex[`${b.index},${a.index}`] || a.index === b.index;
}
function fade(opacity) {
return d => {
node.style('stroke-opacity', function (o) {
const thisOpacity = isConnected(d, o) ? 1 : opacity;
this.setAttribute('fill-opacity', thisOpacity);
return thisOpacity;
});
link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity));
};
}
update(nodes, links_data)
</script>
</body>
</html>
身体{
背景色:#e6;
}
svg{
宽度:100%;
身高:100%;
}
.节点{
指针事件:全部;
光标:指针;
z指数:1000;
}
.节点文本{
字体:8px无衬线;
}
分区工具提示{
位置:绝对位置;
背景色:白色;
最大宽度;200px;
高度:自动;
填充:1px;
边框样式:实心;
边界半径:4px;
边框宽度:1px;
盒影:3px 3px 10px rgba(0,0,0,5);
指针事件:无;
}
//节点数据
变量节点=[
{“姓名”:“特拉维斯”,“性别”:“M”,“尺码”:1983},
{“name”:“Rake”,“sex”:“M”,“size”:200},
{“姓名”:“戴安娜”,“性别”:“F”,“尺码”:15000},
{“姓名”:“雷切尔”,“性别”:“F”,“尺码”:1800},
{“姓名”:“肖恩”,“性别”:“M”,“尺码”:1983},
{“姓名”:“翡翠”,“性别”:“F”,“大小”:10000}
]
//创建数据链接
变量链接\u数据=[
{“source”:“Travis”,“target”:“Rake”},
{“source”:“Diana”,“target”:“Rake”},
{“来源”:“戴安娜”,“目标”:“瑞秋”},
{“源”:“Rachel”,“目标”:“Rake”},
{“来源”:“雷切尔”,“目标”:“肖恩”},
{“来源”:“翡翠”,“目标”:“雷切尔”}
]
//工具坑声明
变量工具提示=d3。选择(“主体”)
.附加(“div”)
.attr(“类”、“工具提示”)
.样式(“不透明度”,0);
//svg大小
常数宽度=1000,
高度=1000;
//允许缩放
const transform=d3.zoomIdentity;
//查找连接的节点
var linkedByIndex={};
//附加svg信息
const svg=d3.select('body')。append('svg'))
.call(d3.zoom().scaleExtent([1/2,8]).on('zoom',zomed))
.append('g')
.attr('transform','translate(40,0)');
//图形模拟声明
常量模拟=d3.forceSimulation()
.force('link',d3.forceLink().id(函数(d){return d.id;}))
.force('charge',d3.forceManyBody().强度(-15).最大距离(300))
.力('中心',d3.力中心(宽度/2,高度/4))
.on('勾选',勾选)
//更新图形信息的函数(节点位置、链接…)
功能更新(节点、链接和数据){
//提取源和目标信息的链接
link=svg
.selectAll(“.links\u data”)
.data(links_data,函数(d){return d.source.id})
.data(links_data,函数(d){return d.target.id})
link.exit().remove()
//客户链接
常量linkEnter=link
.输入()
.append('行')
.数据(链接)
.attr('class','link')
.style('stroke','#000')
.style('opacity','0.2')
.style('笔划宽度',2)
.attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.source.x;})
.attr(“y2”,函数(d){返回d.source.y;})
link=linkEnter.merge(link)
//向svg添加节点
node=svg
.selectAll(“.node”)
.data(节点,函数(d){return d.id})
node.exit().remove()
//Custumzie节点
const nodenter=节点
.输入()
.append('g')
.attr('类','节点')
.attr('stroke','#666')
.attr('stroke-width',2)
.style('填充',颜色)
.on(“鼠标悬停”,焦点)
.on('mouseover.tooltip',函数(d){
tooltip.transition()
.持续时间(300)
.样式(“不透明度”,0.9);
html(“标签:+d.name+”度:+d.size)
.style(“左”,“d3.event.pageX)+“px”)
.style(“top”,(d3.event.pageY+10)+“px”);
})
.on('mouseover.fade',fade(0.1))
.on(“mouseout.tooltip”,函数(){
tooltip.transition()
.持续时间(100)
.样式(“不透明度”,0);
})
.on('mouseout.fade',fade(1))
.on(“mousemove”,function(){
tooltip.style(“左”,(d3.event.pageX)+“px”)
.style(“top”,(d3.event.pageY+10)+“px”);
})
.call(d3.drag()
.on('start',dragstarted)
.on('拖动',拖动)
.on('结束',绘图))
//绘制节点
nodeEnter.append('circle'))
.attr(“r”,函数(d){return Math.sqrt(d.size)/10 | | 4.5;})
.style('text-anchor',函数(d){返回d.children?'end':'start';})
.text(函数(d){返回d.name})
node=nodenter.merge(节点)
模拟。节点(节点)
模拟。力(“链接”)。链接(链接)
}
函数sizeContain(num){
num=num>1000?num/1000:num/100
如果(num<4)num=4
返回数
}
功能色(d){
退回d.#儿童?#51A1DC”//折叠包裹
:d.儿童?#51A1DC”//扩展包
:“#F94B4C”;//叶n
<script type="text/javascript">
// node data
var nodes_data = [
{"name": "Travis", "sex": "M","size": 1983, 'col': "#1f77b4", 'shape': "circle"},
{"name": "Rake", "sex": "M","size": 200, 'col': '#FF0000', 'shape': 'rect'},
{"name": "Diana", "sex": "F","size": 15000, 'col': "#0000FF", 'shape': 'circle'},
{"name": "Rachel", "sex": "F","size": 1800, 'col': "#0000FF", 'shape': 'rect'},
{"name": "Shawn", "sex": "M","size": 1983, 'col': "#1f77b4", 'shape': 'circle'},
{"name": "Emerald", "sex": "F","size": 10000, 'col': "#306754", 'shape': 'rect'}
]
// links data
var links_data = [
{"source": "Travis", "target": "Rake"},
{"source": "Diana", "target": "Rake"},
{"source": "Diana", "target": "Rachel"},
{"source": "Rachel", "target": "Rake"},
{"source": "Rachel", "target": "Shawn"},
{"source": "Emerald", "target": "Rachel"}
]
</script>
<script type="text/javascript">
//toolpit
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//svg size
const width = 1000,
height = 1000;
// Allow zoom
const transform = d3.zoomIdentity;
// Find connected nodes
var linkedByIndex = {};
// Append svg info
const svg = d3.select('body').append('svg')
.call(d3.zoom().scaleExtent([1/2, 8]).on('zoom', zoomed))
.append('g')
.attr('transform', 'translate(40,0)');
// graph simulation
const simulation = d3.forceSimulation()
.force('link',
d3.forceLink().id(function(d) { return d.name; }).strength(0.1)
.distance(function(d) { return radius(d.source.value / 2) + radius(d.target.value / 2); })
//.strength(function(d) {return 0.75; })
)
.force('charge', d3.forceManyBody().strength(-15).distanceMax(300))
.force('center', d3.forceCenter( width/2, height/4 ))
.on('tick', ticked)
// Function to update graph informations (nodes positions, links....)
function update(nodes_data, links_data) {
//Extract links source and target information
link = svg.append()
.attr('class', 'link')
.selectAll('path')
.data(links_data)
.enter().append("svg:path")
.style('stroke', 'black')
.style('opacity', 0.2)
.style('fill', 'none')
.style("stroke-width", '2px');
// Add nodes to svg
node = svg
.selectAll('.nodes_data')
.data(nodes_data, function(d){ return d.id });
node.exit().remove()
// Custumzie nodes
const nodeEnter = node
.enter()
.append('g')
.attr('class', 'node')
.attr("d",function(d) {return d.shape;}) // PB de shape des noeuds
.attr('stroke', function (d) { return d.col; })
.attr('stroke-width', 1)
.style("fill", function (d) { return d.col; })
.on("mouseover", focus)
.on('mouseover.tooltip', function(d) {
tooltip.transition()
.duration(300)
.style("opacity", 0.9);
tooltip.html("Label:" + d.name + "<p/>Degree:" + d.size)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY + 10) + "px");
})
.on('mouseover.fade', fade(0.1))
.on("mouseout.tooltip", function() {
tooltip.transition()
.duration(100)
.style("opacity", 0);
})
.on('mouseout.fade', fade(1))
.on("mousemove", function() {
tooltip.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY + 10) + "px");
})
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended))
// Draw nodes
nodeEnter.append('circle')
.attr("r", function(d) { return Math.sqrt(d.size) / 10 || 4.5; })
.style('text-anchor', function(d){ return d.children ? 'end' : 'start'; })
.text(function(d){ return d.name })
node = nodeEnter.merge(node)
simulation.nodes(nodes_data)
simulation.force("link").links(links_data);
}
function radius(d) {
return d._children ? 8
: d.children ? 8
: 4
}
function ticked() {
link.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" +
d.source.x + "," +
d.source.y + "A" +
dr + "," + dr + " 0 0,1 " +
d.target.x + "," +
d.target.y;
});
node
.attr('transform', function(d){ return `translate(${d.x}, ${d.y})`})
}
function clicked(d) {
if (!d3.event.defaultPrevented) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update()
}
}
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 flatten(root) {
const nodes = []
function recurse(node) {
if (node.children) node.children.forEach(recurse)
if (!node.id) node.id = ++i;
else ++i;
nodes.push(node)
}
recurse(root)
return nodes
}
function zoomed() {
svg.attr('transform', d3.event.transform)
}
function isConnected(a, b) {
return linkedByIndex[`${a.index},${b.index}`] || linkedByIndex[`${b.index},${a.index}`] || a.index === b.index;
}
function fade(opacity) {
return d => {
node.style('stroke-opacity', function (o) {
const thisOpacity = isConnected(d, o) ? 1 : opacity;
this.setAttribute('fill-opacity', thisOpacity);
return thisOpacity;
});
link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity));
};
}
update(nodes_data, links_data)
</script>
node = svg
.selectAll('.nodes_data')
.data(nodes_data, function(d){ return d.name });