Built with blockbuilder.org
forked from tomshanley's block: Makeover Monday - YouTube ratings
forked from tomshanley's block: Makeover Monday - YouTube ratings
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;top:0;right:0;bottom:0;left:0; font-family: sans-serif; }
.domain { display: none; }
.tick text { fill: #808080 }
.axis-label { fill: #808080; font-size: 12; }
.tick line { stroke: #808080; shape-rendering: crispEdges; }
.hull { stroke:#808080; stroke-width: 20; stroke-linejoin: round;}
.legend rect, .legend text { cursor: pointer; }
</style>
</head>
<body>
<select id="user"></select>
<div id="chart"></div>
<script>
var maxVideoViews;
var maxSubscribers;
var radius = 2;
var mutedOpacity = 0.05;
function formatBillions(d) {
var roundedNumber = Math.round(d/1000000000);
return roundedNumber + "bn";
};
function formatMillions(d) {
var roundedNumber = Math.round(d/1000000);
return roundedNumber + "m";
};
d3.csv("data.csv", convertTextToNumbers, function(error, data) {
if(error) { throw error; };
var dropDown = d3.select("#user").on("change", highlightUser);
dropDown.selectAll("option")
.data(data)
.enter()
.append("option")
.attr("value", function(d) { return d.User; })
.text(function(d) { return d.User; });
maxVideoViews = d3.max(data, function(d){ return d.VideoViews; });
maxSubscribers = d3.max(data, function(d){ return d.Subscribers; });
drawChart(data);
});
function highlightUser() {
var sel = document.getElementById('user');
var selectedUser = sel.options[sel.selectedIndex].value;
d3.selectAll("circle")
.style("opacity", function(d) { return d.User==selectedUser ? 1 : 0.2; })
.attr("r", function(d) { return d.User==selectedUser ? 5 : radius; });
};
function drawChart(data) {
var width = 800;
var height = width;
var margin = {"top": 50, "left": 50, "right": 150, "bottom": 50,}
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom);
var colorScale = d3.scaleOrdinal()
.domain(["A-plus", "A", "A-minus", "B-plus", "B", "B-minus", "C-and-D"])
.range(["#081d58", "#253494", "#225ea8", "#1d91c0", "#41b6c4", "#7fcdbb", "#c7e9b4"]);
var yScale = d3.scaleLinear()
.range([height, 0])
.domain([0,maxVideoViews]);
var yAxis = d3.axisLeft(yScale).tickFormat(formatBillions);
var xScale = d3.scaleLinear()
.range([0,width])
.domain([0,maxSubscribers]);
var xAxis = d3.axisBottom(xScale).tickFormat(formatMillions);
svg.append("g")
.attr("transform", "translate(" + (margin.left) + "," + (margin.top + height) + ")")
.call(xAxis);
svg.append("g")
.attr("transform", "translate(" + (margin.left) + "," + margin.top + ")")
.call(yAxis);
var g = svg.append("g")
.attr("transform", "translate(" + (margin.left) + "," + margin.top + ")");
g.append("text")
.text("Views (billions)")
.attr("class", "axis-label")
.attr("x", -margin.left/2)
.attr("y", yScale(maxVideoViews));
g.append("text")
.text("Subscribers (millons)")
.attr("class", "axis-label")
.attr("x", xScale(maxSubscribers))
.attr("y", yScale(200000000))
.style("text-anchor", "end");
var nestedData = d3.nest()
.key(function(d){ return d.Rating; })
.sortKeys(d3.ascending)
.entries(data);
nestedData.forEach(function(d) {
var ratingData = [];
d.values.forEach(function(d) {
ratingData.push([xScale(d.Subscribers),yScale(d.VideoViews)])
})
var hullData = ratingData.length == 2 ? ratingData : d3.polygonHull(ratingData);
var hull = g.append("path")
.attr("class", "hull")
.attr("id", "hull-" + d.key)
.datum(hullData)
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.style("fill", colorScale(d.key))
.style("stroke", colorScale(d.key))
.style("opacity", mutedOpacity);
});
var circles = g.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("class", "user-circle")
.attr("transform", function(d) { return "translate(" + xScale(d.Subscribers) + "," + yScale(d.VideoViews) +")"; });
circles.append("circle")
.attr("r", radius)
.attr("cx", 0)
.attr("cy", 0)
.style("fill", function(d) { return colorScale(d.Rating); })
.style("fill-opacity", 0.8 );
circles.append("text")
.text(function(d){ return d.User; })
.attr("class", "user-label")
.attr("x", 0)
.attr("y", -5)
.attr("text-anchor", "middle")
.style("visibility", function(d){
if (d.Rating == "A-plus" || d.Subscribers > 12000000 || d.VideoViews > 4000000000) {
return "inherit";
} else {
return "hidden";
};
});
d3.selectAll("circle")
.on("mouseover", function(d){
d3.select("#user").property('value', d.User);
highlightUser();
})
.on("mouseout", function(d){
d3.selectAll("circle").style("opacity", 0.7).attr("r", radius);
})
var legendBoxWidth = 20;
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + (margin.left + width) + "," + margin.top + ")");
legend.append("text")
.text("Ratings:")
.attr("x", 0)
.attr("y", -5);
legend.append("rect")
.attr("class", "legend-border")
.attr("x", -3)
.attr("y", -25)
.attr("width", margin.right - 50)
.attr("height", 180)
.style("fill", "none")
.style("stroke", "grey")
var legendEntries = legend.selectAll("g")
.data(["A-plus", "A", "A-minus", "B-plus", "B", "B-minus", "C-and-D"])
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + (i * (legendBoxWidth + 2)) + ")"; });
legendEntries.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", legendBoxWidth)
.attr("height", legendBoxWidth)
.attr("class", "legend-rect")
.attr("id", function(d) { return "legend-rect-" + d; })
.style("fill", function(d) { return colorScale(d); })
.style(
"opacity", mutedOpacity)
.on("click", showHideHull);
legendEntries.append("text")
.text(function(d) { return d; })
.attr("x", legendBoxWidth + 3)
.attr("y", legendBoxWidth - 3)
.on("click", showHideHull);
}
function convertTextToNumbers(d) {
d.Rank = +d.Rank;
d.Subscribers = +d.Subscribers;
d.VideoViews = +d.VideoViews;
return d;
};
function showHideHull(d) {
var hullID = "#hull-" + d;
var rectID = "#legend-rect-" + d;
var currentOpacity = d3.select(hullID).style("opacity");
//if (currentOpacity == 0) {
//selectedHullOpacity = 0.6;
//d3.select(hullID).style("opacity", selectedHullOpacity);
//d3.select(rectID).style("opacity", selectedHullOpacity);
//} else {
var selectedHullOpacity = currentOpacity == mutedOpacity ? 0.5 : mutedOpacity;
//var otherHullsOpacity = currentOpacity == mutedOpacity ? 0 : mutedOpacity;
//d3.selectAll(".hull").style("opacity", otherHullsOpacity);
d3.select(hullID).style("opacity", selectedHullOpacity);
//d3.selectAll(".legend-rect").style("opacity", otherHullsOpacity);
d3.select(rectID).style("opacity", selectedHullOpacity);
//};
}
</script>
</body>
https://d3js.org/d3.v4.min.js