Classic D3 Examples
Old school D3 from simpler times
johnburnmurdoch
Full window
Github gist
<!DOCTYPE html> <html lang="en-GB"> <head> <title>Histo-packing</title> <script src="https://unpkg.com/d3"></script> <script src="https://unpkg.com/d3-jetpack-module"></script> <style> body{background: #212121; margin: 20px;} text{font-family: Avenir; font-size: 18px; fill:#fff;} .domain{display: none;} .y .tick#_0 line{stroke: #ccc;} .tick line{stroke: #808080;} .y text{display:none;} </style> </head> <body> <script type="text/javascript" charset="utf-8"> var width = 700, height = 800, margin = {top: 30, right: 20, bottom: 70, left: 5}, // n = 1000, // radius = 5.5, // t = 3000; // n = 2500, // radius = 3.6, // t = 4000; n = 5000, radius = 2.6, t = 6000; var svg = d3.select("body") .append("svg#svg") .st({ 'width':width, 'height':height }); var x = d3.scaleLinear() .range([margin.left, width - margin.right]) .domain([0,100]); var xScale = d3.axisBottom() .scale(x) .ticks(10) .tickSize(-(height - (margin.top + margin.bottom))); var xAxis = svg.append("g.axis.x") .translate([0,height-margin.bottom]) .call(xScale) .selectAll(".tick") .at({ id: d => "_" + d }) .selectAll("text") .at({ dy: 15 }); var y = d3.scaleLinear() .range([height-margin.bottom, margin.top]) .domain([0,100]); var yScale = d3.axisLeft() .scale(y) .ticks(10) .tickSize(-(width - (margin.left + margin.right))); var yAxis = svg.append("g.axis.y") .translate([margin.left,0]) .call(yScale) .selectAll(".tick") .at({ id: d => "_" + d }) .filter(d => d != 0) .remove(); var colours = d3.scaleLinear() .range(["#FCAB27", "#FF2B4F"]) .domain([0, 30]); var circlesData = []; d3.json("circleData.json", function(error, data){ data = data.filter(d => d >= 0 && d <= 100).slice(0,n).sort((a,b) => (Math.abs(a-50) - Math.abs(b-50))); // Run the line below if you want to bin the data, in this case by rounding to the nearest whole number // data = data.map(d => +d3.format(".0f")(d)); var circles = svg.appendMany(data, "circle") .at({ cx: d => x(d), cy: y(100)-radius-20, r: radius-0.75, fill: "#aaa", stroke: "#aaa", "stroke-width": 1, "fill-opacity": 0.9 }); data.forEach((datum,index) => { var thisCircle = data[index]; var xInRange = circlesData.filter(d => Math.abs(x(d.x) - x(thisCircle)) <= (2*radius)).sort(function(a,b){ if(a.y == b.y){ return Math.abs(b.x - thisCircle) - Math.abs(a.x - thisCircle) }else{ return a.y - b.y } }); var cy = 0, it = 0; if(xInRange.length >= 1){ for(var it=0; it < xInRange.length; it++){ if(((Math.pow(Math.pow((y(xInRange[it].y)-radius) - (y(cy)-radius),2)+Math.pow(x(thisCircle)-x(xInRange[it].x),2),0.5))) >= 1.99*radius && (((Math.pow(Math.pow((y(xInRange[d3.max([0,it-1])].y)-radius) - (y(cy)-radius),2)+Math.pow(x(thisCircle)-x(xInRange[d3.max([0,it-1])].x),2),0.5))) >= 1.99*radius) && (((Math.pow(Math.pow((y(xInRange[d3.min([xInRange.length-1,it+1])].y)-radius) - (y(cy)-radius),2)+Math.pow(x(thisCircle)-x(xInRange[d3.min([xInRange.length-1,it+1])].x),2),0.5))) >= 1.99*radius)){ break; }else{ cy = y.invert(d3.min([d3.max([0, it-1]),it].map(d => y(xInRange[d].y) - ((Math.pow(Math.pow(2*radius,2)-Math.pow(x(thisCircle)-x(xInRange[d].x),2),0.5)))))); } } } svg.selectAll("circle").filter((d,i) => i == index) .transition() .ease(d3.easeLinear) .delay(index * (t/Math.pow(index+1,0.85))) .duration((t/Math.pow(index+2,0.85))) .attr("cy", y(cy)-radius) .style("stroke", d => colours(Math.pow(Math.pow(thisCircle-50,2) + Math.pow(cy,2),0.5))) .style("fill", d => colours(Math.pow(Math.pow(thisCircle-50,2) + Math.pow(cy,2),0.5))); circlesData.push({x: thisCircle, y: cy}); }); }); // After your data-points have been programmatically positioned once, simply open the web inspector, type copy(circlesData) into the console, then paste from the clipboard into a text editor, save the file as positionedCircles.json, comment out the d3.json... block above, and run the block below to instantly render your predetermined layout. // d3.json("positionedCircles.json", function(error, data){ // var circles = svg.appendMany(data, "circle") // .at({ // cx: d => x(d.x), // cy: d => y(d.y)-radius, // r: radius-0.75, // fill: d => colours(Math.pow(Math.pow(d.x-50,2) + Math.pow(d.y,2),0.5)), // stroke: d => colours(Math.pow(Math.pow(d.x-50,2) + Math.pow(d.y,2),0.5)), // "stroke-width": 1, // "fill-opacity": 0.9 // }); // }); </script> </body> </html>
https://unpkg.com/d3
https://unpkg.com/d3-jetpack-module