D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
kcsluis
Full window
Github gist
Enter, Update, Exit
<!DOCTYPE html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> body { font-family: 'arial', sans-serif; font-size: 9px; width: 960px; } h1 { font-size: 24px; } .axis path { display: none; } .axis line { stroke-width: 1px; stroke: #ccc; stroke-dasharray: 2px 2px; } button { margin: 12px 12px 0px 0px; } circle.dot { fill: #000; stroke: #fff; } </style> </head> <body> <h1></h1> </body> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script> <script> // ENTER-UPDATE-EXIT PATTERN // 1. Make new data join // 2. Get rid of old elements // 3. Enter new elements // 4. Append elements as needed // 5. Update new selection // https://bl.ocks.org/mbostock/3808218 // https://bost.ocks.org/mike/join/ // https://bost.ocks.org/mike/circles/ // separating steps makes for cleaner, more maintainable code var margin = {top: 6, right: 20, bottom: 20, left: 20}; var width = 960 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); d3.tsv("ans_quart.tsv", function(error, data) { if (error) throw error; data.forEach( function (d) { d.x = +d.x; d.y = +d.y; }); // add my buttons var allGroups = data.map( function (d) { return d.group; }); var groupList = d3.set(allGroups).values(); var buttons = d3.select("body").selectAll("button") .data(groupList) .enter() .append("button") .text( function (d) { return "Group " + d; }) .on("click", function (d) { drawGroup(d); }); // fixed domain for scales means consistent graph var xScaled = d3.scale.linear() .range([0, width]) .domain([0, 20]); var yScaled = d3.scale.linear() .range([height, 0]) .domain([0, 16]); var xAxis = d3.svg.axis() .scale(xScaled) .tickSize(-height) .tickPadding(8) .orient("bottom"); var yAxis = d3.svg.axis() .scale(yScaled) .tickSize(-width) .tickPadding(8) .orient("left"); var xAxisGroup = svg.append("g") .call(xAxis) .attr("class", "axis") .attr("transform", "translate(0," + height + ")"); var yAxisGroup = svg.append("g") .call(yAxis) .attr("class", "axis"); // graph drawing function function drawGroup (groupID) { var activeData = data.filter( function (d) { return d.group === groupID; }); // xAxisGroup.call(xAxis); // yAxisGroup.call(yAxis); // 1. Make new data join var circleGroupData = svg.selectAll("g.circleGroup") .data(activeData); // 2. Get rid of old elements circleGroupData.exit().remove(); // 3. Enter new elements var circleGroupEnter = circleGroupData .enter() .append("g") .attr("class", "circleGroup") .attr("transform", function (d) { return "translate(" + xScaled(d.x) + "," + yScaled(d.y) + ")"; }); // 4. Append elements as needed circleGroupEnter.append("circle") .attr("class", "dot") .attr("r", 5); circleGroupEnter.append("text") .attr("class", "circleLabel") .attr("y", 3) .attr("x", 8) .text( function (d) { return (d.x).toFixed(1) + ", " + (d.y).toFixed(1) }); // 5. Update new selection circleGroupData = svg.selectAll(".circleGroup") .transition() .duration(400) // explicitly telling it to transform is the key .attr("transform", function (d) { return "translate(" + xScaled(d.x) + "," + yScaled(d.y) + ")"; }); // must use .select to maintain data join circleGroupData.select("text") .text( function (d) { return (d.x).toFixed(1) + ", " + (d.y).toFixed(1) }); d3.select("h1") .text("Anscombe's Quartet — Group " + groupID); }; var groupSelection = "I"; drawGroup(groupSelection); }); </script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js