I have a stacked bar chart with bars that need some custom labeling. Each bar needs to display the bar's value preceeded by a label. To support this, I have created a custom labelFunction for the various BarSeries in the BarChart (see below).
The function is successfully rendering the labels, but in the case of the stacked bars, the label values are not displaying what I want. Instead of showing the bar's value, it is showing the sum of the bars in the stack. For example, if a BarSet contains three bars with values 3, 4, and 5, the labels are being displayed not as "3", "4", and "5", but "3", "7", and "12".
From this example it looks like I can achieve the results I want by creating a separate labelFunction for each individual BarSeries and accessing the specific property (e.g. data.item.#fooCount). However, I'd prefer having just one generic function if possible. Is there another property I can access in place of xNumber that gets me the bar's particular value and not the sum?
Note that the default label behavior (i.e. not setting a labelFunction) displays the individual values, not the sums... So I'm assuming it's possible, hopefully without a lot of extra hoops to jump through. :)
My custom labelFunction:
private function setCustomLabel(item:ChartItem, series:Series):String
{
var data:BarSeriesItem = BarSeriesItem(item);
var currentSeries:BarSeries = BarSeries(series);
return currentSeries.displayName + ": " + data.xNumber;
}
A snippet of some of the BarChart code:
<mx:BarChart id="myChart" showDataTips="true"
height="180" width="100%">
...
<mx:BarSet type="stacked">
<mx:BarSeries displayName="Foo Count" xField="fooCount"
labelFunction="setCustomLabel" />
<mx:BarSeries displayName="Bar Count" xField="barCount"
labelFunction="setCustomLabel" />
</mx:BarSet>
</mx:series>
</mx:BarChart>
Thanks!
I believe what you want to do is use the dataProvider. Right now, your xNumber would be for the stacked series, and not of the data coming in.
So, I would try something like this:
private function setCustomLabel(item:ChartItem, series:Series):String
{
var data:BarSeriesItem = BarSeriesItem(item);
var currentSeries:BarSeries = BarSeries(series);
return currentSeries.displayName + ": " + data.item[currentSeries.xField];
}
This is not tested, but I think you get the idea of getting the raw data instead of using what the item displays.
Related
I have a linear-gradient legend for my map. The x-axis values are calculated based on the minimum
and maximum values from the underlying data. I adapted this legend from this website:
https://www.visualcinnamon.com/2016/05/smooth-color-legend-d3-svg-gradient.html
The legend shows up when user selects a "field condition" from the dropdownlist. However, when
user selects a "state" from a dropdownlist, all the tick marks' text disappear. Same thing when user
selects a "county" from another dropdownlist. I haven't had luck trying to figure this out.
I'm calculating the tick mark values (shows as text) as follows:
var dataRange = getDataRange();
var min = parseFloat(dataRange[0].toFixed(3));
var max = parseFloat(dataRange[1].toFixed(3));
var legendW = 160, legendH = 20;
//create tick marks
var legendX = d3.scaleLinear()
.domain([min, max])
.range([0, legendW]);
var axis = d3.axisBottom(legendX);
d3.select("#svgLegend")
.attr("class", "axis")
.attr("width", legendW)
.attr("height", legendH * 2)
.append("g")
.attr("id", "g-legend")
.attr("transform", "translate(2," + legendH + ")") //margin.left; height/2
.call(axis);
For working example, please see: http://realtimeceap.brc.tamus.edu
I just glanced at the code on the page you referenced the working example at and think I figured out the issue.
Here's the line that taking out the ticks from the legend SVG:
d3.selectAll("text").remove();
which is a part of the onChange function for $("#stateSelect").
Line number: 279 to be more specific (in index.html file)
I think you want to take out all the texts from the mainSVG i.e. with the id: svgMap2.
Changing the above selection will fix the issue. (for eg. if you have a class for the texts to be removed, use d3.selectAll('text.<classname>').
Hope this helps.
I figured out why it's "disappearing". The Web is a stateless medium. So, every time I changed selection from the dropdownlist, the svg refreshes and losses its current state. So I needed to re-create my legend for the state and county dropdownlists. But also, for the county dropdownlist, since there is a Zoom function, it meant that everytime I zoom to another county, I loss my map state again. So I moved the recreate legend function into the zoomedIn method (that is, AFTER the zoom state). It works now.
I'm drawing a line chart with javafx categoryaxis. e.g. I have 100 points on the plot. As such, all of my tick labels are squished together, resulting in 100 bunched-up ellipses. All I want to do is render every tenth label. I've looked through the documentation but there doesn't seem to be any way to turn individual tick labels visible or invisible, or how to change the setting of the tick unit on a CategoryAxis.
or I have to redraw xAxis?
just got an idea, add number of invisible char into the categoryaxis, so that each xaxis is still 'unique'
if (i%5 == 0)
str = DateFormat.getDateInstance(DateFormat.DEFAULT).format(date);
else {
str = invisible;
invisible += (char)29;
}
I have a advanced datagrid label function like this:
private function dgFormat(item:Object, column:AdvancedDataGridColumn):String{
var v3:int = item.value1 - item.value2;
return "Total: " + v3;
}
How can I change the text color of v3 dynamically? I want it to be red if it's less than zero & black otherwise.
thanks!
There's a few ways of doing this, but personally if I were you, I'd just create a custom item renderer for the columns that you want the color to change and do something like:
<s:Label text="Total: {data}" color="{data < 0?0xFF0000:0x000000}" />
This way, you bind the difference right off the bat without having to add 'total' in your data, and bind the color change as well.
You'll need a custom item renderer for your AdvancedDataGridColumn. The item renderer will check the value being set, and update the color of the text depending on its content.
This should get you started.
I have a column chart that uses a label function to format the vertical axis. I added a button and want the axis (or chart) to redraw when the button is clicked. Right now, the chart axis renders OK only when initially added to the view state.
I have a function that sets various properties after the chart is initially created. In there, I have tried all these:
myChart.verticalAxis.dataChanged();
myChart.validateNow();
myChart.validateDisplayList();
myChart.validateProperties();
myChart.invalidateDisplayList();
myChart.invalidateProperties();
But they do not change the axis formatting. How can I do this?
The MXML code for the axis is:
< mx:LinearAxis id="verticalAxis" labelFunction="vAxisFormat"/>
The label function is:
private function vAxisFormat(labelValue:Number, previousValue:Object, axis:IAxis):String {
axis.getLabelEstimate();
if (_scale == 1){
return currencyFormatter.format(labelValue/_scale);
}else {
return numberFormatter.format(labelValue/_scale);
}
}
Try updating the data provider. This redraws the graph, so all the components.
Example:
ArrayCollection
arr.refresh ();
XML
char.dataprovider = xmlData
regars
I have a clustered chart with 2 column series. The problem is that sometimes one column's values are so large, the other column is dwarfed. So I added checkboxes to show/hide a given column, and set the visibility of the ColumnSeries as such:
visible="{checkbox.selected}" includeInLayout="{checkbox.selected}"
This shows/hides the given column correctly, the problem is that it does not reset the Y-Axis, so the other column never actually grows in height (when the column with the larger values is hidden). I've tried resetting the data provider, validating/invalidating the chart, and nothing seems to work.
Anyone have any ideas?
Thanks!
I would imagine from your description that you actually need to remove the series from the chart. So
public function onToggle(){
var newSeries:Array = [];
if(bigSeries.selected) {
newSeries.push(bigSeries);
}
if(smallSeries.selected) {
newSeries.push(smallSeries);
}
chart.series = newSeries;
}