This scatterplot was based on a movies dataset consisting of Movie Name, Revenue (in millions), Budget (in millions), ROI, Genre, and Rating. The plot shows the relationship between Revenue (x-axis) and Budget (on the y-axis), with visual encodings of ROI as size and Genre as color.
Detail on demand (the Movie name and exact Revenue and Budget amounts) is available by hovering over each circle.
Filtering is also available by clicking on a specific genre in the legend, so that only that genre is displayed. Clicking again on the genre will again display all genres.
Built with blockbuilder.org
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<h1 style="font-size:34px">Comparing Movie Budget vs. Revenue</h1>
<script src="https://d3js.org/d3.v3.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Raleway+Dots" rel="stylesheet">
</head>
<style>
body {
font: 12px "Raleway Dots";
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #FFF;
}
.tooltip {
position: absolute;
width: 200px;
height: 28px;
pointer-events: none;
}
</style>
<body>
<script>
// setup margins
var margin = {top: 20, right: 22, bottom: 30, left: 40},
width = 900 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// setup x
// returns the value to encode
var xValue = function(d) { return d.Revenue;},
// maps value to a visual display encoding, such as a pixel position
xScale = d3.scale.linear().range([0, width]),
// maps from data value to display value
xMap = function(d) { return xScale(xValue(d));},
//sets up axis
xAxis = d3.svg.axis().scale(xScale).orient("bottom");
// setup y
var yValue = function(d) { return d["Budget cost"];},
yScale = d3.scale.linear().range([height, 0]),
yMap = function(d) { return yScale(yValue(d));},
yAxis = d3.svg.axis().scale(yScale).orient("left");
// setup range for radius
var r = d3.scale.linear()
.range([7, 25]);
// setup fill color based on genre
var cValue = function(d) { return d.Genre;},
color = d3.scale.category10();
// add the graph canvas to the body of the webpage
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// set up tooltip
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//loading the data
d3.csv("movies.csv", function (error, data) {
// change string (from CSV) into number format
data.forEach(function(d) {
d.Revenue = +d.Revenue;
d["Budget cost"] = +d["Budget cost"];
d.ROI = +d.ROI;
// console.log(d);
});
// create domains for x, y, and radius
xScale.domain([d3.min(data, xValue)-1, d3.max(data, xValue)+1]);
yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]);
r.domain(d3.extent (data, function (d) {return d.ROI;}));
// create x-axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Revenue in millions");
// create y-axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Budget in millions");
// draw dots
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", function(d) {return r(d.ROI)})
.attr("cx", xMap)
.attr("cy", yMap)
.style("opacity", 0.8)
.style("fill", function(d) { return color(cValue(d));})
.on("mouseover", function(d) {
// on mouseout, use D3 to select element and double size
d3.select(this).attr({
r: function(d) {return r(d.ROI)*2}
});
//on mouseover, show tooltip by increasing opacity
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(d["Movie"] + "<br/> ($" + xValue(d)
+ ", $" + yValue(d) + ")")
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
// on mouseout, use D3 to select element and reduce size to normal
d3.select(this).attr({
r: function(d) {return r(d.ROI)}
});
// on mouseout, hide tooltip by setting opacity to 0
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
// setup clicked variable
var clicked = ""
// draw legend
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
// draw legend colored rectangles
legend.append("rect")
.attr("x", width - 18)
.attr("y", 20)
.attr("width", 18)
.attr("height", 18)
.style("fill", color)
.on("click",function(d){
d3.selectAll(".dot").style("opacity",0.8)
//filter genres on legend click
if (clicked !== d){
d3.selectAll(".dot")
.filter(function(e){
return e.Genre !== d;
})
.style("opacity",0.1)
clicked = d
}
else{
clicked = ""
}
});
// draw legend text
legend.append("text")
.attr("x", width - 24)
.attr("y", 30)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d;})
});
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js