Built with blockbuilder.org
Extented from bl.ocks.org circle pack
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.node {
cursor: pointer;
}
.node:hover {
stroke: #000;
stroke-width: 1.5px;
}
.node--leaf {
fill: white;
}
.label {
font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
text-anchor: middle;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
}
.label,
.node--root,
.node--leaf {
pointer-events: none;
}
.alignleft {
float: left;
font-size: 16px;
margin:0px 25px;
}
.alignright {
float: right;
font-size: 16px;
margin:0px 25px;
}
</style>
</head>
<body>
<script>
d3.json("data.json", function(err, data) {
if(err){
console.error(err);
return;
}
function nestObj(obj,par){
for(var prop in obj){
if(typeof obj[prop] == "object"){
par.children.push(
{
name : prop,
children: []
}
);
nestObj(obj[prop],par.children[par.children.length-1]);
}else{
par.children.push(
{
name : prop,
size: obj[prop]
}
);
}
}
}
var newData = {
name:"products",
children:[]
};
nestObj(data.products,newData)
var svg = d3.select("body").append("svg")
.attr("width", 800)
.attr("height", 800)
var margin = 10,
width = +svg.attr("width") - margin - margin,
height = +svg.attr("height") - margin - margin;
//set size for rendering
var diameter = +svg.attr("width"),
g = svg.append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
//color for circle
var color = d3.scaleLinear()
.domain([-1, 15])
.range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
.interpolate(d3.interpolateHcl);
//color for bars
var colorBar = d3.scaleLinear()
.domain([-1, 7])
.range(["hsl(0, 100%, 50%)", "hsl(0, 100%, 80%)"])
.interpolate(d3.interpolateHcl);
//initiate circle pack
var pack = d3.pack()
.size([diameter - margin, diameter - margin])
.padding(2);
var root = newData;
root = d3.hierarchy(root)
.sum(function(d) {
return d.size;
});
var focus = root,
nodes = pack(root).descendants(),
view;
var circle = g.selectAll("circle")
.data(nodes.filter(function(d) {
return d.height > 0
}))
.enter().append("circle")
.attr("class", function(d) {
return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root";
})
.style("fill", function(d) {
return d.children ? color(d.depth) : null;
})
.on("click", function(d) {
if (focus !== d) {
if (d.children) {
zoom(d, this), d3.event.stopPropagation();
}
}
});
//platform to draw charts
var leaf = g.selectAll(".bars")
.data(nodes.filter(function(d) {
//get all leaf node data
return d.height == 1
}))
.enter()
.append("g")
.attr("id", (d) => d.parent.data.name + "_" + d.data.name)
.attr("height", function(d) {
return d.x + d.r
})
.attr("width", function(d) {
return d.y + d.r
})
.attr("class", "bars")
.each(function(d) {
drawBarData(this, this.__data__, d);
});
var text = g.selectAll(".label")
.data(nodes.filter(function(d) {
return d.height > 0
}))
.enter().append("text")
.attr("class", "label")
.style("fill-opacity", function(d) {
return d.parent === root ? 1 : 0;
})
.style("display", function(d) {
return d.parent === root ? "inline" : "none";
})
.text(function(d) {
return d.data.name;
});
var node = g.selectAll("circle,.bars,.label");
svg
.style("background", color(-1))
.on("click", function() {
zoom(root, this);
});
zoomTo([root.x, root.y, root.r * 2 + margin]);
function zoom(d, ele) {
var focus0 = focus;
focus = d;
var transition = d3.transition()
.duration(d3.event.altKey ? 7500 : 750)
.tween("zoom", function(d) {
var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
return function(t) {
zoomTo(i(t), focus, ele);
};
});
transition.selectAll(".label")
.filter(function(d) {
return d.parent === focus || this.style.display === "inline";
})
.style("fill-opacity", function(d) {
return d.parent === focus ? 1 : 0;
})
.on("start", function(d) {
if (d.parent === focus) this.style.display = "inline";
})
.on("end", function(d) {
if (d.parent !== focus) this.style.display = "none";
});
}
function zoomTo(v, focus, ele) {
var k = diameter / v[2];
view = v;
node.attr("transform", function(d) {
return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")";
});
circle.attr("r", function(d) {
if (d && d.height == 1) {
setTimeout(function() {
//reste bar charts
drawBarData("", d, d, d.r * k);
}, 0)
}
return d.r * k;
});
}
//ele : The g element
//data : data for which we need to draw chart
//d : high level pack data(just in case if we need)
//zoomRadius : Its used under condition when we zoom-in/zoom-out
function drawBarData(ele, data, d, zoomRadius) {
if (!data && !data.parent)
return;
var rectwidth = (zoomRadius) ? zoomRadius : d.r;
var rectheight = rectwidth;
var maxDataPoint = d3.max(data.data.children, function(d) {
return d.size
});
var linearScale = d3.scaleLinear()
.domain([0, maxDataPoint])
.range([0, rectheight]);
var x = d3.scaleBand()
.range([0, rectwidth])
.padding(0.1);
var y = d3.scaleLinear()
.range([rectheight, 0]);
// Scale the range of the data in the domains
x.domain(data.data.children.map(function(d) {
return d.name;
}));
y.domain([0, d3.max(data.data.children, function(d) {
return d.size;
})]);
d3.select("#" + data.parent.data.name + "_" + data.data.name).html("");
var bg = d3.select("#" + data.parent.data.name + "_" + data.data.name).append("g")
.attr("class", "chart-wrapper")
.attr("transform", function(d) {
return "translate(" + -rectwidth / 2 + "," + -rectwidth / 2 + ")";
});
bg.selectAll(".bar")
.data(data.data.children)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.name);
})
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.size);
})
.attr("height", function(d) {
return rectheight - y(d.size);
})
.attr("fill", (d, i) => colorBar(i))
.append("svg:title")
.text((d) => d.name + ' : sold pieces ' + d.size)
//just a safe check to render axis only if we have space
if (rectheight > 100) {
bg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + rectheight + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("y", 0)
.attr("x", -10)
.attr("dy", ".35em")
.attr("transform", "rotate(-90)")
.style("text-anchor", "end");
bg.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y))
}
}
})
</script>
</body>
https://d3js.org/d3.v4.min.js