I am using it to generate a heavy amount of words in my application and I grab data from a json file like below:
var a = [];
for (var i=0; i < a.length; i++){
a.push(a[i].word);
}
And this gives us an array.
a = ["gsad","sagsa","gsag","sagas","gsag","gsagas","yhff","gag"];
I have it display on the screen correctly but since the row is too long it got out from the border and I'd like to give it a link break instead of change the SVG size, How may i do this?
UPDATE:
The code below is how i insert my codes:
var PositiveArr = ["gsad","sagsa","gsag","sagas","gsag","gsagas","yhff","gag"]; //consider the NegativeArr,NeutralArr have the similar contents
var fill = d3.scale.category20();
d3.layout.cloud().size([600, 300])
.words([NegativeArr,NeutralArr,PositiveArr].map(function(d) {
return {text: d, size: 10 + Math.random() * 50};
}))
.rotate(function() { return ~~(Math.random() * 2) * 90; })
.font("Impact")
.fontSize(function(d) { return d.size; })
.on("end", draw)
.start();
function draw(words) {
d3.select("#pre-theme").append("svg")
.attr("width", 600)
.attr("height", 300)
.append("g")
.attr("transform", "translate(300,150)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) { return d.size + "px"; })
.style("font-family", "Impact, Arial")
.style("fill", function(d, i) { return fill(i); })
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) { return d.text; });
}
SOLUTION:
I have found myself a solution, i just merge all my arrays into one using
var allResult = PersonsArr.concat(PlacesArr,PatternsArr,ProductsArr,CompaniesArr);
and insert the to the .map like
.words(entityResult.map(function(d) {
return {text: d, size: 10 + Math.random() * 50};
}))
SOLUTION: I have found myself a solution, i just merge all my arrays into one using
var allResult = PersonsArr.concat(PlacesArr,PatternsArr,ProductsArr,CompaniesArr);
and insert the to the .map like
.words(entityResult.map(function(d) {
return {text: d, size: 10 + Math.random() * 50};
}))
I am new to D3 and trying to dynamically update the chart if the source json is modified. But I am not able to achieve this.
Please check this plunkr
Js:
var width = 500,
height = 500,
radius = Math.min(width, height) / 2;
var x = d3.scale.linear()
.range([0, 2 * Math.PI]);
var y = d3.scale.sqrt()
.range([0, radius]);
var color = d3.scale.category10();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ") rotate(-90 0 0)");
var partition = d3.layout.partition()
.value(function(d) {
return d.size;
});
var 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, y(d.y));
})
.outerRadius(function(d) {
return Math.max(0, y(d.y + d.dy));
});
//d3.json("/d/4063550/flare.json", function(error, root) {
var root = initItems;
var g = svg.selectAll("g")
.data(partition.nodes(root))
.enter().append("g");
var path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.on("click", click)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
});
//.append("text")
var text = g.append("text")
.attr("x", function(d) {
return y(d.y);
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
.text(function(d) {
return d.name;
})
.style("fill", "white");
function computeTextRotation(d) {
var angle = x(d.x + d.dx / 2) - Math.PI / 2;
return angle / Math.PI * 180;
}
function click(d) {
console.log(d)
// fade out all text elements
if (d.size !== undefined) {
d.size += 100;
};
text.transition().attr("opacity", 0);
path.transition()
.duration(750)
.attrTween("d", arcTween(d))
.each("end", function(e, i) {
// check if the animated element's data e lies within the visible angle span given in d
if (e.x >= d.x && e.x < (d.x + d.dx)) {
// get a selection of the associated text element
var arcText = d3.select(this.parentNode).select("text");
// fade in the text element and recalculate positions
arcText.transition().duration(750)
.attr("opacity", 1)
.attr("transform", function() {
return "rotate(" + computeTextRotation(e) + ")"
})
.attr("x", function(d) {
return y(d.y);
});
}
});
} //});
// Word wrap!
var insertLinebreaks = function(t, d, width) {
alert(0)
var el = d3.select(t);
var p = d3.select(t.parentNode);
p.append("g")
.attr("x", function(d) {
return y(d.y);
})
// .attr("dx", "6") // margin
//.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
//p
.append("foreignObject")
.attr('x', -width / 2)
.attr("width", width)
.attr("height", 200)
.append("xhtml:p")
.attr('style', 'word-wrap: break-word; text-align:center;')
.html(d.name);
alert(1)
el.remove();
alert(2)
};
//g.selectAll("text")
// .each(function(d,i){ insertLinebreaks(this, d, 50 ); });
d3.select(self.frameElement).style("height", height + "px");
// Interpolate the scales!
function arcTween(d) {
var 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) {
console.log(path);
var _self = this;
var i = d3.interpolate({ x: this.x0, dx: this.dx0 }, a);
return function(t) {
var b = i(t);
console.log(window);
_self.x0 = b.x;
_self.dx0 = b.dx;
return arc(b);
};
}
setTimeout(function() {
path.data(partition.nodes(newItems))
.transition()
.duration(750)
.attrTween("d", arcTweenUpdate)
}, 2000);
In addition to what #Cyril has suggested about removing the following line:
d3.select(self.frameElement).style("height", height + "px");
I made further modifications in your fiddle: working fiddle
The idea used here is to add a function updateChart which takes the items and then generate the chart:
var updateChart = function (items) {
// code to update the chart with new items
}
updateChart(initItems);
setTimeout(function () { updateChart(newItems); }, 2000);
This doesn't use the arcTweenUpdate function you have created but I will try to explain the underlying concept:
First, you will need to JOIN the new data with your existing data:
// DATA JOIN - Join new data with old elements, if any.
var gs = svg.selectAll("g").data(partition.nodes(root));
then, ENTER to create new elements if required:
// ENTER
var g = gs.enter().append("g").on("click", click);
But, we also need to UPDATE the existing/new path and text nodes with new data:
// UPDATE
var path = g.append("path");
gs.select('path')
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
//.on("click", click)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
})
.transition().duration(500)
.attr("d", arc);
var text = g.append("text");
gs.select('text')
.attr("x", function(d) {
return y(d.y);
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
.text(function(d) {
return d.name;
})
.style("fill", "white");
and, after everything is created/updated remove the g nodes which are not being used i.e. EXIT:
// EXIT - Remove old elements as needed.
gs.exit().transition().duration(500).style("fill-opacity", 1e-6).remove();
This whole pattern of JOIN + ENTER + UPDATE + EXIT is demonstrated in following articles by Mike Bostock:
General Update Pattern - I
General Update Pattern - II
General Update Pattern - III
In side the fiddle the setTimeout is not running because:
d3.select(self.frameElement).style("height", height + "px");
You will get Uncaught SecurityError: Failed to read the 'frame' property from 'Window': Blocked a frame with origin "https://fiddle.jshell.net" from accessing a frame with origin and the setTimeout never gets called.
So you can remove this line d3.select(self.frameElement).style("height", height + "px"); just for the fiddle.
Apart from that:
Your timeout function should look like this:
setTimeout(function() {
//remove the old graph
svg.selectAll("*").remove();
root = newItems;
g = svg.selectAll("g")
.data(partition.nodes(newItems))
.enter().append("g");
/make path
path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.on("click", click)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
});
//make text
text = g.append("text")
.attr("x", function(d) {
return y(d.y);
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
.text(function(d) {
return d.name;
})
.style("fill", "white");
}
working fiddle here
for the enter() and transitions to work you need to give d3 a way to identify each item in your data. the .data() function has a second parameter that lets you return something to use as an id. enter() will use the id to decide whether the object is new.
try changing
path.data(partition.nodes(newItems))
.data(partition.nodes(root));
to
path.data(partition.nodes(newItems), function(d){return d.name});
.data(partition.nodes(root), function(d){return d.name});
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I need to create D3 chart as in the following link:
D3 bubble chart (Data displayed as Overall and by Sector)
Below are the screenshots of charts:
Overall View:
Sector view:
I have searched a lot, but not able to find any codebase or example for the same. So, i'm not sure of How i can achieve the same.
Please share the code/pointers to achieve the same chart using D3.
Thanks in advance,
Manish Kumar
Below you can find the code for the chart in your link. It is in the source code of the website. I would suggest you learn from it, but i wouldn't copy it...
(function() {
var margin = {top: 20, right: 95, bottom: 10, left: 125},
width = 970 - margin.left - margin.right,
height,
tickExtension = 20; // extend grid lines beyond scale range
var formatPercent = d3.format(".0%"),
formatTenthPercent = d3.format(".1%"),
formatNumber = d3.format(",.3s"),
formatDollars = function(d) { return (d < 0 ? "-" : "") + "$" + formatNumber(Math.abs(d)).replace(/G$/, "B"); };
var nameAll = "S.\x26P.\xa0500 companies";
var x = d3.scale.linear()
.domain([0, .6])
.rangeRound([0, width - 60])
.clamp(true)
.nice();
var y = d3.scale.ordinal();
var y0 = d3.scale.ordinal()
.domain([nameAll])
.range([150]);
var r = d3.scale.sqrt()
.domain([0, 1e9])
.range([0, 1]);
var z = d3.scale.threshold()
.domain([.1, .2, .3, .4, .5])
.range(["#b35806", "#f1a340", "#fee0b6", "#d8daeb", "#998ec3", "#542788"].reverse());
var xAxis = d3.svg.axis()
.scale(x)
.orient("top")
.ticks(5)
.tickFormat(formatPercent);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSize(-width + 60 - tickExtension * 2, 0)
.tickPadding(6);
var quadtree = d3.geom.quadtree()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; });
var svg = d3.select(".g-graphic").append("svg")
.attr("height", 420 + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.select(".g-graphic").append("svg")
.style("margin-top", "20px")
.attr("height", 80)
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(renderChartKey);
var gx = svg.append("g")
.attr("class", "g-x g-axis")
.call(xAxis);
var tickLast = gx.selectAll(".g-x .tick:last-of-type");
tickLast.select("text")
.text(function() { return "\u2265 " + this.textContent; });
tickLast.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("transform", "translate(" + width + ",0)")
.select("text")
.text("N.A.");
var titleX = gx.append("text")
.attr("class", "g-title")
.attr("y", -9)
.style("text-anchor", "end");
titleX.append("tspan")
.attr("x", -20)
.style("font-weight", "bold")
.text("Effective tax rate");
titleX.append("tspan")
.attr("x", -20)
.attr("dy", "1em")
.text("2007-12");
d3.tsv("http://graphics8.nytimes.com/newsgraphics/2013/05/13/corporate-taxes/ee84b0191a75f5c652087293ab0efd4710e21f94/companies.tsv", type, function(error, companies) {
var sectors = d3.nest()
.key(function(d) { return d.sector; })
.entries(companies);
// Compute the overall rate for all data.
var overallRate = rate(d3.sum(companies, taxes), d3.sum(companies, earnings));
// Compute the overall rate by sector.
sectors.forEach(function(d) {
d.rate = rate(d3.sum(d.values, taxes), d3.sum(d.values, earnings));
});
// Sort sectors by ascending overall rate.
sectors.sort(function(a, b) {
return a.rate - b.rate;
});
// Compute the rate for each company.
companies.forEach(function(d) {
d.rate = rate(d.taxes, d.earnings);
});
height = 120 * sectors.length;
y
.domain(sectors.map(function(d) { return d.key; }))
.rangePoints([10, height], 1);
svg.append("g")
.attr("class", "g-y g-axis g-y-axis-sector")
.attr("transform", "translate(-" + tickExtension + ",0)")
.call(yAxis.scale(y))
.call(yAxisWrap)
.style("stroke-opacity", 0)
.style("fill-opacity", 0)
.selectAll(".tick text,.tick tspan")
.attr("x", -95)
.style("text-anchor", "start");
svg.append("g")
.attr("class", "g-y g-axis g-y-axis-overall")
.attr("transform", "translate(-" + tickExtension + ",0)")
.call(yAxis.scale(y0))
.call(yAxisWrap);
var companyClip = svg.append("defs").selectAll("clipPath")
.data(companies)
.enter().append("clipPath")
.attr("id", function(d, i) { return "g-clip-company-" + i; })
.append("circle")
.attr("cx", function(d) { return d.cx; })
.attr("cy", function(d) { return d.cy - y0(nameAll); })
.attr("r", function(d) { return r(d.capitalization) + 20; });
var gVoronoi = svg.append("g")
.attr("class", "g-voronoi")
gVoronoi.selectAll("path")
.data(companies)
.enter().append("path")
.attr("clip-path", function(d, i) { return "url(#g-clip-company-" + i + ")"; })
.on("mouseover", mouseover)
.on("mouseout", mouseout);
gVoronoi.call(updateVoronoi,
function(d) { return d.cx; },
function(d) { return d.cy + y0(nameAll); },
420);
var sector = svg.append("g")
.attr("class", "g-sector")
.selectAll("g")
.data(sectors)
.enter().append("g")
.attr("transform", function(d) { return "translate(0," + y(d.key) + ")"; });
var sectorNote = d3.select(".g-sector-notes")
.style("opacity", 0)
.style("display", "none")
.selectAll("div")
.data(sectors)
.enter().append("div")
.attr("class", "g-sector-note")
.style("top", function(d) { return y(d.key) + "px"; })
.html(function(d) { return sectorNoteByName[d.key]; });
var sectorCompany = sector.append("g")
.attr("class", "g-sector-company")
.selectAll("circle")
.data(function(d) { return d.values; })
.enter().append("circle")
.attr("cx", function(d) { return d.cx; })
.attr("cy", function(d) { return d.cy - y(d.sector) + y0(nameAll); })
.attr("r", function(d) { return r(d.capitalization); })
.style("fill", function(d) { return isNaN(d.rate) ? null : z(d.rate); })
.on("mouseover", mouseover)
.on("mouseout", mouseout);
var sectorOverall = sector.append("g")
.attr("class", "g-overall")
.attr("transform", function(d) { return "translate(" + x(d.rate) + "," + (y0(nameAll) - y(d.key)) + ")"; })
.style("stroke-opacity", 0)
.style("fill-opacity", 0);
sectorOverall.append("line")
.attr("y1", -100)
.attr("y2", +127);
var sectorOverallText = sectorOverall.append("text")
.attr("y", -106);
sectorOverallText.append("tspan")
.attr("x", 0)
.text(function(d) { return formatPercent(d.rate); });
sectorOverallText.filter(function(d, i) { return !i; }).append("tspan")
.attr("x", 0)
.attr("dy", "-11")
.style("font-size", "8px")
.text("OVERALL");
var overall = svg.append("g")
.attr("class", "g-overall g-overall-all")
.attr("transform", "translate(" + x(overallRate) + "," + y0(nameAll) + ")");
overall.append("line")
.attr("y1", -100)
.attr("y2", +127);
var overallText = overall.append("text")
.attr("y", -106)
.style("font-weight", "bold");
overallText.append("tspan")
.attr("x", 0)
.style("font-size", "13px")
.text(formatTenthPercent(overallRate));
overallText.append("tspan")
.attr("x", 0)
.attr("dy", "-14")
.style("font-size", "8px")
.text("OVERALL");
var currentView = "overall";
d3.selectAll(".g-content button[data-view]")
.datum(function(d) { return this.getAttribute("data-view"); })
.on("click", transitionView);
var searchInput = d3.select(".g-search input")
.on("keyup", keyuped);
var searchClear = d3.select(".g-search .g-search-clear")
.on("click", function() {
searchInput.property("value", "").node().blur();
search();
});
var tip = d3.select(".g-tip");
var tipMetric = tip.selectAll(".g-tip-metric")
.datum(function() { return this.getAttribute("data-name"); });
d3.selectAll(".g-annotations b,.g-sector-notes b")
.datum(function() { return new RegExp("\\b" + d3.requote(this.textContent), "i"); })
.on("mouseover", mouseoverAnnotation)
.on("mouseout", mouseout);
function keyuped() {
if (d3.event.keyCode === 27) {
this.value = "";
this.blur();
}
search(this.value.trim());
}
function search(value) {
if (value) {
var re = new RegExp("\\b" + d3.requote(value), "i");
svg.classed("g-searching", true);
sectorCompany.classed("g-match", function(d) { return re.test(d.name) || re.test(d.sector) || (d.symbol && re.test(d.symbol)) || (d.alias && re.test(d.alias)); });
var matches = d3.selectAll(".g-match");
if (matches[0].length === 1) mouseover(matches.datum());
else mouseout();
searchClear.style("display", null);
} else {
mouseout();
svg.classed("g-searching", false);
sectorCompany.classed("g-match", false);
searchClear.style("display", "none");
}
}
function transitionView(view) {
if (currentView === view) view = view === "overall" ? "sector" : "overall";
d3.selectAll(".g-buttons button[data-view]").classed("g-active", function(v) { return v === view; })
switch (currentView = view) {
case "overall": return void transitionOverall();
case "sector": return void transitionSector();
}
}
function transitionOverall() {
gVoronoi.style("display", "none");
var transition = d3.transition()
.duration(750);
transition.select("svg")
.delay(720)
.attr("height", 420 + margin.top + margin.bottom)
.each("end", function() {
gVoronoi.call(updateVoronoi,
function(d) { return d.cx; },
function(d) { return d.cy + y0(nameAll); },
420);
});
transition.select(".g-annotations-overall")
.each("start", function() { this.style.display = "block"; })
.style("opacity", 1);
transition.select(".g-sector-notes")
.style("opacity", 0)
.each("end", function() { this.style.display = "none"; });
transition.selectAll(".g-y-axis-sector")
.style("stroke-opacity", 0)
.style("fill-opacity", 0);
transition.selectAll(".g-y-axis-overall")
.style("stroke-opacity", 1)
.style("fill-opacity", 1);
var transitionOverall = transition.select(".g-overall-all")
.delay(x(overallRate))
.style("stroke-opacity", 1)
.style("fill-opacity", 1);
transitionOverall.select("line")
.attr("y2", +127);
transitionOverall.select("text")
.attr("y", -106);
var transitionSectorOverall = transition.selectAll(".g-sector .g-overall")
.delay(function(d) { return x(d.rate); })
.attr("transform", function(d) { return "translate(" + x(d.rate) + "," + (y0(nameAll) - y(d.key)) + ")"; })
.style("stroke-opacity", 0)
.style("fill-opacity", 0);
transitionSectorOverall.select("line")
.attr("y1", -100)
.attr("y2", +127);
transitionSectorOverall.select("text")
.attr("y", -106);
transition.selectAll(".g-sector-company circle")
.delay(function(d) { return d.cx; })
.attr("cx", function(d) { return d.cx; })
.attr("cy", function(d) { return d.cy - y(d.sector) + y0(nameAll); });
}
function transitionSector() {
gVoronoi.style("display", "none");
var transition = d3.transition()
.duration(750);
transition.select("svg")
.attr("height", height + margin.top + margin.bottom)
.transition()
.delay(720)
.each("end", function() {
gVoronoi.call(updateVoronoi,
function(d) { return d.x; },
function(d) { return y(d.sector) + d.y; },
height);
});
transition.select(".g-annotations-overall")
.style("opacity", 0)
.each("end", function() { this.style.display = "none"; });
transition.select(".g-sector-notes")
.delay(250)
.each("start", function() { this.style.display = "block"; })
.style("opacity", 1);
transition.selectAll(".g-y-axis-sector,.g-sector-note")
.delay(250)
.style("stroke-opacity", 1)
.style("fill-opacity", 1);
transition.selectAll(".g-y-axis-overall")
.style("stroke-opacity", 0)
.style("fill-opacity", 0);
var transitionOverall = transition.select(".g-overall-all")
.delay(x(overallRate))
.style("stroke-opacity", 0)
.style("fill-opacity", 0);
transitionOverall.select("line")
.attr("y2", height - y0(nameAll));
var transitionSectorOverall = transition.selectAll(".g-sector .g-overall")
.delay(function(d) { return x(d.rate); })
.attr("transform", function(d) { return "translate(" + x(d.rate) + ",0)"; })
.style("stroke-opacity", 1)
.style("fill-opacity", 1);
transitionSectorOverall.select("line")
.attr("y1", -25)
.attr("y2", +25);
transitionSectorOverall.select("text")
.attr("y", -31);
transition.selectAll(".g-sector-company circle")
.delay(function(d) { return d.x; })
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
function updateVoronoi(gVoronoi, x, y, height) {
companyClip
.attr("cx", x)
.attr("cy", y);
gVoronoi
.style("display", null)
.selectAll("path")
.data(d3.geom.voronoi().x(x).y(y)(companies))
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.datum(function(d) { return d.point; });
}
function mouseoverAnnotation(re) {
var matches = sectorCompany.filter(function(d) { return re.test(d.name) || re.test(d.alias); }).classed("g-active", true);
if (d3.sum(matches, function(d) { return d.length; }) === 1) mouseover(matches.datum());
else tip.style("display", "none");
}
function mouseover(d) {
sectorCompany.filter(function(c) { return c === d; }).classed("g-active", true);
var dx, dy;
if (currentView === "overall") dx = d.cx, dy = d.cy + y0(nameAll);
else dx = d.x, dy = d.y + y(d.sector);
dy -= 19, dx += 50; // margin fudge factors
tip.style("display", null)
.style("top", (dy - r(d.capitalization)) + "px")
.style("left", dx + "px");
tip.select(".g-tip-title")
.text(d.alias || d.name);
tipMetric.select(".g-tip-metric-value").text(function(name) {
switch (name) {
case "rate": return isNaN(d.rate) ? "N.A." : formatPercent(d.rate);
case "taxes": return formatDollars(d.taxes);
case "earnings": return formatDollars(d.earnings);
}
});
}
function mouseout() {
tip.style("display", "none");
sectorCompany.filter(".g-active").classed("g-active", false);
}
});
function renderChartKey(g) {
var formatPercent = d3.format(".0%"),
formatNumber = d3.format(".0f");
// A position encoding for the key only.
var x = d3.scale.linear()
.domain([0, .6])
.range([0, 240]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(13)
.tickValues(z.domain())
.tickFormat(function(d) { return d === .5 ? formatPercent(d) : formatNumber(100 * d); });
g.append("text")
.attr("x", -25)
.style("text-anchor", "end")
.style("font", "bold 9px sans-serif")
.text("CHART KEY");
var gColor = g.append("g")
.attr("class", "g-key-color")
.attr("transform", "translate(140,-7)");
gColor.selectAll("rect")
.data(z.range().map(function(d, i) {
return {
x0: i ? x(z.domain()[i - 1]) : x.range()[0],
x1: i < 4 ? x(z.domain()[i]) : x.range()[1],
z: d
};
}))
.enter().append("rect")
.attr("height", 8)
.attr("x", function(d) { return d.x0; })
.attr("width", function(d) { return d.x1 - d.x0; })
.style("fill", function(d) { return d.z; });
gColor.call(xAxis);
var gColorText = g.append("text")
.attr("x", 140 - 6)
.style("text-anchor", "end");
gColorText.append("tspan")
.style("font-weight", "bold")
.text("Color");
gColorText.append("tspan")
.style("fill", "#777")
.text(" shows effective rate");
var gSize = g.append("g")
.attr("class", "g-key-size")
.attr("transform", "translate(580,-7)");
var gSizeInstance = gSize.selectAll("g")
.data([1e9, 10e9, 50e9, 100e9])
.enter().append("g")
.attr("class", "g-sector");
gSizeInstance.append("circle")
.attr("r", r);
gSizeInstance.append("text")
.attr("x", function(d) { return r(d) + 4; })
.attr("dy", ".35em")
.text(function(d) { return "$" + Math.round(d / 1e9) + "B"; });
var gSizeX = 0;
gSizeInstance.attr("transform", function() {
var t = "translate(" + gSizeX + ",3)";
gSizeX += this.getBBox().width + 15;
return t;
});
var gSizeText = g.append("text")
.attr("x", 580 - 10)
.style("text-anchor", "end");
gSizeText.append("tspan")
.style("font-weight", "bold")
.text("Size");
gSizeText.append("tspan")
.style("fill", "#777")
.text(" shows market capitalization");
}
function yAxisWrap(g) {
g.selectAll(".tick text")
.filter(function(d) { return /[ ]/.test(d) && this.getComputedTextLength() > margin.left - tickExtension - 10; })
.attr("dy", null)
.each(function(d) {
d3.select(this).text(null).selectAll("tspan")
.data(d.split(" "))
.enter().append("tspan")
.attr("x", this.getAttribute("x"))
.attr("dy", function(d, i) { return (i * 1.35 - .35) + "em"; })
.text(function(d) { return d; });
});
}
function taxes(d) {
return d.taxes;
}
function earnings(d) {
return d.earnings;
}
function rate(taxes, earnings) {
return earnings <= 0 ? NaN : taxes / earnings;
}
function type(d) {
d.x = +d.x;
d.y = +d.y;
d.cx = +d.cx;
d.cy = +d.cy;
d.taxes *= 1e6;
d.earnings *= 1e6;
d.capitalization *= 1e6;
return d;
}
var sectorNoteByName = {
"Utilities": "Utilities benefited from the 2009 stimulus bill, which included tax breaks for companies that make capital-intensive investments, like power plants.",
"Information technology": "Technology companies can often move operations overseas for accounting purposes. And younger firms tend to have recent losses, holding down the sector’s overall rate.",
"Industrials": "As with the corporate sector, large industrial companies — like <b>Boeing</b>, <b>Caterpillar</b>, <b>General Electric</b> and <b>Honeywell</b> — pay lower taxes on average than small companies.",
"Telecom": "<b>Verizon</b> had a much lower effective tax rate than its rival <b>AT&T</b>, despite having similar profits over the six-year period.",
"Health care": "Within health care, managed care companies pay relatively higher tax rates, and makers of equipment, supplies and technology pay relatively lower rates.",
"Pharma": "Tax breaks for research and the ability to locate operations in low-tax countries have helped pharmaceutical and biotech companies to pay low taxes.",
"Consumer products": "Movie studios and packaged-food company pay more than 30 percent, on average. Soft-drink companies pay only 19 percent, and restaurant companies, 25 percent.",
"Materials": "The materials industry (chemicals, minerals, etc.) exemplifies a point often made by tax experts: within industries, tax rates vary greatly, in ways that often evade simple explanation.",
"Financials": "As financial firms have recovered from the crisis, some have paid relatively high tax rates.",
"Retailers": "Brick-and-mortar retailers, like <b>Bed Bath & Beyond</b> and <b>Home Depot</b>, tend to pay high tax rates. Online retailers, like <b>Amazon</b>, face low rates.",
"Energy": "Large oil companies typically pay high rates, but some economists argue that the high rates do not cover the pollution costs imposed on society.",
"Insurance": "Many insurers pay lower-than-average rates. But <b>A.I.G.</b> — which had an $83 billion loss while paying $8 billion in taxes — drives the sector’s average up."
};
})()
I'm trying to display a sunburst with text. I used the code from a sunburst example and tried to add text to it (worked), but when it updates, my text disappears. I can only get it to display all text or text when loaded then no text. So when it updates, the text is either gone or is not in sync with the data.
Can anybody tell me what is wrong because I don't know anymore.
Original code: http://bl.ocks.org/mbostock/4348373
My adaptions:
var width = 1060,
height = 900,
radius = Math.min(width, height) / 2;
var x = d3.scale.linear()
.range([0, 2 * Math.PI]);
var y = d3.scale.sqrt()
.range([0, radius]);
var color = d3.scale.category20c();
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")");
var partition = d3.layout.partition()
.value(function(d) { return d.size; });
var 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, y(d.y)); })
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
d3.json("http://localhost:50043/data.json", function (error, root) {
if (error) throw error;
var data = partition.nodes(root);
var path = svg.selectAll("path")
.data(partition.nodes(root))
.enter()
//.append("g");
.append("path")
//.attr("display", function (d) { return d.depth ? null : "none"; })
.attr("d", arc)
.style("fill", function (d) { return color((d.children ? d : d.parent).name); })
.on("click", click);
var text = svg.selectAll("text")
.data(data)
.enter()
.append("text")
.classed("label", true)
.attr("x", function (d) { return d.x; })
.attr("text-anchor", "middle")
// translate to the desired point and set the rotation
.attr("transform", function (d) {
if (d.depth > 0) {
return "translate(" + arc.centroid(d) + ")" +
"rotate(" + getAngle(d) + ")";
} else {
return null;
}
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("pointer-events", "none")
.text(function (d) { return d.name; });
function click(data) {
text.remove();
text = svg.selectAll("text")
.data(data)
.enter()
.append("text")
.classed("label", true)
.attr("x", function(d) { return d.x; })
.attr("text-anchor", "middle")
// translate to the desired point and set the rotation
.attr("transform", function(d) {
if (d.depth > 0) {
return "translate(" + arc.centroid(d) + ")" +
"rotate(" + getAngle(d) + ")";
} else {
return null;
}
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("pointer-events", "none")
.text(function (d) { return d.name; });
path.transition()
.duration(750)
.attrTween("d", arcTween(data));
}
function getAngle(d) {
// Offset the angle by 90 deg since the '0' degree axis for arc is Y axis, while
// for text it is the X axis.
var thetaDeg = (180 / Math.PI * (arc.startAngle()(d) + arc.endAngle()(d)) / 2 - 90);
// If we are rotating the text by more than 90 deg, then "flip" it.
// This is why "text-anchor", "middle" is important, otherwise, this "flip" would
// a little harder.
return (thetaDeg > 90) ? thetaDeg - 180 : thetaDeg;
}
function arcTween(d) {
var 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); };
};
}
});
d3.select(self.frameElement).style("height", height + "px");
Update: You can find my code on https://github.com/KenBonny/D3-Chart-Test
You can view the handywork on github page: https://kenbonny.github.io/D3-Chart-Test/
It's because you are not passing any data to click
wirte function click() { instead of function click(data) {
and I think it will work
I'm trying to add text to the partition-sunburst example. I have followed a hint given on Google Group and I was able to add the text. Now I want to rotate it. The new angles seem to be correct, but all the text get gathered in one point.
This is the piece of code where I add and rotate the text:
var text = vis.data([json]).selectAll("text")
.data(partition.nodes)
.enter().append("svg:text")
.attr("x", function(d) { return radius * Math.cos(d.x + d.dx/2); } )
.attr("y", function(d) { return radius * Math.sin(d.x + d.dx/2); } )
.attr("dy", ".31em")
.style("font-size", "5px")
.attr("transform", function(d) {
var angle = (2 * Math.PI - d.x) * (180/Math.PI);
var rotation = "rotate(" + angle + ")";
console.log(rotation);
console.log("d.x=" + d.x + ", d.y=" + d.y);
return rotation;
})
.text(function(d) { return d.name; });
This is an image of what I get:
and this is the full script:
var width = 1000,
height = 1000,
radius = 350,
x = d3.scale.linear().range([0, 2 * Math.PI]),
y = d3.scale.pow().exponent(1.3).domain([0, 1]).range([0, radius]),
padding = 5,
color = d3.scale.category20c();
var vis = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var partition = d3.layout.partition()
.sort(null)
.size([2 * Math.PI, radius * radius])
.value(function(d) { return 1; });
var arc = d3.svg.arc()
.startAngle(function(d) { return d.x; })
.endAngle(function(d) { return d.x + d.dx; })
.innerRadius(function(d) { return Math.sqrt(d.y); })
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
d3.json("fracking.json", function(json) {
var path = vis.data([json]).selectAll("path")
.data(partition.nodes)
.enter().append("svg:path")
.attr("display", function(d) { return d.depth ? null : "none"; })
// hide inner ring
.attr("d", arc)
.attr("fill-rule", "evenodd")
.style("stroke", "#fff")
.style("fill", function(d) { return color((d.children ? d : d.parent).name); })
.each(stash);
var text = vis.data([json]).selectAll("text")
.data(partition.nodes)
.enter().append("svg:text")
.attr("x", function(d) { return radius * Math.cos(d.x + d.dx/2); } )
.attr("y", function(d) { return radius * Math.sin(d.x + d.dx/2); } )
.attr("dy", ".31em")
.style("font-size", "5px")
.attr("transform", function(d) {
var angle = (2 * Math.PI - d.x) * (180/Math.PI);
var rotation = "rotate(" + angle + ")";
console.log(rotation);
console.log("d.x=" + d.x + ", d.y=" + d.y);
return rotation;
})
.text(function(d) { return d.name; });
d3.select("#size").on("click", function() {
path
.data(partition.value(function(d) { return d.size; }))
.transition()
.duration(1500)
.attrTween("d", arcTween);
d3.select("#size").classed("active", true);
d3.select("#count").classed("active", false);
});
d3.select("#count").on("click", function() {
path
.data(partition.value(function(d) { return 1; }))
.transition()
.duration(1500)
.attrTween("d", arcTween);
d3.select("#size").classed("active", false);
d3.select("#count").classed("active", true);
});
});
// Stash the old values for transition.
function stash(d) {
d.x0 = d.x;
d.dx0 = d.dx;
}
// Interpolate the arcs in data space.
function arcTween(a) {
var i = d3.interpolate({x: a.x0, dx: a.dx0}, a);
return function(t) {
var b = i(t);
a.x0 = b.x;
a.dx0 = b.dx;
return arc(b);
};
}
I think you need to specify the center of rotation. Try this:
var text = vis.data([json]).selectAll("text")
.data(partition.nodes)
.enter().append("svg:text")
.attr("x", function(d) { return radius * Math.cos(d.x + d.dx/2); } )
.attr("y", function(d) { return radius * Math.sin(d.x + d.dx/2); } )
.attr("dy", ".31em")
.style("font-size", "5px")
.attr("transform", function(d) {
var angle = (2 * Math.PI - d.x) * (180/Math.PI);
var rotation = "rotate(" + angle + "," + d3.select(this).attr("x") + "," d3.select(this).attr("y") +")";
console.log(rotation);
console.log("d.x=" + d.x + ", d.y=" + d.y);
return rotation;
})
.text(function(d) { return d.name; });