Published
Edited
May 26, 2020
1 fork
5 stars
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const x = d3.scaleLinear().rangeRound([0, width]);
const y = d3.scaleLinear().rangeRound([0, height]);

const svg = d3.create("svg")
.attr("viewBox", [0.5, -30.5, width, height + 30])
.style("font", "10px sans-serif");

let group = svg.append("g")
.call(render, treemap(dataToHierarchy()));

function render(group, root) {
const node = group
.selectAll("g")
.data(root.children.concat(root))
.join("g");

node.filter(d => d === root ? d.parent : d.children)
.attr("cursor", "pointer")
.on("click", d => d === root ? zoomout(root) : zoomin(d));

node.append("title")
.text(d => `${name(d)}\n${format(d.value)}`);

node.append("rect")
.attr("id", d => (d.leafUid = DOM.uid("leaf")).id)
.attr("fill", d => color(d.data.name))
.attr("stroke", "#fff");

node.append("clipPath")
.attr("id", d => (d.clipUid = DOM.uid("clip")).id)
.append("use")
.attr("xlink:href", d => d.leafUid.href);

node.append("text")
.attr("clip-path", d => d.clipUid)
.attr("font-weight", d => d === root ? "bold" : null)
.selectAll("tspan")
.data(d => (d === root ? name(d) : d.data.name).split(/(?=[A-Z][^A-Z])/g).concat(format(d.value)))
.join("tspan")
.attr("x", 3)
.attr("y", (d, i, nodes) => `${(i === nodes.length - 1) * 0.3 + 1.1 + i * 0.9}em`)
.attr("fill-opacity", (d, i, nodes) => i === nodes.length - 1 ? 0.7 : null)
.attr("font-weight", (d, i, nodes) => i === nodes.length - 1 ? "normal" : null)
.text(d => d);

group.call(position, root);
}

function position(group, root) {
group.selectAll("g")
.attr("transform", d => d === root ? `translate(0,-30)` : `translate(${x(d.x0)},${y(d.y0)})`)
.select("rect")
.attr("width", d => d === root ? width : x(d.x1) - x(d.x0))
.attr("height", d => d === root ? 30 : y(d.y1) - y(d.y0));
}

// When zooming in, draw the new nodes on top, and fade them in.
function zoomin(d) {
const group0 = group.attr("pointer-events", "none");
const group1 = group = svg.append("g").call(render, d);

x.domain([d.x0, d.x1]);
y.domain([d.y0, d.y1]);

svg.transition()
.duration(750)
.call(t => group0.transition(t).remove()
.call(position, d.parent))
.call(t => group1.transition(t)
.attrTween("opacity", () => d3.interpolate(0, 1))
.call(position, d));
}

// When zooming out, draw the old nodes on top, and fade them out.
function zoomout(d) {
const group0 = group.attr("pointer-events", "none");
const group1 = group = svg.insert("g", "*").call(render, d.parent);

x.domain([d.parent.x0, d.parent.x1]);
y.domain([d.parent.y0, d.parent.y1]);

svg.transition()
.duration(750)
.call(t => group0.transition(t).remove()
.attrTween("opacity", () => d3.interpolate(1, 0))
.call(position, d))
.call(t => group1.transition(t)
.call(position, d.parent));
}

return svg.node();
}
Insert cell
treemap = data => d3.treemap()
.tile(tile)
(d3.hierarchy(data)
.sum(d => d.value)
.sort((a, b) => b.value - a.value))
Insert cell
Insert cell
function tile(node, x0, y0, x1, y1) {
d3.treemapBinary(node, 0, 0, width, height);
for (const child of node.children) {
child.x0 = x0 + child.x0 / width * (x1 - x0);
child.x1 = x0 + child.x1 / width * (x1 - x0);
child.y0 = y0 + child.y0 / height * (y1 - y0);
child.y1 = y0 + child.y1 / height * (y1 - y0);
}
}
Insert cell
list_of_ship = d3.csv(
'https://raw.githubusercontent.com/sharpsonmong/comp4462_data_visualization/master/equipment/wiki_list_of_ship.csv')
Insert cell
list_of_vehicle = d3.csv('https://raw.githubusercontent.com/sharpsonmong/comp4462_data_visualization/master/equipment/wiki_list_of_vehicles.csv')
Insert cell
list_of_aircraft = d3.csv('https://raw.githubusercontent.com/sharpsonmong/comp4462_data_visualization/master/equipment/wiki_operational_aircraft.csv')
Insert cell
list_of_weapon = d3.csv('https://raw.githubusercontent.com/sharpsonmong/comp4462_data_visualization/master/equipment/wiki_list_of_common_world_war_ii_infantry_weapons.csv')
Insert cell
dataToHierarchy()
Insert cell
function dataToHierarchy(){
var aix = ["Regia Marina", "Kriegsmarine", "Imperial Japanese Navy", "Romania", "Nazi Germany", "Germany",
"Japan", "Italy"]
var sideFilterS, sideFilterA, sideFilterV
switch(side){
case 'All':
sideFilterS = ''
sideFilterA = ''
sideFilterV = ''
break;
case 'allies':
sideFilterS = (v) => !_.includes(aix, v['Country or organization'])
sideFilterA = (v) => !_.includes(aix, v['Country of origin'])
sideFilterV = (v) => !_.includes(aix, v['Country'])
break;
case 'axis':
sideFilterS = (v) => _.includes(aix, v['Country or organization'])
sideFilterA = (v) => _.includes(aix, v['Country of origin'])
sideFilterV = (v) => _.includes(aix, v['Country'])
break;
}
var ship = _.chain(list_of_ship)
.filter(sideFilterS)
.groupBy('Country or organization')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Type')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Class')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Ship')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
, 'value': value.length }))
.value()}))
.value()}))
.value()}))
.value()
var aircraft =_.chain(list_of_aircraft)
.filter(sideFilterA)
.groupBy('Country of origin')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Categories')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Name of aircraft')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
, 'value': value.length }))
.value()
}))
.value()}))
.value()
var weapon =_.chain(list_of_weapon)
.filter(sideFilterV)
.groupBy('Country')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Type')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Weapon')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
, 'value': value.length }))
.value()}))
.value()}))
.value()
var vehicle = _.chain(list_of_vehicle)
.filter(sideFilterV)
.groupBy('Country')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Types')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
.groupBy('Name')
.map((value, key) => ({ 'name': key, 'children':_.chain(value)
, 'value': value.length }))
.value()}))
.value()}))
.value()

var temp= new Object
temp.name = ''
temp.children = vehicle
switch(equipment){
case 'ship':
temp.children = ship
break;
case 'aircraft':
temp.children = aircraft
break;
case 'vehicle':
temp.children = vehicle
break;
case 'weapon':
temp.children = weapon
break;
}
return temp;
}
Insert cell
_ = require('lodash')
Insert cell
color = d3.scaleOrdinal(d3.schemeSet3)
Insert cell
name = d => d.ancestors().reverse().map(d => d.data.name).join("/")
Insert cell
width = 954
Insert cell
height = 924
Insert cell
format = d3.format(",d")
Insert cell
d3 = require("d3@5")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more