Skip to content

Instantly share code, notes, and snippets.

@pierreelliott
Last active January 7, 2020 11:40
Show Gist options
  • Save pierreelliott/7fd4df774b16d42858bd7581bf410e34 to your computer and use it in GitHub Desktop.
Save pierreelliott/7fd4df774b16d42858bd7581bf410e34 to your computer and use it in GitHub Desktop.
Projet Dataviz - Simple visu 2
license: mit
{"categories": [{"cat_name": "Search", "sites": [{"total": 3085729, "session_length": 0.196933333333277, "data": {"text": {"html": {"val": 756083, "prop": 245}, "javascript": {"val": 2183083, "prop": 707}, "plain": {"val": 12389, "prop": 4}, "val": 2951555, "prop": 956, "type": "text"}, "application": {"javascript": {"val": 0, "prop": 0}, "binary": {"val": 17254, "prop": 5}, "json": {"val": 50103, "prop": 16}, "val": 67357, "prop": 21, "type": "application"}, "image": {"png": {"val": 66459, "prop": 21}, "webp": {"val": 0, "prop": 0}, "x-icon": {"val": 355, "prop": 0}, "val": 66814, "prop": 21, "type": "image"}, "others": {"val": 3, "prop": 2, "types": ["font", "x-unknown"], "type": "others"}}, "total_proportion": 1000, "array_data": [{"html": {"val": 756083, "prop": 245}, "javascript": {"val": 2183083, "prop": 707}, "plain": {"val": 12389, "prop": 4}, "val": 2951555, "prop": 956, "type": "text"}, {"javascript": {"val": 0, "prop": 0}, "binary": {"val": 17254, "prop": 5}, "json": {"val": 50103, "prop": 16}, "val": 67357, "prop": 21, "type": "application"}, {"png": {"val": 66459, "prop": 21}, "webp": {"val": 0, "prop": 0}, "x-icon": {"val": 355, "prop": 0}, "val": 66814, "prop": 21, "type": "image"}, {"val": 3, "prop": 2, "types": ["font", "x-unknown"], "type": "others"}], "website": "Google"}], "average": {"website": "Average Search website", "data": {"text": {"val": 2951555, "prop": 956}, "application": {"val": 67357, "prop": 21}, "image": {"val": 66814, "prop": 21}, "others": {"val": 3, "prop": 2}}, "total": 3085729, "total_proportion": 1000}}, {"cat_name": "Video", "sites": [{"total": 5386678, "session_length": 3.6858000000000857, "data": {"text": {"html": {"val": 119748, "prop": 22}, "plain": {"val": 123, "prop": 0}, "javascript": {"val": 389326, "prop": 72}, "css": {"val": 24046, "prop": 4}, "xml": {"val": 59, "prop": 0}, "val": 533302, "prop": 98, "type": "text"}, "image": {"jpeg": {"val": 81063, "prop": 15}, "webp": {"val": 915222, "prop": 169}, "gif": {"val": 1088, "prop": 0}, "x-icon": {"val": 0, "prop": 0}, "png": {"val": 24789, "prop": 4}, "val": 1022162, "prop": 188, "type": "image"}, "video": {"webm": {"val": 2363563, "prop": 438}, "x-flv": {"val": 37, "prop": 0}, "val": 2363600, "prop": 438, "type": "video"}, "audio": {"webm": {"val": 1400875, "prop": 260}, "val": 1400875, "prop": 260, "type": "audio"}, "others": {"val": 66739, "prop": 16, "types": ["font", "application", "x-unknown"], "type": "others"}}, "total_proportion": 1000, "array_data": [{"html": {"val": 119748, "prop": 22}, "plain": {"val": 123, "prop": 0}, "javascript": {"val": 389326, "prop": 72}, "css": {"val": 24046, "prop": 4}, "xml": {"val": 59, "prop": 0}, "val": 533302, "prop": 98, "type": "text"}, {"jpeg": {"val": 81063, "prop": 15}, "webp": {"val": 915222, "prop": 169}, "gif": {"val": 1088, "prop": 0}, "x-icon": {"val": 0, "prop": 0}, "png": {"val": 24789, "prop": 4}, "val": 1022162, "prop": 188, "type": "image"}, {"webm": {"val": 2363563, "prop": 438}, "x-flv": {"val": 37, "prop": 0}, "val": 2363600, "prop": 438, "type": "video"}, {"webm": {"val": 1400875, "prop": 260}, "val": 1400875, "prop": 260, "type": "audio"}, {"val": 66739, "prop": 16, "types": ["font", "application", "x-unknown"], "type": "others"}], "website": "YouTube"}, {"total": 7503932, "session_length": 3.712033333333352, "data": {"image": {"jpeg": {"val": 75056, "prop": 10}, "gif": {"val": 9356, "prop": 1}, "png": {"val": 4602, "prop": 0}, "val": 89014, "prop": 11, "type": "image"}, "application": {"json": {"val": 38904, "prop": 5}, "javascript": {"val": 152058, "prop": 20}, "x-javascript": {"val": 33394, "prop": 4}, "vnd.apple.mpegurl": {"val": 5713, "prop": 0}, "x-gzip": {"val": 0, "prop": 0}, "val": 230069, "prop": 29, "type": "application"}, "video": {"mp2t": {"val": 6679158, "prop": 890}, "webm": {"val": 488788, "prop": 65}, "val": 7167946, "prop": 955, "type": "video"}, "others": {"val": 16903, "prop": 5, "types": ["text", "x-unknown"], "type": "others"}}, "total_proportion": 1000, "array_data": [{"jpeg": {"val": 75056, "prop": 10}, "gif": {"val": 9356, "prop": 1}, "png": {"val": 4602, "prop": 0}, "val": 89014, "prop": 11, "type": "image"}, {"json": {"val": 38904, "prop": 5}, "javascript": {"val": 152058, "prop": 20}, "x-javascript": {"val": 33394, "prop": 4}, "vnd.apple.mpegurl": {"val": 5713, "prop": 0}, "x-gzip": {"val": 0, "prop": 0}, "val": 230069, "prop": 29, "type": "application"}, {"mp2t": {"val": 6679158, "prop": 890}, "webm": {"val": 488788, "prop": 65}, "val": 7167946, "prop": 955, "type": "video"}, {"val": 16903, "prop": 5, "types": ["text", "x-unknown"], "type": "others"}], "website": "DailyMotion"}], "average": {"website": "Average Video website", "data": {"text": {"val": 266651, "prop": 41}, "image": {"val": 555588, "prop": 86}, "video": {"val": 4765773, "prop": 739}, "audio": {"val": 700437, "prop": 108}, "others": {"val": 41821, "prop": 9}, "application": {"val": 115034, "prop": 17}}, "total": 6445304, "total_proportion": 1000}}]}
{"categories": [{"cat_name": "Search", "sites": [{"total": 26730129, "session_length": 0.1433833333334178, "data": {"text": {"html": {"val": 4983005, "prop": 186}, "javascript": {"val": 14881339, "prop": 556}, "css": {"val": 959916, "prop": 35}, "plain": {"val": 81125, "prop": 3}, "val": 20905385, "prop": 780, "type": "text"}, "image": {"png": {"val": 2628541, "prop": 98}, "webp": {"val": 263175, "prop": 9}, "x-icon": {"val": 28769, "prop": 1}, "svg+xml": {"val": 30735, "prop": 1}, "jpeg": {"val": 2231486, "prop": 83}, "gif": {"val": 158254, "prop": 5}, "vnd.microsoft.icon": {"val": 0, "prop": 0}, "val": 5340960, "prop": 197, "type": "image"}, "font": {"woff2": {"val": 275701, "prop": 10}, "val": 275701, "prop": 10, "type": "font"}, "others": {"val": 208083, "prop": 13, "types": ["x-unknown", "application"], "type": "others"}}, "total_proportion": 1000, "array_data": [{"html": {"val": 4983005, "prop": 186}, "javascript": {"val": 14881339, "prop": 556}, "css": {"val": 959916, "prop": 35}, "plain": {"val": 81125, "prop": 3}, "val": 20905385, "prop": 780, "type": "text"}, {"png": {"val": 2628541, "prop": 98}, "webp": {"val": 263175, "prop": 9}, "x-icon": {"val": 28769, "prop": 1}, "svg+xml": {"val": 30735, "prop": 1}, "jpeg": {"val": 2231486, "prop": 83}, "gif": {"val": 158254, "prop": 5}, "vnd.microsoft.icon": {"val": 0, "prop": 0}, "val": 5340960, "prop": 197, "type": "image"}, {"woff2": {"val": 275701, "prop": 10}, "val": 275701, "prop": 10, "type": "font"}, {"val": 208083, "prop": 13, "types": ["x-unknown", "application"], "type": "others"}], "website": "Google"}], "average": {"website": "Average Search website", "data": {"text": {"val": 20905385, "prop": 782}, "image": {"val": 5340960, "prop": 199}, "font": {"val": 275701, "prop": 10}, "others": {"val": 208083, "prop": 9}}, "total": 26730129, "total_proportion": 1000}}]}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" crossorigin="anonymous"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.back-grey { background-color: grey; }
svg { background-color: pink}
.hidden {
display: none;
}
div.tooltip {
color: #222;
background-color: #fff;
padding: .5em;
text-shadow: #f5f5f5 0 1px 0;
border-radius: 2px;
opacity: 0.9;
position: absolute;
}
#my_dataviz {
width: 500px
}
</style>
</head>
<body>
<div id="my_dataviz" class="back-grey"></div>
<script>
// Bind MIME types to readable types (HTML, Scripts, Images, ...)
var bindings = {
"text/html": "HTML",
"text/javascript": "script"
}
</script>
<script>
var margin = {top: 20, right: 30, bottom: 20, left: 50},
width = getSize(d3.select("#my_dataviz").style("width")) - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var bar = {height: 100, margin: 10};
var svg = d3.select("#my_dataviz")
.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})`);
var graph = svg;
d3.json("data.json").then(data => {
console.warn(data)
showSimpleConsumption(d3.select("#my_dataviz"), graph, data.categories[1].sites[0], data.categories[1])
});
function showSimpleConsumption(container, svg, site, category) {
console.log("Site:",site)
console.log("Average:",category.average)
console.log("Svg:", svg)
var tooltip = container.append('div')
.attr('class', 'hidden tooltip');
var color = d3.scaleQuantize() .range(["#93c3df","#6daed5","#4b97c9","#2f7ebc","#1864aa","#0a4a90","#08306b"])
.domain([0, Object.keys(site.data).length]);
const sorting = (x,y) => d3.descending(x.prop, y.prop);
var data = [formatData(site), formatData(category.average)];
console.log("data", data)
var max = d3.max([site, category.average], e => e.total)
var x = d3.scaleLinear()
.range([0, width])
.domain([0, max]);
svg.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", (d,i) => `translate(0, ${(bar.height+bar.margin)*i})`)
.each((d,i,n) => siteDataStack(n[i], d))
svg.append("g")
.attr("class", "y_axis")
.attr("transform", `translate(0,0)`)
.call(d3.axisLeft(d3.scaleBand()
.domain(["Mon site"])))
function siteDataStack(svgElem, site) {
var stack = createStack()
d3.select(svgElem)
.selectAll("rect")
.data(site)
.enter()
.append("rect")
.attr("class", "data")
.attr("height", 100)
.attr("fill", (d,i) => color(i))
.attr("width", (d) => {
// console.warn(d.val)
// console.log("width scaled:", x(d.val))
return x(d.val);
})
.attr("x", (d, i, arr) => {
return stack(x(d.val))
})
.attr("y", 0)
.on("mouseover", function(d) {
var elem = d3.select(this);
elem.style("fill", d3.rgb(elem.style("fill")).darker(0.5));
})
.on('mousemove', function(d) {
// on recupere la position de la souris
var mousePos = d3.mouse(this);
// on affiche le toolip
var subtypes = Object.keys(d)
.filter(e => typeof d[e] === "object" && !Array.isArray(d[e]))
subtypes = subtypes.map(s => formatSubtype(s, d[s].val));
if(d.type === "others") subtypes = d.types
tooltip.classed('hidden', false)
.attr("transform", svgElem.transform)
// on positionne le tooltip en fonction de la position de la souris
.attr('style', 'left:' + (mousePos[0] + 15) +
'px; top:' + (mousePos[1] - 35) + 'px')
// on affiche le nom de l'etat et sa valeur (ou un message d'erreur)
.html(`${d.type} (${subtypes ? subtypes.join(", "): ""})`);
})
.on('mouseout', function() {
// on cache le tooltip
tooltip.classed('hidden', true);
var elem = d3.select(this);
elem.style("fill", d3.rgb(elem.style("fill")).brighter(0.5));
});
}
}
function createStack() {
var items = [];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
return function(item) {
let totalProportion = items.length > 0 ? items.reduce(reducer): 0;
items.push(item)
return totalProportion;
}
}
function formatData(site) {
return Object.entries(site.data).map(e => {
e[1]["type"] = e[0];
return e[1];
})
}
function formatSubtype(subtype, subtypeSize) {
let cpt = 0, size = ["o", "Ko", "Mo", "Go"], val = subtypeSize;
while(cpt < size.length && val > 1e3) {
val = val/1e3; cpt++;
}
return `${subtype}: ${val.toFixed(2)} ${size[cpt]}`
}
function getSize(width) {
let w = width, max = width.length;
while(max > 0 && isNaN(w = w.slice(0, -1))) {
max--;
}
return +w;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment