D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
ValentinCrr
Full window
Github gist
Iris Scatterplot
Built with
blockbuilder.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Iris Scatterplot</title> <script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script> <script src="index.js">//d3-tip</script> <style type="text/css"> .axis path, .axis line{ fill: none; stroke: black; shape-rendering: crispEdges; } .axis text { font-family : sans-serif; font-size: 10px; } .regression { stroke-width: 2px; stroke: red; stroke-dasharray: 10,5; } .grid line { stroke: lightgrey; stroke-opacity: 0.7; shape-rendering: crispEdges; } .grid path { stroke-width: 0; } .graphTitle text { font-family : sans-serif; font-size: 25px; } .d3-tip { line-height: 1; padding: 6px; background: rgba(0, 0, 0, 0.8); color: #fff; border-radius: 4px; font-size: 12px; } .zoom { cursor: move; fill: none; pointer-events: all; } </style> </head> <body> <script type="text/javascript"> // Data parameters : x_coord = "petal_width"; y_coord = "petal_length"; // Svg parameters var w = 650; var h = 400; var barPadding = 1; var xAxisPadding = 70; var yAxisPadding = 50; var xLegend = 1.5*yAxisPadding; var yLegend = xAxisPadding; const symbolScale = d3.scaleOrdinal() .range([d3.symbol().type(d3.symbolCircle).size(20)(), d3.symbol().type(d3.symbolStar).size(20)(), d3.symbol().type(d3.symbolWye).size(20)() ]); const colorScale = d3.scaleOrdinal() .range(["#eb8e37", "#1ac6cf", "#12854b"]); var svg = d3.select("body").append("svg") .attr("width", w) .attr("height", h); // Load Dataset var dataset; d3.csv("iris.csv", function(error,data) { // Test if (error){console.log(error)} else{console.log(data); // Save data dataset = data; // Extremums var Xmin = d3.min(dataset, function(d) { return d.petal_width;}); var Xmax = d3.max(dataset, function(d) { return d.petal_width;}); var Ymin = d3.min(dataset, function(d) { return d.petal_length;}); var Ymax = d3.max(dataset, function(d) { return d.petal_length;}); //**********************************// // Graph Setup // //**********************************// // Graph title svg.append("text") .attr("class","graphIitle") .attr("x", (w / 2)) .attr("y", 0 + (xAxisPadding / 2)) .attr("text-anchor", "middle") .text("Iris Dataset Scatterplot") .style("font-size","25px"); // Create scales var scaleX = d3.scaleLinear() .domain([0,Xmax]) .range([yAxisPadding,w - yAxisPadding]); var scaleY = d3.scaleLinear() .domain([0,Ymax]) .range([h - xAxisPadding,xAxisPadding]); // Create axis var xAxis = d3.axisBottom() .scale(scaleX); var yAxis = d3.axisLeft() .scale(scaleY); var gX = svg.append("g") .attr("class","axis") .attr("transform", "translate(0," + (h - xAxisPadding) + ")") .call(xAxis); var gY = svg.append("g") .attr("class", "axis") .attr("transform", "translate(" + yAxisPadding + ",0)") .call(yAxis); // Axis titles svg.append("text") .attr("transform", "rotate(-90)") .attr("y", 0) .attr("x",0 - (h/2)) .attr("dy", "1em") .style("text-anchor", "middle") .text(y_coord.replace(/_/g, ' ')); svg.append("text") .attr("transform","translate(" + (w/2) + " ," + (h - yAxisPadding + 20) + ")") .style("text-anchor", "middle") .text(x_coord.replace(/_/g, ' ')); // gridlines in X axis function function make_x_gridlines() { return d3.axisBottom(scaleX) .ticks(5) } // gridlines in Y axis function function make_y_gridlines() { return d3.axisLeft(scaleY) .ticks(5) } // add the X gridlines svg.append("g") .attr("class", "grid") .attr("transform", "translate(0," + (h - xAxisPadding) + ")") .call(make_x_gridlines() .tickSize(2*xAxisPadding-h) .tickFormat("") ) // add the Y gridlines svg.append("g") .attr("class", "grid") .attr("transform", "translate(" + yAxisPadding + ",0)") .call(make_y_gridlines() .tickSize(2*yAxisPadding-w) .tickFormat("") ) //*************************// // Regression function // //*************************// function regression(data, x, y, minX, maxX){ // Takes 5 parameters : // (1) The dataset // (2) Column of data plotted on x-axis // (3) Column of data plotted on y-axis // (4) Minimum value of x-axis // (5) Maximum value of y-axis // Initialization var n = data.length; var sum = 0; var xSum = 0; var ySum = 0; var sumSq = 0; // Build (x,y,x*y) array var pts = []; data.forEach(function(d,i){ var obj = {}; obj.x = Number(d[x]); obj.y = Number(d[y]); obj.mult = obj.x*obj.y; pts.push(obj); }); // Compute slope and intercept pts.forEach(function(pt){ sum = sum + pt.mult; xSum = xSum + pt.x; ySum = ySum + pt.y; sumSq = sumSq + (pt.x * pt.x); }); var a = sum * n; var b = xSum * ySum; var c = sumSq * n; var d = xSum * xSum; var m = (a - b) / (c - d); // Slope var b = ( ySum - m*xSum ) / n; // Intercept // Return 2 points for regression line return{ ptA : { x: minX, y: m * minX + b }, ptB : { y: m * maxX + b, x: maxX } } } //**********************// // Drawing area // //**********************// // Drawing area var view = svg.append("g") // Add new group (containing all dots) .attr("class", "view"); //**********************// // Regression line // //**********************// var lg = regression(data, "petal_width", "petal_length", Xmin, Xmax); var regressionLine = view.append("line") .attr("class", "regression") .attr("x1", scaleX(lg.ptA.x)) .attr("y1", scaleY(lg.ptA.y)) .attr("x2", scaleX(lg.ptB.x)) .attr("y2", scaleY(lg.ptB.y)) //**********************// // Data plots // //**********************// // Create tool_tip : dot info var tool_tip = d3.tip() .attr("class", "d3-tip") .offset([-10, 0]) .html(function(d) { return "Petal length : " + d.petal_length + "<br>" + "Petal width : " + d.petal_width + "<br>" + "Sepal length : " + d.sepal_length + "<br>" + "Sepal width : " + d.sepal_width; }); svg.call(tool_tip); // Create zoom behavior var zoomBeh = d3.zoom() .on("zoom", zoomFunction); // Create and display dots var dots = view.selectAll("path") .data(dataset) .enter() .append("path") // added new path // (x,y) coordinates .attr("transform",function(d) {return "translate(" + scaleX(d.petal_width) +","+scaleY(d.petal_length)+")" ;}) // Change symbol .attr("d", d => symbolScale(d.species)) // change color .attr('fill',d => colorScale(d.species)) // Display details on "mouseover" .on("mouseover", tool_tip.show) .on("mouseout", tool_tip.hide); // append zoom area var zoomArea = svg.append("rect") .attr("class", "zoom") .attr("width", w) .attr("height", h) .call(zoomBeh); //**************************// // Legend // //**************************// Leg = svg.append("rect") .attr("x",xLegend) .attr("y",yLegend) .attr("width",100) .attr("height",105) .attr("fill","white") .attr("stroke","black") .attr("stroke-width","0.5"); svg.call(colorLegend, { colorScale: colorScale, positionX: xLegend+10, // Box content X position positionY: yLegend+45, // Box content Y position tickRadius: 10, tickSpacing: 22, tickPadding: 8, label: "Species", labelX: 15, labelY: -25 }); //**************************// // Other functions // //**************************// // Coloring fucntion function colorLegend(selection, props){ const colorScale = props.colorScale; const positionX = props.positionX; const positionY = props.positionY; const tickRadius = props.tickRadius; const tickSpacing = props.tickSpacing; const tickPadding = props.tickPadding; const label = props.label; const labelX = props.labelX; const labelY = props.labelY; let legendG = selection .selectAll(".legend--color") .data([null]); legendG = legendG .enter().append("g") .attr("class", "legend legend--color") .merge(legendG) .attr("transform", `translate(${positionX}, ${positionY})`); const legendLabel = legendG .selectAll(".legend__label") .data([null]); legendLabel .enter().append("text") .attr("class", "legend__label") .merge(legendLabel) .attr("x", labelX) .attr("y", labelY) .text(label); const ticks = legendG .selectAll(".tick") .data(colorScale.domain()) const ticksEnter = ticks .enter().append("g") .attr("class", "tick"); ticksEnter .merge(ticks) .attr("transform", (d, i) => `translate(0, ${i * tickSpacing})`); ticks.exit().remove(); ticksEnter .append("g").append("path") .attr("d", symbolScale) .attr("fill", colorScale); ticksEnter .append("text") .merge(ticks.select("text")) .attr("x", tickRadius + tickPadding) .attr("y", 3) .text(d => d); } } // Zoom functions function zoomFunction() { // update dots view view.attr("transform", d3.event.transform); // update axes gX.call(xAxis.scale(d3.event.transform.rescaleX(scaleX))); gY.call(yAxis.scale(d3.event.transform.rescaleY(scaleY))); }; }); </script> </body> </html>
https://d3js.org/d3.v4.min.js