I'm trying to create a column chart with minimum pixel height columns. This is easy in chartjs (set the minBarLength property), however I can't figure out how to do so in amcharts.
I've tried setting series.column.template.minHeight to no effect. I've also tried setting pixelHeight and height, but also with no luck.
one workaround can be using scrollbar in Y axis like this following:
chart.scrollbarY = new am4core.Scrollbar();
chart.scrollbarY.start = 0;
chart.scrollbarY.end = 0.08;
with value Axis
valueAxis.min = 0;
valueAxis.max = 10;
This is not the best solution i agree but you can use it to slightly zoom with the buttons and scale and see
let me know if it works!
Related
Background:
Following the example of stacked and clustered charts as shown here I have created a chart with clustered and stacked columns. I am also attempting to display the total of the individual stacks on the top of the column as shown here
Issue faced:
The main is I am facing is the total value is displayed for all the data in the ValueAxis and not for individual stacks. Please help in displaying individual totals for the clustered columns.
Sample code:
Note the inbuilt APIs used to calculate and display totals
// Fully working example in the CodePen
// Enabling totals calculation
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.calculateTotals = true;
// Displaying the total in the LabelBullet
let totalBullet = totalSeries.bullets.push(new am4charts.LabelBullet());
totalBullet.label.text = "{valueY.sum}";
Codepen depicting the issue (note the totals on top of the stacked columns)
Alternate approaches considered:
Adding a field in the data with the totals for the stacks and displaying it instead (Problem: Unable to deselect using the Label - the value would be static and won't change)
Other help from StackOverflow:
Found samples of showing totals on stacked charts, but unable to find help on dealing with grouping
Although this is 7months old, I didn't find an answer either for this anywhere. If you haven't found a solution yet I was able to work around this by creating two Y axes and assigning them the series individually, then adding in the 'none' series for the totals bullet as well.
I adapted your Codepen example here in jsfiddle (codepen freezes for me for some reason)
Essentially though you create the two axes, and hide the labels for the second one.
let valueAxis0 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis0.min = 0;
valueAxis0.calculateTotals = true;
valueAxis0.title.text = "Expenditure (M)";
var valueAxis1 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis1.renderer.grid.template.disabled = true;
valueAxis1.calculateTotals = true;
valueAxis1.syncWithAxis = chart.yAxes.getIndex(0);
valueAxis1.min = 0;
valueAxis1.renderer.labels.template.disabled = true;
Then select it when creating the series and assign to the appropriate axis with series.yAxis = valueAxis;
function createSeries(field, name, stacked, yAxes) {
var valueAxis;
if (yAxes == 0) {
valueAxis = valueAxis0;
} else if (yAxes == 1) {
valueAxis = valueAxis1;
}
let series = chart.series.push(new am4charts.ColumnSeries());
...
series.yAxis = valueAxis;
Then the same goes for the TotalSeries
I want to add margin-top styling to level 1 column template in Amcharts v4 TreeMap chart.
I have tried the following code but known of them works.
level0ColumnTemplate.column.marginTop = 30;
level0ColumnTemplate.marginTop = 30;
code Link:
http://jsfiddle.net/t42asecw/3/
It looks like you're trying to create vertical space between treemap columns. Can't do it on the actual series columns.template because those try to occupy as much space as possible. What you can try then, is to put a paddingTop on the column, e.g.:
level1ColumnTemplate.column.paddingTop = 30;
// Don't forget to shift bullet, too
bullet1.dy = 15;
Fork of your code:
http://jsfiddle.net/notacouch/2vrk3e6s/
Or if you want even spacing on all sides, you can increase the strokeWidth, just be sure to increase column.cornerRadius* values as well (if your corners are rounded at all):
level1ColumnTemplate.column.cornerRadius(30, 30, 30, 30)
level1ColumnTemplate.strokeWidth = 30;
I use code like this to make a plot in MATLAB 2015:
plot(rand(1,40))
box off
ax=gca;
ax.TickDir='out';
ax.TickLength=3*ax.TickLength;
]
I want to put a bit of distance between the axes and the plot like in the figure below, which I made using Photoshop:
How can I do this?
I can think of a way to do it, but:
I don't know if it's the "right" way.
It's only good for static images (i.e. if you zoom/pan the plot, the bounds won't change accordingly).
The idea is you create two more axes and specify their positions such that they're far enough from your data, then hide the original axes (either fully or partially), which gives the desired result:
%% // Create axes and plot something:
figure();
hA(1) = axes;
hA(2) = copyobj(hA(1),gcf);
hA(3) = copyobj(hA(1),gcf);
plot(hA(1),rand(1,40));
%% // Add the new axes:
%// Move them around
FRACTION_OF_POSITION = 0.6;
hA(2).Position(1) = FRACTION_OF_POSITION*hA(2).Position(1);
hA(3).Position(2) = FRACTION_OF_POSITION*hA(3).Position(2);
%// Change their style
hA(2).Color = 'none'; hA(3).Color = 'none';
hA(2).XTick = []; hA(3).YTick = [];
hA(2).XRuler.Axle.Visible = 'off';
hA(3).YRuler.Axle.Visible = 'off';
%% // Remove the box/ticks/labels of the original axes:
if true
%// Alternative 1 (Remove everything at once, including background):
set(hA(1),'Visible','off')
else
%// Alternative 2 (Remove only certain elements):
hA(1).Box = 'off';
hA(1).XRuler.Axle.Visible = 'off';
hA(1).YRuler.Axle.Visible = 'off';
end
Which results in:
Additional considerations:
If you copyobj the axes before plotting, the axis tick values would be default - you probably don't want that. You will have to set the ticks and labels manually, OR, copyobj after plotting but then delete the line child-objects of hA(2:3).
If you want to support zoom/pan behavior, this might be acheivable using linkaxes.
Credits: the idea to use .XRuler.Axle was taken from Dan here, who in turn took it from UndocumentedMatlab.
Is there a way in d3 to not draw overlapping tick labels? For example, if I have a bar chart, but the bars are only 5 pixels wide and the labels are 10 pixels wide, I end up with a cluttered mess. I'm currently working on an implementation to only draw the labels when they do not overlap. I can't find any existing way to do that, but wasn't sure if anyone else had dealt with this problem.
There is no way of doing this automatically in D3. You can set the number of ticks or the tick values explicitly (see the documentation), but you'll have to figure out the respective numbers/values yourself. Another option would be to rotate the labels such that there is less chance of them overlapping.
Alternatively, like suggested in the other answer, you could try using a force layout to place the labels. To clarify, you would use the force layout on the labels only -- this is completely independent of the type of chart. I have done this in this example, which is slightly more relevant than the one linked in the other answer.
Note that if you go with the force layout solution, you don't have to animate the position of the labels. You could simply compute the force layout until it converges and then plot the labels.
I've had a similar problem with multiple (sub-)axis, where the last tick overlaps my vertical axis in some situations (depending on the screen width), so I've just wrote a little function that compares the position of the end of the text label with the position of the next axis. This code is very specific to my use case, but could adapted easily to your needs:
var $svg = $('#svg');
// get the last tick of each of my sub-axis
$('.tick-axis').find('.tick:last-of-type').each(function() {
// get position of the end of this text field
var endOfTextField = $(this).offset().left + $(this).find('text').width();
// get the next vertical axis
var $nextAxis = $('line[data-axis="' + $(this).closest('.tick-axis').attr('data-axis') + '"]');
// there is no axis on the very right, so just use the svg width
var positionOfAxis = ($nextAxis.length > 0) ? $nextAxis.offset().left : $svg.offset().left + $svg.width();
// hide the ugly ones!
if (endOfTextField > positionOfAxis) {
$(this).attr('class', 'tick hide');
}
});
The ticks with color: aqua are the hidden ones:
The legend currently auto-sizes according to the max width of the labels it contains, which is throwing my layout. I need to set a width or min-width. Here is my legend creation method:
public Legend CreateLegend()
{
var legend = new Legend();
legend.Enabled = true;
legend.Font = new Font("Arial", 11F);
legend.ForeColor = Color.FromArgb(102, 102, 102);
return legend;
}
It seems like anything I do which accesses the Position object for the legend (defines X an Y coords, width and height) makes the legend disappear completely.
So legend.Position.Width = 5 would make it disappear...
Okay, turns out that if you do not define all four properties of the Position object, it sets them to zero...so height was zero...so it disappeared. Awesome.