Published
Edited
Dec 30, 2021
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
// drawChart()
Insert cell
Insert cell
Insert cell
cos_graph = FileAttachment("link-cos@27.json").json()
Insert cell
Insert cell
node_types = Array.from(new Set(link_graph.nodes.map(d => d.doc_type)))
Insert cell
Insert cell
Insert cell
drawChart={
const link_links = link_graph.links.map(d => Object.create(d))
const cos_links = cos_graph.links.map(d => Object.create(d))
const nodes = link_graph.nodes.map(d => Object.create(d))
const radius = 5;
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
const simulation = d3.forceSimulation(nodes)
// .force("link_link", d3.forceLink(link_links).id(d => d.id))
.force("cos_link", d3.forceLink(cos_links).id(d => d.id))
.force("charge", d3.forceManyBody().strength(-30))
.force("cos_link", d3.forceLink().strength(0))
.force("center", d3.forceCenter(width/2, height/2))
.force("collide", d3.forceCollide().radius(30).strength(.5).iterations(1));
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
const legend = svg.append("g")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
const l_link = svg.append("g")
.attr("stroke-opacity", 0.5)
.selectAll("line")
.data(link_links)
.join("line")
.attr("stroke", 'blue')
.attr("stroke-width", 2)

;
const c_link = svg.append("g")
.attr("stroke-opacity", 0.5)
.selectAll("line")
.data(cos_links)
.join("line")
.attr("stroke", "red")
.attr("stroke-width", 1)
;
const node = svg.append("g")
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", radius)
.attr("fill", d=> node_color(d.doc_type))
.call(drag(simulation))
.on('mouseover.fade', fade(0.1))
.on('mouseout.fade', fade(1));
const textElems = svg.append('g')
.selectAll('text')
.data(nodes)
.join('text')
.text(d => d.id)
.attr('font-size',10)
.attr('font-size',10)
.attr("pointer-events","none");
simulation.on("tick", () => {
c_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);
l_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("cx", function(d) { return d.x = Math.max((radius+1), Math.min(width - (radius+1), d.x)); })
.attr("cy", function(d) { return d.y = Math.max((radius+1), Math.min(height - (radius+1), d.y)); });
textElems
.attr("x", d => d.x + 10)
.attr("y", d => d.y)
.attr("visibility", "hidden")
//show nodes with degree 7 or above
.attr('visibility', function (d) { return d.degree > 7 ? "visible" : "hidden" });
});
function fade(opacity) {
return d => {
node.style('opacity', function (o) { return isConnected(d, o) ? 1 : opacity });
textElems.style('visibility', function (o) { return isConnected(d, o) ? "visible" : "hidden" });
c_link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity));
l_link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity));
if(opacity === 1){
node.style('opacity', 1)
textElems.style('visibility', 'hidden')
textElems.style('visibility', function (d) { return d.degree > 7 ? "visible" : "hidden" });
c_link.style('stroke-opacity', 0.3)
l_link.style('stroke-opacity', 0.3)
}
};
}
const linkedByIndex = {};
cos_links.forEach(d => {
linkedByIndex[`${d.source.index},${d.target.index}`] = 1;
});
link_links.forEach(d => {
linkedByIndex[`${d.source.index},${d.target.index}`] = 1;
});

function isConnected(a, b) {
return linkedByIndex[`${a.index},${b.index}`] || linkedByIndex[`${b.index},${a.index}`] || a.index === b.index;
}
invalidation.then(() => simulation.stop());
return svg.node()
}
Insert cell
Insert cell
Insert cell
#----------------------------------------------------------------------------
Insert cell
# D3 树
Insert cell
Insert cell
function renderImg(name) {
var path = 'https://raw.githubusercontent.com/zhihaohowardyao/visualizations/master/img/';
return (path + name);
}
Insert cell
data = JSON.parse(`
{
"name":"The news","level": 1, "group":"1",
"children":[
{
"name":"Press Statement","level": 2, "group":"1",
"children":[
{
"name":"people","level": 3, "group":"1",
"children":[
{
"name":"rights","level": 4, "group":"1",
"size":8833, "img":"Relation_Two.png"
},
{
"name":"human","level": 4, "group":"1",
"size":2047, "img":"Many_Points.png"
},
{
"name":"including","level": 4, "group":"1",
"size":3812, "img":"Non_Cyc.png"
}

]
}
]
},


{
"name":"Readout","level": 2, "group":"2",
"children":[
{
"name":"Secretary","level": 3, "group":"2",
"children":[
{
"name":"Blinken","level": 4, "group":"2",
"size":1983, "img":"Few_Points.png"
},
{
"name":"Minister","level": 4, "group":"2",
"size":3812, "img":"Two_per_Item.png"
},
{
"name":"Foreign","level": 4, "group":"2",
"size":2047, "img":"Many_Points.png"
}
]
}
]
},




{
"name":"Media Note","level": 2, "group":"3",
"children":[
{
"name":"support","level": 3, "group":"3",
"size":3812, "img":"Many_Cat.png"
}
]
},




{
"name":"Interview","level": 2, "group":"4",
"children":[
{
"name":"Secretary","level": 3, "group":"4",
"children":[
{
"name":"Blinken","level": 4, "group":"4",
"size":2165, "img":"Component.png"
},
{
"name":"Question","level": 4, "group":"4",
"size":2165, "img":"Total.png"
},
{
"name":"President","level": 4, "group":"4",
"size":2165, "img":"Simple_Total.png"
}
]
}
]
},


{
"name":"Fact Sheet","level": 2, "group":"5",
"children":[
{
"name":"security","level": 3, "group":"5",
"size":1983, "img":"Single_Cat.png"
},
{
"name":"including","level": 3, "group":"5",
"size":2165, "img":"Simple_Total.png"
},
{
"name":"support","level": 3, "group":"5",
"size":3812, "img":"Non_Cyc.png"
},
{
"name":"climate","level": 3, "group":"5",
"size":1732, "img":"Relation_Three.png"
}
]
},

{
"name":"Special Briefing","level": 2, "group":"6",
"children":[
{
"name":"Secretary","level": 3, "group":"6",
"size":8833, "img":"Relation_Two.png"
},
{
"name":"Question","level": 3, "group":"6",
"size":2165, "img":"Simple_Total.png"
}
]
},



{
"name":"Remarks to the Press","level": 2, "group":"7",
"children":[
{
"name":"Thank","level": 3, "group":"7",
"children":[
{
"name":"people","level": 4, "group":"7",
"size":1983, "img":"Few_Points.png"
},
{
"name":"Secretary","level": 4, "group":"7",
"size":3812, "img":"Two_per_Item.png"
}
]
}
]
},


{
"name":"Notice to the Press","level": 2, "group":"8",
"children":[
{
"name":"Secretary","level": 3, "group":"8",
"size":8833, "img":"Relation_Two.png"
},
{
"name":"state","level": 3, "group":"8",
"size":1732, "img":"Relation_Three.png"
},
{
"name":"gov","level": 3, "group":"8",
"size":2165, "img":"Total.png"
}
]
},


{
"name":"Speech","level": 2, "group":"9",
"children":[
{
"name":"Secretary","level": 3, "group":"9",
"children":[
{
"name":"world","level": 4, "group":"9",
"size":2165, "img":"Many_Absolute.png"
},
{
"name":"countries","level": 4, "group":"9",
"size":2165, "img":"Many_Relative.png"
},
{
"name":"climate","level": 4, "group":"9",
"size":2165, "img":"Few_Relative.png"
}
]
}
]
}

]
}
`)
Insert cell
html `
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans" />
<style>
.pill-box {
font-family: Open Sans,Arial,sans-serif;
display: flex;
padding-left: 10px;
padding-bottom: 10px;
line-height: 32px;
align-items: center;
}
.pill-box__pills {
display: flex;
}
.pill-box__pill {
text-decoration: none;
color: #fff;
font-size: 12px;
font-weight: bold;
padding: 0 4px 0 15px;
line-height: 32px;
display: inline-block;
text-align: center;
background-color: #307abb;
margin-right: 10px;
border-radius: 16px;
}
.pill-box__pill-text {
pointer-events: none;
}
.pill-box__pill-icon {
display: inline-block;
background-color: #fff;
border-radius: 12px;
color: #307abb;
line-height: 24px;
height: 24px;
width: 24px;
margin-left: 7px;
cursor: pointer;
}
</style>
<code>pillCSS</code>
`
Insert cell
d3_tree = require("d3@v3")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more