Set max bar height in horizontalBar chart - height

Is it possible?
I tried something like
"elements": {
"bar": {
"maxHeight": 10,
"height": 10
}
},
But it did not work...
When I have many values, it looks like this:
And when there are only a few values, it looks like this (and i would like it to be thin as in the previous image):

I reached to an answer myself.
First, I create the chart inside a div:
<div id="chart-control">
<canvas id="chart"></canvas>
</div>
Then I change the div's height based on the quantity of lines[data.length] * (4/3)
document.getElementById("chart-control").style.height = (data.length * (4/3)) + "em";

Related

Howto show absolute number in Apexcharts pie chart

The pie chart I created with Apexcharts shows relative (percentage) numbers at the circle (like the "99.9%" in the screenshot below).
Instead of the relative number I'd like to show the absolute value like what's in the tooltip (see example: "6752").
I tried a formatter function with signature function(value, {seriesIndex,dataPointIndex,w}), but value is the relative value (e.g. 99.9), dataPointIndex is undefined, seriesIndex is always 1 and w contains the whole chart config without being specific to this slice of the pie.
How can I show absolute numbers?
You have the right strategy, but probably not the right formatter. The one you need is dataLabels.formatter:
let options = {
series: [10, 20, 15],
chart: {
width: 350,
type: 'pie'
},
labels: ['Label 1', 'Label 2', 'Label 3'],
dataLabels: {
formatter: (val, { seriesIndex, w }) => w.config.series[seriesIndex] // <--- HERE
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>

How do I move the x axis like a window in google chart while x increases

I would like to draw a chart to my html, the chart I am using is google chart. However, while my x value is increasing, the chart is getting bigger. But I just want a fixed size window which increase both minimum x value and maximum x value. Like sliding window.
The attachment below is my code. This is the js code which updates the gets the value and updates the chart
// load google charts library
google.load("visualization", "1", {packages:["corechart"]});
// for rest, walk, fast_walk data
var data, options, chart;
var xMin = 0;
var xMax = 10;
var i = 0;
/* initialize chart1 - rest, walk, fast_walk data */
function drawChart(data, options) {
var chart = new
google.visualization.LineChart(document.getElementById('data-container'));
chart.draw(data, options);
return(chart);
}
/* update the chart1 - rest, walk, fast_walk data */
function updateChart(percentage) {
i = (i + 1);
data.addRow([
""+i,
percentage
]);
if(xMax >= 9) {
xMin + 1;
}
xMax + 1;
chart.draw(data, options);
}
$(function() {
data = google.visualization.arrayToDataTable([
['Time', 'percentage'],
['0', 0],
]);
options = {
title: 'Energy data',
"curveType": "function",
vAxis: {
min: xMin,
max: xMax
}
};
chart = drawChart(data, options);
});
/* reset charts */
function reset(){
i = 0;
data = google.visualization.arrayToDataTable([
['Time', 'percentage'],
['0', 0],
]);
options = {
title: 'Energy data',
"curveType": "function",
hAxis: {
viewWindow: {
min: 0,
max: 10
}
}
};
chart = drawChart(data, options);
}
I am wondering if it can be designed into a sliding window, so that the x value doesn't stick with the minimum value 0. instead if we want to see the earliest value, we can just scroll left.
According to the documentation at [https://developers.google.com/chart/interactive/docs/gallery/linechart]
/* copied from site*/
var options = {
chart: {
title: 'Box Office Earnings in First Two Weeks of Opening',
subtitle: 'in millions of dollars (USD)'
},
width: 900, //<--- set fixed width like so
height: 500
};
To get a scrollable div,you can wrap your chart inside another div
<div class='h-scrollable' > <!---- chart code here ----> </div>
and for css
.h-scrollable {
width: 100%;
overflow: hidden; // only if you don't want y axis to be scrollable
overflow-x: auto;
}
Now, for the chart give a width depending on the number of x values you have. You could do a mathematical computation by taking the width of the h-scrollbale div in javascript and dividing it by number of x-points you want in a window and then multiplying it with total x values you have and setting it as chart width.
Update:
inititally get the width of h-scrollable as let viewWidth = document.querySelector(".h-scrollable").offsetWidth
[refer : How to find the width of a div using raw JavaScript?
Then if you want to show 10 x values in a view, divide viewWidth by 10 to get one xWidth. Now you can re-render the chart each time by setting width as no.of X values * xWidth so that it scrolls accordingly
Upon each update, you can just remove the first raw.

Google Chart: Showing bars wrongly

I am currently working on Google Bar Chart-Dual-X and it is working nice.
Issue:
The bar is showing wrongly.For an example: Suppose I want to show Obtained Marks and Total Marks.But Issue is Google Chart shows Obtained Marks Bar bigger than the Total Mark(which is not true at all). You can see below pic :
As you can see in the pic that Chap 6,7,8 is having Obtained Mark Bar is bigger than the Total Mark Bar.
Code
<script type="text/javascript">
google.load("visualization", "1.1", {packages:["bar"]});
google.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Subject', 'Obtained Marks', 'Total Marks'],
<?php
$i=1;
foreach($sql_get_marks_results as $sql_get_marks_result){
echo "['".$sql_get_marks_result->meta_subject."', ".$sql_get_marks_result->obtained_marks.", ".$sql_get_marks_result->total_marks."]";
if($i != count($sql_get_marks_results)){echo ",";}
$i++;
}
?>
]);
var options = {
width: 900,
chart: {
title: 'Markesheet',
subtitle: 'distance on the left, brightness on the right'
},
bars: 'horizontal', // Required for Material Bar Charts.
series: {
0: { axis: 'obtained' }, // Bind series 0 to an axis named 'distance'.
1: { axis: 'total' } // Bind series 1 to an axis named 'brightness'.
},
axes: {
x: {
obtained: {label: 'Obtained'}, // Bottom x-axis.
total: {side: 'top', label: 'Total'} // Top x-axis.
}
}
};
var chart = new google.charts.Bar(document.getElementById('dual_x_div'));
chart.draw(data, options);
};
</script>
Is anyone here who came across similar problem or anyone can help me out in this ?
Tell me if you want more detail about this.
The display shown in your screen shots is correct.
The "total marks" (red) dataset follows the bottom x-axis.
And the "Obtained" (blue) dataset follows the top x-axis.
I think that the scale (inferred by your data range) of your two X-axis is quite close. And because of this it's easy to confuse them.
Dual x-axis charts are good for complementary datasets with values in very different ranges as in the example given in the documentation.
In your case you'd be better of using a simple (single axis) bar chart to avoid that kind of confusion.

Multiple Canvas in ScaleRaphael - circle in 2nd canvas appears in 1st

I just got started with Raphael, but I don't get it right to make multiple canvases in ScaleRaphael
(I#m using this to make the site after responsive > are there alternatives for that?
Multiple ScaleRaphael Canvases: http://jsfiddle.net/karo/gMyP5/13/
or full view: http://jsfiddle.net/karo/gMyP5/13/embedded/result/
A strange thing happens here.
The red circle should be in the 2nd div but if you look in the code with eg. firebug in the fullview then you see that both svgs are in the inside a Why is that?
Do you have any idea for me?
Thanks Kaor
my code:
HTML
<div id="wrapper">
<div id="paper"></div>
<br>
<div id="paper2"></div>
</div>
JavaScript:
var paper = new ScaleRaphael("paper",200,200);
var circle = paper.circle(100, 100, 60).attr({fill:'red'});
var paper2 = new ScaleRaphael("paper2",200,200);
var circle2 = paper2.circle(50, 50, 30).attr({fill:'black'});
function resizePaper(){
var win = $(this);
paper.changeSize(win.width(), win.height(), true, false);
paper2.changeSize(win.width(), win.height(), true, false);
}
resizePaper();
$(window).resize(resizePaper);
CSS
#wrapper
{
position:relative;
}
#paper {
background-color: lightgray;
width:100%;
height:200px;
position:relative!important;
}
#paper2
{
background-color: orange;
width:100%;
height:100px;
position:relative!important;
}
svg
{
position:absolute!important;
top:0;
left:0;
}
ScaleRaphael only supports one canvas. In the code you can see it re-referencing the first existing svggroup or vmlgroup element.
You do not need ScaleRaphael to do what you are doing. Since version 2 Raphael has included Paper.setViewBox and it always included Paper.setSize, which together do this already.
I found an issue and a workaround how it works....
Have a look here: http://jsfiddle.net/karo/r4qvt/12/
I have first the paper div and then the red div
<div id="paper"></div>
<div id="red"></div>
</div>
</div>
And if I make the redpaper for the div "red" and the rectangle in it before I make the paperGrey and "talk to the" first div. THEN IT WORKS
var redpaper = new ScaleRaphael("red",300,200);
redpaper.rect(0, 0, 250, 100).attr({fill:'red'});
var paperGrey = new ScaleRaphael("paper",400,200);
var circle = paperGrey.circle(40, 140, 60).attr({fill:'blue'});
If I do it the OTHER WAY ROUND IT DOESNT WORK
var paperGrey = new ScaleRaphael("paper",400,200);
var circle = paperGrey.circle(40, 140, 60).attr({fill:'blue'});
var redpaper = new ScaleRaphael("red",300,200);
redpaper.rect(0, 0, 250, 100).attr({fill:'red'});
...strange, but I found a solution ;)

Multiple baselines with dual y-axis Google Chart

I'm using the Google Visualization API for a simple sales chart that has two series, number of sales and sales value, that I'm showing on a column chart with two vetical axes. The sales value can be negative, such as for returns, but this is causing the graph to show two different baselines. The zero baseline for number of sales is in line with the lowest sales value figure. Here's an example of the code with some sample data:
google.load('visualization', '1.0', { 'packages': ['corechart'] });
google.setOnLoadCallback(drawSalesChart);
function drawSalesChart() {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Order Source');
dataTable.addColumn('number', 'Num Sales');
dataTable.addColumn('number', 'Sales Value');
dataTable.addRows([
['Web (Order)', 300, 31000],
['Call Centre (Order)', 700, 61000],
['Call Centre (Return)', 50, -4100],
['Call Centre (Exchange)', 10, 800]
]);
var options = {
title: 'Sales by Order Source',
hAxis: { title: 'Order Source' },
series: {
0: { targetAxisIndex: 0 },
1: { targetAxisIndex: 1 },
},
vAxes: {
0: { title: 'Num Sales' },
1: { title: 'Sales Value' }
}
};
new google.visualization.ColumnChart(
document.getElementById('livesales-chart-container')).draw(dataTable, options);
}
I've been through the API documentation as there's information on setting the baseline but there doesn't seem to be a way to tie the zero of each vAxis to the same point. I've tried searching Google and StackOverflow and there are similar questions but I can't see that anyone has had this problem.
How can I, or even can I, show a single baseline at zero for both series?
From a visualization perspective, it may be a lot better to create two separate charts on top of each other since the data provided is very different both in scope and in what it is explaining.
<!--
You are free to copy and use this sample in accordance with the terms of the
Apache license (http://www.apache.org/licenses/LICENSE-2.0.html)
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>
Google Visualization API Sample
</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', {packages: ['corechart']});
</script>
<script type="text/javascript">
function drawSalesChart() {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Order Source');
dataTable.addColumn('number', 'Num Sales');
dataTable.addColumn('number', 'Sales Value');
dataTable.addRows([
['Web (Order)', 300, 31000],
['Call Centre (Order)', 700, 61000],
['Call Centre (Return)', 50, -4100],
['Call Centre (Exchange)', 10, 800]
]);
var dataView1 = new google.visualization.DataView(dataTable);
dataView1.setColumns([0,1]);
var dataView2 = new google.visualization.DataView(dataTable);
dataView2.setColumns([0,2]);
var options1 = {
title: 'Sales by Order Source',
hAxis: { title: 'Order Source' },
vAxis: { title: 'Num Sales' }
};
var options2 = {
title: null,
hAxis: { title: null, textPosition: 'none' },
vAxis: { title: 'Sales Value' }
};
new google.visualization.ColumnChart(
document.getElementById('chart1')).draw(dataView1, options1);
new google.visualization.ColumnChart(
document.getElementById('chart2')).draw(dataView2, options2);
}
google.setOnLoadCallback(drawSalesChart);
</script>
</head>
<body style="font-family: Arial;border: 0 none;">
<div id="chart1" style="width: 600px; height: 300px;"></div>
<div id="chart2" style="width: 600px; height: 100px;"></div>
</body>
</html>
Of course, this would need some prettying-up to make the graphs line up properly, and to make the colors work as you'd like, but this way you can focus on the main data you want to show, while keeping the other info nearby as a reference.
If you are insistent on doing them on the same graph, you will need to write a function to be able to calculate where the grid lines should lie (or figure out how Google does it, but I couldn't find it on a web search).
To figure out what the max/min values should be on a graph, an "easy" way is to take the difference between the minimum and maximum values, count the number of grid lines you will have (default for google is 5), round up to the nearest significant digit of your biggest number, and use those as your grid line dividers.
e.g. Taking your first column: 300, 700, 50, 10
Max Value: 700
Min Value: 10
Exponent: LEN(Max)-1 = 2 = 10^2, nearest 100
Grid Lines: 5 - 1 = 4 (assuming you want the bottom value to serve as the floor at the same rounding, you need 4 more iterations to go over the top value)
Difference Between Max and Min: 690
Required Interval: 690 / 4 = 172.5
Rounded up to the nearest 100: 200
Min Value: FLOOR(Min,200) = 0
Max Value: CEILING(Max,200) = 800
Grid Line 1: 0
Grid Line 2: 200
Grid Line 3: 400
Grid Line 4: 600
Grid Line 5: 800
Note, this matches what your chart shows. However, it won't work for negative values because the math gets a bit more complicated.
First you need to figure out the ratio of negative values to the total difference in min and max values.
e.g. Given your Column 2 data: 31000, 61000, -4100, 800
Min Value: -4100
Max Value: 61000
Difference: 65100
Negative Ratio: 6.3%
So 6.3% of your range is in the negative portion. Given 5 grid lines, that means that one grid line will need to be below 0, and you only have 4 grid lines for the positive portion. Since the negative portion is smaller than the positive portion, the positive portion will determine the grid line spacings.
So now you have 4 grid lines to cover the positive portion (0 - 61000), which means you have 3 segments from 0 to reach 61000.
That means 61000 / 3, rounded up to 4 significant digits, or 30,000.
That makes your gridlines:
-30,000
0
30,000
60,000
90,000
Coincidentally, this is what you got in your chart.
Now that you know the second series has 1 negative gridline, you'd have to readjust your first series to match the second one. So instead of having 5 gridlines (0 and 4 above), you now have 1 negative gridline, 1 0, and then 3 above zero that need to reach 700. So you take the 700 positive value you have, divide by 3, for 233.333.
Round that up to the nearest 100, and you get 300.
So your first chart max/min would be readjusted to -300, and 900 for the following gridlines:
-300
0
300
600
900
This will set the same baseline.
That will solve your problem -- all you need to do is code that logic in to Javascript! Let us know if you do it, I'm sure someone else will have the same issue down the line.