How to prevent first/last bars from being cut off in a chart with time scale - momentjs

How do I prevent the first and last bars from being cut off (showing half)?
I need to show the short month names on the x-axis. I've tried playing around with various min/max settings, but I can't seem to get it right.
var graphData = {
dates: [
'2016-06-01',
'2016-07-01',
'2016-08-01',
'2016-09-01',
'2016-10-01',
'2016-11-01',
'2016-12-01',
'2017-01-01',
'2017-02-01',
'2017-03-01',
'2017-04-01',
'2017-05-01'
],
wins: [23, 5, 13, 24, 8, 11, 23, 5, 13, 24, 8, 11],
draws: [2, 1, 2, 0, 2, 2, 3, 1, 2, 4, 0, 1],
losses: [3, 1, 2, 10, 8, 8, 3, 1, 2, 10, 8, 8],
winRates: [50, 40, 72, 30, 46, 80, 50, 40, 72, 30, 46, 80]
};
var winsMax = Math.max.apply(Math, graphData.wins);
var lossesMax = Math.max.apply(Math, graphData.losses);
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "bar",
data: {
labels: graphData.dates.map((date) => moment(date)),
datasets: [
{
type: "bar",
backgroundColor: "green",
hoverBackgroundColor: "green",
data: graphData.wins,
yAxisID: "winsAndLosses"
},
{
type: "bar",
backgroundColor: "red",
hoverBackgroundColor: "red",
data: graphData.losses.map((i) => -i),
yAxisID: "winsAndLosses"
},
{
type: "line",
data: graphData.winRates,
fill: true,
backgroundColor: "gray",
pointRadius: 0,
pointHoverRadius: 0,
yAxisID: "winRate"
}
]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "month",
displayFormats: {
month: "MMM"
}
},
stacked: true,
gridLines: {
display: false
},
ticks: {
callback: (label) => label.toUpperCase(),
fontSize: 10
}
}],
yAxes: [
{
id: "winsAndLosses",
stacked: true,
ticks: {
min: (lossesMax + 10) * -1,
max: winsMax + 10,
callback: (label) => Math.abs(label) // TODO: Localization (number formatting).
},
display: false
},
{
id: "winRate",
ticks: {
min: 0,
max: 100,
stepSize: 10,
callback: (label) => label + "%", // TODO: Localization (number formatting).
fontSize: 10
}
}
]
}
}
});
.myChartDiv {
max-width: 800px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="800" height="400"></canvas>
</div>
</body>
</html>

There's a setting called offset which seems to work for me:
xAxes: [{
offset: true
}]
var graphData = {
dates: [
'2016-06-01',
'2016-07-01',
'2016-08-01',
'2016-09-01',
'2016-10-01',
'2016-11-01',
'2016-12-01',
'2017-01-01',
'2017-02-01',
'2017-03-01',
'2017-04-01',
'2017-05-01'
],
wins: [23, 5, 13, 24, 8, 11, 23, 5, 13, 24, 8, 11],
draws: [2, 1, 2, 0, 2, 2, 3, 1, 2, 4, 0, 1],
losses: [3, 1, 2, 10, 8, 8, 3, 1, 2, 10, 8, 8],
winRates: [50, 40, 72, 30, 46, 80, 50, 40, 72, 30, 46, 80]
};
var winsMax = Math.max.apply(Math, graphData.wins);
var lossesMax = Math.max.apply(Math, graphData.losses);
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "bar",
data: {
labels: graphData.dates.map((date) => moment(date)),
datasets: [
{
type: "bar",
backgroundColor: "green",
hoverBackgroundColor: "green",
data: graphData.wins,
yAxisID: "winsAndLosses"
},
{
type: "bar",
backgroundColor: "red",
hoverBackgroundColor: "red",
data: graphData.losses.map((i) => -i),
yAxisID: "winsAndLosses"
},
{
type: "line",
data: graphData.winRates,
fill: true,
backgroundColor: "gray",
pointRadius: 0,
pointHoverRadius: 0,
yAxisID: "winRate"
}
]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
time: {
unit: "month",
displayFormats: {
month: "MMM"
}
},
stacked: true,
gridLines: {
display: false
},
ticks: {
callback: (label) => label.toUpperCase(),
fontSize: 10
},
offset:true
}],
yAxes: [
{
id: "winsAndLosses",
stacked: true,
ticks: {
min: (lossesMax + 10) * -1,
max: winsMax + 10,
callback: (label) => Math.abs(label) // TODO: Localization (number formatting).
},
display: false
},
{
id: "winRate",
ticks: {
min: 0,
max: 100,
stepSize: 10,
callback: (label) => label + "%", // TODO: Localization (number formatting).
fontSize: 10
}
}
]
}
}
});
.myChartDiv {
max-width: 800px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="800" height="400"></canvas>
</div>
</body>
</html>

Related

Stacked horizontal chart. How to trigger individual hover in the stacked element?

I am trying to show different tooltips for the data stacked in the horizontal bar.
Code from: https://thewebdev.info/2020/08/18/chart-js%E2%80%8A-%E2%80%8Astacked-bar-chart-and-radial-chart/
var ctx = document.getElementById('myChart').getContext('2d');
var stackedBar = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
],
borderWidth: 1
}]
},
options: {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
});
When we hover on the bar, it shows the tooltip data of all stacks at once wherever we hover. But instead, I want a different tooltip on each element of the stack element. I shall really appreciate your help.
You can use the tooltipmode point for this.
Example:
var options = {
type: 'horizontalBar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'red'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: 'blue'
}
]
},
options: {
tooltips: {
mode: 'point'
},
scales: {
yAxes: [{
stacked: true
}],
xAxes: [{
stacked: true
}]
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</body>

How do I draw line after receiving data - Route from GPS Trace

I just started using Here Maps. Before I used Google Direction, I want to try use 'Here Maps' API. This is example JSON result. After I got this result, How do I implement this into Polyline or Direction (MAP Here)? Thanks
{
RouteLinks: [
{
linkId: 25664478,
functionalClass: 5,
shape: "51.1017723 0.3934907 51.1018066 0.3933491 51.1018295 0.39326",
linkLength: 15.575699313408467
},
{
linkId: 25664473,
functionalClass: 4,
shape: "51.1018295 0.39326 51.1022491 0.39348",
linkLength: 44.17562556306323
},
{
linkId: 25664459,
functionalClass: 4,
shape: "51.1022491 0.39348 51.1022987 0.39351",
linkLength: 5.305684979980019
},
{
linkId: 781742854,
functionalClass: 4,
shape: "51.1022987 0.39351 51.1025505 0.39365",
linkLength: 26.670487136749067
},
{
linkId: 781742855,
functionalClass: 4,
shape: "51.1025505 0.39365 51.1027794 0.39378",
linkLength: 24.302012297623005
},
{
linkId: 25664450,
functionalClass: 4,
shape: "51.1027794 0.39378 51.1030807 0.39403",
linkLength: 33.974229462422905
},
{
linkId: 25664444,
functionalClass: 4,
shape: "51.1030807 0.39403 51.103241 0.39413",
linkLength: 17.215963662407898
},
{
linkId: 25664440,
functionalClass: 4,
shape: "51.103241 0.39413 51.1033783 0.39421 51.1035385 0.39433 51.1036797 0.39445",
linkLength: 48.32839625333388
},
{
linkId: 25664427,
functionalClass: 4,
shape: "51.1036797 0.39445 51.1038017 0.39454",
linkLength: 13.445306290244636
},
{
linkId: 860272608,
functionalClass: 4,
shape: "51.1038017 0.39454 51.1039391 0.39465",
linkLength: 15.378381014646559
},
{
linkId: 860272609,
functionalClass: 4,
shape: "51.1039391 0.39465 51.1041908 0.39484",
linkLength: 27.85427285471891
},
{
linkId: 781742870,
functionalClass: 4,
shape: "51.1041908 0.39484 51.1043282 0.39494 51.1045609 0.39506",
linkLength: 39.56626207722863
},
{
linkId: 781742871,
functionalClass: 4,
shape: "51.1045609 0.39506 51.1047287 0.39515 51.1050262 0.3953021",
linkLength: 48.951382959921716
}
],
TracePoints: [
{
confidenceValue: 1, linkIdMatched: 25664478, matchDistance: 1.46,
routeLinkSeqNrMatched: 0, lat: 51.10177, lon: 0.39349,
elevation: 0, speedMps: 0, headingDegreeNorthClockwise: 10000,
latMatched: 51.10178065190155, lonMatched: 0.3934977183445852,
timestamp: 0, headingMatched: 114.46568884011239,
minError: 1.3027890756593314
},
{
confidenceValue: 1, linkIdMatched: 25664478, matchDistance: 1.57,
routeLinkSeqNrMatched: 0, lat: 51.10181, lon: 0.39335,
elevation: 0, speedMps: 0, headingDegreeNorthClockwise: 10000,
latMatched: 51.10182, lonMatched: 0.39336,
timestamp: 0, headingMatched: -65.53429247174023,
minError: 1000000
},
{
confidenceValue: 1, linkIdMatched: 781742854, matchDistance: 1,
routeLinkSeqNrMatched: 4, lat: 51.10255, lon: 0.39366,
elevation: 0, speedMps: 0, headingDegreeNorthClockwise: 10000,
latMatched: 51.102547928304084, lonMatched: 0.3936687569824506,
timestamp: 0, headingMatched: 20.644254301899522,
minError: 0.6541474931313044
},
{
confidenceValue: 1, linkIdMatched: 860272608, matchDistance: 4.59,
routeLinkSeqNrMatched: 10, lat: 51.10398, lon: 0.39466,
elevation: 0, speedMps: 0, headingDegreeNorthClockwise: 10000,
latMatched: 51.10394, lonMatched: 0.39465,
timestamp: 0, headingMatched: 25.217234923243595,
minError: 1.2405405512432781
},
{
confidenceValue: 1, linkIdMatched: 1022687693, matchDistance: 1.33,
routeLinkSeqNrMatched: 14, lat: 51.10501, lon: 0.39533,
elevation: 0, speedMps: 0, headingDegreeNorthClockwise: 10000,
latMatched: 51.105012239590245, lonMatched: 0.39531827230152644,
timestamp: 0, headingMatched: 16.91643828307876,
minError: 0.8568378930601925
}
],
Warnings: [
{
"tracePointSeqNum": -1,
"routeLinkSeqNum": 3,
"category": 3,
"text": "Entering link 781742854 into forbidden driving direction"
}
],
MapVersion: "2013Q4" }
*linkId,shape is like that trip points which is given by Heremap api step1.
You just draw route by polyline function.
addPolylineToMap(map,linkId);
function addPolylineToMap(map,linkId) {
for (j = 0; j < (shape.length - 1); j = j + 2) {
var strip = new H.geo.Strip();
strip.pushPoint({lat: shape[j],lng: shape[j+1]});
}
}

highcharts, four aeraranges with linear gradients

I'm trying to create chart in Highcharts with four arearanges and one line. I'm doing my best to get something like on image:
arearanges
I'v managed to do something like this:
$(function () {
var rangesHI = [
[1246406400000, 90, 75],
[1248998400000, 90, 75]
],
rangesME = [
[1246406400000, 75, 60],
[1248998400000, 75, 60]
],
rangesNO = [
[1246406400000, 60, 35],
[1248998400000, 60, 35]
],
rangesLO = [
[1246406400000, 35, 15],
[1248998400000, 35, 15]
],
averages = [
[1246406400000, 31.5],
[1246492800000, 32.1],
[1246579200000, 33],
[1246665600000, 33.8],
[1246752000000, 31.4],
[1246838400000, 31.3],
[1246924800000, 38.3],
[1247011200000, 35.4],
[1247097600000, 36.4],
[1247184000000, 47.7],
[1247270400000, 47.5],
[1247356800000, 37.6],
[1247443200000, 47.7],
[1247529600000, 46.8],
[1247616000000, 47.7],
[1247702400000, 46.3],
[1247788800000, 47.8],
[1247875200000, 48.1],
[1247961600000, 57.2],
[1248048000000, 54.4],
[1248134400000, 53.7],
[1248220800000, 55.7],
[1248307200000, 54.6],
[1248393600000, 55.3],
[1248480000000, 45.3],
[1248566400000, 55.8],
[1248652800000, 65.2],
[1248739200000, 74.8],
[1248825600000, 44.4],
[1248912000000, 55],
[1248998400000, 43.6]
];
$('#container').highcharts({
title: {
text: null
},
xAxis: {
type: 'datetime'
},
yAxis: {
max:90,
min:20,
title: {
text: null
}
},
series: [{
name: 'RH',
data: averages,
zIndex: 1
}, {
data: rangesHI,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [0, 0, 0, 300],
stops: [
[0, 'rgba(255,0,0, 0.2)'],
[1, 'rgba(255,0,0, 1)']
]
},
zIndex: 0
}, {
data: rangesME,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [300, 0, 300, 400],
stops: [
[0, 'rgba(237,230,126, 0.2)'],
[1, 'rgba(237,230,126, 1)']
]
},
zIndex: 0
}, {
data: rangesNO,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [500, 0, 500, 600],
stops: [
[0, 'rgba(104,217,91, 0.2)'],
[1, 'rgba(104,217,91, 0.7)']
]
},
zIndex: 0
}, {
data: rangesLO,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [0, 0, 0, 220],
stops: [
[0, 'rgba(91,187,217, 0.2)'],
[1, 'rgba(91,187,217, 0.7)']
]
},
zIndex: 0
}]
}, function (chart) {
chart.renderer.text('EKSTREMALNA', 80, 95).css({
fontSize: '16pt',
color: 'rgba(255,0,0, 1)'
}).add();
chart.renderer.text('WYSOKA', 80, 145).css({
fontSize: '16pt',
color: 'rgba(237,230,126, 1)'
}).add();
chart.renderer.text('KOMFORTOWA', 80, 225).css({
fontSize: '16pt',
color: 'rgba(104,217,91, 01)'
}).add();
chart.renderer.text('NISKA', 80, 305).css({
fontSize: '16pt',
color: 'rgba(91,187,217, 1)'
}).add();
});
http://jsfiddle.net/qazopap4/1/ but this is far from what I'v expected.
I can't make linear gradient for each arearange separately.
You can use plotBands which allows you to apply gradients.
yAxis: {
plotBands: [{
from: 60,
to: 90,
color: {
linearGradient: [0, 0, 0, 300],
stops: [
[0, 'rgba(255,0,0, 0.2)'],
[1, 'rgba(255,0,0, 1)']
]
}
}],
max: 90,
min: 20,
title: {
text: null
}
},
Example: http://jsfiddle.net/pag5qgsm

graphaeljs error

I am using the graphaeljs library to display charts, at an ASP.NET MVC 4
I have copied this code from the graphaeljs website
<script src="scripts/raphael.js"></script>
<script src="scripts/g.raphael-min.js"></script>
<script src="scripts/g.bar-min.js"></script>
<script>
window.onload = function () {
var r = Raphael("holder"),
fin = function () {
this.flag = r.popup(this.bar.x, this.bar.y, this.bar.value || "0").insertBefore(this);
},
fout = function () {
this.flag.animate({ opacity: 0 }, 300, function () { this.remove(); });
},
fin2 = function () {
var y = [], res = [];
for (var i = this.bars.length; i--;) {
y.push(this.bars[i].y);
res.push(this.bars[i].value || "0");
}
this.flag = r.popup(this.bars[0].x, Math.min.apply(Math, y), res.join(", ")).insertBefore(this);
},
fout2 = function () {
this.flag.animate({ opacity: 0 }, 300, function () { this.remove(); });
},
txtattr = { font: "12px sans-serif" };
r.text(160, 10, "Single Series Chart").attr(txtattr);
r.text(480, 10, "Multiline Series Stacked Chart").attr(txtattr);
r.text(160, 250, "Multiple Series Chart").attr(txtattr);
r.text(480, 250, "Multiline Series Stacked Chart\nColumn Hover").attr(txtattr);
r.barchart(10, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10]]).hover(fin, fout);
r.hbarchart(330, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55]], { stacked: true }).hover(fin, fout);
r.hbarchart(10, 250, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55]]).hover(fin, fout);
var c = r.barchart(330, 250, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55]], { stacked: true, type: "soft" }).hoverColumn(fin2, fout2);
};
</script>
But when I run at my browser, this message appears
Uncaught TypeError: Cannot read property 'x' of undefined raphael.js:11
c._engine.create raphael.js:11
c raphael.js:9
window.onload (index):92
I do not know what I do wrong, and I used the libraries exactly as they are. Can you please tell me, what might be my mistake?
Sorry, I don't see anything wrong with the code you posted.
I made a fiddle for you.
It is obviously an issue with the raphael.js file.
Be sure to include class="raphael" on your body tag, and a div with id="holder".
If that fails, try re-downloading raphael.js.

Issue with datetime values and printing a spline plot between the data points

Anyone able to help with the following problem:
Trying to draw a chart with four data series, two of which are scatter and one is spline. Purpose of the spline is just to draw a line between specific spots on the chart, not joining all of them together. The following is my code so far:
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'scatter',
zoomType: 'xy'
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
ordinal: false,
labels: {
formatter: function() {
return Highcharts.dateFormat('%H', this.value);
}
}
},
yAxis: {
categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
gridLineWidth: 0,
step: 1,
title: '',
labels: {
style: {
color: '#6D869F',
fontSize: '9px',
}
},
},
tooltip: {
formatter: function() {
return ''+
this.x +' cm, '+ this.y +' kg';
}
},
legend: {
layout: 'vertical',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 70,
floating: true,
backgroundColor: '#FFFFFF',
borderWidth: 1
},
plotOptions: {
scatter: {
marker: {
radius: 5,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
states: {
hover: {
marker: {
enabled: false
}
}
}
}
},
series: [{
name: 'sleep time',
marker: {
symbol: 'circle',
},
color: '#81c65b',
data: [[Date.UTC(2012, 1, 1, 22, 15), 0],
[Date.UTC(2012, 1, 1, 20, 30), 3],
[Date.UTC(2012, 1, 1, 21, 45), 5],
[Date.UTC(2012, 1, 1, 22, 00), 6]]
},
{
name: 'wakeup time',
marker: {
symbol: 'circle',
fillColor: '#76a4fb',
},
data: [[Date.UTC(2012, 1, 2, 08, 15), 0],
[Date.UTC(2012, 1, 2, 07, 10), 1],
[Date.UTC(2012, 1, 2, 09, 20), 2],
[Date.UTC(2012, 1, 2, 07, 40), 3],
[Date.UTC(2012, 1, 2, 07, 30), 4],
[Date.UTC(2012, 1, 2, 08, 20), 5],
[Date.UTC(2012, 1, 2, 09, 30), 6]],
},
{
name: 'sleep time over average',
color: 'rgba(119, 152, 191, .5)',
marker: {
symbol: 'square',
fillColor: '#000',
},
data: [[Date.UTC(2012, 1, 1, 20, 15), 1],
[Date.UTC(2012, 1, 1, 23, 40), 2],
[Date.UTC(2012, 1, 1, 21, 20), 4]]
},
{
name: '',
legend: {
enabled: false,
},
color: '#d62a9c',
type: 'spline',
marker: {
enabled: false,
},
data: [[Date.UTC(2012, 1, 1, 22, 15), 0],
[Date.UTC(2012, 1, 2, 08, 15), 0],
[Date.UTC(2012, 1, 1, 20, 15), 1],
[Date.UTC(2012, 1, 2, 07, 10), 1],
[Date.UTC(2012, 1, 1, 23, 40), 2],
[Date.UTC(2012, 1, 2, 09, 20), 2],
[Date.UTC(2012, 1, 1, 20, 30), 3],
[Date.UTC(2012, 1, 2, 07, 40), 3],
[Date.UTC(2012, 1, 1, 21, 20), 4],
[Date.UTC(2012, 1, 2, 07, 30), 4],
[Date.UTC(2012, 1, 1, 21, 45), 5],
[Date.UTC(2012, 1, 2, 08, 20), 5],
[Date.UTC(2012, 1, 1, 22, 00), 6],
[Date.UTC(2012, 1, 2, 09, 30), 6]]
}]
});
});
});
My problem now is, in the spline series, if I add a null between elements to prevent plotting the line between two points, the whole plot goes mayhem. The idea is to draw lines only so that points which are vertically on the same line get joined, eg. in this case "sleep time" and "wakeup time". For example,
data: [
[Date.UTC(2012, 1, 1, 22, 15), 0],
[Date.UTC(2012, 1, 2, 08, 15), 0], null,
[Date.UTC(2012, 1, 1, 20, 15), 1],
[Date.UTC(2012, 1, 2, 07, 10), 1], null,
[Date.UTC(2012, 1, 1, 23, 40), 2],
...
You may try out the code at this jsfiddle.
Try the following.
data: [
[Date.UTC(2012, 1, 1, 22, 15), 0],
[Date.UTC(2012, 1, 2, 08, 15), 0],
[Date.UTC(2012, 1, 2, 08, 15), null],
[Date.UTC(2012, 1, 1, 20, 15), 1],
[Date.UTC(2012, 1, 2, 07, 10), 1],
[Date.UTC(2012, 1, 2, 08, 15), null],
[Date.UTC(2012, 1, 1, 23, 40), 2],
[Date.UTC(2012, 1, 2, 09, 20), 2],
[Date.UTC(2012, 1, 2, 08, 15), null],
...
]
As you can see you have to pass an array which the first value have to be any date.
Demo

Resources