D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
SJXdct
Full window
Github gist
Bilevel graph of 28 sites and their trackers
<!DOCTYPE html> <meta charset="utf-8"> <style> circle, path { cursor: pointer; } circle { fill: none; pointer-events: all; } </style> <body> <script src="https://d3js.org/d3.v3.min.js"></script> <script> var colors = { "haosou.com":"#CD2626", "xiaomi.com":"#CD2626", "bing.com":"#5687d1", "weibo.com":"#CD2626", "uber.com":"#5687d1", "xunlei.com":"#CD2626", "instagram.com":"#5687d1", "baidu.com":"#CD2626", "sohu.com":"#CD2626", "youku.com":"#CD2626", "taobao.com":"#CD2626", "meituan.com":"#CD2626", "qq.com":"#CD2626", "163.com":"#CD2626", "twitter.com":"#5687d1", "apple.com":"#5687d1", "sina.com.cn":"#CD2626", "toutiao.com":"#CD2626", "google.com":"#5687d1", "hao123.com":"#CD2626", "wandoujia.com":"#CD2626", "amazon.com":"#5687d1", "renren.com":"#CD2626", "alipay.com":"#CD2626", "10086.cn":"#CD2626", "tmall.com":"#CD2626", "yahoo.com":"#5687d1", "facebook.com":"#5687d1", "RU":"#6E8B3D", "FR":"#bbbbbb", "CN":"#CD2626", "CA":"#FFFF00", "DE":"#de783b", "JP":"#7b615c", "US":"#5687d1", "HK":"#B23AEE", "GB":"#E0FFFF", "Others":"#030303" }; var margin = {top: 350, right: 480, bottom: 350, left: 480}, radius = Math.min(margin.top, margin.right, margin.bottom, margin.left) - 10; var hue = d3.scale.category10(); var luminance = d3.scale.sqrt() .domain([0, 1e6]) .clamp(true) .range([90, 20]); var svg_ = d3.select("body").append("svg") .attr("width", margin.left + margin.right) .attr("height", margin.top + margin.bottom); var svg =svg_ .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var partition = d3.layout.partition() .sort(function(a, b) { return d3.ascending(a.name, b.name); }) .size([2 * Math.PI, radius]); var arc = d3.svg.arc() .startAngle(function(d) { return d.x; }) .endAngle(function(d) { return d.x + d.dx ; }) .padAngle(.01) .padRadius(radius / 3) .innerRadius(function(d) { return radius / 3 * d.depth; }) .outerRadius(function(d) { return radius / 3 * (d.depth + 1) - 1; }); d3.json("flare-top28.json", function(error, root) { if (error) throw error; //drawLegend(); //addLegend(); // Compute the initial layout on the entire tree to sum sizes. // Also compute the full name and fill color for each node, // and stash the children so they can be restored as we descend. partition .value(function(d) { return d.size; }) .nodes(root) .forEach(function(d) { d._children = d.children; d.sum = d.value; d.key = key(d); d.fill = fill(d); }); // Now redefine the value function to use the previously-computed sum. partition .children(function(d, depth) { return depth < 2 ? d._children : null; }) .value(function(d) { return d.sum; }); var center = svg.append("circle") .attr("r", radius / 3) .on("click", zoomOut); center.append("title") .text("zoom out"); var path = svg.selectAll("path") .data(partition.nodes(root).slice(1)) //.text("test!!!!!!") //.append("test!!!!!!") .enter().append("path") .attr("d", arc) //.style("fill", function(d) { return d.fill; }) .style("fill", function(d) { return colors[d.name]; }) .each(function(d) { this._current = updateArc(d); }) .on("click", zoomIn); var text = svg.selectAll("text") .data(partition.nodes(root).slice(1)) .enter() .append("text") /*.attr({ "x": function (d) { return arc.centroid(d)[0] }, "y": function (d) { return arc.centroid(d)[1] } })*/ //.attr("x", function(d) { return arc.centroid(d)[0] }) //.attr("y", function(d) { return arc.centroid(d)[1] }) //.attr("transform", "rotate(30)") .attr("transform", function(d) { return "rotate(" + (d.x + d.dx / 2 - Math.PI / 2) / Math.PI * 180 + ")"; }) .attr("x", function(d) { return Math.sqrt(d.y); }) .attr("dx", "120") // margin .attr("dy", ".35em") // vertical-align //.text(function(d) { return d.key; }); .text(function (d) { console.log(d); return d.depth == 1 ? d.name : ""; }) function zoomIn(p) { if (p.depth > 1) p = p.parent; if (!p.children) return; zoom(p, p); } function zoomOut(p) { if (!p.parent) return; zoom(p.parent, p); var text = svg.selectAll("text") .data(partition.nodes(root).slice(1)) .enter() .append("text") /*.attr({ "transform":function(d){ return "translate("+(arc.centroid(d)[0] +margin.left +","+(arc.centroid(d)[1]+margin.right)) } })*/ .attr("transform", function(d) { return "rotate(" + (d.x + d.dx / 2 - Math.PI / 2) / Math.PI * 180 + ")"; }) .attr("x", function(d) { return Math.sqrt(d.y); }) .attr("dx", "120") // margin .attr("dy", ".35em") // vertical-align .text(function(d){ return d.depth == 1 ? d.name : ""; }) } // Zoom to the specified new root. function zoom(root, p) { svg.selectAll("text").data([]).exit().remove() if (document.documentElement.__transition__) return; // Rescale outside angles to match the new layout. var enterArc, exitArc, outsideAngle = d3.scale.linear().domain([0, 2 * Math.PI]); function insideArc(d) { return p.key > d.key ? {depth: d.depth - 1, x: 0, dx: 0} : p.key < d.key ? {depth: d.depth - 1, x: 2 * Math.PI, dx: 0} : {depth: 0, x: 0, dx: 2 * Math.PI}; } function outsideArc(d) { return {depth: d.depth + 1, x: outsideAngle(d.x), dx: outsideAngle(d.x + d.dx) - outsideAngle(d.x)}; } center.datum(root); // When zooming in, arcs enter from the outside and exit to the inside. // Entering outside arcs start from the old layout. if (root === p) enterArc = outsideArc, exitArc = insideArc, outsideAngle.range([p.x, p.x + p.dx]); path = path.data(partition.nodes(root).slice(1), function(d) { return d.key; }); // When zooming out, arcs enter from the inside and exit to the outside. // Exiting outside arcs transition to the new layout. if (root !== p) enterArc = insideArc, exitArc = outsideArc, outsideAngle.range([p.x, p.x + p.dx]); d3.transition().duration(d3.event.altKey ? 7500 : 750).each(function() { path.exit().transition() .style("fill-opacity", function(d) { return d.depth === 1 + (root === p) ? 1 : 0; }) .attrTween("d", function(d) { return arcTween.call(this, exitArc(d)); }) .remove(); path.enter().append("path") .style("fill-opacity", function(d) { return d.depth === 2 - (root === p) ? 1 : 0; }) .style("fill", function(d) { return colors[d.name]; }) .on("click", zoomIn) //.text(function(d) { return d.data.key; }); .each(function(d) { this._current = enterArc(d); }); path.transition() .style("fill-opacity", 1) .attrTween("d", function(d) { return arcTween.call(this, updateArc(d)); }); }); } // ========== // = legend_lh = // ========== var legend_data = [ /*"RU", "FR", "NL", "CN", "VG", "CA", "DE", "JP", "US", "HK", "BE", "GB", "MY", "PL", "KR"*/ "US", "CN", "FR", "HK", "DE", "GB", "JP", "RU", "CA", "Others" ]; var legend_g = svg_.append("g").attr("transform","translate("+(margin.left + margin.right -100)+",20)"); var legend_rect = legend_g.selectAll("rect").data(legend_data); var legend_text = legend_g.selectAll("text").data(legend_data); legend_rect.enter().append("rect") .attr({ "x":0, "y":function (d,i) { return 10 * (i + 1) + (i * 20) }, "width":20, "height":20, "fill":function (d) { return colors[d]; } }); legend_text.enter().append("text") .attr({ "x":30, "y":function (d,i) { return 10 * (i + 1) + (i * 20) + 15 } }) .text(function (d) { return d; }); }); function key(d) { var k = [], p = d; while (p.depth) k.push(p.name), p = p.parent; return k.reverse().join("."); } function fill(d) { var p = d; while (p.depth > 1) p = p.parent; var c = d3.lab(hue(p.name)); c.l = luminance(d.sum); return c; } function arcTween(b) { var i = d3.interpolate(this._current, b); this._current = i(0); return function(t) { return arc(i(t)); }; } function updateArc(d) { return {depth: d.depth, x: d.x, dx: d.dx}; } d3.select(self.frameElement).style("height", margin.top + margin.bottom + "px"); </script>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js