Skip to content

Instantly share code, notes, and snippets.

@andydavies
Last active August 17, 2017 20:20
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 andydavies/23408e175720298c082dd1b72fc7399b to your computer and use it in GitHub Desktop.
Save andydavies/23408e175720298c082dd1b72fc7399b to your computer and use it in GitHub Desktop.
Sunburst Chart of Web Page composition / download size
license: cc-by-sa-4.0

Experiment to visualise page size data using Sunburst charts

Data was generated using WebPageTest and the raw CSV read directly from WPT

(can only cope with data from a single run ATM)

<html>
<head>
<style>
body {
font-family: sans-serif;
font-size: 12px;
font-weight: 400;
background-color: #fff;
width: 960px;
min-height: 700px;
margin-top: 10px;
}
#details {
min-height: 2em;
}
</style>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src=" https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head>
<body>
<div id="details">
Mouse over a segment
</div>
<div id="chart">
</div>
<script>
var csv = "https://www.webpagetest.org/result/170811_Z1_e9728d4262dc67429faa87a8aa80e729/170811_Z1_e9728d4262dc67429faa87a8aa80e729_news.bbc.co.uk_requests.csv";
var width = 500,
height = 500,
radius = (Math.min(width, height) / 2) - 10,
color = d3.scaleOrdinal(d3.schemeCategory10);
var x = d3.scaleLinear()
.range([0, 2 * Math.PI]);
var y = d3.scaleSqrt()
.range([0, radius]);
var formatNumber = d3.format(",d");
var arc = d3.arc()
.startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x0))); })
.endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x1))); })
.innerRadius(function(d) { return Math.max(0, y(d.y0)); })
.outerRadius(function(d) { return Math.max(0, y(d.y1)); });
var partition = d3.partition();
var nest = d3.nest()
.key(function(d) { return d.host; })
.key(function(d) { return d.type; });
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")");
d3.csv(csv, type, function(error, data) {
if (error) throw error;
var root = d3.hierarchy({values: nest.entries(data)}, function(d) { return d.values; })
.sum(function(d) { return d.size; });
root.sum(function(d) { return d.size; });
svg.selectAll("path")
.data(partition(root).descendants())
.enter().append("path")
.attr("display", function(d) { return d.depth ? null : "none"; }) // hide inner ring
.attr("d", arc)
.style("stroke", "#fff")
.style("fill", function(d) { return typeColors(d.data.type || d.data.key); })
.on("mouseover", mouseover )
.on("mouseleave", mouseleave )
.append("title")
.text(function(d) { return (d.data.url || d.data.key) + "\n" + formatNumber(d.value); });
});
function mouseover(d) {
var details = d3.select("#details")
.text((d.data.url || d.data.key) + " (" + formatNumber(d.value) + " bytes)");
}
function mouseleave(d) {
var details = d3.select("#details")
.text("");
}
function type(d) {
return {
host: d["Host"],
url: d["URL"],
type: normaliseType(d["Content Type"]),
size: d["Bytes In"]
}
}
/*
* Order entries by resource type and then size (descending)
*/
function orderEntries(a, b) {
var result = a.type.localeCompare(b.type);
if(result !== 0) {
return result;
}
else {
return b.size - a.size;
}
}
/*
* Convert mimetype into normalised value e.g. html, css, js etc.
*/
function normaliseType(type) {
switch(type.toLowerCase()) {
case "text/html":
return "html";
break;
case "text/css":
return "css";
break;
case "application/x-javascript":
case "application/javascript":
case "application/ecmascript":
case "text/javascript":
case "text/ecmascript":
return "js";
break;
case "application/font-woff":
case "font/woff2":
case "application/vnd.ms-fontobject ":
case "application/font-sfnt":
return "font";
break;
case "image/jpeg":
case "image/png":
case "image/gif":
case "image/webp":
case "image/svg+xml":
case "image/x-icon":
return "image";
break;
}
return "other";
}
/*
* Maps a colour to a content type
* Based on WebPageTest colours
*/
function typeColors(type) {
switch(type) {
case 'html':
return d3.rgb(130,181,252);
case 'css':
return d3.rgb(178,234,148);
case 'image':
return d3.rgb(196,154,232);
case 'js':
return d3.rgb(254,197,132);
case 'font':
return d3.rgb(255,82,62);
}
return d3.rgb(186,186,186);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment