this is my fiddle, which I am building with from this example
what is the best way to convert the text lables from 0.08 to 8% format.
This is my attempt, but is there a better/other way?
.text(function(d) { return Math.floor(d.frequency*100)+"%"; });
The most common way to do it (let's call it the "d3 way") is to use the d3 formatting functions:
var format = d3.format("%");
Here is the Fiddle: https://jsfiddle.net/cr91xf1t/
You can play with several built in formats, or even create your own. Have a look here: http://bl.ocks.org/zanarmstrong/05c1e95bf7aa16c4768e
Related
rowChart
.width(500)
.height(200)
.dimension(neighborhoodDimension)
.group(neighborhoodGroup)
.label(function (d) { return d.value;})
I wanted to concatenate symbol/icon with bar chart's label something like screen shots. Working example in JsFiddle- http://jsfiddle.net/3chM6/460/
If you just want to add a symbol to the single-line label that is supported by dc.js, you can do it by supplying a custom .label() function. [As noted in the comments, multi-line labels and labels to the sides of bars would need some custom pretransition code.]
The default label for bar charts is the obscure
_chart.label(function (d) {
return dc.utils.printSingleValue(d.y0 + d.y);
}, false);
(source link)
It is this way because bar charts are stacked, so this finds the total up to the stack. Labels are only shown for the top stack.
The bar chart labels use selection.text() to specify the content:
.text(function (d) {
return _chart.label()(d);
});
(source link)
Since that's .text() and not .html(), this means you can't use HTML character entities. But you can still add a Unicode symbol by typing the symbol directly into your UTF8 source:
.label(d => d.y0 + d.y + '⯅');
I got this one on Linux by typing leftctrl-shift-U2bc5space - other operating systems have different ways of typing directly in UTF8.
Result:
You could add some logic to this to choose different symbols, but that's about as far as you can go with the built-in functionality. You won't be able to have the color different from the text, and they can only go on top of the bars.
Adding custom labels with custom placement, multiple lines, multiple colors, isn't too hard but I don't have time to work up an example right now. Search for [dc.js] pretransition or renderlet and you should dig up some examples here on SO.
I have an x-axis with long tick names, and I want to provide their abbreviations as tick values. Long tick names are used to set the domain.
axisElement = d3.axisBottom(scale)
.tickValues(tickValues); // these are long names when axis is first drawn
chart.append("g")
.attr("class", "bottomAxis")
.attr("transform", "translate(0, " + height + ")")
.call(axisElement);
I first draw the axis with proper long names which looks like this, and then try to update the ticks using axis.tickValues() function in D3.
updateTicks(tickValues) {
chart.select(".bottomAxis").call(this.axisElement.tickValues(tickValues));
}
But when D3 draws the ticks, it uses the old domain values in scale (which are the long names) and messes up the positioning of abbreviated names. It looks like this. I also get the following error:
Error: <g> attribute transform: Expected number, "translate(NaN,0)".
Which, I believe, is saying that it tried to translate the tick according to old domain values, but found abbreviated value so it can't translate.
I tried changing the scale's domain to abbreviated names, and then D3 positions them appropriately.
My question is, is it possible to change tickValues without changing the domain values?
You can do it like the following. You need to call axisBottom on your svg element and then use tickFormat to set the abbreviated text values. I have included a small example in the fiddle to show you. In the example, I am initially setting the long tick values first by default and then changing it to the abbreviated ones like you want to do.
var abbr = ["ll1", "ll2", "ll3", "ll4"];
svg
.call(d3.axisBottom(x).tickFormat(function(d, i) {
return abbr[i];
}));
JSFiddle - https://jsfiddle.net/tkw07c96/
I'm having trouble drawing belgium with a dc.js choropleth map.
I've read it can be a projection problem in another stackoverflow response (map json works on Geojson.io but it doesnt work on dc.js choropleth map), but I can't find the right parameters to write.
I would really appreciate any help with this issue.
Big thanks in advance !
Here is the geojson data I used:
https://github.com/Datafable/rolling-blackout-belgium/blob/master/data/geospatial/municipalities-belgium.geojson
And here is my code:
d3.json("data/municipalities-belgium.geojson", function (geojson) {
mapChart
.dimension(provinceDimension)
.group(provinceGroup)
.width(400)
.height(400)
.transitionDuration(1000)
.projection(d3.geo.mercator()
// .parallels([49, 52])
// .origin([0,40])
// .translate([200,900])
// .scale(150000000)
)
.overlayGeoJson(geojson.features, 'somename', function(d) {
return d.properties.shn;
})
;
dc.renderAll();
});
(The result is a blue square 400x400 that seems to select shn=BE391141)
Even if you put a scale, you don't get anything drawn?
As for the overlay, the name of the dimension has to be the name of the province you want to set the color of. How is provinceDimension defined? does it use shn as the key?
As an aside, your geojson contains lots of stuff you don't need (eg uk), having it only for the belgium provinces would make it much smaller.
There is something wrong in the dataset.
I have a composite chart of 2 line charts however I need to add a third chart to it.
This third chart will have these unique properties:
The data will come in via an ajax call and be available as a two dimensional array [[timestamp,value],[timestamp,value]...]
Every new ajax call needs to replace the values of the previous one
It does not need to respect any of the filters and will not be used on any other charts
It will however need to use a differently scaled Y axis.. (and labeled so on the right)
This is how the chart currently looks with only two of the charts
This is my code with the start of a third line graph... Assuming I have the array of new data available i'm at a little loss of the best/simplest way to handle this.
timeChart
.width(width).height(width*.333)
.dimension(dim)
.renderHorizontalGridLines(true)
.x(d3.time.scale().domain([minDate,maxDate]))
.xUnits(d3.time.months)
.elasticY(true)
.brushOn(true)
.legend(dc.legend().x(60).y(10).itemHeight(13).gap(5))
.yAxisLabel(displayName)
.compose([
dc.lineChart(timeChart)
.colors(['blue'])
.group(metric, "actual" + displayName)
.valueAccessor (d) -> d.value.avg
.interpolate('basis-open')
.dimension(dim),
dc.lineChart(timeChart)
.colors(['red'])
.group(metric, "Normal " + displayName)
.valueAccessor (d) -> d.value.avg_avg
.interpolate('basis-open'),
dc.lineChart(timeChart)
.colors(['#666'])
.y()#This needs to be scaled and labeled on the right side of the chart
.group() #I just want to feed a simple array of values into here
])
Also side note: I've noticed what I might be a small bug with the legend rendering. As you can see in the legend both have the same label but i've used different strings in the second .group() argument.
I believe you are asking a few questions here. I will try to answer the main question: how do you add data to a dc chart.
I created an example here: http://jsfiddle.net/djmartin_umich/qBr7y/
In this example I simply add random data to the crossfilter, though this could easily be adapted to pull data from the server:
function AddData(){
var q = Math.floor(Math.random() * 6) + 1;
currDate = currDate.add('month', 1);
cf.add( [{date: currDate.clone().toDate(), quantity: q}]);
$("#log").append(q + ", ");
}
I call this method once a second. Once it completes, I reset the x domain and redraw the chart.
window.setInterval(function(){
AddData();
lineChart.x(d3.time.scale().domain([startDate, currDate]));
dc.redrawAll();
}, 1000);
I recommend trying to get this working in isolation before trying to add the complexity of multiple y-axis scales.
Currently your best bet is to create a fake group. Really the .data method on the charts is supposed to do this, but it doesn't work for charts that derive from the stack mixin.
https://github.com/dc-js/dc.js/wiki/FAQ#filter-the-data-before-its-charted
I'm trying to make an chart using the default line plus bar chart, but I want to use two or more streams in the bars, is it possible?
Currently, when I try to do this, I got some trouble with the effects of the chart, and so I can't show properly the hover balloon of the bars, he always display the data of just one of the streams. But the main problem is the dates of x axis, displaying 1970's dates, when I remove the second stream of bars, the dates display well:
Anyone already tried to do this kind of chart successfully?
EDIT
Adding Fiddles:
Fiddle with two columns stream and messy dates
Fiddle with just one column stream and ok dates
I'm calling this kind of graph:
linePlusBarChart()
The problem with the dates is that your data contains timestamps (i.e. in seconds), but Javascript expects milliseconds. This is easily fixed by multiplying the values by 1000:
series.values = series.values.map(function (d) {
return {
x: d[0]*1000,
y: d[1]
}
});
The tooltip problem is actually a bug in NVD3 -- it's not meant to be used this way. The problem boils down to the mouseover handler assuming that the first item of the data is representative of what you want. You can fix this for your case by selecting the item by data point number modulo 2 (because there're two bars):
.on('mouseover', function(d,i) {
d3.select(this).classed('hover', true);
dispatch.elementMouseover({
point: d,
series: data[i%2],
pos: [x(getX(d,i)), y(getY(d,i))],
pointIndex: i,
seriesIndex: i%2,
e: d3.event
});
})
This will only work for exactly two bar series though. Updated jsfiddle with the modified NVD3 code here.