An example model-driven scatter plot using model.js
. Draws from the D3 scatter plot example.
Curran Kelleher 4/17/2014
Updated DOM creation pattern and posted to bl.ocks.org 9/10/2015.
An example model-driven scatter plot using model.js
. Draws from the D3 scatter plot example.
Curran Kelleher 4/17/2014
Updated DOM creation pattern and posted to bl.ocks.org 9/10/2015.
{ | |
"xField": "sepalWidth", | |
"yField": "sepalLength", | |
"xLabel": "Sepal Width (cm)", | |
"yLabel": "Sepal Width (cm)", | |
"margin": { | |
"top": 20, | |
"right": 20, | |
"bottom": 30, | |
"left": 40 | |
} | |
} |
sepalLength | sepalWidth | petalLength | petalWidth | species | |
---|---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa | |
4.9 | 3.0 | 1.4 | 0.2 | setosa | |
4.7 | 3.2 | 1.3 | 0.2 | setosa | |
4.6 | 3.1 | 1.5 | 0.2 | setosa | |
5.0 | 3.6 | 1.4 | 0.2 | setosa | |
5.4 | 3.9 | 1.7 | 0.4 | setosa | |
4.6 | 3.4 | 1.4 | 0.3 | setosa | |
5.0 | 3.4 | 1.5 | 0.2 | setosa | |
4.4 | 2.9 | 1.4 | 0.2 | setosa | |
4.9 | 3.1 | 1.5 | 0.1 | setosa | |
5.4 | 3.7 | 1.5 | 0.2 | setosa | |
4.8 | 3.4 | 1.6 | 0.2 | setosa | |
4.8 | 3.0 | 1.4 | 0.1 | setosa | |
4.3 | 3.0 | 1.1 | 0.1 | setosa | |
5.8 | 4.0 | 1.2 | 0.2 | setosa | |
5.7 | 4.4 | 1.5 | 0.4 | setosa | |
5.4 | 3.9 | 1.3 | 0.4 | setosa | |
5.1 | 3.5 | 1.4 | 0.3 | setosa | |
5.7 | 3.8 | 1.7 | 0.3 | setosa | |
5.1 | 3.8 | 1.5 | 0.3 | setosa | |
5.4 | 3.4 | 1.7 | 0.2 | setosa | |
5.1 | 3.7 | 1.5 | 0.4 | setosa | |
4.6 | 3.6 | 1.0 | 0.2 | setosa | |
5.1 | 3.3 | 1.7 | 0.5 | setosa | |
4.8 | 3.4 | 1.9 | 0.2 | setosa | |
5.0 | 3.0 | 1.6 | 0.2 | setosa | |
5.0 | 3.4 | 1.6 | 0.4 | setosa | |
5.2 | 3.5 | 1.5 | 0.2 | setosa | |
5.2 | 3.4 | 1.4 | 0.2 | setosa | |
4.7 | 3.2 | 1.6 | 0.2 | setosa | |
4.8 | 3.1 | 1.6 | 0.2 | setosa | |
5.4 | 3.4 | 1.5 | 0.4 | setosa | |
5.2 | 4.1 | 1.5 | 0.1 | setosa | |
5.5 | 4.2 | 1.4 | 0.2 | setosa | |
4.9 | 3.1 | 1.5 | 0.2 | setosa | |
5.0 | 3.2 | 1.2 | 0.2 | setosa | |
5.5 | 3.5 | 1.3 | 0.2 | setosa | |
4.9 | 3.6 | 1.4 | 0.1 | setosa | |
4.4 | 3.0 | 1.3 | 0.2 | setosa | |
5.1 | 3.4 | 1.5 | 0.2 | setosa | |
5.0 | 3.5 | 1.3 | 0.3 | setosa | |
4.5 | 2.3 | 1.3 | 0.3 | setosa | |
4.4 | 3.2 | 1.3 | 0.2 | setosa | |
5.0 | 3.5 | 1.6 | 0.6 | setosa | |
5.1 | 3.8 | 1.9 | 0.4 | setosa | |
4.8 | 3.0 | 1.4 | 0.3 | setosa | |
5.1 | 3.8 | 1.6 | 0.2 | setosa | |
4.6 | 3.2 | 1.4 | 0.2 | setosa | |
5.3 | 3.7 | 1.5 | 0.2 | setosa | |
5.0 | 3.3 | 1.4 | 0.2 | setosa | |
7.0 | 3.2 | 4.7 | 1.4 | versicolor | |
6.4 | 3.2 | 4.5 | 1.5 | versicolor | |
6.9 | 3.1 | 4.9 | 1.5 | versicolor | |
5.5 | 2.3 | 4.0 | 1.3 | versicolor | |
6.5 | 2.8 | 4.6 | 1.5 | versicolor | |
5.7 | 2.8 | 4.5 | 1.3 | versicolor | |
6.3 | 3.3 | 4.7 | 1.6 | versicolor | |
4.9 | 2.4 | 3.3 | 1.0 | versicolor | |
6.6 | 2.9 | 4.6 | 1.3 | versicolor | |
5.2 | 2.7 | 3.9 | 1.4 | versicolor | |
5.0 | 2.0 | 3.5 | 1.0 | versicolor | |
5.9 | 3.0 | 4.2 | 1.5 | versicolor | |
6.0 | 2.2 | 4.0 | 1.0 | versicolor | |
6.1 | 2.9 | 4.7 | 1.4 | versicolor | |
5.6 | 2.9 | 3.6 | 1.3 | versicolor | |
6.7 | 3.1 | 4.4 | 1.4 | versicolor | |
5.6 | 3.0 | 4.5 | 1.5 | versicolor | |
5.8 | 2.7 | 4.1 | 1.0 | versicolor | |
6.2 | 2.2 | 4.5 | 1.5 | versicolor | |
5.6 | 2.5 | 3.9 | 1.1 | versicolor | |
5.9 | 3.2 | 4.8 | 1.8 | versicolor | |
6.1 | 2.8 | 4.0 | 1.3 | versicolor | |
6.3 | 2.5 | 4.9 | 1.5 | versicolor | |
6.1 | 2.8 | 4.7 | 1.2 | versicolor | |
6.4 | 2.9 | 4.3 | 1.3 | versicolor | |
6.6 | 3.0 | 4.4 | 1.4 | versicolor | |
6.8 | 2.8 | 4.8 | 1.4 | versicolor | |
6.7 | 3.0 | 5.0 | 1.7 | versicolor | |
6.0 | 2.9 | 4.5 | 1.5 | versicolor | |
5.7 | 2.6 | 3.5 | 1.0 | versicolor | |
5.5 | 2.4 | 3.8 | 1.1 | versicolor | |
5.5 | 2.4 | 3.7 | 1.0 | versicolor | |
5.8 | 2.7 | 3.9 | 1.2 | versicolor | |
6.0 | 2.7 | 5.1 | 1.6 | versicolor | |
5.4 | 3.0 | 4.5 | 1.5 | versicolor | |
6.0 | 3.4 | 4.5 | 1.6 | versicolor | |
6.7 | 3.1 | 4.7 | 1.5 | versicolor | |
6.3 | 2.3 | 4.4 | 1.3 | versicolor | |
5.6 | 3.0 | 4.1 | 1.3 | versicolor | |
5.5 | 2.5 | 4.0 | 1.3 | versicolor | |
5.5 | 2.6 | 4.4 | 1.2 | versicolor | |
6.1 | 3.0 | 4.6 | 1.4 | versicolor | |
5.8 | 2.6 | 4.0 | 1.2 | versicolor | |
5.0 | 2.3 | 3.3 | 1.0 | versicolor | |
5.6 | 2.7 | 4.2 | 1.3 | versicolor | |
5.7 | 3.0 | 4.2 | 1.2 | versicolor | |
5.7 | 2.9 | 4.2 | 1.3 | versicolor | |
6.2 | 2.9 | 4.3 | 1.3 | versicolor | |
5.1 | 2.5 | 3.0 | 1.1 | versicolor | |
5.7 | 2.8 | 4.1 | 1.3 | versicolor | |
6.3 | 3.3 | 6.0 | 2.5 | virginica | |
5.8 | 2.7 | 5.1 | 1.9 | virginica | |
7.1 | 3.0 | 5.9 | 2.1 | virginica | |
6.3 | 2.9 | 5.6 | 1.8 | virginica | |
6.5 | 3.0 | 5.8 | 2.2 | virginica | |
7.6 | 3.0 | 6.6 | 2.1 | virginica | |
4.9 | 2.5 | 4.5 | 1.7 | virginica | |
7.3 | 2.9 | 6.3 | 1.8 | virginica | |
6.7 | 2.5 | 5.8 | 1.8 | virginica | |
7.2 | 3.6 | 6.1 | 2.5 | virginica | |
6.5 | 3.2 | 5.1 | 2.0 | virginica | |
6.4 | 2.7 | 5.3 | 1.9 | virginica | |
6.8 | 3.0 | 5.5 | 2.1 | virginica | |
5.7 | 2.5 | 5.0 | 2.0 | virginica | |
5.8 | 2.8 | 5.1 | 2.4 | virginica | |
6.4 | 3.2 | 5.3 | 2.3 | virginica | |
6.5 | 3.0 | 5.5 | 1.8 | virginica | |
7.7 | 3.8 | 6.7 | 2.2 | virginica | |
7.7 | 2.6 | 6.9 | 2.3 | virginica | |
6.0 | 2.2 | 5.0 | 1.5 | virginica | |
6.9 | 3.2 | 5.7 | 2.3 | virginica | |
5.6 | 2.8 | 4.9 | 2.0 | virginica | |
7.7 | 2.8 | 6.7 | 2.0 | virginica | |
6.3 | 2.7 | 4.9 | 1.8 | virginica | |
6.7 | 3.3 | 5.7 | 2.1 | virginica | |
7.2 | 3.2 | 6.0 | 1.8 | virginica | |
6.2 | 2.8 | 4.8 | 1.8 | virginica | |
6.1 | 3.0 | 4.9 | 1.8 | virginica | |
6.4 | 2.8 | 5.6 | 2.1 | virginica | |
7.2 | 3.0 | 5.8 | 1.6 | virginica | |
7.4 | 2.8 | 6.1 | 1.9 | virginica | |
7.9 | 3.8 | 6.4 | 2.0 | virginica | |
6.4 | 2.8 | 5.6 | 2.2 | virginica | |
6.3 | 2.8 | 5.1 | 1.5 | virginica | |
6.1 | 2.6 | 5.6 | 1.4 | virginica | |
7.7 | 3.0 | 6.1 | 2.3 | virginica | |
6.3 | 3.4 | 5.6 | 2.4 | virginica | |
6.4 | 3.1 | 5.5 | 1.8 | virginica | |
6.0 | 3.0 | 4.8 | 1.8 | virginica | |
6.9 | 3.1 | 5.4 | 2.1 | virginica | |
6.7 | 3.1 | 5.6 | 2.4 | virginica | |
6.9 | 3.1 | 5.1 | 2.3 | virginica | |
5.8 | 2.7 | 5.1 | 1.9 | virginica | |
6.8 | 3.2 | 5.9 | 2.3 | virginica | |
6.7 | 3.3 | 5.7 | 2.5 | virginica | |
6.7 | 3.0 | 5.2 | 2.3 | virginica | |
6.3 | 2.5 | 5.0 | 1.9 | virginica | |
6.5 | 3.0 | 5.2 | 2.0 | virginica | |
6.2 | 3.4 | 5.4 | 2.3 | virginica | |
5.9 | 3.0 | 5.1 | 1.8 | virginica |
<!-- | |
A reactive scatter plot using model.js. | |
Curran Kelleher 4/17/2014 | |
Updated with new CDN link and posted to bl.ocks.org 9/10/2015. | |
--> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="styles.css"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script src="http://curran.github.io/model/cdn/model-v0.2.4.js"></script> | |
<script src="scatterPlot.js"></script> | |
</head> | |
<body> | |
<div id="scatterPlotContainer"></div> | |
<script src="main.js"></script> | |
</body> | |
</html> |
// The main program that runs the scatter plot. | |
// It periodically updates various aspects of the chart | |
// with random values, to illustrate that the chart | |
// is dynamic and reacts to changes in its model. | |
// | |
// Curran Kelleher 4/17/2014 | |
// Revived 9/10/2015 | |
var div = document.getElementById("scatterPlotContainer"), | |
scatterPlot = ScatterPlot(); | |
div.appendChild(scatterPlot.el); | |
d3.json("configuration.json", function (config) { | |
scatterPlot.set(config); | |
}); | |
d3.tsv("data.tsv", function (d) { | |
d.sepalLength = +d.sepalLength; | |
d.sepalWidth = +d.sepalWidth; | |
return d; | |
}, function(error, data) { | |
// Set size once to initialize | |
setSizeFromDiv(); | |
// Set size on resize | |
window.addEventListener("resize", setSizeFromDiv); | |
// Set the data | |
scatterPlot.data = data; | |
// Reset data each second | |
setInterval(function () { | |
// Include each element with a 10% chance. | |
var randomSample = data.filter(function(d){ | |
return Math.random() < 0.1; | |
}); | |
scatterPlot.data = randomSample; | |
}, 1000); | |
// Randomly change the margin every 1.7 seconds. | |
function random(){ return Math.random() * 100; } | |
setInterval(function () { | |
scatterPlot.margin = { | |
top: random(), | |
right: random(), | |
bottom: random(), | |
left: random() | |
}; | |
}, 1700); | |
// Change the Y axis label every 600 ms. | |
function randomString() { | |
var possibilities = ["Frequency", "Population", "Alpha", "Beta"], | |
i = Math.round(Math.random() * possibilities.length); | |
return possibilities[i]; | |
} | |
setInterval(function () { | |
scatterPlot.yLabel = randomString(); | |
}, 600); | |
}); | |
function setSizeFromDiv(){ | |
scatterPlot.size = { | |
width: div.clientWidth, | |
height: div.clientHeight | |
}; | |
} |
// An adaptation of the [D3 scatter plot example](http://bl.ocks.org/mbostock/3887118) | |
// that uses `model.js`. This version, unlike the original example, | |
// is model driven and reactive. When a part of the model updates, | |
// only the parts of the visualization that depend on those parts | |
// of the model are updated. There are no redundant calls to visualization | |
// update code when multiple properties are changed simultaneously. | |
function ScatterPlot(){ | |
var x = d3.scale.linear(), | |
y = d3.scale.linear(), | |
xAxis = d3.svg.axis().scale(x).orient("bottom"), | |
yAxis = d3.svg.axis().scale(y).orient("left"), | |
div = document.createElement("div"), | |
svg = d3.select(div).append("svg"), | |
g = svg.append("g"), | |
xAxisG = g.append("g").attr("class", "x axis"), | |
yAxisG = g.append("g").attr("class", "y axis"), | |
xAxisLabel = yAxisG.append("text") | |
.attr("class", "label") | |
.attr("y", -6) | |
.style("text-anchor", "end"), | |
yAxisLabel = yAxisG.append("text") | |
.attr("class", "label") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end"), | |
model = new Model(); | |
model.el = div; | |
model.when("xLabel", xAxisLabel.text, yAxisLabel); | |
model.when("yLabel", yAxisLabel.text, yAxisLabel); | |
model.when("margin", function (margin) { | |
g.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
}); | |
model.when("size", function (size) { | |
svg.attr("width", size.width) | |
.attr("height", size.height); | |
}); | |
model.when(["size", "margin"], function (size, margin) { | |
model.width = size.width - margin.left - margin.right; | |
model.height = size.height - margin.top - margin.bottom; | |
}); | |
model.when("width", function (width) { | |
xAxisLabel.attr("x", width); | |
}); | |
model.when("height", function (height) { | |
xAxisG.attr("transform", "translate(0," + height + ")"); | |
}); | |
model.when(["width", "height", "data", "xField", "yField"], function (width, height, data, xField, yField) { | |
var dots; | |
x.domain(d3.extent(data, function(d) { return d[xField]; })).nice(); | |
y.domain(d3.extent(data, function(d) { return d[yField]; })).nice(); | |
x.range([0, width]); | |
y.range([height, 0]); | |
xAxisG.call(xAxis); | |
yAxisG.call(yAxis); | |
dots = g.selectAll(".dot").data(data); | |
dots.enter().append("circle") | |
.attr("class", "dot") | |
.attr("r", 3.5); | |
dots | |
.attr("cx", function(d) { return x(d[xField]); }) | |
.attr("cy", function(d) { return y(d[yField]); }); | |
dots.exit().remove(); | |
}); | |
return model; | |
} |
/* Size the visualization container. */ | |
#scatterPlotContainer { | |
position: fixed; | |
top: 30px; | |
bottom: 30px; | |
left: 30px; | |
right: 30px; | |
} | |
/* Style the visualization. | |
* This CSS is copied verbatim from the | |
* D3 scatter plot example found at | |
* http://bl.ocks.org/mbostock/3887118 */ | |
body { | |
font: 12px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.dot { | |
stroke: #000; | |
} |