Skip to content

Instantly share code, notes, and snippets.

@jensgrubert
Created January 7, 2014 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jensgrubert/8296876 to your computer and use it in GitHub Desktop.
Save jensgrubert/8296876 to your computer and use it in GitHub Desktop.
Positioning Technologies Parallel Coordinates
technologies Cost Accuracy Range Robustness User Number
WLANRSSI 1 1 1 1 4
Ultrasound 1 4 1 1 1
PulseRadar 3 3 2 2 3
FMCWRadar 3 3 3 3 3
Laser 4 4 4 2 1
RFID 1 1 0 2 3
<!DOCTYPE html>
<!-- based on http://mbostock.github.io/d3/talk/20111116/iris-parallel.html -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<link type="text/css" rel="stylesheet" href="style.css"/>
<style type="text/css">
svg {
font-size: 14px;
}
.foreground path {
fill: none;
stroke-opacity: .5;
stroke-width: 1.5px;
}
.foreground path.fade {
stroke: #000;
stroke-opacity: .05;
}
.legend {
font-size: 18px;
font-style: oblique;
}
.legend line {
stroke-width: 2px;
}
.WLANRSSI {
stroke: #800;
}
.Ultrasound {
stroke: #080;
}
.PulseRadar {
stroke: #008;
}
.FMCWRadar {
stroke: #808;
}
.Laser {
stroke: #088;
}
.RFID {
stroke: #000;
}
.brush .extent {
fill-opacity: .3;
stroke: #fff;
shape-rendering: crispEdges;
}
.axis line, .axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
text-shadow: 0 1px 0 #fff;
cursor: move;
}
</style>
</head>
<body>
<h2>
Positioning Technology Overview<br>
parallel coordinates
</h2>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="d3.v3.min.js"></script>
<script type="text/javascript">
var technologies = ["WLANRSSI", "Ultrasound", "PulseRadar", "FMCWRadar", "Laser", "RFID"];
var characteristics = ["Cost", "Accuracy", "Range", "Robustness", "User Number"];
var m = [80, 160, 100, 50],
w = 800 - m[1] - m[3],
h = 500 - m[0] - m[2];
var x = d3.scale.ordinal().domain(characteristics).rangePoints([0, w]),
y = {};
var line = d3.svg.line(),
axis = d3.svg.axis().orient("left"),
foreground;
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
d3.csv("data.csv", function(flowers) {
// Create a scale and brush for each characteristic.
characteristics.forEach(function(d) {
// Coerce values to numbers.
flowers.forEach(function(p) { p[d] = +p[d]; });
y[d] = d3.scale.linear()
.domain(d3.extent(flowers, function(p) { return p[d]; }))
.range([h, 0]);
y[d].brush = d3.svg.brush()
.y(y[d])
.on("brush", brush);
});
// Add a legend.
var legend = svg.selectAll("g.legend")
.data(technologies)
.enter().append("svg:g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate("+ (w + 30) +"," + (i * 20 + h/2) + ")"; });
legend.append("svg:line")
.attr("class", String)
.attr("x2", 8);
legend.append("svg:text")
.attr("x", 12)
.attr("dy", ".31em")
.text(function(d) { return d; });
// Add foreground lines.
foreground = svg.append("svg:g")
.attr("class", "foreground")
.selectAll("path")
.data(flowers)
.enter().append("svg:path")
.attr("d", path)
.attr("class", function(d) { return d.technologies; });
// Add a group element for each characteristic.
var g = svg.selectAll(".characteristic")
.data(characteristics)
.enter().append("svg:g")
.attr("class", "characteristic")
.attr("transform", function(d) { return "translate(" + x(d) + ")"; })
.call(d3.behavior.drag()
.origin(function(d) { return {x: x(d)}; })
.on("dragstart", dragstart)
.on("drag", drag)
.on("dragend", dragend));
// Add an axis and title.
g.append("svg:g")
.attr("class", "axis")
.each(function(d) { d3.select(this).call(axis.scale(y[d])); })
.append("svg:text")
.attr("text-anchor", "middle")
.attr("y", -9)
.text(String);
// Add a brush for each axis.
g.append("svg:g")
.attr("class", "brush")
.each(function(d) { d3.select(this).call(y[d].brush); })
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
function dragstart(d) {
i = characteristics.indexOf(d);
//console.log(i);
}
function drag(d) {
x.range()[i] = d3.event.x;
characteristics.sort(function(a, b) { return x(a) - x(b); });
g.attr("transform", function(d) { return "translate(" + x(d) + ")"; });
foreground.attr("d", path);
}
function dragend(d) {
x.domain(characteristics).rangePoints([0, w]);
var t = d3.transition().duration(500);
t.selectAll(".characteristic").attr("transform", function(d) { return "translate(" + x(d) + ")"; });
t.selectAll(".foreground path").attr("d", path);
}
});
// Returns the path for a given data point.
function path(d) {
return line(characteristics.map(function(p) { return [x(p), y[p](d[p])]; }));
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = characteristics.filter(function(p) { return !y[p].brush.empty(); }),
extents = actives.map(function(p) { return y[p].brush.extent(); });
foreground.classed("fade", function(d) {
return !actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
});
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment