I created a row chart to show some negative values. I'd like to place the chart right next to another row chart with positive values since stacking isn't supported for the row chart.
The problem is, that the rows aren't shown completely. elasticX seems to be the problem. The x-axis scale range is limited from the lowest value to the highest.
I've created an snippet to demonstrate the bahaviour.
In the example the range is from -2000 to -800 which is the lowes value. But I obviously need it to be -2000 to 0.
I didn't get a solution. So any help would be much appreciated!
var data = [{
"name": "A",
"out": 1000
}, {
"name": "B",
"out": 1200
}, {
"name": "C",
"out": 1500
}, {
"name": "D",
"out": 800
}, {
"name": "E",
"out": 2000
}];
var rowChart = dc.rowChart("#rowChart");
var ndx = crossfilter(data),
nameDimension = ndx.dimension(function(d) {
return d.name;
}),
outGroup = nameDimension.group().reduceSum(function(d) {
return -d.out;
});
rowChart.width(300)
.height(500)
.margins({top: 10, right: 10, bottom: 30, left: 50})
.dimension(nameDimension)
.group(outGroup)
.elasticX(true)
.xAxis().ticks(2);
dc.renderAll();
<script src='https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.5/crossfilter.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.0-dev/dc.min.js'></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.0-dev/dc.css"/>
<div id="rowChart"> </div>
This bug was reported as #879 and was fixed in 2.0 beta 32.
Problem is, that the 2.1.0-dev version is quite old, can't be updated, and can't be deprecated due to an apparent bug in npm.
A development tag makes absolutely no sense! So the develop branch can't be distributed via a real CDN. If you want to use the development version of dc.js, you need to specify the dependency in your package.json using github url syntax:
"dc": "dc-js/dc.js#develop"
Or if you're not using npm, and a fake CDN is acceptable, you can use:
https://cdn.rawgit.com/dc-js/dc.js/develop/dc.js
Snippet corrected by using 2.0 beta 33 below.
Hopefully we'll push a real version 2.1 soon and 2.1.0-dev will get buried.
var data = [{
"name": "A",
"out": 1000
}, {
"name": "B",
"out": 1200
}, {
"name": "C",
"out": 1500
}, {
"name": "D",
"out": 800
}, {
"name": "E",
"out": 2000
}];
var rowChart = dc.rowChart("#rowChart");
var ndx = crossfilter(data),
nameDimension = ndx.dimension(function(d) {
return d.name;
}),
outGroup = nameDimension.group().reduceSum(function(d) {
return -d.out;
});
rowChart.width(300)
.height(500)
.margins({top: 10, right: 10, bottom: 30, left: 50})
.dimension(nameDimension)
.group(outGroup)
.elasticX(true)
.xAxis().ticks(2);
dc.renderAll();
<script src='https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.5/crossfilter.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0-beta.33/dc.js'></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0-beta.33/dc.css"/>
<div id="rowChart"> </div>
I notice that the external scripts are in the wrong order - crossfilter.js relies on d3.js and therefore it should come after but before dc.js; perhaps that is why the chart isn't rendering correctly.
Related
I am trying to add basic interactivity to my AMCHARTS 5 labels. Take this chart as an example:
I need to be able to click on the names at the left of the chart. That is actually yAxis because I use an inverted chart.
In the function that creates the series, I placed this code:
series.columns.template.events.once("click", function(ev) {
console.log("Clicked on a column", ev.target);
});
And it makes my bars to be clickable. I don't know how to refer to the labels on the left.
Labels as interactive elements in amCharts 5 are tricky. Basically, it's super hard to determine hover/click over just text because it's impossible to completely eradicate antialising, and the actual colored area is super tiny.
Therefore, if we need tooltip to be interactive - have a hover tooltip or handle click events - we need to add a background to it.
The background does not necessarily have to be visible: we can just set its fillOpacity: 0 to make it completely transparent.
Source: Labels – amCharts 5 Documentation
After the declaration and initialization of your yAxis, you can put this piece of code:
yAxis.get("renderer").labels.template.setup = target => {
target.setAll({
cursorOverStyle: "pointer",
background: am5.Rectangle.new(root, {
fill: am5.color(0x000000),
fillOpacity: 0
})
});
};
yAxis.get("renderer").labels.template.events.on("click", e => {
console.log(e.target.dataItem.dataContext.category);
});
Full example:
am5.ready(() => {
let root = am5.Root.new("chartdiv");
let chart = root.container.children.push(am5xy.XYChart.new(root, {}));
let data = [{
category: "Category 1",
value: 10
}, {
category: "Category 2",
value: 20
}, {
category: "Category 3",
value: 15
}];
let yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: "category",
renderer: am5xy.AxisRendererY.new(root, {
inversed: true,
cellStartLocation: 0.1,
cellEndLocation: 0.9
})
}));
yAxis.data.setAll(data);
yAxis.get("renderer").labels.template.setup = target => {
target.setAll({
cursorOverStyle: "pointer",
background: am5.Rectangle.new(root, {
fill: am5.color(0x000000),
fillOpacity: 0
})
});
};
yAxis.get("renderer").labels.template.events.on("click", e => {
console.log(e.target.dataItem.dataContext.category);
});
let xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
min: 0,
renderer: am5xy.AxisRendererX.new(root, {})
}));
let series = chart.series.push(am5xy.ColumnSeries.new(root, {
name: "Series",
xAxis: xAxis,
yAxis: yAxis,
valueXField: "value",
categoryYField: "category"
}));
series.data.setAll(data);
});
#chartdiv {
width: 100%;
height: 350px;
}
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<div id="chartdiv"></div>
I am using the new amcharts5 and I cannot seem to change my pie chart "slice" and label to a pure number despite referencing my old code and other links.
Basically my code and chart loads, but the issue is my values is depicted in percentages instead of numbers. This is my code below where I tried to address this.
Any assistance will be appreciated.
// Set data
series.data.setAll([
{ value: Type[0], category: "Type 1" },
{ value: Type[1], category: "Type 2" },
{ value: Type[2], category: "Type 3" },
]);
// Create legend
var legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.percent(50),
x: am5.percent(50),
marginTop: 15,
marginBottom: 15
}));
legend.labels.template.text = "{category}: {value.value}";
legend.slices.template.tooltipText = "{category}: {value.value}";
chart.legend.valueLabels.template.text = "{value.value}";
legend.data.setAll(series.dataItems);
Regards
v5 is completely different from v4, API-wise. In order to configure the pie chart's legend, you have to set it inside the series as documented here:
let series = chart.series.push(
am5percent.PieSeries.new(root, {
name: "Series",
categoryField: "country",
valueField: "sales",
legendLabelText: "{category}",
legendValueText: "{value}"
})
);
Tooltips need to be set on the slices using set or setAll (see the settings documentation for more info):
series.slices.template.set('tooltipText', '{category}: {value}');
Similarly for the slice labels, set the text property using the above functions:
series.labels.template.set('text', '{category}: {value}');
Demo:
var root = am5.Root.new("chartdiv");
root.setThemes([
am5themes_Animated.new(root)
]);
var chart = root.container.children.push(
am5percent.PieChart.new(root, {
layout: root.verticalLayout
})
);
var data = [{
country: "France",
sales: 100000
}, {
country: "Spain",
sales: 160000
}, {
country: "United Kingdom",
sales: 80000
}];
var series = chart.series.push(
am5percent.PieSeries.new(root, {
name: "Series",
valueField: "sales",
categoryField: "country",
legendLabelText: "{category}",
legendValueText: "{value}"
})
);
series.slices.template.set('tooltipText', '{category}: {value}');
series.labels.template.set('text', '{category}: {value}');
series.data.setAll(data);
var legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.percent(50),
x: am5.percent(50),
marginTop: 15,
marginBottom: 15
}));
legend.data.setAll(series.dataItems);
#chartdiv {
width: 100%;
height: 500px;
}
<script src="//cdn.amcharts.com/lib/5/index.js"></script>
<script src="//cdn.amcharts.com/lib/5/percent.js"></script>
<script src="//cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<div id="chartdiv"></div>
I have a chart that refuses to render properly if I include the categoryAxis property in the chart options. By "render properly", I mean that the plot area shows up, the title is displayed, but none of the columns are rendered.
I am using an AmCharts serial chart with GrantMStevens amChartsDirective because my project is built in Angularjs.
Here is a plunk with the categoryAxis commented out. If you enable that line of code, the chart will immediately exhibit this behavior.
This chart uses text values for the categoryField and numeric vlaues for the valueField. I have another chart that uses date values for the categoryField and numeric values for the valueField and it works just fine.
I am assuming that there some interaction between the fact that this a not a categoryField is not a date value that causes this but I cannot find any combination of properties that lets me set properties on the categoryField.
This is what I WANT to do:
categoryAxis: {
gridAlpha: 0.3,
gridColor: "GRAY"
},
Does anyone know why this doesn't work?
Here is the HTML:
<html ng-app="amChartsDirectiveExample">
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>
<div ng-controller="amChartsController2" style="height: 400px; width: 600px;">
<am-chart id="mySecondChart" options="amChartOptions2"></am-chart>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.0/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/amcharts.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/serial.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/themes/light.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/themes/chalk.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/themes/black.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/themes/dark.js"></script>
<script src="https://rawgit.com/ThumbsAlmighty/amCharts-Angular/master/dist/amChartsDirective.js"></script>
<script src="script.js"></script>
<script src="theme.js"></script>
</body>
And here is the JavaScript:
angular.module('amChartsDirectiveExample', ['amChartsDirective'])
.controller('amChartsController2', function($scope) {
$scope.chartData = [
{
"EscalationCount": "2",
"Area": "One"
},
{
"EscalationCount": "9",
"Area": "Two"
},
{
"EscalationCount": "5",
"Area": "Three"
},
{
"EscalationCount": "4",
"Area": "Four"
},
{
"EscalationCount": "3",
"Area": "Five"
}];
$scope.amChartOptions2 = {
type: "serial",
categoryField: "Area",
startDuration: 1,
rotate: true,
theme: "light",
trendLines: [],
//categoryAxis: {}, // Uncomment this line to break the chart.
graphs: [{
balloonText: "[[title]] for [[category]]: [[value]]",
fillAlphas: 1,
id: "AmGraph-1",
title: "Escalation Volume",
type: "column",
valueField: "EscalationCount"
}],
guides: [],
valueAxes: [{
id: "ValueAxis-1",
title: "EscalationCount",
}],
allLabels: [],
balloon: [],
legend: {
enabled: false
},
titles: [{
id: "Title-1",
size: 15,
text: "Lookit me! I rendered the Chart title!"
}],
data: $scope.chartData
};
});
For some reason the angular directive sets parseDates to true by default if you have a categoryAxis defined, which breaks if your chart isn't date-based. If you set parseDates: false in your categoryAxis, it will work.
categoryAxis: {
parseDates: false,
gridAlpha: 0.3,
gridColor: "#d3d3d3"
},
Here's your updated plunk: http://plnkr.co/edit/TYZdR0KEOAKcbHnGdTfP?p=preview
Note, I changed your gridColor to the hex equivalent. While named colors will work, if you plan on using the export plugin, you'll need to set your colors as a hex string.
Is it possible in nvd3 multichart yaxis to start from zero and max be determined by the input data?
I tried chart.yDomain1([0,100]); but chart gets cut off at max of 100. I need the max to be dynamic.
So you helped me figure out how to set the y axis range so I thought Id try and return the favour, even if it is six months later
I started with the source code from the multi-chart example
https://github.com/nvd3-community/nvd3/blob/gh-pages/examples/multiChart.html
What you want to do is to calculate the max of your data and then use that within the chart.yDomain1() function.
Example fiddle - https://jsfiddle.net/q72tzyaL/1/
var data = [{
"key": "key",
"type": "bar",
"values": [
{ x: 2012, y: 40 },
{ x: 2013, y: 36 }
]
}, {
"key": "key",
"type": "bar",
"values": [
{ x: 2012, y: 40 },
{ x: 2013, y: 36 }
]
}];
// each item is an object from the array with an array of values
// get the values that we need from that array and then get the max of that
function getMax(item) {
return d3.max(item.values.map(function(d){ return d.y; }));
}
// get the max. Pass in your data array and the function to get max
var max = d3.max(data, getMax);
nv.addGraph(function() {
var chart = nv.models.multiChart()
.margin({top: 30, right: 60, bottom: 50, left: 70})
.yDomain1([0, max]);
d3.select('#chart1 svg')
.datum(data)
.transition().duration(500).call(chart);
return chart;
});
I'm using a NVD3 and D3 to create some simple visuals, one of which is a horizontal bar chart. The options are:
{
"type": "multiBarHorizontalChart",
"height": 600,
"showControls": false,
"showValues": true,
"duration": 500,
"xAxis": {
showMaxMin: false,
axisLabelDistance: 400,
axisLabelWidth: 500,
},
"yAxis": {
"axisLabel": "",
"tickFormat": function (d) { return d; }
},
"yDomain" : [0, 10000],
x : (function(d) { return d.label }),
y : (function(d) { return d.value }),
showLegend: false,
valueFormat: d3.format(".0f"),
}
And the output looks like:
Default output
However, the project style police don't like that the range of the graph appears unbounded and they'd like it to look like this:
Desired output
Is this possible?
Thanks
The actual problem here was how the library build on top of D3 (NVD3) chose to draw it's bar charts.
Rather than re-invent the wheel, a decision was made to use Amcharts instead.