Legends are placed on default at the "Top-Left" with an additional offset for XY. What I would like to do is place the Legend at the "Bottom-Middle" (preferably without tweaking the XY)
Tried (1) -> Puts the legend in the "Top-Left"
var chart = dc.pieChart("#Chart");
chart
.width(600)
.height(600)
.legend(dc.legend().horizontal(true))
Tried (2) -> Makes the legend invisible
var chart = dc.pieChart("#Chart");
chart
.width(600)
.height(600)
.legend(dc.legend().horizontal(true).x(130).y(630))
Tried (3) -> Puts the legend on top of the pie-chart
var chart = dc.pieChart("#Chart");
chart
.width(600)
.height(600)
.legend(dc.legend().horizontal(true).x(130).y(570))
Tried (4) -> Makes the legend visible, but moves the chart a little bit down
var chart = dc.pieChart("#Chart");
chart
.width(600)
.height(700)
.legend(dc.legend().horizontal(true).x(130).y(670))
Tried (5) -> Throws an error "align is not a function"
var chart = dc.pieChart("#Chart");
chart
.width(600)
.height(700)
.legend(dc.legend().horizontal(true).align("Bottom-Middle"))
Did somebody figure out a workaround for this (perhaps a function for calculating XY)?
Related
I have a bar chart with in dc.js. The x axis is dimension and y is the measure ranging from 1 - 10k. I want to show all the bars and their labels not overlapping each other. Chart looks fine when there are few bars when the number of bars starts to increase they look not okay. I am looking to auto resize the labels for the bar-chart.
Sample Chart
I tried this method of renderlet to change the fontsize automatically
stackedBarChart.on('renderlet', function(chart) {
chart.selectAll('text.barLabel')
.attr('transform', function(d) {
//How do i get/set the width of the label here ?
});
I tried the below and I am able to do dynamic label sizing. I used pretransistion and inside that fetched all bar lables and altered their font-size. The font sizing is altered according to Gordon's Idea, Getting each bar's size and and assigning the font size dynamically. For testing I have used .2 as a factor to reduce the font size.
.on('pretransition', function(chart) {
var chart_width = chart.width();
chart.selectAll("text.barLabel").attr('font-size', function(data) {
let total_bars = chart.group().all().length;
let sing_bar_width = Math.floor(chart_width / total_bars);
return (sing_bar_width * .2) + "px";
});
});
I would like to be able to recenter a Pie charts legend after it has been filtered. Slices/Legends will removed when filtering because we remove empty bins. I added a pretransition listener to chart2, but that seems to be to late because the legend y value is the previous value and not current.
.on('pretransition', chart => buildLegend (chart))
If Male is selected on the Gender Pie chart I want the 4 legend items on the Job Pie chart to be re-centered. Any suggestions?
You can see a jsFiddle example.
A little more digging around showed me how to reference and update SVG elements.
function recenterLegend(chart) {
chart.selectAll('g.dc-legend')
.attr('transform', function(d) {
let legendY = (300 - (chart.group().all().length * 16)) / 2;
let translate = 'translate(220,' + legendY + ')';
return translate ;
});
}
Here is the updated jsfiddle.
I have created a horizontally stacked bar chart after referencing multiple examples on D3 portal. I set out to to achieve following goals
Tooltip on chart
Mouse hover on legend to highlight corresponding data
Mouse click on legend to
3.1. Change opacity of legend (unselect effect)
3.2. filter data based on selection
3.3. with transition effects
Was able to get #1, #2 & #3.1 requirements satisfied except for #3.2 & #3.3 i.e. data filtering based on legend selection with transition effects.
Here's sample code where I need help with data filtering and transition code upon clicking legend. Complete code on Plunker
.on("click", (function(d){
var y = "sqbar color-" + color(d).substring(1);
console.log("Class =" + y);
var opacity = document.getElementsByClassName(y)[0].style.opacity;
console.log ("Old opacity =" + opacity);
if (opacity === "1") {
svg.selectAll(".sqbar.color-" + color(d).substring(1)).style("opacity", "0.2");
//svg.selectAll(".rect.color-" + color(d).substring(1)).remove();
}
else{
svg.selectAll(".sqbar.color-" + color(d).substring(1)).style("opacity", "1");
//svg.selectAll(".rect.color-" + color(d).substring(1)).d.enter().append();
}
opacity = document.getElementsByClassName(y)[0].style.opacity;
console.log ("New opacity =" + opacity);
}))
Is it possible to add labels to scatter plot points in c3.js like in this google charts example?
https://google-developers.appspot.com/chart/interactive/docs/gallery/bubblechart#javascript
c3 doesn't support this currently - https://github.com/masayuki0812/c3/issues/481. But you can easily add the functionality - just loop through the chart series and points and add the labels as necessary.
var labels = [
['AA', 'BB', 'CC', 'DD', 'EE', 'FF', 'GG', 'HH'],
['ZA', 'ZB', 'ZC', 'ZD', 'ZE', 'ZF', 'ZG', 'ZH']
];
// series
var series = chart.internal.main
.selectAll('.' + c3.chart.internal.fn.CLASS.circles)[0];
// text layers
var texts = chart.internal.main
.selectAll('.' + c3.chart.internal.fn.CLASS.chartTexts)
.selectAll('.' + c3.chart.internal.fn.CLASS.chartText)[0]
series.forEach(function (series, i) {
var points = d3.select(series).selectAll('.' + c3.chart.internal.fn.CLASS.circle)[0]
points.forEach(function (point, j) {
d3.select(texts[i])
.append('text')
.attr('text-anchor', 'middle')
.attr('dy', '0.3em')
.attr('x', d3.select(point).attr('cx'))
.attr('y', d3.select(point).attr('cy'))
.text(labels[i][j])
})
});
Fiddle - http://jsfiddle.net/6phuuans/
Currently C3.js doesnt provide us with the option to add labels to a scatter plot chart. But the following method can be used to add responsive data labels:
After the chart is rendered (in the "onrendered" property of the chart), identify the data points ( tags) and add tags with the x and y coodinates picked from the relevant circle, as the tags sibling.
Code Snippet:
onrendered: function(){
// get the parent of the the <circles> to add <text as siblings>
var g = d3.selectAll('.c3-circles');
//Get all circle tags
var circles = d3.selectAll('circle')[0];
//go to each circle and add a text label for it
for(var i = 0; i < circles.length; i++){
//fetch x-coordinate
var x = $(circles[i])[0].cx;
//fetch y-coordinate
var y = $(circles[i])[0].cy;
//create and append the text tag
g.append('text')
.attr('y', y.baseVal.value - 15) // (-15) places the tag above the circle, adjust it according to your need
.attr('x', x.baseVal.value)
.attr('text-anchor', 'middle')
.attr('class', 'c3-text c3-text-'+i)
.text(data[i].<data point key>) // the text that needs to be added can be hard coded or fetched for the original data.
//Since I am using a JSON to plot the data, I am referencing it and using the key of the value to be shown.
}
}
This will add the label, but on resize , multiple data labels will be plotted. To handle that, on the charts resize, we must remove the previous data labels (in the "onresize" property of the chart).
Code Snippet:
onresize: function () {
$('.c3-shapes.c3-circles text').remove();
}
I am making a bubble chart using dc.js , crossfilter.js but bubbles are not showing in the chart !!!! It is just showing x axis and y axis but the bubbles are disappeared.
I was trying make this bubble chart in click to see
here is my code :
var dateDim = ndx.dimension(function(d) {return d.Date;});
var minDate = dateDim.bottom(1)[0].Date;
var maxDate = dateDim.top(1)[0].Date;
console.log(minDate);
console.log(maxDate);
//var ageDim = ndx.dimension(function(d){return +d.Age;});
var daySum = dateDim.group().reduceSum(function(d){return 1;});
//print_filter("ageSum");
// var hits = dateDim.group().reduceSum(function(d) {return d.Age;});
var brush = d3.svg.brush();
suicideBubbleChart
.width(990).height(200)
.transitionDuration(1500)
.dimension(dateDim)
.group(daySum)
.colors(d3.scale.category10())
.x(d3.time.scale().domain([minDate,maxDate]))
.y(d3.time.scale().domain([minDate,maxDate]))
.r(d3.scale.linear().domain([0, 4000]))
.minRadiusWithLabel(15)
.yAxisLabel("Suicides")
.elasticY(true)
.yAxisPadding(100)
.elasticX(true)
.xAxisPadding(200)
.maxBubbleRelativeSize(0.07)
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true)
.renderLabel(true)
.renderTitle(true);
Thank you.
I fixed enough to start getting stuff showing up on the chart.
There was a space before Date that caused that field name to come out wrong, and the date format was wrong, and I added a radiusValueAccessor.
var dateFormat = d3.time.format('%m/%d/%Y');
...
.r(d3.scale.linear().domain([0, 10]))
.radiusValueAccessor(function(d) {
return d.value;
})
http://jsfiddle.net/gordonwoodhull/wjeonreq/15/
Obviously it is still not the chart you want, but hopefully now that you have some stuff showing up on the screen, you can start to shape and debug it.
In particular, you will need a valueAccessor in order to place the bubbles in Y, and a Y scale.
It is one of the frustrating things about dc & d3 that if something doesn't work, then you just get an empty chart. The way I tracked this down, after dealing with the errors above, which showed up in the console, was
look at daySum.all() to make sure the data was okay (it was, after the date correction)
Inspect the svg element in the Elements tab of the Developer tools. The g.chart-body inside there has the actual content. I saw that the bubbles were there but had radius zero. Then I looked back at the stock example to see what radius setup must be missing.