Ich arbeite mit this example eines Sunburst-Diagramms. Ich versuche, die äußere Ebene zu entfernen, die SKU-Informationen einer Kategorie anzeigt und nur Gruppen- und Kategorie-Layer hat. Ich habe noch nie mit D3 gearbeitet, also denke ich, dass die Baumtiefe ein Problem ist, aber ich konnte nicht herausfinden, welcher Teil des Codes bearbeitet werden soll, also habe ich einen alternativen Ansatz versucht.D3 Sunburst Diagrammtiefe
Was ich hoffte, würde das Problem lösen, alle JSON-Daten zu entfernen, die in der äußeren Schicht verwendet werden. Diese fiddle zeigen das Ergebnis. Leider scheint der Code nicht "schlau" genug zu sein, um die Lücken zu füllen/die Scheibenbreite anzupassen. Und da ich auch nicht schlauer bin, komme ich zu dir um Hilfe.
Aufgrund der Zeichenbeschränkung poste ich nur Teile des Codes, die ich für relevant halte.
Original-Datenstruktur:
var data1 = JSON.parse('[
{
"group":["Books","Arts","ZD111111"],"current":{"count":37}
},{
"group":["Electronics","Audio","ZD111288"],"current":{"count":36}
},{
"group":["Electronics","Camcorders","ZD111301"],"current":{"count":35}
}, ... ]);
Edited Datenstruktur:
var data1 = JSON.parse('[
{
"group":["Books","Arts"],"current":{"count":37}
},{
"group":["Electronics","Audio"],"current":{"count":36}
},{
"group":["Electronics","Camcorders"],"current":{"count":35}
}, ... ]);
Sunburst Diagramm:
treePath = ["group","category"],
var controller = function(data, progress) {
if(progress === 100) {
data2 = $.extend(true, [], data2);
var flatData = [];
data.map(function(d) {
var item = {};
for(var i = 0; i < treePath.length; i++) {
item[treePath[i]] = d.group[i];
}
//item.size = d3.selectAll("input").filter(function (d) { return this.checked; }).attr("value") === "count" ? d.current.count : d.current.metrics.price.sum;
item.size = d.current.count; // always show count data
item.model = d;
return flatData.push(item);
});
flatData.forEach(function(d) {
d.model.group = d.model.group[d.model.group.length - 1];
});
var treeData = genJSON(flatData, treePath.slice(0, treePath.length - 1));
d3.select("#vis")
.datum(treeData)
.call(chart);
}
};
function genJSON(csvData, groups) {
var genGroups = function(data) {
return _.map(data, function(element, index) {
return { name : index, children : element };
});
};
var nest = function(node, curIndex) {
if (curIndex === 0) {
node.children = genGroups(_.groupBy(csvData, groups[0]));
_.each(node.children, function (child) {
nest(child, curIndex + 1);
});
}
else {
if (curIndex < groups.length) {
node.children = genGroups(
_.groupBy(node.children, groups[curIndex])
);
_.each(node.children, function (child) {
nest(child, curIndex + 1);
});
}
}
return node;
};
return nest({}, 0);
}
function isInt(n) {
return n % 1 === 0;
}
function sunburst() {
var instance = this,
svg = null,
timestamp = new Date().getTime(),
widgetHeight = 600,
widgetWidth = 600,
widgetSize = 'large',
margin = {top: 0, right: 0, bottom: 0, left: 10},
width = widgetWidth - margin.left - margin.right,
height = widgetHeight - margin.top - margin.bottom,
radius = Math.min(width, height)/2,
x = d3.scale.linear().range([0, 2 * Math.PI]),
y = d3.scale.pow().exponent(1),
pgColor = d3.scale.ordinal().range([
{"family": "Blue", 1: "#0000CC", 2: "#0099FF", 3: "#CCFFFF"},
{"family": "Orange", 1: "#FF6600", 2: "#FFCC00", 3: "#FFFFCC"},
{"family": "Green", 1: "#009900", 2: "#99CC33", 3: "#CCFF99"},
{"family": "Red", 1: "#FF3333", 2: "#FF9999", 3: "#FFCCCC"},
{"family": "Purple", 1: "#CC0099", 2: "#FF66CC", 3: "#FFCCFF"},
{"family": "Grey", 1: "#7b7b7b", 2: "#999999", 3: "#eeeeee"}]),
luminance = d3.scale.sqrt()
.domain([0, 1e6])
.clamp(true)
.range([90, 20]),
i = 0,
partition = d3.layout.partition().sort(function(a, b) { return d3.ascending(a.name || a[treePath[treePath.length - 1]], b.name || b[treePath[treePath.length - 1]])}),
arc = d3.svg.arc()
.startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
.endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
.innerRadius(function(d) { return Math.max(0, d.y ? y(d.y) : d.y); })
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
function chart(selection) {
selection.each(function(data) {
instance.data = data;
width = widgetWidth - margin.left - margin.right;
height = widgetHeight - margin.top - margin.bottom;
radius = Math.min(width, height)/2;
y.range([0, radius]);
// Select the svg element, if it exists.
svg = d3.select(this).selectAll("svg").data([data]);
var gEnter = svg.enter()
.append("svg")
.attr("width", "600")
.attr("height", "600")
.append("g")
.attr("class", "main-group");
gEnter.append("defs")
.append("clipPath")
.attr("id", "clip-" + timestamp)
.append("rect")
.attr("x", 0)
.attr("y", 0);
var sunburstGroup = gEnter.append("g")
.attr("class", "sunburst-area")
.append("g")
.attr("class", "sunburst-group");
sunburstGroup.append("rect")
.attr("class", "sunburst-background")
.attr("x", 0)
.attr("y", 0)
.style("fill", "white");
// Update the inner group dimensions.
var g = svg.select("g.main-group")
.attr("transform", "translate(" + (width/2 + margin.left) + "," + (height/2 + margin.top) + ")");
g.select(".sunburst-background")
.attr("width", width)
.attr("height", height);
partition.value(function(d) { return d.size; })
.nodes(data)
.forEach(function(d) {
d.key = key(d);
});
var path = g.select(".sunburst-group").selectAll(".sunArcs")
.data(partition.nodes(data), function(d) { return d.key; });
path.enter().append("path")
.attr("class", "sunArcs")
.attr("d", arc)
.style("fill", function(d) {
if(d.depth === 0) return "#fff";
var color = pgColor(d.key.split(".")[0]);
return color[d.depth];
})
.style("fill-opacity", 0)
.on("click", click)
.on("mouseover", mouseover)
.on("mouseleave", mouseleave)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
});
path.transition()
.duration(duration)
.style("fill-opacity", 1)
.attrTween("d", arcTweenUpdate);
path.exit()
.transition()
.duration(duration)
.attrTween("d", arcTweenUpdate)
.style("fill-opacity", 0)
.remove();
function key(d) {
var k = [], p = d;
while (p.depth) k.push(p.name || p[treePath[treePath.length - 1]]), p = p.parent;
return k.reverse().join(".");
}
function click(d) {
path.transition()
.duration(duration)
.attrTween("d", arcTween(d));
}
function getParents(d) {
var parents = [], p = d;
while (p.depth >= 1) {
parents.push(p);
p = p.parent;
}
return parents;
}
function mouseover(d) {
if(d.depth === 0) return;
var parentNodes = getParents(d);
// Fade all the arcs.
d3.selectAll(".sunArcs")
.style("opacity", 0.3);
// Highlight all arcs in path
d3.selectAll(".sunArcs").filter(function(d){
return (parentNodes.indexOf(d) >= 0);
})
.style("opacity", 1);
// Initialize variables for tooltip
var group = d.name || d[treePath[treePath.length - 1]],
valueFormat = d3.format(",.0f"),
textMargin = 5,
popupMargin = 10,
opacity = 1,
fill = d3.select(this).style("fill"),
hoveredPoint = d3.select(this),
pathEl = hoveredPoint.node(),
// Fade the popup stroke mixing the shape fill with 60% white
popupStrokeColor = d3.rgb(
d3.rgb(fill).r + 0.6 * (255 - d3.rgb(fill).r),
d3.rgb(fill).g + 0.6 * (255 - d3.rgb(fill).g),
d3.rgb(fill).b + 0.6 * (255 - d3.rgb(fill).b)
),
// Fade the popup fill mixing the shape fill with 80% white
popupFillColor = d3.rgb(
d3.rgb(fill).r + 0.8 * (255 - d3.rgb(fill).r),
d3.rgb(fill).g + 0.8 * (255 - d3.rgb(fill).g),
d3.rgb(fill).b + 0.8 * (255 - d3.rgb(fill).b)
),
// The running y value for the text elements
y = 0,
// The maximum bounds of the text elements
w = 0,
h = 0,
t,
box,
rows = [], p = d,
overlap;
var hoverGroup = d3.select(this.parentNode.parentNode.parentNode.parentNode).append("g").attr("class", "hoverGroup");
// Add a group for text
t = hoverGroup.append("g");
// Create a box for the popup in the text group
box = t.append("rect")
.attr("class", "tooltip");
if(!isInt(d.value)) {
valueFormat = d3.format(",.2f");
}
while (p.depth >= 1) {
rows.push(treePath[p.depth - 1] + ": " + (p.name || p[treePath[treePath.length - 1]]));
p = p.parent;
}
rows.reverse();
rows.push("Volume: " + valueFormat(d.value));
t.selectAll(".textHoverShapes").data(rows).enter()
.append("text")
.attr("class", "textHoverShapes")
.text(function (d) { return d; })
.style("font-size", 14);
// Get the max height and width of the text items
t.each(function() {
w = (this.getBBox().width > w ? this.getBBox().width : w);
h = (this.getBBox().width > h ? this.getBBox().height : h);
});
// Position the text relatve to the bubble, the absolute positioning
// will be done by translating the group
t.selectAll("text")
.attr("x", 0)
.attr("y", function() {
// Increment the y position
y += this.getBBox().height;
// Position the text at the centre point
return y - (this.getBBox().height/2);
});
// Draw the box with a margin around the text
box.attr("x", -textMargin)
.attr("y", -textMargin)
.attr("height", Math.floor(y + textMargin) - 0.5)
.attr("width", w + 2 * textMargin)
.attr("rx", 5)
.attr("ry", 5)
.style("fill", popupFillColor)
.style("stroke", popupStrokeColor)
.style("stroke-width", 2)
.style("opacity", 0.95);
// Move the tooltip box next to the line point
t.attr("transform", "translate(" + margin.left + " , " + 10 + ")");
}
// Mouseleave Handler
function mouseleave(d) {
d3.selectAll(".sunArcs")
.style("opacity", 1);
d3.selectAll(".hoverGroup")
.remove();
}
// Interpolate the scales!
function arcTween(d) {
xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, 1]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
return function(d, i) {
return i
? function(t) { return arc(d); }
: function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
};
}
function arcTweenUpdate(a) {
var updateArc = this;
var i = d3.interpolate({x: updateArc.x0, dx: updateArc.dx0}, a);
return function(t) {
var b = i(t);
updateArc.x0 = b.x;
updateArc.dx0 = b.dx;
return arc(i(t));
};
}
});
}
Ich werde entweder Lösung akzeptieren.
Danke.
Es gibt eine gute Chance, niemand wird diese Frage beantworten ... es ist nicht sehr spezifisch, was Sie fordern .. Aber wer weiß :-) – Ryan