On a horizontal bar chart, being fed from an external data source, I need to change the data values to text (for display purposes) on the valueAxis labels and tooltip text.
I've managed to find a way to change the valueAxis labels, which seems to work (although not sure if it's best practice?).
But I'm struggling to change the text on the valueAxis tooltip and series tooltip, as shown in the screenshot, where "3" needs to display as "FAIRLY IMPORTANT" as well as the other values when hovering over the chart.
EDIT
I've added this code which calls the amCharts adapter, and returns the valueAxis text as XXXXXX, but the target values are not working as they should.
I can't see where I'm going wrong though?
// This Adapter is to change the text in the valueAxis Tooltip
valueAxis.adapter.add("getTooltipText", (text, target) => {
if (target.dataItem && (target.dataItem.value == 0)) {
return "NOT NEEDED";
}
if (target.dataItem && (target.dataItem.value == 1)) {
return "UNSURE";
}
if (target.dataItem && (target.dataItem.value == 3)) {
return "NICE TO HAVE";
}
if (target.dataItem && (target.dataItem.value == 5)) {
return "MUST HAVE";
}
else {
return "XXXXXX";
}
});
Quick summary below.
The data source comes in as...
"Name": "Photographer",
"Category A": 3,
"Category B": 5,
"Category C": 1,
"Category D": 0,
"Category E": 3
On the chart, I want to display the numeric values as text...
0 to display as FAIRLY IMPORTANT
1 to display as NOT SURE
3 to display as FAIRLY IMPORTANT
5 to display as VERY IMPORTANT
Here's my code (so far) which I need to clean up a bit once I've finished working on it...
// Create chart instance
var chart = am4core.create("CHARTDIV", am4charts.XYChart);
// base64 encoded version of sample data as a data URI
function dataURI() {
return "data:application/json;base64,ewogICJyZWNvcmRzIjogWwogICAgewogICAgICAiaWQiOiAxLAogICAgICAiZmllbGRzIjogewogICAgICAgICJOYW1lIjogIlBob3RvZ3JhcGhlciIsCiAgICAgICAgIkNhdGVnb3J5IEEiOiAzLAogICAgICAgICJDYXRlZ29yeSBCIjogNSwKICAgICAgICAiQ2F0ZWdvcnkgQyI6IDEsCiAgICAgICAgIkNhdGVnb3J5IEQiOiAwLAogICAgICAgICJDYXRlZ29yeSBFIjogMwogICAgICB9LAogICAgICAiY3JlYXRlZFRpbWUiOiAiMjAxOC0wNC0xMlQxNzoyNzowNi4wMDBaIgogICAgfQogIF0KfQ==";
}
// Add data
chart.dataSource.url = dataURI(); //fake URL for demonstration purposes
// Always needed when using Airtable JSON output for amCharts compatibility
chart.dataSource.events.on("parseended", function(ev) {
// parsed data is assigned to data source's `data` property
ev.target.data = ev.target.data.records.map(function(dataItem) {
return {
"Category A": dataItem.fields["Category A"],
"Category B": dataItem.fields["Category B"],
"Category C": dataItem.fields["Category C"],
"Category D": dataItem.fields["Category D"],
"Category E": dataItem.fields["Category E"],
"Name": dataItem.fields.Name
}
});
});
// Needed when the Airtable rows and columns need transposing
chart.dataSource.events.on("parseended", function(ev) {
var questionMap = {}; //lookup table to map questions to data elements
ev.target.data.forEach(function(item) {
Object.keys(item).forEach(function(key) {
if (key.indexOf('Name') == -1) { //act on non-response keys
if (!questionMap[key]) {
questionMap[key] = {
"Name": key
}; //create an object containing the name/question pair if it doesn't exist
}
questionMap[key][item.Name] = item[key]; // assign response+value to the object (e.g. "Must Have": 75)
}
});
});
//remap lookup table as array
ev.target.data = Object.keys(questionMap).map(function(question) {
return questionMap[question];
});
});
// Set cell size in pixels
var cellSize = 50;
chart.events.on("datavalidated", function(ev) {
// Get objects of interest
var chart = ev.target;
var categoryAxis = chart.yAxes.getIndex(0);
// Calculate how we need to adjust chart height
var adjustHeight = chart.data.length * cellSize - categoryAxis.pixelHeight;
// get current chart height
var targetHeight = chart.pixelHeight + adjustHeight;
// Set it on chart's container
chart.svgContainer.htmlElement.style.height = targetHeight + "px";
});
// Create category axes
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "Name";
categoryAxis.renderer.grid.template.location = 0;
// Bar or column width for category axis
categoryAxis.renderer.cellStartLocation = 0.1;
categoryAxis.renderer.cellEndLocation = 0.9;
// Create value axes
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.numberFormatter.numberFormat = "#";
valueAxis.min = 0;
valueAxis.max = 6;
valueAxis.cursorTooltipEnabled = true;
// Create value axes - LABELS DISABLED
valueAxis.renderer.grid.template.disabled = true;
valueAxis.renderer.labels.template.disabled = true;
// Create value axes - DEFINE GRID LINES
function createGrid(value) {
var range = valueAxis.axisRanges.create();
range.value = value;
range.label.text = "";
}
createGrid(0);
createGrid(1);
createGrid(3);
createGrid(5);
createGrid(6);
// Create value axes - DEFINE GRID LABELS
function createLabel(value, label, location) {
var range = valueAxis.axisRanges.create();
range.value = value;
range.grid.strokeOpacity = 0;
range.label.location = location | 0;
range.label.dataItem.text = label;
range.label.fillOpacity = 1;
}
createLabel("0", "NOT IMPORTANT");
createLabel("1", "NOT SURE");
createLabel("3", "FAIRLY IMPORTANT");
createLabel("5", "VERY IMPORTANT");
// This Adapter is to change the text in the valueAxis Tooltip
valueAxis.adapter.add("getTooltipText", (text, target) => {
if (target.dataItem && (target.dataItem.value >= 0)) {
return "NOT IMPORTANT";
}
if (target.dataItem && (target.dataItem.value == 1)) {
return "NOT SURE";
}
if (target.dataItem && (target.dataItem.value == 3)) {
return "FAIRLY IMPORTANT";
}
if (target.dataItem && (target.dataItem.value == 5)) {
return "VERY IMPORTANT";
}
else {
return "XXXXXX";
}
});
// Create series
function createSeries(field, name) {
// Set up series
var series = chart.series.push(new am4charts.ColumnSeries());
series.name = name;
series.dataFields.valueX = field;
series.dataFields.categoryY = "Name";
series.sequencedInterpolation = true;
// Make it stacked
series.stacked = true;
// Configure columns
series.tooltip.getFillFromObject = false;
series.tooltip.background.fill = am4core.color("#272d3a");
series.tooltip.background.strokeWidth = 0;
series.tooltipText = "{name}: [bold]{valueX}[/]";
series.tooltip.paddingTop = -1;
series.tooltip.fontSize = 16;
// Add label
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color("#fff");
bullet.circle.strokeWidth = 2;
return series;
}
var series1 = createSeries("Photographer", "Photographer");
// Labels configuration for category axis
var categoryLabel = categoryAxis.renderer.labels.template;
categoryLabel.fill = am4core.color("#272d3a");
categoryLabel.fontSize = 16;
categoryLabel.fontWeight = 700;
categoryLabel.truncate = true;
// Labels configuration for value axis
var valueLabel = valueAxis.renderer.labels.template;
valueLabel.fill = am4core.color("#272d3a");
valueLabel.fontSize = 16;
// Tooltip configuration for category axis
var categoryTooltip = categoryAxis.tooltip;
categoryTooltip.background.fill = am4core.color("#272d3a");
categoryTooltip.fontSize = 16;
categoryTooltip.fontWeight = 700;
categoryTooltip.background.strokeWidth = 0;
categoryTooltip.background.cornerRadius = 3;
categoryTooltip.background.pointerLength = 4;
categoryTooltip.dy = 0;
categoryTooltip.dx = -2;
categoryTooltip.paddingTop = 0;
// Tooltip configuration for value axis
var valueTooltip = valueAxis.tooltip;
valueTooltip.background.fill = am4core.color("#272d3a");
valueTooltip.fontSize = 16;
valueTooltip.background.strokeWidth = 0;
valueTooltip.background.cornerRadius = 3;
valueTooltip.background.pointerLength = 4;
valueTooltip.dy = 2;
valueTooltip.dx = 0;
valueTooltip.paddingTop = 0;
// Tooltip configuration for value axis - DISABLED
valueTooltip.disabled = false;
// Add cursor
chart.cursor = new am4charts.XYCursor();
chart.cursor.behavior = "zoomXY";
chart.cursor.lineX.disabled = true;
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<div id="CHARTDIV" style="width: 100%; height: 600px;"></div>
I was struggling with something similar for that category axis, and found this tutorial: https://www.amcharts.com/docs/v4/tutorials/override-categoryaxis-tooltip-content-with-an-adapter/ that might help.
The relevant part:
categoryAxis.tooltip.label.adapter.add("text", function(text, target) {
if (target.dataItem) {
return target.dataItem.dataContext.axisLabel;
}
return text;
});
We were able to solve this like so:
import { ValueAxis } from "#amcharts/amcharts4/charts";
export default class CategoryValueAxis extends ValueAxis {
formatLabel(value) {
if (this.labelFunction) {
return this.labelFunction(value);
}
return super.formatLabel(value);
}
}
Simply define your labelFunction on the CategoryValueAxis when you inject it into the chart axes.
Related
New user to Amcharts (and programming!) and was trying to use one of their examples (https://codepen.io/team/amcharts/pen/gOpWroQ),
but when I pull the data from and external JSON file, it doesn't work properly. The JSON structure and format is correct and I literally copied the data from the JSON file into the var data [] and it works fine.
The pen is here: https://codepen.io/moneycarlo/pen/zYKdyGz (however I can't host a json file).
Line 10 is where I'm loading the JSON data, but if I remove the var data info and uncomment out line 10, the result doesn't draw 4 lines. Instead, it's 1 line with multiple stacked points on it for each date.
I'm guessing it's something in the pre-processor. I was under the impression that when you loaded from external data like the JSON it would automatically be assigned to the data property and those functions would work the same.
What am I missing?
am4core.useTheme(am4themes_animated);
// Source data
var data = [
{"date":"2019-07-05","domain":"aol.com","hits":"119489"},{"date":"2019-07-05","domain":"gmail.com","hits":"295834"},{"date":"2019-07-05","domain":"hotmail.com","hits":"8000"},{"date":"2019-07-05","domain":"yahoo.com","hits":"324263"},{"date":"2019-07-06","domain":"aol.com","hits":"195042"},{"date":"2019-07-06","domain":"gmail.com","hits":"258402"},{"date":"2019-07-06","domain":"hotmail.com","hits":"100000"},{"date":"2019-07-06","domain":"yahoo.com","hits":"427865"}
];
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
//chart.dataSource.url = "data_1.php";
// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
dateAxis.renderer.minGridDistance = 30;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
chart.colors.list = [
am4core.color("red"),
am4core.color("blue"),
am4core.color("green")
];
// Create series
function createSeries(field, name, id) {
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = "hits";
series.dataFields.dateX = "date";
series.name = name;
series.tooltipText = "{dateX}: [b]{valueY}[/]";
series.strokeWidth = 2;
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color("#fff");
bullet.circle.strokeWidth = 2;
// Add data pre-processor
series.data = data;
series.events.on("beforedatavalidated", function(ev) {
var source = ev.target.data;
var data = [];
for(var i = 0; i < source.length; i++) {
var row = source[i];
if (row.domain == id) {
data.push(row);
}
}
ev.target.data = data;
});
return series;
}
createSeries("hits", "Yahoo", "yahoo.com");
createSeries("hits", "Hotmail", "hotmail.com");
createSeries("hits", "Gmail", "gmail.com");
chart.legend = new am4charts.Legend();
chart.cursor = new am4charts.XYCursor();
dataSource assigns the data into the data array at the chart object, not at the series like the rest of your code does. You'll need to hook into the dataSource's parseended event and process each series with the existing beforedatavalidated code. You'll also want to keep track of the id value in your createSeries method as it won't be available in the parseended event:
chart.dataSource.events.on('parseended', function(ev){
// process parsed data into each series' data array
ev.target.component.series.each(function(series) {
var source = ev.target.data;
var data = [];
for(var i = 0; i < source.length; i++) {
var row = source[i];
if (row.domain == series.id) {
data.push(row);
}
}
series.data = data;
});
// clear out data array so that it isn't re-assigned to the chart
// data array
ev.target.data = [];
});
// ...
function createSeries(field, name, id) {
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = "hits";
series.dataFields.dateX = "date";
series.id = id; //store id for later
series.name = name;
series.tooltipText = "{dateX}: [b]{valueY}[/]";
series.strokeWidth = 2;
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color("#fff");
bullet.circle.strokeWidth = 2;
return series;
}
Codepen
I am new to AmCharts and attempting to load JSON data from an array into a chart and get sorted data, the chart is not loading, here is what I am doing, I have this error Chart was not disposed id-191 how can I correct this? Thank you.
HTML
<div id="Fourdiv">
Javascript
window.addEventListener("load", genFunction());
function genFunction() {
var x2;
var jsonx;
var x = [];
var ref = firebase.database().ref("Chartdata");
ref.on('value', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var childKey = childSnapshot.key;
x2 = childSnapshot.val();
jsonx = JSON.stringify(x2);
x.push(jsonx);
});
});
am4core.ready(function () {
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("Fourdiv", am4charts.XYChart);
for (i = 0; i < x.length; i++) {
chart.x.push({ "x": x[i].x, "y": x[i].y });
}
// Add data
chart.data = x;
// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "x";
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.renderer.minGridDistance = 30;
categoryAxis.renderer.labels.template.adapter.add("dy", function (dy, target) {
if (target.dataItem && target.dataItem.index & 2 == 2) {
return dy + 25;
}
return dy;
});
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.valueY = "y";
series.dataFields.categoryX = "x";
//series.name = "Visits";
series.columns.template.tooltipText = "{categoryX}: [bold]{valueY}[/]";
series.columns.template.fillOpacity = .8;
var columnTemplate = series.columns.template;
columnTemplate.strokeWidth = 1;
columnTemplate.strokeOpacity = 1;
});// end am4core.ready()
}
am4core.ready is the same as window.addEventListener("load", ...). You don't need it if you're already using your own onload handler.
You also set up the event listener incorrectly - you need to pass in the function reference (without the parentheses):
window.addEventListener("load", genFunction);
Also note that you should assign your data to a temporary variable outside of the chart instance, instead of using chart.x (which you don't even use later on):
var data = [];
for (i = 0; i < x.length; i++) {
data.push({ "x": x[i].x, "y": x[i].y });
}
chart.data = data;
I have an Multi Value AmChart where I'm sending dynamic values and is working as expected but as I'm sending the values dynamically which is of percentage value it doesn't require the Y-axis separately for all the lines . Only one y axis is enough for all the lines.
I'm able to disable the appearing y axis and and I also created a single y-axis (static y axis) but it is not synchronized with the series of chart.
trend() {
this._chart = am4core.create( "trend_yield", am4charts.XYChart );
this._chart.data = this._TChart;
this._chart.legend = new am4charts.Legend();
this._selectedItems.forEach( selectedItem => {
if ( selectedItem.id != 1 && selectedItem.id != 2 ) {
this.createAxisAndSeries();
let valueAxis = this._chart.yAxes.push( new am4charts.ValueAxis() );
let series = this._chart.series.push( new am4charts.LineSeries() );
series.dataFields.valueY = selectedItem.itemName;
series.dataFields.dateX = "date";
series.tensionX = 0.8;
series.strokeWidth = 2;
series.strokeOpacity = 5;
// series.yAxis = valueAxis;
series.name = selectedItem.itemName;
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.disabled = true; //disables axis line
valueAxis.renderer.labels.template.disabled = true;
valueAxis.renderer.grid.template.disabled = true;
}
} );
if ( this._selectedItems.length > 1 ) {
let valueAxis = this._chart.yAxes.push( new am4charts.ValueAxis() );
valueAxis.autoGridCount = false;
valueAxis.max = 100;
valueAxis.min = 0;
valueAxis.unit = "%";
valueAxis.unitPosition = "right";
valueAxis.renderer.line.strokeOpacity = 1;
valueAxis.renderer.line.strokeWidth = 1;
valueAxis.renderer.line.stroke = am4core.color( "#3787ac" );
// Enable export
this._chart.exporting.menu = new am4core.ExportMenu();
this._chart.exporting.filePrefix = "Yield Chart";
this._chart.exporting.menu.items = [
{
"label": "...",
"menu": [
{ "type": "pdf", "label": "PDF" },
{ "label": "Print", "type": "print" }
]
}
];
}
}
createAxisAndSeries() {
this._chart.cursor = new am4charts.XYCursor();
this._chart.colors.step = 6;
// Create axes
let dateAxis = this._chart.xAxes.push( new am4charts.DateAxis() );
dateAxis.renderer.grid.template.location = 0.5;
dateAxis.renderer.minGridDistance = 40;
dateAxis.renderer.labels.template.location = 0.0001;
dateAxis.renderer.minLabelPosition = 0.05;
dateAxis.renderer.maxLabelPosition = 0.95;
dateAxis.renderer.ticks.template.disabled = false;
dateAxis.renderer.ticks.template.strokeOpacity = 1;
dateAxis.renderer.ticks.template.stroke = am4core.color( "#495C43" );
dateAxis.renderer.ticks.template.strokeWidth = 2;
dateAxis.renderer.ticks.template.length = 10;
dateAxis.renderer.ticks.template.location = 0.5;
dateAxis.renderer.line.strokeOpacity = 1;
dateAxis.renderer.line.strokeWidth = 1;
dateAxis.renderer.line.stroke = am4core.color( "#3787ac" );
dateAxis.startLocation = 0.5;
dateAxis.endLocation = 0.5;
}
please, I'm trying to create with AmCharts 4 chart with multiple data sets. In previous version it is done this way: https://www.amcharts.com/demos/multiple-data-sets/
but I can't find anything how to make it in 4th version.
I use the code from their website.
Everything is ok, next chart I want to add in section starting with comment add ATR -> I need to show it under the original chart.
Thank you very much for any help.
Have a nice day!
var chart = am4core.create("candlestick-chart", am4charts.XYChart);
chart.paddingRight = 20;
// chart.dateFormatter.inputDateFormat = "YYYY-MM-dd";
chart.dateFormatter.inputDateFormat = "x";
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
/*
add default series
*/
var series = chart.series.push(new am4charts.CandlestickSeries());
series.dataFields.dateX = "date";
series.dataFields.valueY = "close";
series.dataFields.openValueY = "open";
series.dataFields.lowValueY = "low";
series.dataFields.highValueY = "high";
series.dataFields.atr = "atr";
series.dataFields.average_atr = "average_atr";
series.simplifiedProcessing = true;
series.tooltipText = "Open:${openValueY.value}\nLow:${lowValueY.value}\nHigh:${highValueY.value}\nClose:${valueY.value}\nATR:{atr.formatNumber('#.000')}\nAverage ATR:{average_atr.formatNumber('#.000')}";
series.riseFromPreviousState.properties.fillOpacity = 1;
series.dropFromPreviousState.properties.fillOpacity = 0;
chart.cursor = new am4charts.XYCursor();
/*
add scrollbar
*/
// a separate series for scrollbar
var scrollbarSeries = chart.series.push(new am4charts.LineSeries());
scrollbarSeries.dataFields.dateX = "date";
scrollbarSeries.dataFields.valueY = "close";
// need to set on default state, as initially series is "show"
scrollbarSeries.defaultState.properties.visible = false;
// hide from legend too (in case there is one)
scrollbarSeries.hiddenInLegend = true;
scrollbarSeries.fillOpacity = 0.5;
scrollbarSeries.strokeOpacity = 0.5;
var scrollbarX = new am4charts.XYChartScrollbar();
scrollbarX.series.push(scrollbarSeries);
chart.scrollbarX = scrollbarX;
/*
add ATR
-> I need to show it under the original chart
*/
var lineSeriesATR = chart.series.push(new am4charts.LineSeries());
lineSeriesATR.dataFields.dateX = "date";
lineSeriesATR.dataFields.valueY = "atr";
lineSeriesATR.defaultState.properties.visible = false;
// hide from legend too (in case there is one)
lineSeriesATR.hiddenInLegend = true;
lineSeriesATR.fillOpacity = 0.5;
lineSeriesATR.strokeOpacity = 0.5;
chart.data = {!! json_encode($candles) !!};
AmCharts 4 does not have the stock chart implemented yet. You can approximate panels and synced cursor and zoom by using the chart's containers to create additional charts and using the API to make the cursor and scrollbar affect all the charts.
You can create each chart and push them onto the chart container like so:
var container = am4core.create("chartdiv", am4core.Container); //create the container
container.width = am4core.percent(100); //set dimensions and layout
container.height = am4core.percent(100);
container.layout = "vertical";
// ... for each chart
var chart = container.createChild(am4charts.XYChart);
// ..set up as usual
While setting up each chart, you'll need to set up events to sync up zoom events:
// whenever any of the charts is zoomed, we should zoom all other charts
dateAxis.events.on("selectionextremeschanged", function (event) {
syncDateAxes(event.target);
})
// ...
function syncDateAxes(syncWithAxis) {
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
var dateAxis = chart.xAxes.getIndex(0);
if (dateAxis != syncWithAxis) {
dateAxis.events.disableType("selectionextremeschanged");
dateAxis.start = syncWithAxis.start;
dateAxis.end = syncWithAxis.end;
dateAxis.events.enableType("selectionextremeschanged");
}
}
}
You'll also want to set up each chart's cursor and sync each of them up:
function initCursorListeners() {
cursorShowDisposers = [];
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
var cursor = chart.cursor;
cursor.interactionsEnabled = true;
cursorShowDisposers.push(cursor.events.on("shown", function (event) {
handleShowCursor(event.target);
}));
}
}
var shownCursorChangeDisposer;
var shownCursorZoomStartedDisposer;
var shownCursorZoomEndedDisposer;
function handleShowCursor(shownCursor) {
// disable mouse for all other cursors
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
var cursor = chart.cursor;
if (cursor != shownCursor) {
cursor.interactionsEnabled = false;
}
// remove show listener
cursorShowDisposers[i].dispose();
}
// add change disposer to the hovered chart cursor
shownCursorChangeDisposer = shownCursor.lineX.events.on("positionchanged", function (event) {
syncCursors(shownCursor);
});
shownCursorZoomStartedDisposer = shownCursor.events.on("zoomstarted", function (event) {
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
var cursor = chart.cursor;
if (cursor != event.target) {
var point = { x: event.target.point.x, y: 0 };
cursor.triggerDown(point);
}
}
});
shownCursorZoomEndedDisposer = shownCursor.events.on("zoomended", function (event) {
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
var cursor = chart.cursor;
if (cursor != event.target) {
var point = { x: event.target.point.x, y: 0 };
cursor.triggerUp(point);
}
}
});
shownCursor.events.once("hidden", function (event) {
shownCursorChangeDisposer.dispose();
shownCursorZoomStartedDisposer.dispose();
shownCursorZoomEndedDisposer.dispose();
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
var cursor = chart.cursor;
cursor.hide(0);
cursorShowDisposers[i].dispose();
}
initCursorListeners();
});
}
function syncCursors(syncWithCursor) {
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
var cursor = chart.cursor;
var point = { x: syncWithCursor.point.x, y: 0 };
if (cursor != syncWithCursor) {
cursor.triggerMove(point);
}
}
}
There are other UI tweaks you can make like disabling the zoom out button on other charts except the top-most one as well as showing the date axis labels on just the last chart.
Here's a full demo on how to do all of this. This is also included in the examples folder in the AmCharts zip file.
If you're using Stock Chart, you might want to hold off.
Stock chart is not yet available for V4. We're planning it for the
second part of 2018. No exact ETA, yet. Sorry.
https://www.amcharts.com/docs/v4/getting-started/migrating-from-v3/#No_Stock_chart_yet
I have created box plot chart dynamically but would like to add a tooltip to the box plot chart so that when user mouse over the box plot series, the box plot series values will be displayed out in tooltip.
This is my code to create box plot chart:
Chart Chart1= new Chart();
Chart1.DataSource = dt;
Chart1.Width = 800;
Chart1.Height = 490;
Chart1.Series.Add(new Series());
Chart1.Series[0].ChartType = SeriesChartType.BoxPlot;
Chart1.Series.Add(new Series());
Chart1.Series[1].ChartType = SeriesChartType.Point;
List<object> List1 = dt.AsEnumerable().ToList<object>();
int Chart1_AVG = 0;
int Chart1_POINTINDEX = 0;
foreach (DataRow row in dt.Rows)
{
Chart1_AVG = (int)row["AVG"];
Chart1.Series[0].Points.AddXY(row["CUSTOMER"], new object[] { row["MIN"], row["MAX"], row["25TH_PCT_NUMBER"], row["75TH_PCT_NUMBER"], row["50TH_PCT_NUMBER"], row["AVG"] });
Chart1_POINTINDEX = Chart1.Series[1].Points.AddXY(row["CUSTOMER"], new object[] { row["AVG"] });
if ((Chart1_AVG >= AvgMinColorGreen) && (Chart1_AVG <= AvgMaxColorGreen))
{
Chart1.Series[1].Points[Chart1_POINTINDEX].MarkerColor = Color.Green;
}
else if ((Chart1_AVG >= AvgMinColorYellow) && (Chart1_AVG <= AvgMaxColorYellow))
{
Chart1.Series[1].Points[Chart1_POINTINDEX].MarkerColor = Color.Orange;
}
else if ((Chart1_AVG >= AvgMinColorRed) && (Chart1_AVG <= AvgMaxColorRed))
{
Chart1.Series[1].Points[Chart1_POINTINDEX].MarkerColor = Color.Red;
}
}
Chart1.Series[0]["BoxPlotShowMedian"] = "false"; //hide the average point
//create chartareas
ChartArea ca= new ChartArea();
//databind
Chart1.DataBind();
Chart1.Visible = true;
panel.Controls.Add(Chart1);
Please help me on this, thanks.
Use this
Chart1.Series[0].ToolTip = "#VAL"
Other possible tooltips are LegendToolTip, LabelToolTip ...
For keywords see https://msdn.microsoft.com/de-de/library/vstudio/dd456687%28v=vs.110%29.aspx