D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
JoshFeldman777
Full window
Github gist
UFO Sightings
Built with
blockbuilder.org
<!DOCTYPE html> <meta charset="utf-8"> <head> <style> svg { float: left; } #title { width: 700px; text-align: center; font-family: 'Corben', Georgia, Times, serif; } #commentDiv { float: left; margin-left: 20px; /*height: 100%; overflow: auto;*/ } .links line { /*stroke: #999;*/ /*stroke-opacity: 0.6;*/ } .nodes circle { /*stroke: #fff;*/ stroke-width: 5px; } .green { color: #32CD32; } .node text { pointer-events: none; font: 16px sans-serif; text-anchor: middle; } /*This borrowed is stolen from: https://www.w3schools.com/css/tryit.asp?filename=trycss_table_fancy*/ #table { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; border-collapse: collapse; width: 400px; table-layout: fixed; } #intro { width: 362px; border: 1px solid #ddd; padding: 18px; margin-left: 20px; float: left; font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; } #table td, #table th { border: 1px solid #ddd; padding: 18px; } #table tr:nth-child(even){background-color: #f2f2f2;} #table tr:hover {background-color: #ddd;} #table th { padding-top: 12px; padding-bottom: 12px; text-align: center; background-color: #4CAF50; color: white; } div.tooltip { position: absolute; text-align: center; width: 100px; height: 40px; padding: 2px; font: 12px sans-serif; background-color: #D0F0F0; border: 1px; border-radius: 8px; pointer-events: none; } </style> <script src="https://d3js.org/d3.v4.min.js"></script> </head> <body> <h2 id="title">Common Words in UFO Sighting Descriptions</h2> <svg width="700" height="600"></svg> <div id="commentDiv"></div> <div id="intro"> <p> Each circle represents a common word in descriptions of alien cities. The size of the circle corresponds to the frequency of the word. Each link between 2 words represents the frequency with which those two words were in the same comment. <h3>Click a word to see some of the descriptions it belongs to!</h3> </p> </div> <script> var comments = []; var chosenComments = []; var chosenWord = "No Word Selected" var chosenWordCount = 0 var linkSet = {} var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); var color = d3.scaleOrdinal(d3.schemeCategory20); var minRadius = 15; var maxRadius = 100; var minLinkWidth = 1 var maxLinkWidth = 30 var simulation = d3.forceSimulation() .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(200)) .force("charge", d3.forceManyBody().strength(-250)) .force("center", d3.forceCenter(width / 2, height / 2)); function createlinkSet(links) { result = new Set(); links.forEach(link => { source = link['source']; target = link['target']; sourceTarget = source + ' ' + target; targetSource = target + ' ' + source; result.add(sourceTarget); result.add(targetSource); }) return result; } d3.json("force_250.json", function(error, graph) { if (error) throw error; linkSet = createlinkSet(graph.links); var minGroup = Math.min.apply(Math, graph.nodes.map(function(d){return d["group"];})); var maxGroup = Math.max.apply(Math, graph.nodes.map(function(d){return d["group"];})); var minValue = Math.min.apply(Math, graph.links.map(function(d){return d["value"];})); var maxValue = Math.max.apply(Math, graph.links.map(function(d){return d["value"];})); var rScale = d3.scaleSqrt() .domain([minGroup, maxGroup]) .range([minRadius, maxRadius]); var linkScale = d3.scaleLinear() .domain([minValue, maxValue]) .range([minLinkWidth, maxLinkWidth]); var link = svg.append("g") .attr("class", "links") .selectAll("line") .data(graph.links) .enter().append("line") .attr("stroke", "#999") .attr("stroke-width", function(d) { return linkScale(d.value); }) .attr("stroke-opacity", 0.6) ; var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("g") .attr("class", "node") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)) .on("click", function(d) { circleClicked(d) }) ;; node.append("circle") .attr("r", function(d) {return rScale(d.group)}) .attr("fill", function(d) { return color(d.group); }) ; node.append("title") .text(function(d) { return d.id; }); node.append("text") .attr("clip-path", function(d) { return "url(#clip-" + d.id + ")"; }) .attr("dx", 0) .attr("dy", ".35em") .text(function(d) { return d.id; }); simulation .nodes(graph.nodes) .on("tick", ticked); simulation.force("link") .links(graph.links); 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("cx", function(d) { return d.x = Math.max( rScale(d.group) + minRadius/2, Math.min(width - rScale(d.group), d.x) - minRadius/2 ); }) .attr("cy", function(d) { return d.y = Math.max( rScale(d.group) + minRadius/2, Math.min(height - rScale(d.group), d.y) - minRadius/2 ); }) .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); } }); 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 linkExists(word1, word2){ word12 = word1 + ' ' + word2; return linkSet.has(word12); } function getColorForWord(chosenCircleID, d) { if (d.id == chosenCircleID) { return "black"; } else if(linkExists(chosenCircleID, d.id)) { return "black"; } else { return color(d.group); } } function getStrokeOpacity(word, d) { if (word == d.source.id || word == d.target.id) { return 1.0; } else { return 0.6; } } function getStroke(word, d) { if (word == d.source.id || word == d.target.id) { return "black"; } else { return "#999"; } } function updateCircles(chosenCircleID) { d3.selectAll("circle") .attr("stroke", function(d) { return getColorForWord(chosenCircleID, d); }) .attr("stroke-width", function(d) { return d.id == chosenCircleID ? "5px" : "2.5px"; }) ; d3.selectAll("line") .attr("stroke", function(d) { return getStroke(chosenCircleID, d); }) .attr("stroke-opacity", d => getStrokeOpacity(chosenCircleID, d)) ; } function circleClicked(d) { updateCircles(d.id); if (comments) { chosenWord = d["id"]; chosenWordCount = Math.round(d["group"] * 100000); chosenComments = comments.filter(function(comment) { if (comment) { return comment.includes(" " + chosenWord); } else { return false; } }); updateChosenWord(chosenWord, chosenWordCount); updateComments(chosenComments); } } d3.json("comments_common_500.json", function(error, data) { comments = data console.log("Loaded comments: " + comments.length) }) var commentTable = d3.select('#commentDiv') .append('table') .attr('id', 'table') ; var commentTableHead = commentTable.append('thead') .append('tr') .append('th') .attr('id', 'commentHeadText') .text(chosenWord) ; var commentTableBody = commentTable.append('tbody'); function updateChosenWord(chosenWord, numChosenComments) { d3.select("#commentHeadText") .text(chosenWord + " (Count: " + numChosenComments + ")") ; } function createCommentHTML(comment, word) { var regex = new RegExp(" " + word, 'ig'); var replacement = "<span class=green> " + word + "</span>"; return comment.replace(regex, replacement); } function updateComments(chosenComments) { var rows = commentTableBody.selectAll('tr') .data(shuffle(chosenComments)) ; rows.exit() .remove(); rows .enter() .append('tr') .merge(rows) .html(d => "<td>" + createCommentHTML(d, chosenWord) + "</td>"); } updateComments(chosenComments); updateChosenWord(chosenWord, chosenComments.length); // Borrowed from https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array function shuffle(array) { var currentIndex = array.length, temporaryValue, randomIndex; // While there remain elements to shuffle... while (0 !== currentIndex) { // Pick a remaining element... randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; // And swap it with the current element. temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; } </script> </body>
https://d3js.org/d3.v4.min.js