Anyone know why my google chart is displaying the numbers on the left in such a strange order?
Here is an image of the problem:
And here is the code I'm using:
<script type="text/javascript">
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Ad', 'Views', 'Conversions', 'Appointments'],
["green", "9", "2", "2"],["logo", "18", "8", "1"],["maps", "8", "2", "0"],["resign", "14", "9", "1"],["scanimage", "1", "0", "0"], ]);
var options = {
chart: {
title: ''
}
};
var chart = new google.charts.Bar(document.getElementById('ad_chart'));
chart.draw(data, options);
}
</script>
The axis type is determined by the values in the data.
String values result in a Discrete axis, Numbers Continuous...
google.charts.load('44', {'packages': ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
// Number data (Continuous)
var data0 = google.visualization.arrayToDataTable([
['Ad', 'Views', 'Conversions', 'Appointments'],
["green", 9, 2, 2],
["logo", 18, 8, 1],
["maps", 8, 2, 0],
["resign", 14, 9, 1],
["scanimage", 1, 0, 0]
]);
// String data (Discrete)
var data1 = google.visualization.arrayToDataTable([
['Ad', 'Views', 'Conversions', 'Appointments'],
["green", "9", "2", "2"],
["logo", "18", "8", "1"],
["maps", "8", "2", "0"],
["resign", "14", "9", "1"],
["scanimage", "1", "0", "0"]
]);
var options = {
chart: {
title: ''
}
};
var chart0 = new google.charts.Bar(document.getElementById('ad_chart0'));
chart0.draw(data0, options);
var chart1 = new google.charts.Bar(document.getElementById('ad_chart1'));
chart1.draw(data1, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="ad_chart0"></div>
<div id="ad_chart1"></div>
Related
I am having trouble with reactivity Chartjs in Svelte. I wish that chart update eminently when the data for energy changes. What is missing in this code ?
<script lang="ts">
import { Line } from "svelte-chartjs";
import { onMount } from "svelte";
let labels = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
let energy =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let data = {
labels,
datasets: [
{
label: "Dataset",
data: energy,
borderColor: "rgb(255, 99, 132)",
backgroundColor: "rgba(255, 99, 132, 0.5)"
},
]
};
$:labels,energy,data
onMount(() => {
const interval = setInterval(() => {
rendom();
console.log(energy)
}, 1000);
return () => {
clearInterval(1);
};
})
function rendom() {
let index=Math.round(Math.random()*9);
energy[index]=Math.round(Math.random()*100)
}
</script>
<Line data={data}/>
Answers for my problem.
Looking at the Line Chart Example some imports from chart.js and ChartJS.register() seem to be necessary
The Line component from svelte-chartjs exports a reference to the chart on which .update() can be called after changing the data. The reference can be accessed via a local variable and bind:
Notice that clearInterval() takes the reference to the interval (and maybe change rendom to random as in Math.random())
REPL
<script>
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
LineElement,
LinearScale,
PointElement,
CategoryScale,
} from 'chart.js';
ChartJS.register(
Title,
Tooltip,
Legend,
LineElement,
LinearScale,
PointElement,
CategoryScale
);
import { Line } from "svelte-chartjs";
import { onMount } from "svelte";
let labels = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
let energy =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let chartRef
let data = {
labels,
datasets: [
{
label: "Dataset",
data: energy,
borderColor: "rgb(255, 99, 132)",
backgroundColor: "rgba(255, 99, 132, 0.5)"
},
]
};
onMount(() => {
const interval = setInterval(() => {
rendom();
}, 1000);
return () => {
clearInterval(interval);
};
})
function rendom() {
let index=Math.round(Math.random()*9);
energy[index]=Math.round(Math.random()*100)
chartRef.update()
}
</script>
<Line bind:chart={chartRef} data={data}/>
I'm trying to have 2 pie charts and show in the legend only the inner labels.
The issues is that seems the labels color (in the legend) are taken from the the outer dataset, probably because it is the first.
How can I change it?
var ctx = $("#myChart");
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['InnerLabel1','InnerLabebl2','InnerLabel3'],
datasets: [{
data: [1, 2, 1, 4],
backgroundColor: [
'rgba(31,119,180,0.5)','rgba(255,127,14,0.5)','rgba(255,127,14,0.5)','rgba(44,160,44,0.5)'
],
labels: [
'OuterLabel1','OuterLabel2','OuterLabel3','OuterLabel4'
]
}, {
data: [1, 3, 4],
backgroundColor: [
'#1f77b4','#ff7f0e','#2ca02c'
],
labels: ['InnerLabel1','InnerLabebl2','InnerLabel3'],
}, ]
},
options: {
responsive: true,
legend: {
display: true,
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ': ' + dataset.data[index];
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
<canvas id="myChart"></canvas>
You probably have to generate the legend labels yourself by defining a legend.labels.generateLabels function together with a legend.onClick that takes care of hiding and showing individual pie slices.
Here's an attempt of how this could be done.
const innerDataset = {
data: [1, 3, 4],
backgroundColor: ['#1f77b4', '#ff7f0e', '#2ca02c'],
labels: ['InnerLabel1', 'InnerLabebl2', 'InnerLabel3'],
};
var myChart = new Chart('myChart', {
type: 'pie',
data: {
datasets: [{
data: [1, 2, 1, 4],
backgroundColor: ['rgba(31,119,180,0.5)', 'rgba(255,127,14,0.5)', 'rgba(255,127,14,0.5)', 'rgba(44,160,44,0.5)'],
labels: ['OuterLabel1', 'OuterLabel2', 'OuterLabel3', 'OuterLabel4']
},
innerDataset
]
},
options: {
responsive: true,
legend: {
display: true,
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ': ' + dataset.data[index];
}
}
},
legend: {
labels: {
generateLabels: () => innerDataset.labels.map((label, i) => ({
text: label,
fillStyle: innerDataset.backgroundColor[i],
strokeStyle: '#fff',
hidden: myChart ? myChart.getDatasetMeta(1).data[i].hidden : false
}))
},
onClick: (event, legendItem) => {
const metaData = myChart.getDatasetMeta(1).data;
const iData = innerDataset.labels.indexOf(legendItem.text);
metaData[iData].hidden = !metaData[iData].hidden;
myChart.update();
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="myChart"></canvas>
Im trying to create a vega chart in an ember octane app but in doing so im able to render the chart once, but from then on, even if the values change, the chart doesn't get rerendered
the code im using is
component.ts
#tracked
model!: any;
get chartData() {
const data = this.model.data;
return {
table: data.map((datum: any) => {
return {
...datum
};
})
};
}
chart.hbs
{{vega-vis spec=this.spec data=this.chartData}}
why isn't it not working, but at the same time
doing set(this,"dataSource",this.model.data) works
dataSource: computed(function() {
return emberArray([
{"category": "A", "amount": 28},
{"category": "B", "amount": 55},
{"category": "C", "amount": 43},
{"category": "D", "amount": 91},
{"category": "E", "amount": 81},
{"category": "F", "amount": 53},
{"category": "G", "amount": 19},
{"category": "H", "amount": 87}
]);
}),
data: computed('dataSource.{[],#each.amount}', function () {
const dataSource = get(this, 'dataSource');
return {
table: dataSource.map((datum) => {
// return a copy because Vega Vis will mutate the dataset.
return {
...datum
};
})
};
})
Click here to view the Graph figure...
That would be a nice feature, but I don't think there is a direct way to do that. You could use the afterBuildTicks call back in combination with the min, max, and autoSkip options.
The Fix
The afterBuildTicks callback is passed the scale object. The scale object has an array of all the ticks to be displayed (stored in scale.ticks) so you could set your ticks in that array. Chart.js tries to make your chart look nice, so it will not show all the ticks by default. To fix this set the min and max to the lowest and highest values in your custom scale range. Also set autoSkip = false to make sure that all the ticks are displayed.
Example
jsfiddle with your example scale
jsfiddle with a smaller scale range
var ticks = [11000, 10000, 7000, 3000, 1000, 500, 100];
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
datasets: [{
data: [6000, 5000, 8000, 2000, 10000, 3500, 6000, 2000, 4000, 6000]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
autoSkip: false,
min: ticks[ticks.length - 1],
max: ticks[0]
},
afterBuildTicks: function(scale) {
scale.ticks = ticks;
return;
},
beforeUpdate: function(oScale) {
return;
}
}]
}
}
});
I'm using google visualization
var data2 = new google.visualization.DataTable();
data2.addColumn('string', 'time');
data2.addColumn('number', 'amount');
data2.addColumn({ type: 'string', role: 'tooltip' });
data2.addRows(rows_data);
var options2 = {
vAxis: { textPosition: 'none', title: '', textStyle: { fontName: 'arial'} },
hAxis: { slantedText: false, textStyle: { color: '#E6EFFA' }, gridlines: { color: '#E6EFFA', count: 20} },
backgroundColor: '#E6EFFA',
legend: 'none',
chartArea: { top: 0 },
colors: ['#435988'],
chartArea: { width: 800 }
};
chart2 = new google.visualization.LineChart(document.getElementById('chart_div_volume'));
I want the vAxis position to be on the right.
is it possible ?
Short Answer: Yes, but it's tricky.
Long Answer:
You need to set up a multi-axis chart. Basically, you create a dummy axis with no labels or anything to make it look like an axis. Then you configure a secondary axis. You create one set of dummy values (hidden) to put on the first axis, and plot your real data on the second.
Here is an example:
function drawVisualization() {
// Create and populate the data table.
var data = google.visualization.arrayToDataTable([
['Year', 'Dummy', 'Sales', 'Expenses'],
['2004', 0, 1000, 400],
['2005', null, 1170, 460],
['2006', null, 660, 1120],
['2007', null, 1030, 540]
]);
var options = {
title: 'Company Performance',
series: { 0: {targetAxisIndex: 0, visibleInLegend: false, pointSize: 0, lineWidth: 0},
1: {targetAxisIndex: 1},
2: {targetAxisIndex: 1}
},
vAxes: {
0: {textPosition: 'none'},
1: {},
}
};
var chart = new google.visualization.LineChart(document.getElementById('visualization'));
chart.draw(data, options);
}
google.charts.load('current', { 'packages': ['corechart'] });
google.charts.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Productivity');
data.addColumn('number', 'Composite');
data.addColumn({ type: 'number', role: 'annotation' });
data.addColumn('number', 'Average(N=5)');
var compositeDataArry = [];
compositeDataArry.push(["Ravi", 11, 11, 5]);
compositeDataArry.push(["Wasif", 5, 5, 5]);
compositeDataArry.push(["Vipin", 2, 2, 5]);
compositeDataArry.push(["Ankur", 3, 3, 5]);
compositeDataArry.push(["Pankaj", 1, 1, 5]);
compositeDataArry.push(["Dheeraj", 4, 4, 5]);
data.addRows(compositeDataArry);
var options = {
title: 'My Chart',
titleTextStyle: { color: '#264158', fontSize: 24 },
seriesType: 'bars',
annotations: {
alwaysOutside: true,
textStyle: {
color: '#000000',
fontSize: 15
}
},
hAxis: {
slantedText: true,
slantedTextAngle: -45
},
series: {
0: { targetAxisIndex: 0, },
1: { targetAxisIndex: 1, type: 'line' }
},
vAxes: {
0: { textPosition: 'none' },
1: {}
}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="chart_div" style="height: 500px; width: 100%"></div>
</body>
</html>