Built with blockbuilder.org
xxxxxxxxxx
<meta charset="utf-8">
<style>
.node {
cursor: pointer;
}
.node:hover {
stroke: #000;
stroke-width: 1.5px;
}
.node--leaf {
fill: white;
}
.label {
font: 14px "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;
}
.slider-wrapper {
display: inline-block;
width: 1000px;
padding: 0;
}
.slider-wrapper input {
width: 500px;
height: 20px;
margin: 0;
}
#tooltip {
position: absolute;
width: 150;
height: auto;
padding: 10px;
background-color: white;
opacity: 1.0;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
border: 1px solid black;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
.title {
margin: 0;
font-family: sans-serif;
font-weight: bold;
font-size: 12px;
line-height: 20px;
}
.value {
margin: 0;
font-family: sans-serif;
font-size: 12px;
line-height: 20px;
}
#dropdown {
margin-bottom: 20px;
margin-right: 35px;
}
</style>
<div class="slider-wrapper">
<input type="range" min="0" id="slider1">
<label id="rangeText" />
</div>
<!-- dropdown -->
<select id="dropdown"></select>
<svg width="960" height="960"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3-queue/3.0.4/d3-queue.min.js"></script>
<script>
// Feel free to change or delete any of the code you see in this editor!
var datetimearr = [];
var datearr = [];
var flarepatharr = [];
// var data = [];
var data = {};
// Load data and let's do it.
d3.csv("datetime.csv", function(error, datetime) {
// Date slider stuff
var dates = [];
datetime.map(function(d) {
if (d.Time != '') datetimearr.push(d.Time);
dates.push(d.Time.split(' ')[0]);
});
dates = dates.filter((v, i, a) => a.indexOf(v) === i); //Unique dates
dates.map(function(x) {
datearr.push({
key: "date",
value: x
});
});
d3.select("#dropdown")
.selectAll("option")
.data(datearr)
.enter()
.append("option")
.attr("value", function(option) {
return option.value;
})
.text(function(option) {
return option.value;
});
// Dynamic data file name reading stuff
for (var i = 0; i < datetime.length; i++) {
flarepatharr.push("flare " + datetime[i].Time.replace(/\:/g, '') + ".json")
}
var q = d3.queue();
for (var i = 0; i < 2; i++) {
q.defer(d3.json, flarepatharr[i]);
}
q.awaitAll(function(error, results) {
if (error) throw error;
for (var i = 0; i < results.length; i++) {
data[datetime[i].Time] = results[i];
}
draw(data[datetimearr[0]]);
});
});
$(function() {
$('#slider1').attr('max', datetimearr.length - 1);
$('#slider1').attr('value', datetimearr.length - 1);
// on page load, set the text of the label based the value of the range
$('#rangeText').text(datetimearr[$('#slider1').val()]);
// setup an event handler to set the text when the range value is dragged (see event for input) or changed (see event for change)
$('#slider1').on('input change', function() {
$('#rangeText').text(datetimearr[$(this).val()]);
});
});
var svg = d3.select("svg"),
margin = 20,
diameter = +svg.attr("width"),
g = svg.append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
var color = d3.scaleLinear()
.domain([-1, 5])
.range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
.interpolate(d3.interpolateHcl);
var pack = d3.pack()
.size([diameter - margin, diameter - margin])
.padding(2);
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.attr("id", "tooltip");
var tooltiptitle = d3.select("#tooltip")
.append("p")
.attr("class", "title");
var tooltipvalue = d3.select("#tooltip")
.append("p")
.attr("class", "value");
var rangetext = d3.select('#rangeText');
var slider = d3.select('#slider1');
slider
.on('input change', function() {
draw(data[datetimearr[this.value]]);
})
// do the svg append stuff outside with empty stuff
// to reference https://jsfiddle.net/VividD/WDCpq/8/
function draw(root) {
root = d3.hierarchy(root)
.sum(function(d) {
return d.size;
})
.sort(function(a, b) {
return b.value - a.value;
});
root.each(d => d.value = +d.data.size).sort(function(a, b) {
return b.value - a.value;
});
var focus = root,
nodes = pack(root).descendants(),
view;
var circle = g.selectAll("circle")
.data(nodes, function(d) {
return d.data.name; //<-- add a key function to uniquely identify a node
});
circle
.transition()
.duration(1000)
// .attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; })
.attr("r", function(d) {
return d.r;
});
circle.exit().transition()
.duration(1000)
.attr("r", function(d) {
return 0;
})
.remove(); //<-- those nodes leaving
circle = circle.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) zoom(d), d3.event.stopPropagation();
})
.on("mouseover", function(d) {
tooltip
.style("visibility", "visible");
tooltiptitle
.text(concatname(d));
tooltipvalue
.text("Customer Count: " + d.data.CustCount);
})
.on("mousemove", function() {
return tooltip
.style("top", (event.pageY - 10) + "px")
.style("left", (event.pageX + 10) + "px");
})
.on("mouseout", function() {
return tooltip.style("visibility", "hidden");
})
// .merge(circle)
.transition()
.duration(1000); //<-- those entering and updating
function concatname(d) {
return d.parent ? d.parent.data.name == 'flare' ? d.data.name : concatname(d.parent) + ':' + d.data.name : d.data.name;
}
var text = g.selectAll("text")
.data(nodes)
.enter().append("text")
.attr("class", "label")
.attr("dy", -7)
.style("fill-opacity", function(d) {
return d.parent === root ? 1 : 0;
})
.style("display", function(d) {
return d.parent === root ? "inline" : "none";
})
.style('text-anchor', 'middle')
.text(function(d) {
return d.data.name;
});
var node = g.selectAll("circle,text,text2");
svg
.style("background", color(-1))
.on("click", function() {
zoom(root);
});
zoomTo([root.x, root.y, root.r * 2 + margin]);
function zoom(d) {
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));
};
});
transition.selectAll("text")
.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) {
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) {
return d.r * k;
});
}
function sumChildren(node) {
node.size = node.children.reduce(function(r, v) {
return r + (v.children ? sumChildren(v) : v.data.size);
}, 0);
//return node.size;
return 0;
}
}
</script>
https://d3js.org/d3.v4.min.js
https://code.jquery.com/jquery-3.3.1.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-queue/3.0.4/d3-queue.min.js