I want to update my Tooltip in my canvas js Chart without reloading the whole chart.
let arr = this.graph_arr;
let a = [];
let b = [];
arr.map((val) => {
val.data.map((val2) => {
b.push({
x: new Date(val2.date),
y: val2.revenue,
cn: val2.check_in,
rp: val2.rev_par,
arr: val2.avrr,
adr: val2.avg_daily_rate,
date: moment(val2.date).format('Do, MMMM'),
day: moment(val2.date).format('dddd')
})
})
a.push({
type: "spline",
name: val.channel_img.split('.')[0].toUpperCase(),
markerSize: 1,
showInLegend: true,
dataPoints: b,
label: val.channel_img,
})
b = [];
})
let chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
theme: "light2",
axisY2: {
valueFormatString: "1'%'"
},
axisY: {
suffix: "%"
},
axisX: {
gridThickness: 1,
valueFormatString: "DD/MMM"
},
legend: {
cursor: "pointer",
itemclick: this.toogleDataSeries
},
toolTip: {
shared: false,
content: this.selected == 'arr' ?
`<div style='\"'width: 210px;'\"'>ARR: {arr}, date: {date} </div>` :
this.selected == 'adr' ?
`<div style='\"'width: 210px;'\"'>ARR: {arr}, date: {date] </div>` : null,
cornerRadius: '8'
},
data: a
});
chart.render();
I have this Custom Tooltip. I want to change data in it from a dropdown without reloading. Currently I am using ternary operator and reloading chart. I want to change Tooltip content without reloading when user select from dropdown.
You can programmatically show toolip by using showAtX method. Below is an example:
var chart = new CanvasJS.Chart("chartContainer", {
title:{
text: "Show Tooltip based on dropdown"
},
data: [
{
type: "column",
dataPoints: [
{ x: 10, y: 71 },
{ x: 20, y: 55 },
{ x: 30, y: 50 },
{ x: 40, y: 65 },
{ x: 50, y: 95 },
{ x: 60, y: 68 },
{ x: 70, y: 28 },
{ x: 80, y: 34 },
{ x: 90, y: 14 }
]
}
]
});
chart.render();
var xVal = document.getElementById("xVal");
//Pass dataPoints as option to drop-down
for(var i=0; i<chart.options.data[0].dataPoints.length;i++){
var xValOption = document.createElement("option");
xValOption.text = chart.options.data[0].dataPoints[i].x = chart.options.data[0].dataPoints[i].x;
xVal.appendChild(xValOption);
}
xVal.addEventListener( "change", showTooltip);
//
function showTooltip(e){
if(xVal.value)
chart.toolTip.showAtX(Number(xVal.value));
else
chart.toolTip.hide();
}
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 360px; width: 80%; float: left"></div>
<div style="float: right; width: 15%">
Show Tooltip for <select id="xVal">
<option>Select</option>
</select>
</div>
Related
I'm currently creating a chart whose data is dynamically fetch from a database. Based on this data, I want to create a Horizontal Stacked Bar Chart that has only one series. Would that be possible in AmCharts? Or do I need a different approach?
Here's what I'd like as final result:
Here's a sample of what I'm currently doing: Chart Sample
I'm also aware that using series.stacked = true; would make a column chart stacked but I think this needs to have multiple series which I want to avoid for now.
<html>
<head></head>
<style></style>
<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<body>
<div id="chartdiv" style="width: 600px;height: 200px;background:#c7cacb;margin: 0 auto;"></div>
<script>
am5.ready(function () {
var root = am5.Root.new("chartdiv");
root._logo.dispose();
root.setThemes([
am5themes_Animated.new(root)
]);
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: false,
wheelY: false,
layout: root.verticalLayout
}));
var data = [{
"year": "Payments",
"europe": 50,
"namerica": 0,
"asia": 0,
}, {
"year": "Invoiced",
"europe": 30,
"namerica": 0,
"asia": 0,
}, {
"year": "Other Adjustment Sum",
"europe": 40,
"namerica": 20,
"asia": 39,
}]
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: "year",
renderer: am5xy.AxisRendererY.new(root, {}),
tooltip: am5.Tooltip.new(root, {})
}));
yAxis.data.setAll(data);
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
min: 0,
renderer: am5xy.AxisRendererX.new(root, {})
}));
xAxis = chart.xAxes.push(
am5xy.ValueAxis.new(root, {
min: 0,
numberFormat: "''",
renderer: am5xy.AxisRendererX.new(root, {
strokeOpacity: 1,
strokeWidth: 1,
minGridDistance: 60
}),
})
);
let myRange = [
{
x: 20,
},
{
x: 40,
},
{
x: 60,
},
{
x: 80,
},
{
x: 100,
},
];
for (var i = 0; i < data.length + 2; i++) {
let value = myRange[i].x;
let rangeDataItem = xAxis.makeDataItem({
value: value,
});
let range = xAxis.createAxisRange(rangeDataItem);
rangeDataItem.get('label').setAll({
forceHidden: false,
text: value,
});
}
var legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.p50,
x: am5.p50
}));
function makeSeries(name, fieldName, color) {
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
name: name,
stacked: true,
xAxis: xAxis,
yAxis: yAxis,
baseAxis: yAxis,
fill: color,
valueXField: fieldName,
categoryYField: "year"
}));
series.columns.template.setAll({
tooltipText: "{name}, {categoryY}: {valueX}",
tooltipY: am5.percent(90)
});
series.data.setAll(data);
series.appear();
}
makeSeries("Europe", "europe", "#83cdf4");
makeSeries("North America", "namerica","#caa3ed");
makeSeries("Asia", "asia","#eec48b");
chart.appear(1000, 100);
});
</script>
</body>
</html>
I want to design a chart like in the foto. The problem is, that I don't know how to put some labels in the bar! Also I don't want to show up the axes. And I also want to put the numbers like variables, because this chart is a result of a calculation of my calculator, is this possible?
<html>
<body>
<div id="chartContainer" style="height: 370px; width: 100;"></div>
</body>
<script>
//--------------------------------------CHART---------------
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
title:{
text: "Das können Sie beim Widerspruch einer Lebensversicherung herausholen:",
fontFamily: "arial black",
fontColor: "#695A42"
},
axisX: {
display: false,
interval: 1,
intervalType: "year"
},
axisY:{
display: false,
valueFormatString:"$#0bn",
gridColor: "#B6B1A8",
tickColor: "#B6B1A8"
},
toolTip: {
shared: false
},
data: [{
type: "stackedColumn",
showInLegend: true,
color: "#134d59",
name: "Q1",
dataPoints: [
{ y: 6.75, x: new Date(2010,0) },
{ y: 8.57, x: new Date(2011,0) },
{ y: 10.64, x: new Date(2012,0) }
]
},
{
type: "stackedColumn",
showInLegend: true,
name: "Q2",
color: "#e53011",
dataPoints: [
// { y: 6.82, x: new Date(2010,0) },
{ y: 9.02, x: new Date(2011,0) },
// { y: 11.80, x: new Date(2012,0) }
]
},
{
type: "stackedColumn",
showInLegend: true,
name: "Q3",
color: "#92c13f",
dataPoints: [
// { y: 7.28, x: new Date(2010,0) },
// { y: 9.72, x: new Date(2011,0) },
{ y: 13.30, x: new Date(2012,0) }
]
}]
});
chart.render();
function toolTipContent(e) {
var str = "";
var total = 0;
var str2, str3;
for (var i = 0; i < e.entries.length; i++){
var str1 = "<span style= \"color:"+e.entries[i].dataSeries.color + "\"> "+e.entries[i].dataSeries.name+"</span>: $<strong>"+e.entries[i].dataPoint.y+"</strong>bn<br/>";
total = e.entries[i].dataPoint.y + total;
str = str.concat(str1);
}
str2 = "<span style = \"color:DodgerBlue;\"><strong>"+(e.entries[0].dataPoint.x).getFullYear()+"</strong></span><br/>";
total = Math.round(total * 100) / 100;
str3 = "<span style = \"color:Tomato\">Total:</span><strong> $"+total+"</strong>bn<br/>";
return (str2.concat(str)).concat(str3);
}
}
</script>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</html>
https://jsfiddle.net/c74wtx5n/
For giving labels inside bars you need to append following in your data set.
indexLabel:"{y} $",
indexLabelPlacement: "inside",
For hiding axis and its labels add following in axis options
gridThickness: 0,
lineThickness: 0,
labelFormatter: function(e){
return "";
},
tickLength: 0,
I have modified your Jsfiddle, Here is the link to your solution
If you want to learn more about canvasJs customization go here.
There are multiple charts on one page.
Each chart line is common.
I want to display a legend that is common to multiple charts like the figure.It shows and hides all chart lines with OnClick like the default legend.
THIS PICT IS FAKE
Is that possible? how?
I had tried Chart.js sync legend toggle on multiple charts, One legend, multiple charts Chart JS and etc.
But, those solutions have one chart with legend, and that legend affects other charts.
Should I hide the chart and show only the legend?
Should I draw a chart with no data?
I would be grad if you could tell me
HTML
<script src="https://rawgit.com/nnnick/Chart.js/v1.0.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.0-beta/Chart.js"></script>
<div>
<canvas id="myChartA"></canvas>
</div>
<div>
<canvas id="myChartB"></canvas>
</div>
JS
var ctxA = document.getElementById("myChartA").getContext("2d");
var ctxB = document.getElementById("myChartB").getContext("2d");
let data_A1 = [{
x: "2019-01-01 00:01:38",
y: "13.0"
},
{
x: "2019-01-01 01:01:39",
y: "11.0"
},
{
x: "2019-01-01 02:01:40",
y: "16.0"
},
{
x: "2019-01-01 03:01:41",
y: "15.0"
},
{
x: "2019-01-01 04:01:42",
y: "14.0"
}
];
var data_A2 = [{
x: "2019-01-01 00:01:42",
y: 14.671
}, {
x: "2019-01-01 01:01:42",
y: 13.691
}, {
x: "2019-01-01 02:01:42",
y: 16.691
}, {
x: "2019-01-01 03:01:42",
y: 17.691
}, {
x: "2019-01-01 04:01:42",
y: 18.691
}];
let data_B1 = [{
x: "2019-01-02 00:01:38",
y: "12.0"
},
{
x: "2019-01-02 01:01:39",
y: "11.0"
},
{
x: "2019-01-02 02:01:40",
y: "13.0"
},
{
x: "2019-01-02 03:01:41",
y: "14.0"
},
{
x: "2019-01-02 04:01:42",
y: "16.0"
}
];
var data_B2 = [{
x: "2019-01-02 00:00:00",
y: 14.671
}, {
x: "2019-01-02 01:01:42",
y: 13.691
}, {
x: "2019-01-02 02:01:42",
y: 16.691
}, {
x: "2019-01-02 03:01:42",
y: 15.691
}, {
x: "2019-01-02 04:01:42",
y: 14.691
}];
var myChartA = new Chart(ctxA, {
type: 'line',
data: {
datasets: [{
label: '1st Data',
data: data_A1,
borderColor: '#0f0',
showLine: true
}, {
label: '2nd Data',
data: data_A2,
borderColor: '#f00',
showLine: true
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
displayFormat: 'h:mm',
}
}]
}
}
});
var myChartB = new Chart(ctxB, {
type: 'line',
data: {
datasets: [{
label: '1st Data',
data: data_B1,
borderColor: '#0f0',
showLine: true
}, {
label: '2nd Data',
data: data_B2,
borderColor: '#f00',
showLine: true
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
displayFormat: 'h:mm',
}
}]
}
}
});
You can create a common legend and through generateLegend api, if both the datasets are similar.
First disable the default legends though the options
legend: {
display: false
}
Then use generateLegend() api to get the data labels and set it to a common element.
<ul class="legend">
</ul>
Then add event listeners to the generated elements and target all the charts
document.querySelector('.legend').innerHTML = myChartA.generateLegend();
var legendItems = document.querySelector('.legend').getElementsByTagName('li');
for (var i = 0; i < legendItems.length; i++) {
legendItems[i].addEventListener("click", legendClickCallback.bind(this,i), false);
}
function legendClickCallback(legendItemIndex){
document.querySelectorAll('.myChart').forEach((chartItem,index)=>{
var chart = Chart.instances[index];
var dataItem = chart.data.datasets[legendItemIndex]
if(dataItem.hidden == true || dataItem.hidden == null){
dataItem.hidden = false;
} else {
dataItem.hidden = true;
}
chart.update();
})
}
A sample pen is present here
https://codepen.io/srajagop/pen/yLBJOOo
Note I am using chartjs 2.8
If anyone using React version of Chartjs particularly react-chartjs-2, I have done it using React Hooks with react-chartjs-2, see the sandbox demo
I would like to print canvas.js chart using javascript.
The printing code.
when I click print button, the printing popup from browser will show up with printing preview nothing.
How can i resolve this problem??
var html = "<html>";
html += document.getElementById("chartContainerInPT").innerHTML;
html += "</html>";
var printWin = window.open('','','left=0,top=0,width=1,height=1,toolbar=0,scrollbars=0,status =0');
printWin.document.write(html);
printWin.document.close();
printWin.focus();
printWin.print();
printWin.close();
html code
<div id="chart_divInPT" class="chart">
<div id="chartContainerInPT" style="height: 300px; width: 100%;"></div>
</div>
<button class="btn save" type="button" style="float: right;" id="printInPT">Print</button>
js
var chart = new CanvasJS.Chart(
"chartContainerInPT",
{
theme : "theme1",
title : {
text : ""
},
data : [ {
type : "column",
dataPoints : [
{
label : "Attempted",
y : chapterWiseResult['noOfAttempt']
},
{
label : "Correct",
y : chapterWiseResult['noOfCorrect']
},
{
label : "Wrong",
y : wrong
},
{
label : "Unattempted",
y : unattempted
},
]
} ]
});
How can I print chart in browser?
As solution you can save your canvas as image
var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
window.location.href=image;
Updated 2021
Canvas.js chart now added the print(in pdf,png,jpg)formats feature.
enable the export option as below
title: {
text: "Alarm Statistics",
},
**exportEnabled: true**,// enable print option for the chart
data: [{...},{...}]
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer",
{
title: {
text: "Chart with export feature enabled",
},
exportEnabled: true,
axisX:{
minimum: -900,
interval: 100,
},
data: [
{
type: "area",
fillOpacity: .4,
lineThickness: 3,
dataPoints: [
{ x: -100, y: 71 },
{ x: -200, y: 55 },
{ x: -300, y: 50 },
{ x: -400, y: 65 },
{ x: -500, y: 105, markerType: "circle", markerSize: 9, markerColor: "brown", indexLabel: "Highest" },
{ x: -600, y: 68 },
{ x: -700, y: 28 },
{ x: -800, y: 34 },
{ x: -900, y: 14}
]
}
]
});
chart.render();
}
</script>
<script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</head>
<body>
<div id="chartContainer" style="height: 300px; width: 100%;">
</div>
</body>
</html>
I am charting different data with RickshawJS. But I need a way to update the chart when a user clicks the #search button. Right now it just creates a new chart below the old one, and that is pretty messy.
The user enters the page and enters some details and clicks the button to chart it. So ideally I'd like to start with an empty chart that isn't shown, but I can't really figure out how to remove the data from the chart and axes and then update it.
I could call $('#chart svg').remove(); on the chart and axes but it seems messy.
$('#search').click(function(event){
event.preventDefault();
var data = utils.malletData();
var graph = new Rickshaw.Graph( {
element: document.querySelector("#chart"),
width: 800,
height: 250,
series: [ {
name: data['name'],
color: 'steelblue',
data: data['series']
} ]
} );
graph.render();
var hoverDetail = new Rickshaw.Graph.HoverDetail( {
graph: graph,
xFormatter: function(x) {
var date = new Date(x).getTime();
return moment(x).format('MMMM Do YYYY, h:mm:ss a');
},
yFormatter: function(y) { return Math.floor(y) + " users" }
} );
var xAxis = new Rickshaw.Graph.Axis.X( {
graph: graph,
orientation: 'bottom',
element: document.getElementById('x_axis'),
tickFormat: function(x) { return moment(x).fromNow(); },
ticks: 7,
tickSize: 1,
} );
xAxis.render();
var ticksTreatment = 'glow';
var yAxis = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
ticksTreatment: ticksTreatment,
element: document.getElementById('y_axis'),
} );
yAxis.render();
});
There's no official way to do so. However, you could leverage the fact that arrays in javascript are passed by reference and then update the graph.
Have a look at this demo on fiddle
var data = [
{
data: [ { x: 0, y: 120 }, { x: 1, y: 890 }, { x: 2, y: 38 }, { x: 3, y: 70 }, { x: 4, y: 32 } ],
color: "#c05020"
}, {
data: [ { x: 0, y: 80 }, { x: 1, y: 200 }, { x: 2, y: 100 }, { x: 3, y: 520 }, { x: 4, y: 133 } ],
color: "#30c020"
}
];
var graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
renderer: 'line',
height: 300,
width: 800,
series: data
} );
var y_ticks = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
element: document.getElementById('y_axis'),
} );
graph.render();
$('button#add').click(function() {
data.push({
data: [ { x: 0, y: 200 }, { x: 1, y: 390 }, { x: 2, y: 1000 }, { x: 3, y: 200 }, { x: 4, y: 230 } ],
color: "#6060c0"
});
graph.update();
});