Add HTML Element On Top Of Amchart Instance - javascript

I can't find this in the documentation, but is it possible to add a custom div element on top of an Amchart Instance?
Such that:
<div class="container-fluid px-0 mx-0">
<div id="chartdiv"></div>
<ul>
<li>Thailand</li>
<li>Myanmar</li>
<li>Etc...</li>
</ul>
</div>
With the UL displaying at the bottom of the instance?
JS:
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/maps.js"></script>
<script src="https://www.amcharts.com/lib/4/geodata/worldUltra.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<script>
am4core.useTheme(am4themes_animated);
var container = am4core.create("chartdiv", am4core.Container);
container.width = am4core.percent(100);
container.height = am4core.percent(100);
container.layout = "vertical";
// Create map instance
var chart = container.createChild(am4maps.MapChart);
// Set map definition
chart.geodata = am4geodata_worldUltra;
// Set projection
chart.projection = new am4maps.projections.Miller();
// Create map polygon series
var polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
// Exclude Antartica
polygonSeries.exclude = ["AQ"];
// Make map load polygon (like country names) data from GeoJSON
polygonSeries.useGeodata = true;
// Configure series
var polygonTemplate = polygonSeries.mapPolygons.template;
polygonTemplate.tooltipText = "{name}";
polygonTemplate.fill = am4core.color("#dcdcdc");
// Create hover state and set alternative fill color
var hs = polygonTemplate.states.create("hover");
hs.properties.fill = am4core.color("#a98239");
chart.events.on("ready", function(ev) {
chart.zoomToMapObject(polygonSeries.getPolygonById("TH"));
});
chart.zoomControl = new am4maps.ZoomControl();
chart.chartContainer.wheelable = false;
</script>
If I missed something in the docs, I apologize - hoping someone can point me in the right direction!

AmCharts is SVG based so everything in the chartdiv is controlled by the library and mostly contains SVG with a little bit of HTML, without any native options to include custom div objects. One potential workaround is to use a Label object and set its html property to include your HTML code. Note that this uses <foreignObject> to accomplish this, so you may need to be mindful of browser support (IE11, if that still matters).
Here's an example that creates a list on top of the chart
var label = chart.chartContainer.createChild(am4core.Label);
//label.isMeasured = false; //uncomment to make the label not adjust the rest of the chart elements to accommodate its placement
label.fontSize = 16;
label.x = am4core.percent(5);
label.horizontalCenter = "middle";
label.verticalCenter = "bottom";
label.html = "<ul><li>List item 1</li><li>List item 2</li></ul>";
label.toBack(); //move list to top of the chart area. See: https://www.amcharts.com/docs/v4/concepts/svg-engine/containers/#Ordering_elements
Demo:
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Add data
chart.data = [{
"category": "Research",
"value": 450
}, {
"category": "Marketing",
"value": 1200
}, {
"category": "Distribution",
"value": 1850
}];
// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "category";
categoryAxis.renderer.grid.template.location = 0;
//categoryAxis.renderer.minGridDistance = 30;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.valueY = "value";
series.dataFields.categoryX = "category";
var label = chart.chartContainer.createChild(am4core.Label);
//label.isMeasured = false; //uncomment to make the label not adjust the rest of the chart elements to accommodate its placement
label.fontSize = 16;
label.x = am4core.percent(5);
label.horizontalCenter = "middle";
label.verticalCenter = "bottom";
label.html = "<ul><li>List item 1</li><li>List item 2</li></ul>";
label.toBack(); //move list to top of the chart area. See: https://www.amcharts.com/docs/v4/concepts/svg-engine/containers/#Ordering_elements
html, body { width: 100%; height: 100%; margin: 0;}
#chartdiv { width: 100%; height: 100%;}
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<div id="chartdiv"></div>

Related

How do I get rid of the excess white space around pie chart? Using amcharts 4 libs

I have been trying to spread the pie chart I have to cover most of the 'card' I on the page, but no matter how much margin I cut, it either start disappearing behind another border within the card. I noticed that amcharts lib creates a bunch of layers that the developer doesn't have much control over. Anyway, this is what I'm talking about:
Here is the generated HTML code snippet:
Here is my javascript:
am4core.ready(function () {
//Themes
var chartType = am4charts.PieChart3D;
var seriesType = new am4charts.PieSeries3D();
//Create Chart and Series
var chart = createChart(thisWidget.id, chartType);
var pieSeries = chart.series.push(seriesType); // 3D Pie Chart
//Set properties
chart.hiddenState.properties.opacity = 0; // 3D Pie Chart: this creates initial fade-in
pieSeries.slices.template.cornerRadius = 6; //Pie Chart with varying Radius + 3D
pieSeries.colors.step = 3; //Pie Chart with varying Radius + 3D
pieSeries.angle = 45;
//color
if (colorTheme) {
pieSeries.colors.list = getAmchartCustomTheme(colorTheme);
}
//data types
pieSeries.dataFields.value = "count";
pieSeries.dataFields.category = "tag";
chart.paddingTop = 0;
chart.marginTop = 0;
// Put a thick white border around each Slice
pieSeries.slices.template.stroke = am4core.color("#fff");
pieSeries.slices.template
// change the cursor on hover to make it apparent the object can be interacted with
.cursorOverStyle = [
{
"property": "cursor",
"value": "pointer"
}
];
//Make the slice move on hover
var slice = pieSeries.slices.template;
slice.states.getKey("active").properties.shiftRadius = 0;
slice.states.getKey("hover").properties.scale = 1;
slice.states.getKey("hover").properties.shiftRadius = 0.2;
//increase size of Chart
chart.svgContainer.htmlElement.style.height = targetHeight;
chart.svgContainer.autoresize = true;
//disable Ticks and labels to save space
pieSeries.labels.template.disabled = true;
//registering events
pieSeries.slices.template.events.on("hit", function (ev) {
var category = ev.target.slice._dataItem.properties.category;
addInput(category);
});
pieSeries.alignLabels = false;
// Create a base filter effect (as if it's not there) for the hover to return to
var shadow = pieSeries.slices.template.filters.push(new am4core.DropShadowFilter);
shadow.opacity = 0;
// Create hover state
var hoverState = pieSeries.slices.template.states.getKey("hover"); // normally we have to create the hover state, in this case it already exists
// Slightly shift the shadow and make it more prominent on hover
var hoverShadow = hoverState.filters.push(new am4core.DropShadowFilter);
hoverShadow.opacity = 0.7;
hoverShadow.blur = 5;
//Add Data
chart.data = displayItems;
})
strokeOpacity = 0 or strokeWidth = 0 should do the trick.

Amcharts visualize portion of data in horizontal bar chart

I'm trying to visualize an horizontal bar chart and I want to show just a portion of the loaded records and to be able to scroll the results.
I tried to perform this using a vertical scrollbar. This is the resulting JSFiddle: jsfiddle.
function loadBar(){
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Set up data source
chart.data= [
{"name": "Mario12","overhead": 2},
{"name": "Jenny12","overhead": 2},
...
];
//create category axis for years
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
var yTitle = 'Agents';
categoryAxis.title.text = yTitle;
...
//create value axis for income and expenses
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.min = 0;
...
//create columns
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.categoryY = "name";
series.dataFields.valueX = "overhead";
...
chart.scrollbarY = new am4core.Scrollbar();
chart.scrollbarY.parent = chart.leftAxesContainer;
}
loadBar();
The wanted result should be instead result

Change font color of labels and title of a 3D bar chart drawn using amcharts

I have drawn a 3D stacked bar chart as follows.
$scope.DrawFunction = function()
{
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart3D);
// Add data
chart.data = [{
"country": "USA",
"year2017": 3.5,
"year2018": 4.2
}, {
"country": "UK",
"year2017": 1.7,
"year2018": 3.1
}];
// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "country";
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.renderer.minGridDistance = 30;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.title.text = "GDP growth rate";
valueAxis.renderer.labels.template.adapter.add("text", function(text) {
return text + "%";
});
// Create series
var series = chart.series.push(new am4charts.ColumnSeries3D());
series.dataFields.valueY = "year2017";
series.dataFields.categoryX = "country";
series.name = "Year 2017";
series.clustered = false;
series.columns.template.tooltipText = "[white]GDP grow in {category} (2017): [bold]{valueY}[/]";
series.columns.template.fillOpacity = 0.9;
var series2 = chart.series.push(new am4charts.ColumnSeries3D());
series2.dataFields.valueY = "year2018";
series2.dataFields.categoryX = "country";
series2.name = "Year 2018";
series2.clustered = false;
series2.columns.template.tooltipText = "GDP grow in {category} (2017): [bold]{valueY}[/]";
}
graph is generated correctly. I want to change the font color of all labels and the title into another color. I managed to change the font color of tootltip letters but couldn't find a way to change the font color of others.How can I do that ?
As I understand we can't change the font color of all the letters shown through out the graph unless we change the theme we have selected. So in my scenario since my background color is dark I wanted to change all the fonts within the graph to white. For that we need to import another theme rather than trying to change the font-color. you can download the dark theme from the following link
https://www.amcharts.com/lib/4/themes/dark.js
And import the library in your script as follows
<script src="https://www.amcharts.com/lib/4/themes/dark.js"></script>
Next along with animated.js theme call the dark theme as follows
am4core.useTheme(am4themes_dark);
am4core.useTheme(am4themes_animated);
Then all the fonts will become white in color and also the grid lines

How to remove gap between chart and X-axis value in AmChart?

I have a Multi Value Am-chart graph generated by external data (i.e., after Date selection chart will load based on data provided.) But after loading, data my chart shows like below image
As highlighted in yellow color in image. How to remove the space between "Date and chart" . Also Is there any way to display a line for the x-axis in this chart.
Below is my code.
createAxisAndSeries( field, name ) {
// Add cursor
this._chart.cursor = new am4charts.XYCursor();
this._chart.colors.step = 6;
// Create axes
let dateAxis = this._chart.xAxes.push( new am4charts.DateAxis() );
dateAxis.dataFields.category = "date";
dateAxis.renderer.grid.template.location = 0;
dateAxis.renderer.minGridDistance = 40;
dateAxis.dateFormatter.inputDateFormat = "YYYY-MM-DD, HH:mm:ss";
dateAxis.periodChangeDateFormats.setKey("day", "MMM dt");
let valueAxis = this._chart.yAxes.push( new am4charts.ValueAxis() );
let series = this._chart.series.push( new am4charts.LineSeries() );
series.dataFields.valueY = field;
series.dataFields.dateX = "date";
series.tensionX = 0.8;
series.strokeWidth = 2;
series.strokeOpacity = 5;
series.yAxis = valueAxis;
series.name = name;
series.tooltipText = "{name}: [bold]{valueY}[/]";
let interfaceColors = new am4core.InterfaceColorSet();
let bullet = series.bullets.push( new am4charts.CircleBullet() );
bullet.circle.stroke = interfaceColors.getFor( "background" );
bullet.circle.strokeWidth = 2;
valueAxis.renderer.line.strokeOpacity = 1;
valueAxis.renderer.line.strokeWidth = 2;
valueAxis.renderer.line.stroke = series.stroke;
valueAxis.renderer.labels.template.fill = series.stroke;
valueAxis.renderer.grid.template.disabled = true;
}
I know Am-chart have many properties to beautify things but I'm unable to find the exact property according to my requirement.
Any help from experts here.
Thanks in advance.
Finally I got the answer as I mention there is some AmChart property which I was unable to find that. It is nothing but "Positioning Axis Elements"
Just add these lines in dataAxis
dateAxis.renderer.minLabelPosition = 0.05;
dateAxis.renderer.maxLabelPosition = 0.95;
It works. :)

AmChart not showing second y-axis

I have been assigned a task of displaying 2 charts in a graph, therefore I need two y-axis to represent the charts.
One axis will be on the left, the other on the right.
My problem is that only one y axis is showing.
As I am using amCharts, I have noticed one issue where the visible y Axis has an array called allLabels and it has elements in it, but the second y Axis does not, however I don't know
what fills up that array property.
Code:
function addconsumerUsageGraph(consumerUsageGraph) {
//You can ignore this
if (consumerUsageGraph.graphs.length == 2)
{
var gr1 = consumerUsageGraph.graphs[0];
var gr2 = consumerUsageGraph.graphs[1];
consumerUsageGraph.removeGraph(gr1);
consumerUsageGraph.removeGraph(gr2);
}
if (consumerUsageGraph.graphs.length == 1) {
var gr1 = consumerUsageGraph.graphs[0];
consumerUsageGraph.removeGraph(gr1);
}
//I add the two yAxis here:
var yAxis1 = new AmCharts.ValueAxis();
yAxis1.position = "left";
var yAxis2 = new AmCharts.ValueAxis();
yAxis2.position = "right"; // set this to "right" if you want it on the right
//Adding the value axis to the whole graph
consumerUsageGraph.addValueAxis(yAxis1);
consumerUsageGraph.addValueAxis(yAxis2);
var graph = new AmCharts.AmGraph();
graph.valueField = "value";
graph.type = "column";
graph.title = "Usage";
graph.lineAlpha = 1;
graph.fillAlphas = 0.75;
consumerUsageGraph.addGraph(graph);
var graph2 = new AmCharts.AmGraph();
graph2.valueField = "cost";
graph2.type = "line";
graph2.lineAlpha = 1;
graph2.title = "Cost";
graph2.lineColor = graphColour;
graph2.bullet = "round";
graph2.bulletAlpha = 0.5;
graph2.bulletBorderAlpha = 0.8;
//Assigning the second yAxis to the second graph
graph2.valueAxes = yAxis2;
consumerUsageGraph.addGraph(graph2);
//consumerUsageGraph.write("chartdiv");
var legend = new AmCharts.AmLegend();
legend.marginBottom = -10;
legend.useGraphSettings = true;
consumerUsageGraph.addLegend(legend);
}
How the chart looks now:
graph doesn't have property valueAxes, use valueAxis instead:
graph2.valueAxis = yAxis2;

Categories