Stacked Column combined with Line - sapui5

We need to display a stacked column chart combined with a line chart and would like to stick to the VizFrame control offered by UI5. Is there a way to achieve this? It's not listed in the samples (https://sapui5.netweaver.ondemand.com/sdk/explored.html#/entity/sap.viz.ui5.controls.VizFrame/samples) but maybe there is a way to do it anyway.
EDIT
The data we need to display comes in the following format:
var data = [
{week: 1, stacked1: 10, stacked2: 20, stacked3: 30, line: 100},
{week: 2, stacked1: 12, stacked2: 13, stacked3: 14, line: 40},
{week: 3, stacked1: 14, stacked2: 25, stacked3: 26, line: 20},
{week: 4, stacked1: 15, stacked2: 24, stacked3: 33, line: 52}
];
So the idea is to have weeks on the x-axis, a stacked bar for the values stacked1, stacked2 and stacked3 as well as a value point for the line.

I think you want to use setVizType("stacked_combination") [or vizType: "stacked_combination"] on the VizFrame. You can see all the type on the getVizType() VizFrame doumentation. Here is a simple example where I extended the VizFrame and added two functions to display a Line Stacked Column Chart:
sap.viz.ui5.controls.VizFrame.extend("jonova.ui5.chart.JuVizFrame", {
renderer: { },
setLineStackedBar: function() {
var oModel = new sap.ui.model.json.JSONModel(
[{Product:"Total", Date: 2000, Available: 100},
{Product:"Total", Date: 2001, Available: 100},
{Product:"P1", Date: 2000, Utilized: 30},
{Product:"P1", Date: 2001, Utilized: 20},
{Product:"P2", Date: 2000, Utilized: 40},
{Product:"P2", Date: 2001, Utilized: 60}]);
var oDataset = new sap.viz.ui5.data.FlattenedDataset({
dimensions: [{name: 'Date', value: '{Date}'},
{name: 'Product', value: '{Product}'}],
measures: [{name: 'Available', value: '{Available}'},
{name: 'Utilized', value: '{Utilized}' }],
data: {path: "/"}});
var oFeeds = [new sap.viz.ui5.controls.common.feeds.FeedItem({uid: "valueAxis", type: "Measure", values: ["Utilized", "Available"]}),
new sap.viz.ui5.controls.common.feeds.FeedItem({uid: "categoryAxis", type: "Dimension", values: ["Date"]}),
new sap.viz.ui5.controls.common.feeds.FeedItem({uid: "color", type: "Dimension", values: ["Product"]})];
this.setChart("stacked_combination", oDataset, oModel, oFeeds);
},
setChart: function(aVizType, aDataset, aModel, aFeeds) {
this.setVizType(aVizType);
this.setDataset(aDataset);
this.setModel(aModel);
for( var i=0, len=aFeeds.length; i<len; i++) this.addFeed(aFeeds[i]);
},
});

Related

echarts: bar chart start at value?

echarts: bar chart bars are located left and right of the value on the category axis:
How to tell echarts to start the bar with the value on the category axis? Like this:
To clarify the problem, here ist another example. This is a chart of the hourly sum of precipitation. Every bar should show the sum from the bottom to the top of the hour, the data values are conencted to every bottom of the hour.
as you can see, the bars are not starting at 8:00, they are starting at 7:30.
Data: (timestamps are shown in CET)
series: [
{
name: "Niederschlag",
type: "bar",
data: [[1608534000000, 3], [1608537600000, 5], [1608541200000, 2], [1608544800000, 0], [1608548400000, 1] ],
barWidth: '100%'
}
]
It should look like this:
Start point of bar here doesn't matter, you need align labels to left: https://echarts.apache.org/en/option.html#series-bar.label.align
you need a hidden xAxis like below:
option = {
xAxis: [{
type: 'category',
data: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
show: false
}, {
type: 'category',
data: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24],
boundaryGap: false,
axisTick: { alignWithLabel: true },
position: 'bottom'
}],
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70, 110, 130,120,210,110,210],
type: 'bar',
barCategoryGap:'20%',
itemStyle: {
},
xAxisIndex: 0,
backgroundStyle: {
color: 'rgba(220, 220, 220, 0.8)'
}
}]
};
You have not provided the complete chart config, so I recommend using this one. Also pay attention on method useUTC and you need to know that "By default, echarts uses local timezone to formate time labels"
So I see this state of Chart by you data with offset -180:
var myChart = echarts.init(document.getElementById('chart'));
var chartData = [
[1608534000000, 3],
[1608537600000, 5],
[1608541200000, 2],
[1608544800000, 0],
[1608548400000, 1],
];
var option = {
tooltip: {},
xAxis: {
type: 'time',
data: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '22:00', '23:00'],
splitNumber: 24,
},
yAxis: {
type: 'value'
},
series: [{
name: "Niederschlag",
type: "bar",
data: chartData,
barWidth: '100%',
}],
useUTC: false,
};
myChart.setOption(option);
<script src="https://cdn.jsdelivr.net/npm/echarts#4.9.0/dist/echarts.min.js"></script>
<div id="chart" style="width: 1024px;height:400px;"></div>

How can I draw an additional horizontal grid line with a specific value in Google Bar chart (Not average value)

How can I draw an additional horizontal grid line with a specific value in Google Bar chart. The line I want to draw is not the average. It is a specific value.
What I am getting
What I need
How can I do this?
EDIT
This my data model:
var data = google.visualization.arrayToDataTable([
["Month", "Points", { role: "style" }, "TARGET GOAL"],
["Apr-19", 17, "#c4c4c4", 25],
["May-19", 32, "#c4c4c4", 25],
["Jun-19", 20, "#c4c4c4", 25],
["Jul-19", 22, "#c4c4c4", 25],
["Aug-19", 27, "#c4c4c4", 25],
["Sep-19", 26, "#c4c4c4", 25],
["Oct-19", 18, "#008600", 25],
["Nov-19", 18, "#008600", 25],
["Dec-19", 18, "#008600", 25],
]);
And in options object I have this:
seriesType: 'bars',
series:{
3: {
type: 'line'
}
}
Since 25 is the value I want to be rendered as a line and it is in the 4th position.
And finally
var chart = new google.visualization.ComboChart(document.getElementById("container_id"));
Am I missing something?
EDIT-2 Complete script:
google.charts.load("current", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart_ebcg_unitary);
function drawChart_ebcg_unitary() {
var data = google.visualization.arrayToDataTable([
["Month", "Points", { role: "style" }, "TARGET GOAL"],
["Apr-19", 17, "#c4c4c4", 25],
["May-19", 32, "#c4c4c4", 25],
["Jun-19", 20, "#c4c4c4", 25],
["Jul-19", 22, "#c4c4c4", 25],
["Aug-19", 27, "#c4c4c4", 25],
["Sep-19", 26, "#c4c4c4", 25],
["Oct-19", 18, "#008600", 25],
["Nov-19", 18, "#008600", 25],
["Dec-19", 18, "#008600", 25],
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2]);
var options = {
chartArea: {
left: 50,
width: "90%",
height: 250
},
title: "",
width: '100%',
height: 350,
bar: {groupWidth: "90%"},
legend: {position: "none"},
seriesType: 'bars',
series:{
1: {
type: 'line'
}
},
vAxis: {
minValue: 0,
title: 'SALES UNITS'
},
hAxis: {
title: 'MONTH'
},
annotations: {
textStyle: {
fontName: 'Arial, sans-serif',
color: '#000000',
fontSize: 12,
bold: true
},
alwaysOutside: true
}
};
var chart = new google.visualization.ComboChart(document.getElementById("ecbg_unitary"));
chart.draw(view, options);
}
jQuery(window).resize(function () {
drawChart_ebcg_unitary();
});
EDIT 3: Average line
How can I make the average line (please see screenshot) value (25) to appear only once, i.e at the end of the line rather than showing it on every month's column. This needs to look similar as in the screenshot under (What I need) section. Please advise.
use a ComboChart, which allows you to draw series of different types.
in the options, set the main seriesType.
then use the series option, to change the type of a specific series...
{
seriesType: 'bars',
series: {
1: {
type: 'line'
}
}
}
see following working snippet...
google.charts.load("current", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart_ebcg_unitary);
function drawChart_ebcg_unitary() {
var data = google.visualization.arrayToDataTable([
["Month", "Points", { role: "style" }, "TARGET GOAL"],
["Apr-19", 17, "#c4c4c4", 25],
["May-19", 32, "#c4c4c4", 25],
["Jun-19", 20, "#c4c4c4", 25],
["Jul-19", 22, "#c4c4c4", 25],
["Aug-19", 27, "#c4c4c4", 25],
["Sep-19", 26, "#c4c4c4", 25],
["Oct-19", 18, "#008600", 25],
["Nov-19", 18, "#008600", 25],
["Dec-19", 18, "#008600", 25],
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2, 3]);
var options = {
chartArea: {
left: 50,
width: "90%",
height: 250
},
title: "",
width: '100%',
height: 350,
bar: {groupWidth: "90%"},
legend: {position: "none"},
seriesType: 'bars',
series:{
1: {
type: 'line'
}
},
vAxis: {
minValue: 0,
title: 'SALES UNITS'
},
hAxis: {
title: 'MONTH'
},
annotations: {
textStyle: {
fontName: 'Arial, sans-serif',
color: '#000000',
fontSize: 12,
bold: true
},
alwaysOutside: true
}
};
var chart = new google.visualization.ComboChart(document.getElementById("ecbg_unitary"));
chart.draw(view, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="ecbg_unitary"></div>
EDIT
to display the annotation for the average only once,
use your own calculation for the annotation,
and only return a value if the row index equals the last row...
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: 'stringify',
sourceColumn: 1,
type: 'string',
role: 'annotation'
},
2, 3, {
calc: function(dt, row) {
var annotation = null;
if (row === (dt.getNumberOfRows() - 1)) {
annotation = dt.getFormattedValue(row, 3);
}
return annotation;
},
type: 'string',
role: 'annotation'
}
]);

Google Charts - Timeline - Show all times instead of every 2 hours

I have a very simple question that I'm struggling to find out:
Instead of this
I want this:
The problem is that google charts resizes it based on the screen size. But I want to show all hours even on a small screen.
I also want to add an extra line for every 15 minutes between the hours. Just the lines, not the label. Is it possible?
Here is my code:
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'President' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'Work', new Date(2018, 4, 25, 8, 30), new Date(2018, 4, 25, 17, 30) ],
[ 'Rest', new Date(2018, 4, 25, 0, 0), new Date(2018, 4, 25, 8, 30) ],
[ 'Rest', new Date(2018, 4, 25, 17, 30), new Date(2018, 4, 26, 0, 0) ]
]);
chart.draw(dataTable, {
});
}
https://jsfiddle.net/8xpkLe46/

How can configure my y-axis on chart.js?

I am trying to build graph.
My y-axis start with 0 here, I dont know how to configure it and why it is talking 0 - I see other post which mentioned scaleOverride:true, scaleStartValue:0.1, scaleStepWidth:5 - I dont know how to use that in my below code , how can configure y-axis in chart.js.
Any pointer would be
I have following code
var barChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: 'Dataset 1',
backgroundColor: "rgba(220,220,220,0.5)",
data: [6, 6, 6, 8, 6, 9, 8]
}]
};
function barChart() {
var context = document.getElementById('stacked').getContext('2d');
var myBar = new Chart(context, {
type: 'bar',
data: barChartData,
options: {
title:{
display:true,
text:"Chart.js Bar Chart - Stacked"
},
tooltips: {
mode: 'label'
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
};
$(document).ready(function() {
$(document).ready(barChart);
});
Thank you guys for helping, I observed that chart.js will automatically take value for y-axis based on your data, you can change y/x-axis setting under Options > Scales , I also needed to change step size of y-axis and get rid of x-axis grid line,"ticks" is something I was looking for, here is my sample code and steps to achieved all these.
Step 1) Canvas this is place holder where your chart will display on JSP
<canvas width="1393px;" height="500px;" id="stacked"></canvas>
Step 2) Create sample datasets (this is JSON you need to create based on your requirement but make sure you provide exact the same formated JSON response as given below along with your data.
var barChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: 'Dataset 1',
backgroundColor: "red",
data: [9, 6, 6, 8, 6, 9, 8]
},
{
label: 'Dataset 1',
backgroundColor: "rgba(225,226,228,0.5)",
data: [9, 6, 6, 8, 6, 9, 8]
}]
};
or you can call JSON from controller inside script as below
var jsonArry = <%=request.getAttribute("jsonArry")%>;
Step 3) call that JSON which you have created at step 2
function barChart(){
var context = document.getElementById('stacked').getContext('2d');
var myBar = new Chart(context, {
type: 'bar',
data: jsonArry,
options: {
tooltips: {
mode: 'label'
},
responsive: true,
scales: {
xAxes: [{
ticks:{
stepSize : 10,
},
stacked: true,
gridLines: {
lineWidth: 0,
color: "rgba(255,255,255,0)"
}
}],
yAxes: [{
stacked: true,
ticks: {
min: 0,
stepSize: 1,
}
}]
}
}
});
};
Hope this will help , for reference I have used following documentation Chart JS
Thanks.
Just remove the stacked option and it will stop starting from 0 (unless your data starts from 0).
Related fiddle - http://jsfiddle.net/rsyk9he0/
For stacked charts, Chart.js builds a list of positive and negative sums for each stack (bar) and then uses that to figure out the scale min and max values. If there are no negative values, the list of negative sums is a list of 0s. This forces the scale min to be 0.
scaleStartValue, scaleStepWidth, etc. are options from v1.x of Chart.js. You are using v2.x. See How to make integer scale in Chartjs for the 2.x equivalents.

Google Charts API - chart with two yAxis - like the one from Google Sheets

I did quite a big research and I can not believe that with the current version of the Google Charts API I cannot do a chart like the one in Google Sheets - https://support.google.com/drive/answer/2451203?hl=en with 2 yAxis with independant values and one common xAxis.
*Update: So far I managed to do a bar & line chart. I need exactly the same thing but now the vAxis on left has values from 1 to 5. I need additional vAxis on right that has values from 0 to 2 (currently, there is an additional xAxis for "STD", but it's values are not 0 to 2, but 1 to 5)
function drawVisualization() {
var data = google.visualization.arrayToDataTable([
['Month', 'Cups', 'STD'],
['2.2', 4.1, 1.5],
['2.3', 2.1, 1],
['2.4', 3, 1.4],
['2.6', 2, 1.2],
['2.7', 2, 1.3],
['2.1', 1.1, 1.7]
]);
var options = {
title : 'Monthly Coffee Production by Country',
hAxis: {title: "Month"},
vAxis: {
title: "Cups",
gridlines: {
count: 5
},
baseline: 1,
format: "#"
},
seriesType: "bars",
series: {1: {type: "line"}}
};
var chart = new google.visualization.ComboChart(document.getElementById('visualization'));
chart.draw(data, options);
}
Problem solved!
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var data = google.visualization.arrayToDataTable([
['Month', 'AVRG', 'STD'],
['Item 1', 4.1, 1.5],
['Item 2', 2.1, 1.1],
['Item 3', 3, 0.7],
['Item 4', 2, 1.5],
['Item 5', 2, 1.7],
['Item 6', 1.1, 0.3]
]);
var options = {
title : 'Title',
hAxis: {title: "Month"},
vAxes:[
{
title: "AVRG",
gridlines: {
count: 5
},
baseline: 1,
format: "#"
},
{
title: "STD",
gridlines: {
count: 2
},
baseline: 0,
format: "#"
}
],
series:[
{targetAxisIndex:0},
{targetAxisIndex:1, type: "line"}
],
seriesType: "bars"
};
var chart = new google.visualization.ComboChart(document.getElementById('visualization'));
chart.draw(data, options);
}