D3 - stack function bar chart filter - javascript

I have a codepen here - https://codepen.io/anon/pen/WdWyem?editors=1010
I have a simple stacked bar chart with a legend
I'm trying to use the legend to filter the bar chart.
When I click the colored block in the legend I'd like to remove that bar from the chart.
I have some basic data and I'm using D3's stack to create the stackedSeries and passing in the keys from an array 'keys'
I'm using the same 'keys' to create the legend and adding a class to each block that is the name of the key
When the block is clicked I wanted to capture the key name and remove it from the keys array and run the stack function again and redraw the chart.
This isn't working and I can't see how I can change the keys array and re-run the stack and
I haven't thought about getting the bars back yet.
stack = d3.stack()
.keys(getKeys());
function getKeys() {
console.log(keys)
return keys
}
function createStack() {
console.log('here');
stackedSeries = stack(dataToStack);
}
createStack();

To redraw the chart you need to recreate stack, so just move your stack creation into createStack function:
function createStack() {
stack = d3.stack()
.keys(getKeys());
console.log('here');
stackedSeries = stack(dataToStack);
}
Also you have to add the logic related to the colors of bars. For example you can change the colors array dynamically like you change the keys array

Related

How to plot different line patterns for different lines in DC.js series chart?

This is the image of the chart that I have generated : Current Series Chart
I have applied the dashStyle function to the linechart object which has applied the same pattern to all the lines. I need to plot a series chart with each line having a different pattern(dashed, dotted, plane line etc). There are a lot of attributes in the "c" object in the chart function. I am not sure which attribute corresponds to data values. The data attribute of the "c" object has something like "_dc/dc.baseMixin/_chart.data()" I am new to javascript and dc js and do not entirely understand what is going on under the hood.
Is there a way to plot different patterns for different lines in line chart?
Here's my current code which was implemented after referring to this example : http://dc-js.github.io/dc.js/examples/range-series.html
focusChart
.width(920)
.height(380)
.chart(function(c) { console.log(c);return dc.lineChart(c).dashStyle([2,3]).interpolate('cardinal').evadeDomainFilter(true); })
.x(d3.scale.linear().domain([1995,2017]))
.brushOn(false)
.yAxisLabel("Topic Weight")
.xAxisLabel("Year")
.elasticY(true)
.dimension(series1Dimension)
.group(series1Group)
.colorAccessor(function(d){
return d.key.split(",")[0].slice(5);
})
.colors(TopicColorScale)
focusChart.seriesAccessor(function(d) {return " " + d.key[0];})
.keyAccessor(function(d) {return +d.key[1];})
.valueAccessor(function(d) {return +d.value;})
.legend(dc.legend().x(400).itemHeight(13).gap(1).horizontal(10).legendWidth(540).itemWidth(210));
focusChart.yAxis().tickFormat(function(d) {return d3.format('d')(d);});
focusChart.xAxis().tickFormat(function(d) {return d3.format('d')(d);});
focusChart.margins().left += 20;
Any help would be much appreciated!
The line
.chart(function(c) { console.log(c);return dc.lineChart(c).dashStyle([2,3]).interpolate('cardinal').evadeDomainFilter(true); })
provides the function that generates subcharts. The parameters to this function appear to be undocumented, but a quick look at the source reveals
var subChart = _charts[sub.key] || _chartFunction.call(_chart, _chart, chartGroup, sub.key, i);
that the function takes the following parameters:
the composite chart
the chart group where the composite chart is registered
the key for the subchart
the index for the subchart
It's that third argument that you want. It's the key returned by your seriesAccessor, and you can use whatever method you want to set the dashStyle based on that key.

Getting access to already created Chart.js chart

I have created a BarChart with angular-chart like this:
<canvas id="bar"
chart-data="ctrl.barChartData"
chart-options="ctrl.barChartOptions"
chart-labels="ctrl.barChartLabels"
chart-series="ctrl.barChartSeries"
chart-click="ctrl.chartClick"
class="chart chart-bar">
</canvas>
I have wrote a chartClick function based on some example and looks like this:
vm.chartClick = function(evt){
var myBarChart = //how I can obtain a access to my created bar chart?
var activePoints = myBarChart.getPointsAtEvent(evt);
console.log("active: "+activePoints);
}
My question is: how can I obtain an access to chart I have created and assign it to myBarChart?
I have found solution for Highcharts however I can't find it for Chart.js
UPDATE:
Based on link provided by #IBarros I have manage to wrote following few lines of code:
$scope.$on('chart-create', function (event, chart) {
//console.log(chart);
myBarChart = chart;
});
I have 2 charts - one pie chart, one bar chart. What is more the event can be emitted multiple times for each chart so as a result I have a 7 charts printed into console. My next question is: how to find out what chart is a bar chart I'm looking for?
The reason why the event is fired 7 times was explained in this issue: How to get chart instance? #464
If options or other optional attributes are set after the data is set
the chart will be destroyed and recreated. This logic is what allows
the chart to be automatically updated everytime something changes in
the chart settings.
When that happens you should just update the reference on your side.
To figure out which chart object is the one you want, just look for the chart directive id (or chart type) in the chart object.
Example:
Use an object as an associative array
$scope.myCharts = {};
Save object reference in the associative array
$scope.$on('chart-create', function (event, chart) {
console.log(chart.chart.canvas.id);
console.log(chart.chart.config.type);
//If id is the same, reference will be updated
$scope.myCharts[chart.chart.canvas.id] = chart;
});
Access chart object by its directive id
console.log($scope.myCharts[id]);

DC.js Ordering with filters

Hi I am ordering the x values in my bar chart with .ordering. It orders correctly. However on filtering on other linked charts the ordering doesn't change. How do I achieve this behaviour?
Also ordering for me only works when I am overriding the default groupX.all() function with
groupX.all = function() {
return groupX.top(Infinity);
}
How can I make my bar chart order itself everytime it's redrawn?
How about this (untested):
chart.on('preRedraw', function() {
chart.rescale();
});
Since the ordering is implemented via the X scale, this should get the chart to recompute the scale each time.

Pie chart keeps adjusting itself when updating - D3

I'm having a bit of a problem.
I'm using D3 to make a pie chart for an application I'm building. I basically it have it working, but I'm annoyed by one aspect of the chart. I've adapted the chart from here: http://jsfiddle.net/vfkSs/1/ to work with my application.
The data is passed in here:
data = data ? data : { "slice1": Math.floor((Math.random()*10)+1),
"slice2": Math.floor((Math.random()*10)+1),
"slice3": Math.floor((Math.random()*10)+1),
"slice4": Math.floor((Math.random()*10)+1) };
But somewhere in this file these slices are being ordered by value, which is not what I want.
The issue with this chart is that when it updates it adjusts all pieces of the chart to keep them in ascending order. For example the largest portion of the pie is always on the right, and smallest on the left. I would like these to remain in the order they are when the data is passed in.
This is buried a bit in the documentation.
pie.sort([comparator])
If comparator is specified, sets the sort order of data for the layout
using the specified comparator function. Pass null to disable sorting.
(bolding mine)
So, modify your .pie call to:
var cv_pie = d3.layout.pie().sort(null).value(function (d) { return d.value });
Updated fiddle.

d3.js pie chart - legend toggle

I'm working on a d3.js pie chart application. I am trying to develop the functionality that when you click on the legend rectangles, it toggles the slice on/off as well as the fill inside the legend rectangle.
Although there is a bug with an undefined function - but I am not sure why this error is occurring as the function is defined.
http://jsfiddle.net/Qh9X5/3261/
this.piedata = methods.pie(dataSet);
console.log("animate slice2", this.piedata);
This line (233) has turned your currentDataSet from an Array into an Object:
var currentDataSet = jQuery.extend(true, {}, methods.currentDataSet);
d3 then complains when it tries to call the map function on currentDataSet as it is expecting an array.
You need to change it to take an Array as the second parameter:
var currentDataSet = jQuery.extend(true, [], methods.currentDataSet);

Categories