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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more