|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta http-equiv="Content-Type" content="charset=utf-8"/> |
|
<style type="text/css"> |
|
body { |
|
font: 10px sans-serif; |
|
} |
|
|
|
.background path { |
|
fill: none; |
|
stroke: #ccc; |
|
stroke-opacity: .4; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.brush .extent { |
|
fill: #000; |
|
fill-opacity: .2; |
|
stroke: #666; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.axis line, .axis path { |
|
fill: none; |
|
stroke: #AAA; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
#firstChild .axis .tick { |
|
display: none; |
|
} |
|
</style> |
|
<title></title> |
|
</head> |
|
<body> |
|
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> |
|
<script src="//d3js.org/queue.v1.min.js" charset="utf-8"></script> |
|
<script> |
|
|
|
/* -------------------- |
|
Variables |
|
-------------------- */ |
|
var margin = {top: 65, right: 30, bottom: 10, left: 300}, |
|
width = 1200 - margin.left - margin.right, |
|
height = 900 - margin.top - margin.bottom; |
|
|
|
var x = d3.scale.ordinal().rangePoints([0, width], 1), |
|
y = {}, |
|
dragging = {}, |
|
background, |
|
foreground, |
|
letterground; |
|
|
|
var yposArray = new Array(); |
|
var lScale = d3.scale.linear().range([height, 0]); |
|
|
|
var line = d3.svg.line(); |
|
var axis = d3.svg.axis().orient("left"); |
|
|
|
|
|
/* -------------------- |
|
Color variables based |
|
on their logo colors |
|
-------------------- */ |
|
var providerArray = new Array(); |
|
//明治, 森永, 雪印メグミルク, 日本ルナ, オハヨー乳業, 小岩井乳業, メイトー, グリコ乳業 |
|
var colorArray = ["#ff0000", "#8d1231", "#0037ad", "#e60012", "#0275be", "#f7d000", "#e60012", "#f90f00"]; |
|
var colorScale = d3.scale.ordinal() |
|
.range( colorArray ); |
|
|
|
var svg = d3.select("body").append("svg:svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.append("svg:g") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
|
|
/* -------------------- |
|
Load external data |
|
-------------------- */ |
|
queue() |
|
.defer(d3.tsv, "yogurt.tsv") |
|
.await(loadReady); |
|
|
|
|
|
/* -------------------- |
|
Drawing |
|
-------------------- */ |
|
|
|
function loadReady(_error, _data) { |
|
|
|
/* make the list of provider */ |
|
for (var i=0; i<_data.length; i++) { |
|
providerArray[i] = _data[i]["provider"]; |
|
} |
|
colorScale.domain(d3.extent(providerArray)); |
|
|
|
/* delete providers from dataset */ |
|
for (var k=0; k<_data.length; k++) { |
|
delete _data[k]["provider"]; |
|
} |
|
|
|
/* make the list of dimensions */ |
|
x.domain(dimensions = d3.keys(_data[0]).filter(function(d) { |
|
return d != "name" && (y[d] = d3.scale.linear() |
|
.domain(d3.extent(_data, function(p) { return +p[d]; })) |
|
.range([height, 0])); |
|
})); |
|
|
|
/* scale position */ |
|
for (var j=0; j<_data.length; j++) { |
|
yposArray[j] = parseInt(_data[j]["indexid"]); |
|
} |
|
lScale.domain(d3.extent(yposArray)); |
|
|
|
/* lines for every data */ |
|
background = svg.append("svg:g") |
|
.attr("class", "background") |
|
.selectAll("path") |
|
.data(_data) |
|
.enter().append("svg:path") |
|
.attr("d", path); |
|
|
|
/* lines for filtered data */ |
|
foreground = svg.append("svg:g") |
|
.attr("class", "foreground") |
|
.selectAll("path") |
|
.data(_data) |
|
.enter().append("svg:path") |
|
.attr("stroke", function(d,i){ |
|
return colorScale( providerArray[i] ); |
|
}) |
|
.attr("stroke-opacity", 0.6) |
|
.attr("stroke-width", 0.3) |
|
.attr("fill", "none") |
|
.attr("d", path) |
|
.attr("id", function(d){ |
|
return d.name; |
|
}); |
|
|
|
/* list of the products */ |
|
letterground = svg.append("svg:g") |
|
.attr("class", "letterground") |
|
.selectAll(".letters") |
|
.data(_data) |
|
.enter().append("text") |
|
.attr("x", 20) |
|
.attr("y", function(d,i){ |
|
return lScale( d["indexid"] ); |
|
}) |
|
.attr("text-anchor", "end") |
|
.attr("font-family", "sans-serif") |
|
.attr("font-size", "10px") |
|
.text( function(d){ |
|
return d.name; |
|
}); |
|
|
|
/* Add a group element for each dimension. */ |
|
var g = svg.selectAll(".dimension") |
|
.data(dimensions) |
|
.enter().append("svg:g") |
|
.attr("class", "dimension") |
|
.attr("id", function(d,i) { |
|
if (i==0){ return "firstChild" }; |
|
}) |
|
.attr("transform", function(d) { return "translate(" + x(d) + ")"; }); |
|
|
|
/* 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", "start") |
|
.attr("font-family", "sans-serif") |
|
.attr("font-size", "9px") |
|
.attr("y", -9) |
|
.attr("transform", function(d) { |
|
return "rotate(-30)" |
|
}) |
|
.text(function(d,i) { |
|
if (i != 0) { return dimensions[i]; |
|
} else { return "";} |
|
}); |
|
|
|
/* Add and store a brush for each axis. */ |
|
g.append("svg:g") |
|
.attr("class", "brush") |
|
.each(function(d) { d3.select(this).call( y[d].brush = d3.svg.brush().y(y[d]).on("brush", brush)); }) |
|
.selectAll("rect") |
|
.attr("x", -8) |
|
.attr("width", 16); |
|
|
|
}; |
|
|
|
|
|
/* -------------------- |
|
functions |
|
-------------------- */ |
|
|
|
function position(d) { |
|
var v = dragging[d]; |
|
return v == null ? x(d) : v; |
|
} |
|
|
|
function transition(g) { |
|
return g.transition().duration(500); |
|
} |
|
|
|
function path(d) { |
|
return line( dimensions.map(function(p) { return [position(p), y[p](d[p])]; }) ); |
|
} |
|
|
|
function brush() { |
|
|
|
var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }), |
|
extents = actives.map(function(p) { return y[p].brush.extent(); }); |
|
|
|
foreground.style("display", function(d) { |
|
return actives.every(function(p, i) { |
|
return extents[i][0] <= d[p] && d[p] <= extents[i][1]; |
|
}) ? null : "none"; |
|
}); |
|
|
|
letterground.style("display", function(d) { |
|
return actives.every(function(p, i) { |
|
return extents[i][0] <= d[p] && d[p] <= extents[i][1]; |
|
}) ? null : "none"; |
|
}); |
|
|
|
} |
|
|
|
</script> |
|
</body> |
|
</html> |