xkcdForceLayout = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
var radius = 15;
var simulation = d3.forceSimulation();
var START = Math.floor(Math.random() * Math.floor(graph.nodes.length - 300));
var END = START + 300;
graph.links = graph.links.filter( link => link.source >= START);
graph.links = graph.links.filter( link => link.source < END);
graph.links = graph.links.filter( link => link.target >= START);
graph.links = graph.links.filter( link => link.target < END);
for(let i=0;i<graph.links.length;i++)
{
graph.links[i].id = i;
}
let source_ids = graph.links.map( link => link.source);
let target_ids = graph.links.map( link => link.target);
graph.nodes = graph.nodes.filter( node => source_ids.includes(node.id) || target_ids.includes(node.id));
simulation
.nodes(graph.nodes);
var link_force = d3.forceLink(graph.links)
.id(function(d) { return d.id; });
var charge_force = d3.forceManyBody()
.strength(-180);
var center_force = d3.forceCenter(width / 2, height / 2);
simulation
.force("charge_force", charge_force)
.force("center_force", center_force)
.force("links",link_force);
//add tick instructions:
simulation.on("tick", tickActions );
//draw lines for the links
var link = svg
.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) { return d.weight ** 0.75;})
var clickable_link_area = svg
.append("g")
.attr("class", "links-transparent")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", 15)
.attr("stroke", "transparent")
clickable_link_area.on("click", function(link) {
console.log(link);
console.log("text#i" + link.id);
let t = d3.selectAll("text#i" + link.id);
if(t.style("display") == "none")
{
t.style("display", null);
}
else
{
t.style("display", "none");
}
});
//draw circles for the nodes
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter()
.append("circle")
.attr("r", radius);
var link_label = svg.append("g")
.attr("class", "labels")
.selectAll("text")
.data(graph.links)
.enter().append("text")
.attr("id", function(d){ return "i" + d.id;})
.attr("class", "link_label")
.style("display", "none")
.text(function(d) { return d.words; });
link_label.on("click", function(link) {
console.log(link);
console.log("text#i" + link.id);
let t = d3.selectAll("text#i" + link.id);
if(t.style("display") == "none")
{
t.style("display", null);
}
else
{
t.style("display", "none");
}
});
node.on("click", function(node) {
console.log(node.x);
console.log(node.y);
console.log(node.name);
// svg_image.selectAll("image").remove();
// var myimage = svg_image.append("image")
// .attr("xlink:href", "https://raw.githubusercontent.com/billy-mosse/xkcd/main/images/" + node.name + ".png")
// .attr('width', "100%")
// .attr('height', "100%")
// .attr('x', 0)
// .attr('y', 0)
d3.event.stopPropagation();
});
node.on("click", function(node) {
console.log(node.x);
console.log(node.y);
console.log(node.name);
console.log()
// svg_image.selectAll("image").remove();
// var myimage = svg_image.append("image")
// .attr("xlink:href", "https://raw.githubusercontent.com/billy-mosse/xkcd/main/images/" + node.name + ".png")
// .attr('width', "100%")
// .attr('height', "100%")
// .attr('x', 0)
// .attr('y', 0)
d3.event.stopPropagation();
});
var drag_handler = d3.drag()
.on("start", drag_start)
.on("drag", drag_drag)
.on("end", drag_end);
drag_handler(node)
function tickActions() {
//constrains the nodes to be within a box
node
.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); })
.attr("r", function(d) { return d.degree ** 0.39});
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; });
clickable_link_area
.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; });
link_label
.attr("x", function(d) { return (d.source.x + d.target.x)/2; })
.attr("y", function (d) { return (d.source.y + d.target.y)/2; })
.style("font-size", "14px").style("fill", "black").style("font-family", "xkcd");
/*node_balloon
.attr("x", function(d) { return d.x; })
.attr("y", function (d) { return d.y; })
.style("font-size", "14px").style("fill", "black").style("font-family", "xkcd")
.style("width", 20).style("height", 20);*/
}
function drag_start(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function drag_drag(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function drag_end(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
return svg.node();
}