project
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta charset="utf-8">
<style>
svg {
width: 500px;
height: 500px;
border: 1px solid gray;
float: left;
}
.background {
fill: #4B9E9E;
fill-opacity: 0.1;
}
.extent {
fill: #78C5C5;
fill-opacity: 0.4;
}
.resize rect {
fill: #276C86;
}
#table {
width: 400px;
float:left;
}
</style>
</head>
<body>
<svg>
</svg>
<div id="table">
<table>
</table>
</div>
<script src="//d3js.org/d3.v3.js"></script>
<script src="table.js"></script>
<script src="scatter.js"></script>
<script>
d3.json("data.json", function(err, data){
var posts = data.data.children;
//console.log(posts);
var topPadding = 40;
var leftPadding = 60;
var svg = d3.select("svg")
var g = svg.append("g")
.attr("transform", "translate(" + [leftPadding, topPadding ]+")")
var scatter = Scatter();
scatter.data(posts)
scatter(g);
var div = d3.select("#table table");
var table = Table()
.data(posts)
table(div);
scatter.on("filter", function(filtered) {
console.log("filter event", filtered)
table.data(filtered);
table(div);
})
table.on("hover", function(data) {
console.log("hovered", data);
scatter.highlight(data)
})
})
</script>
</body></html>
function Scatter() {
var data;
var dispatch = d3.dispatch(chart, "filter");
var container;
function chart(g) {
container = g;
var chartHeight = 400;
var chartWidth = 400;
var xfield = function(d) {
return d.data.downs;
}
var yfield = function(d) {
return d.data.ups;
}
var yScale = d3.scale.linear()
.domain([0, d3.max(data, yfield)])
.range([0, chartHeight])
var xScale = d3.scale.linear()
.domain([0, d3.max(data, xfield)])
.range([0, chartWidth])
var colorScale = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.data.downs })])
.range(["#17D84D", "#FF1D1D"])
.interpolate(d3.interpolateHsl)
var circles = g
.selectAll("circle")
.data(data)
circles.enter().append("circle")
circles.attr({
cx: function(d,i) { return xScale(xfield(d)); },
cy: function(d) { return chartHeight - yScale(yfield(d))},
fill: function(d) { return colorScale(d.data.downs) },
r: 8,
stroke: "#000",
"fill-opacity": 0.5
})
.on("click", function(d) {
console.log(d.data);
})
yScale.range([chartHeight, 0])
var yaxis = d3.svg.axis()
.scale(yScale)
.orient("left") //left, right, top
.ticks(4) //best guess
var yg = g.append("g")
yaxis(yg)
//yg.attr("transform", "translate(" + [leftPadding, topPadding] + ")")
yg.selectAll("path")
.style({ fill: "none", stroke: "#810808"})
yg.selectAll("line")
.style({ stroke: "#000"})
yg.selectAll(".tick text").attr("transform", "rotate(-26)")
var xaxis = d3.svg.axis()
.scale(xScale)
.orient("bottom") //left, right, top
.ticks(4) //best guess
var xg = g.append("g")
xaxis(xg)
xg.attr("transform", "translate(" + [0, chartHeight] + ")")
xg.selectAll("path")
.style({ fill: "none", stroke: "#810808"})
xg.selectAll("line")
.style({ stroke: "#000"})
xg.selectAll(".tick text").attr("transform", "rotate(-26)")
var brush = d3.svg.brush()
brush.x(xScale)
.y(yScale)
brush.on("brushend", brushHandler);
function brushHandler() {
//console.log(brush.extent())
var minext = brush.extent()[0];
var xmin = minext[0];
var ymin = minext[1];
var maxext = brush.extent()[1];
var xmax = maxext[0];
var ymax = maxext[1];
var filtered = data.filter(function(d) {
var x = xfield(d);
var y = yfield(d);
return x >= xmin
&& x <= xmax
&& y >= ymin
&& y <= ymax;
})
console.log("filtered", filtered, filtered.length)
g.selectAll("circle")
.style("stroke", "#000");
g.selectAll("circle")
.data(filtered, function(d) {
return d.data.id
})
.style("stroke", "#FFFFFF")
dispatch.filter(filtered)
}
brush.extent([
[
10000,
10000
],
[
20000,
20000
]
])
brushHandler();
var bg = g.append("g").classed("brush", true)
brush(bg)
//g.selectAll("rect").attr("height", 88)
bg.selectAll(".background")
.style({visibility: "visible"})
bg.selectAll(".extent")
.style({visibility: "visible"})
bg.selectAll(".resize rect")
.style({visibility: "visible"})
}
chart.data = function(_) {
if(!arguments.length) return data;
data = _;
return chart;
}
chart.highlight = function(data) {
container.selectAll("circle")
.style("stroke-width", 1)
.attr("r", 10)
.data(data, function(d) { return d.data.id })
.style("stroke-width", 10)
.attr("r", 20)
}
return d3.rebind(chart, dispatch, "on");
}
function Table() {
var data;
var dispatch = d3.dispatch(chart, "hover");
//var container;
function chart(div) {
//container = div;
var rows = div.selectAll("tr")
.data(data, function(d) { return d.data.id });
var rowsEnter = rows.enter()
.append("tr");
rowsEnter.append("td").text(function(d) {
return d.data.score
})
rowsEnter.append("td")
.append("a").attr("href", function(d) {
return d.data.url
})
.text(function(d) {
return d.data.title
})
rows.exit().remove();
rows.on("mouseover", function(d,i) {
dispatch.hover([d])
})
rows.on("mouseout", function(d,i) {
dispatch.hover([])
})
}
chart.data = function(_) {
if(!arguments.length) return data;
data = _;
//if(container) chart(container);
return chart;
}
return d3.rebind(chart, dispatch, "on");
}