Here is my chart:
Here's is the chart if I add a line as the first series (note the lack of labels on the x axis):
For some reason, most of the points on the x axis are disappearing.
Here's a reduced case:
$(function () {
$('#container').highcharts({
xAxis: {
type: 'datetime'
},
series: [
{
type: 'line',
data: [
{ x: 1476749571000, y: 36581540.37153554 },
{ x: 1477429910000, y: 36763124.20193958 }
]
},
{
type: 'scatter',
data: [
{ x: 1476749571000, y: 37170874 },
{ x: 1476756736000, y: 36541961 },
{ x: 1476760298000, y: 36412560 },
{ x: 1476771158000, y: 36766829 },
{ x: 1476774759000, y: 36819204 },
{ x: 1476778351000, y: 36193069 },
{ x: 1476781953000, y: 36289990 },
{ x: 1476789144000, y: 36751180 },
{ x: 1476796338000, y: 36058553 },
{ x: 1476807129000, y: 36803593 },
{ x: 1476810763000, y: 35963538 },
{ x: 1476821507000, y: 36896693 },
{ x: 1476825189000, y: 36187712 },
{ x: 1476835902000, y: 37084673 },
{ x: 1476843121000, y: 37136577 },
{ x: 1476846735000, y: 36607531 },
{ x: 1476853934000, y: 36334610 },
{ x: 1476864716000, y: 37140192 },
{ x: 1476875538000, y: 35929136 },
{ x: 1476900734000, y: 36137618 },
{ x: 1476907888000, y: 37195952 },
{ x: 1476915103000, y: 37170028 },
{ x: 1476922333000, y: 36438640 },
{ x: 1476936739000, y: 36425736 },
{ x: 1476951130000, y: 36954993 },
{ x: 1476969138000, y: 36288051 },
{ x: 1476972690000, y: 36666854 },
{ x: 1476976353000, y: 37066932 },
{ x: 1476979924000, y: 36628386 },
{ x: 1476990726000, y: 36997524 },
{ x: 1477005114000, y: 37036777 },
{ x: 1477008734000, y: 36069816 },
{ x: 1477019586000, y: 36788879 },
{ x: 1477026712000, y: 37195266 },
{ x: 1477030349000, y: 36568077 },
{ x: 1477033944000, y: 35936353 },
{ x: 1477041102000, y: 35840667 },
{ x: 1477069967000, y: 36826033 },
{ x: 1477077134000, y: 37165725 },
{ x: 1477084331000, y: 37078309 },
{ x: 1477091521000, y: 37195750 },
{ x: 1477095153000, y: 36788377 },
{ x: 1477105972000, y: 36951953 },
{ x: 1477109539000, y: 37072255 },
{ x: 1477113124000, y: 35688693 },
{ x: 1477120378000, y: 37021539 },
{ x: 1477134712000, y: 36883044 },
{ x: 1477138302000, y: 36838067 },
{ x: 1477141938000, y: 36719537 },
{ x: 1477145571000, y: 35900066 },
{ x: 1477149173000, y: 36141158 },
{ x: 1477156353000, y: 36647699 },
{ x: 1477163535000, y: 36516520 },
{ x: 1477167130000, y: 35817224 },
{ x: 1477181544000, y: 36758274 },
{ x: 1477188754000, y: 36717498 },
{ x: 1477195935000, y: 36913901 },
{ x: 1477203152000, y: 36518492 },
{ x: 1477217518000, y: 37143381 },
{ x: 1477224743000, y: 36334856 },
{ x: 1477231914000, y: 36910162 },
{ x: 1477249968000, y: 36977544 },
{ x: 1477257157000, y: 37174847 },
{ x: 1477267956000, y: 37051864 },
{ x: 1477289539000, y: 36343981 },
{ x: 1477296761000, y: 37020845 },
{ x: 1477300357000, y: 36180803 },
{ x: 1477307506000, y: 36145191 },
{ x: 1477311156000, y: 37102437 },
{ x: 1477325543000, y: 35496804 },
{ x: 1477332732000, y: 37193777 },
{ x: 1477339942000, y: 36683704 },
{ x: 1477354323000, y: 36577391 },
{ x: 1477357932000, y: 36231277 },
{ x: 1477361539000, y: 37198585 },
{ x: 1477365133000, y: 36789070 },
{ x: 1477379517000, y: 37138966 },
{ x: 1477386738000, y: 36953176 },
{ x: 1477397539000, y: 37135591 },
{ x: 1477408304000, y: 35867866 },
{ x: 1477411936000, y: 37141581 },
{ x: 1477415513000, y: 36864017 },
{ x: 1477422756000, y: 36743302 },
{ x: 1477426328000, y: 36948156 },
{ x: 1477429910000, y: 37199122 }
]
}
]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
Any ideas?
There appears to be a difference in how Highcarts interprets things between the line and scatter series types, though I am unclear how the particular scenario is explained.
But you can work around this by using a line series for both, and simply removing the line from the scatter data.
This way, you can skip setting a tickInterval, and you get the dynamic interpretation by the chart that you want.
Example:
{
type: 'line',
lineWidth: 0,
marker: {
enabled: true
},
findNearestPointBy: 'xy',
data: [ ... ]
}
Updated fiddle:
http://jsfiddle.net/jlbriggs/g6fjjach/4/
Set axis.tickInterval to force ticks to be drawn.
xAxis: {
type: 'datetime',
tickInterval: 1000 * 3600 * 24 // one day interval
},
example: http://jsfiddle.net/g6fjjach/2/
Related
Hello I'm having some trouble with drawing 3 lines on a canvas relatively to my mouse click.
The 3 lines make a small smiley face.
So in my code I have a function called parseRecordedLinePoints(), In this function it makes the points from each line relative to my mouse, then strokes it on the canvas.
For some reason when it's called and strokes the canvas, the eyes get stroked above each other. (overlaps)
I've tried to fix it by changing the function to:
function parseRecordedLinePoints(Point, index, arr) {
ctx.lineTo(Point.x, Point.y);
ctx.stroke();
}
When the function is like this it draws the smiley, but not relatively and the lines connect to each other.
Here's the code currently as an snippet, so you can get a better look. You can see how it draws the eyes in the wrong position, and overlaps them directly under my mouse. I'm trying to make it draw the smiley face correctly relatively.
CODE:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var cursorX = 100; //Example position X
var cursorY = 0; //Example position Y
var relX = 0;
var relY = 0;
//3 lines // A smiley face.
var recordedLines = [{
Color: {
r: 0,
g: 50,
b: 0
},
LinePoints: [{
x: 125,
y: 370.2
},
{
x: 125,
y: 367.9
},
{
x: 127.2,
y: 365.7
},
{
x: 128.4,
y: 367.9
},
{
x: 127.2,
y: 370.2
},
{
x: 125,
y: 371.3
},
{
x: 122.8,
y: 370.2
},
{
x: 121.7,
y: 367.9
},
{
x: 121.7,
y: 364.6
},
{
x: 123.9,
y: 363.5
},
{
x: 127.2,
y: 363.5
},
{
x: 128.4,
y: 365.7
},
{
x: 128.4,
y: 369
},
{
x: 126.1,
y: 370.2
},
{
x: 123.9,
y: 369
},
{
x: 122.8,
y: 366.8
},
{
x: 123.9,
y: 364.6
},
{
x: 127.2,
y: 364.6
},
{
x: 127.2,
y: 367.9
},
{
x: 125,
y: 369
},
{
x: 123.9,
y: 366.8
},
{
x: 123.9,
y: 366.8
}
]
},
{
Color: {
r: 100,
g: 0,
b: 0
},
LinePoints: [{
x: 168.4,
y: 365.7
},
{
x: 166.1,
y: 366.8
},
{
x: 163.9,
y: 363.5
},
{
x: 166.1,
y: 362.4
},
{
x: 168.4,
y: 363.5
},
{
x: 167.2,
y: 365.7
},
{
x: 163.9,
y: 365.7
},
{
x: 163.9,
y: 362.4
},
{
x: 165,
y: 360.2
},
{
x: 168.4,
y: 360.2
},
{
x: 169.5,
y: 363.5
},
{
x: 168.4,
y: 365.7
},
{
x: 165,
y: 365.7
},
{
x: 163.9,
y: 363.5
},
{
x: 165,
y: 360.2
},
{
x: 168.4,
y: 360.2
},
{
x: 168.4,
y: 363.5
},
{
x: 168.4,
y: 364.6
}
]
},
{
Color: {
r: 100,
g: 0,
b: 0
},
LinePoints: [{
x: 107.2,
y: 377.9
},
{
x: 109.5,
y: 379
},
{
x: 110.6,
y: 381.3
},
{
x: 112.8,
y: 382.4
},
{
x: 115,
y: 384.6
},
{
x: 117.2,
y: 386.8
},
{
x: 119.5,
y: 387.9
},
{
x: 122.8,
y: 389
},
{
x: 126.1,
y: 390.2
},
{
x: 129.5,
y: 391.3
},
{
x: 132.8,
y: 391.3
},
{
x: 136.1,
y: 391.3
},
{
x: 139.5,
y: 392.4
},
{
x: 142.8,
y: 392.4
},
{
x: 146.1,
y: 392.4
},
{
x: 149.5,
y: 392.4
},
{
x: 152.8,
y: 392.4
},
{
x: 156.1,
y: 391.3
},
{
x: 159.5,
y: 390.2
},
{
x: 161.7,
y: 389
},
{
x: 165,
y: 389
},
{
x: 167.2,
y: 387.9
},
{
x: 169.5,
y: 386.8
},
{
x: 171.7,
y: 385.7
},
{
x: 173.9,
y: 384.6
},
{
x: 176.1,
y: 383.5
},
{
x: 178.4,
y: 382.4
},
{
x: 179.5,
y: 380.2
},
{
x: 181.7,
y: 379
},
{
x: 182.8,
y: 376.8
},
{
x: 183.9,
y: 375.7
}
]
}
];
//----------------------------------
//var relativeARRAY = []; //recordedLines array, but relative to mouse.
//var color = [{ r: 0, g: 0, b: 0 }];
function parseRecordedLinePoints(Point, index, arr) {
relX = Point.x - arr[0].x;
relY = Point.y - arr[0].y;
ctx.lineTo(relX + cursorX, relY + cursorY);
ctx.stroke();
}
//----------------------------------
function parseRecordedLine(Line, index, arr) {
const LinePoints = Line.LinePoints;
//-- parse the x and y points of this line.. to make relative..
LinePoints.forEach(parseRecordedLinePoints);
}
//----------------------------------
c.addEventListener(
"click",
function(e) {
cursorX = e.clientX;
cursorY = e.clientY;
ctx.moveTo(cursorX, cursorY);
recordedLines.forEach(parseRecordedLine);
},
false
);
<canvas id="myCanvas" width="600" height="600" style="border: 1px solid #d3d3d3;"></canvas>
Not sure if you have to use all those points for what you’re working on but here’s a simplified version.
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
let mouse = {
x: null,
y: null,
}
window.addEventListener('click', function(e) {
mouse.x = e.x;
mouse.y = e.y;
drawFace();
});
function drawFace() {
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(mouse.x, mouse.y, 5, 0, Math.PI * 2);
ctx.arc(mouse.x + 30, mouse.y, 5, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(mouse.x + 14, mouse.y + 9, 30, 0.3, Math.PI / 1.1)
ctx.stroke();
ctx.closePath();
}
For your code you need to use moveTo when starting a new draw. lineTo will continue drawing from the previous point. moveTo picks up the pen and moves it to a new start location.
I designed a google scripts to produce an object with keys that relate to arrays of data. It looks like this:
{
Global: [
{
x: "2020-01-21T21:00:00.000Z",
y: 330
},
{
x: "2020-01-22T11:00:00.000Z",
y: 555
},
{
x: "2020-01-23T11:00:00.000Z",
y: 654
},
{
x: "2020-01-23T23:00:00.000Z",
y: 881
},
{
x: "2020-01-24T11:00:00.000Z",
y: 941
},
{
x: "2020-01-24T23:00:00.000Z",
y: 1353
},
{
x: "2020-01-25T11:00:00.000Z",
y: 1434
},
{
x: "2020-01-25T21:00:00.000Z",
y: 2014
},
{
x: "2020-01-26T10:00:00.000Z",
y: 2118
},
{
x: "2020-01-26T22:00:00.000Z",
y: 2794
},
{
x: "2020-01-27T08:00:00.000Z",
y: 2886
},
{
x: "2020-01-27T18:00:00.000Z",
y: 2926
},
{
x: "2020-01-27T19:30:00.000Z",
y: 4473
},
{
x: "2020-01-28T12:00:00.000Z",
y: 4690
},
{
x: "2020-01-28T17:00:00.000Z",
y: 5578
},
{
x: "2020-01-28T22:00:00.000Z",
y: 6057
},
{
x: "2020-01-29T12:30:00.000Z",
y: 6165
},
{
x: "2020-01-29T13:30:00.000Z",
y: 6165
},
{
x: "2020-01-29T20:00:00.000Z",
y: 7782
},
{
x: "2020-01-30T10:00:00.000Z",
y: 8234
},
{
x: "2020-01-31T13:00:00.000Z",
y: 9927
},
{
x: "2020-01-31T18:00:00.000Z",
y: 11374
},
{
x: "2020-02-01T09:00:00.000Z",
y: 12024
},
{
x: "2020-02-02T20:00:00.000Z",
y: 17294
},
{
x: "2020-02-03T20:00:00.000Z",
y: 20198
},
{
x: "2020-02-04T08:40:00.000Z",
y: 20589
},
{
x: "2020-02-04T21:00:00.000Z",
y: 24503
},
{
x: "2020-02-05T08:00:00.000Z",
y: 24607
},
{
x: "2020-02-05T22:00:00.000Z",
y: 28274
},
{
x: "2020-02-06T08:00:00.000Z",
y: 28344
},
{
x: "2020-02-06T13:20:00.000Z",
y: 28353
},
{
x: "2020-02-07T19:13:00.000Z",
y: 31532
},
{
x: "2020-02-07T21:50:00.000Z",
y: 34899
},
{
x: "2020-02-08T21:04:00.000Z",
y: 34963
},
{
x: "2020-02-08T22:04:00.000Z",
y: 37549
},
{
x: "",
y: 0
},
{
x: "",
y: 0
},
{ },
{ },
{ },
{ },
{ }
],
China: [
{
x: "2020-01-21T21:00:00.000Z",
y: 325
},
{
x: "2020-01-22T11:00:00.000Z",
y: 547
},
{
x: "2020-01-23T11:00:00.000Z",
y: 639
},
{
x: "2020-01-23T23:00:00.000Z",
y: 865
},
{
x: "2020-01-24T11:00:00.000Z",
y: 916
},
{
x: "2020-01-24T23:00:00.000Z",
y: 1320
},
{
x: "2020-01-25T11:00:00.000Z",
y: 1399
},
{
x: "2020-01-25T21:00:00.000Z",
y: 1979
},
{
x: "2020-01-26T10:00:00.000Z",
y: 2062
},
{
x: "2020-01-26T22:00:00.000Z",
y: 2737
},
{
x: "2020-01-27T08:00:00.000Z",
y: 2825
},
{
x: "2020-01-27T18:00:00.000Z",
y: 2863
},
{
x: "2020-01-27T19:30:00.000Z",
y: 4409
},
{
x: "2020-01-28T12:00:00.000Z",
y: 4610
},
{
x: "2020-01-28T17:00:00.000Z",
y: 5494
},
{
x: "2020-01-28T22:00:00.000Z",
y: 5970
},
{
x: "2020-01-29T12:30:00.000Z",
y: 6070
},
{
x: "2020-01-29T13:30:00.000Z",
y: 6070
},
{
x: "2020-01-29T20:00:00.000Z",
y: 7678
},
{
x: "2020-01-30T10:00:00.000Z",
y: 8124
},
{
x: "2020-01-31T13:00:00.000Z",
y: 9783
},
{
x: "2020-01-31T18:00:00.000Z",
y: 11221
},
{
x: "2020-02-01T09:00:00.000Z",
y: 11860
},
{
x: "2020-02-02T20:00:00.000Z",
y: 17114
},
{
x: "2020-02-03T20:00:00.000Z",
y: 20014
},
{
x: "2020-02-04T08:40:00.000Z",
y: 20400
},
{
x: "2020-02-04T21:00:00.000Z",
y: 24290
},
{
x: "2020-02-05T08:00:00.000Z",
y: 24391
},
{
x: "2020-02-05T22:00:00.000Z",
y: 28017
},
{
x: "2020-02-06T08:00:00.000Z",
y: 28085
},
{
x: "2020-02-06T13:20:00.000Z",
y: 28088
},
{
x: "2020-02-07T19:13:00.000Z",
y: 31215
},
{
x: "2020-02-07T21:50:00.000Z",
y: 34569
},
{
x: "2020-02-08T21:04:00.000Z",
y: 34620
},
{
x: "2020-02-08T22:04:00.000Z",
y: 37198
},
{
x: "",
y: 0
},
{
x: "",
y: 0
},
{ },
{ },
{ },
{ },
{ }
],
Other: [
{
x: "2020-01-21T21:00:00.000Z",
y: 5
},
{
x: "2020-01-22T11:00:00.000Z",
y: 8
},
{
x: "2020-01-23T11:00:00.000Z",
y: 15
},
{
x: "2020-01-23T23:00:00.000Z",
y: 16
},
{
x: "2020-01-24T11:00:00.000Z",
y: 25
},
{
x: "2020-01-24T23:00:00.000Z",
y: 33
},
{
x: "2020-01-25T11:00:00.000Z",
y: 35
},
{
x: "2020-01-25T21:00:00.000Z",
y: 35
},
{
x: "2020-01-26T10:00:00.000Z",
y: 56
},
{
x: "2020-01-26T22:00:00.000Z",
y: 57
},
{
x: "2020-01-27T08:00:00.000Z",
y: 61
},
{
x: "2020-01-27T18:00:00.000Z",
y: 63
},
{
x: "2020-01-27T19:30:00.000Z",
y: 64
},
{
x: "2020-01-28T12:00:00.000Z",
y: 80
},
{
x: "2020-01-28T17:00:00.000Z",
y: 84
},
{
x: "2020-01-28T22:00:00.000Z",
y: 87
},
{
x: "2020-01-29T12:30:00.000Z",
y: 95
},
{
x: "2020-01-29T13:30:00.000Z",
y: 95
},
{
x: "2020-01-29T20:00:00.000Z",
y: 104
},
{
x: "2020-01-30T10:00:00.000Z",
y: 110
},
{
x: "2020-01-31T13:00:00.000Z",
y: 144
},
{
x: "2020-01-31T18:00:00.000Z",
y: 153
},
{
x: "2020-02-01T09:00:00.000Z",
y: 164
},
{
x: "2020-02-02T20:00:00.000Z",
y: 180
},
{
x: "2020-02-03T20:00:00.000Z",
y: 184
},
{
x: "2020-02-04T08:40:00.000Z",
y: 189
},
{
x: "2020-02-04T21:00:00.000Z",
y: 213
},
{
x: "2020-02-05T08:00:00.000Z",
y: 216
},
{
x: "2020-02-05T22:00:00.000Z",
y: 257
},
{
x: "2020-02-06T08:00:00.000Z",
y: 259
},
{
x: "2020-02-06T13:20:00.000Z",
y: 265
},
{
x: "2020-02-07T19:13:00.000Z",
y: 317
},
{
x: "2020-02-07T21:50:00.000Z",
y: 330
},
{
x: "2020-02-08T21:04:00.000Z",
y: 343
},
{
x: "2020-02-08T22:04:00.000Z",
y: 351
},
{
x: "",
y: 0
},
{
x: "",
y: 0
},
{ },
{ },
{ },
{ },
{ }
]
}
Chart JS has no problem accessing the data and plotting a graph when I don't use an object and output only one array (say the Global Data). When I try and put all the data into one object (so I don't have to send multiple variables to my local JS) the graph doesn't appear.
Here is what I am working with:
Google Sheets Scripts
function doGet() {
var result = {};
var infected = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('graph').getDataRange().getValues();
result = makeObject(infected);
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
}
function makeObject(multiArr) {
var obj = {};
var countrystats = {};
var headers = multiArr.shift();
for(var i = 0; i < headers.length; i++){
countrystats[i] = multiArr.map(function(app) {
return app[i];
})}
// for(var m = 0; m < countrystats[1].length; m++){
// obj[countrystats[1][m]] = 0;
// }
//DATA
for(var j = 5; j < headers.length; j++){
obj[j-5] = countrystats[j][113];
}
var China = {};
for(var j = 5; j < headers.length; j++){
China[j-5] = countrystats[j][114];
}
var Other = {};
for(var j = 5; j < headers.length; j++){
Other[j-5] = countrystats[j][115];
}
// //TIME
// for(var j = 5; j < headers.length; j++){
//
// obj[j-5] = countrystats[j][113];
//
// }
var TimeData = [];
for(var i = 0; i < headers.length; i++){
TimeData[i] = {}
}
for(var i = 0; i < headers.length; i++){
TimeData[i] = {
x: headers[i+5],
y: obj[i]
}
}
var TimeDataChina = []
for(var i = 0; i < headers.length; i++){
TimeDataChina[i] = {
x: headers[i+5],
y: China[i]
}
}
var TimeDataOther = []
for(var i = 0; i < headers.length; i++){
TimeDataOther[i] = {
x: headers[i+5],
y: Other[i]
}
}
var TimeDataAll = {};
TimeDataAll['Global'] = TimeData;
TimeDataAll['China'] = TimeDataChina;
TimeDataAll['Other'] = TimeDataOther;
return TimeDataAll;
}
Local JS
var TotalConfirmed;
var TotalDeaths;
var TotalRecovered;
var TimeData = [];
var FinalOutPut = [];
var TimeDataChina = [];
var TimeDataGlobal = [];
var TimeDataOther = [];
var dateArr;
var out3 = {};
var UpdatesFullName = {};
var infected_dataINT = {};
const url4 = "https://script.google.com/macros/s/AKfycbyZhlnhAjULalpihvgKOQUVfPY6yIvBAniq9rz6fg21NHdFkw-j/exec";
// Declare an async function
const getData4 = async () => {
// Use the await keyword to let JS know this variable has some latency so it should wait for it to be filled
// When the variable is fetched, use the .then() callback to carry on
const DataJSON = await fetch(url4).then(response =>
response.json()
)
return await DataJSON
};
console.log(getData4());
getData4().then(result => {
console.log("Update Information");
TimeData = result;
console.log(TimeData);
FinalOutPut = result;
TimeDataGlobal = TimeData['Global'];
TimeDataChina = TimeData['China'];
TimeDataOther = TimeData['Other'];
console.log(TimeDataGlobal);
console.log(TimeDataChina);
console.log(TimeDataOther);
var TodaysDate = moment();
if (TimeData.length){
console.log("Array has values");
console.log(TimeData.length);
// renderChart();
var timeFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
function newDate(days) {
return moment().add(days, 'd').toDate();
}
function newDateString(days) {
return moment().add(days, 'd').format(timeFormat);
}
var ctx = document.getElementById('canvas').getContext('2d');
window.myLine = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Total Infections Over Time',
backgroundColor: color(window.chartColors.green).alpha(0.5).rgbString(),
borderColor: window.chartColors.green,
fill: false,
lineTension: 0,
data: TimeDataGlobal,
},
{
label: 'Confirmed - China',
backgroundColor: color(window.chartColors.blue).alpha(0.5).rgbString(),
borderColor: window.chartColors.blue,
fill: false,
lineTension: 0,
data: TimeDataChina,
},
{
label: 'Confirmed - Other',
backgroundColor: color(window.chartColors.red).alpha(0.5).rgbString(),
borderColor: window.chartColors.red,
fill: false,
lineTension: 0,
data: TimeDataOther,
}
]
},
options: {
title: {
text: 'Chart.js Time Scale'
},
scales: {
xAxes: [{
gridLines: {
// display: false ,
color: "#333333"
},
ticks: {
min: '2020-01-21T21:00:00.000Z',
max: TodaysDate,
},
type: 'time',
bounds: 'ticks',
distribution: 'linear',
time: {
unit: 'day',
parser: timeFormat,
// round: 'day'
tooltipFormat: 'll HH:mm',
displayFormats: {
quarter: 'MMM D'
}
},
scaleLabel: {
display: true,
labelString: 'Date'
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'value'
},
gridLines: {
// display: false ,
color: "#333333"
},
}]
},
},
});
console.log("Chart Updated");
}
})
// .then(result => {
// renderChart();
// })
console.log(FinalOutPut)
Any help figuring out the problem is greatly appreciated.
Kind Regards, Camden
The problem was I mixed data types. I set timedata as an array in my local JS files, while it was being outputed as an object in my google scripts.
I have a dataset like this:
const dataset = [
{ 'color': 'red', 'data': [{ x: 0, y: 600 }, { x: 2, y: 900 }, { x: 4, y: 650 }, { x: 6, y: 700 }, { x: 9, y: 600 }] },
{ 'color': 'blue', 'data': [{ x: 0, y: 400 }, { x: 2, y: 300 }, { x: 4, y: 450 }, { x: 6, y: 900 }, { x: 9, y: 400 }] },
{ 'color': 'yellow', 'data': [{ x: 0, y: 200 }, { x: 2, y: 100 }, { x: 4, y: 550 }, { x: 6, y: 600 }, { x: 9, y: 400 }] }
];
I want to find domain values for max and min x-axis. I try this code but it doesn't work:
.domain([d3.min(arrangedata, (array) => array.x), d3.max(arrangedata, (array) => array.x)])
I also tried d3.extend, but I couldn't handle it. Any idea ?
For using either d3.max/min or d3.extent, you have to merge the inner arrays, which you can do with Array.prototype.reduce. Then, specify the x property in the accessor.
All together, it's just this:
const extent = d3.extent(dataset.reduce((a, c) => a.concat(c.data), []), d => d.x);
Here is the demo:
const dataset = [{
'color': 'red',
'data': [{
x: 0,
y: 600
}, {
x: 2,
y: 900
}, {
x: 4,
y: 650
}, {
x: 6,
y: 700
}, {
x: 9,
y: 600
}]
},
{
'color': 'blue',
'data': [{
x: 0,
y: 400
}, {
x: 2,
y: 300
}, {
x: 4,
y: 450
}, {
x: 6,
y: 900
}, {
x: 9,
y: 400
}]
},
{
'color': 'yellow',
'data': [{
x: 0,
y: 200
}, {
x: 2,
y: 100
}, {
x: 4,
y: 550
}, {
x: 6,
y: 600
}, {
x: 9,
y: 400
}]
}
];
const extent = d3.extent(dataset.reduce((a, c) => a.concat(c.data), []), d => d.x);
console.log(extent)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
You can try applying Math. min/max to the mapped series data.
d3.minValue = function(dataset, field) {
return d3.min(dataset, series => Math.min.apply(Math, series.data.map(data => data[field])))
}
d3.maxValue = function(dataset, field) {
return d3.max(dataset, series => Math.max.apply(Math, series.data.map(data => data[field])))
}
const dataset = [{
'color': 'red',
'data': [{ x: 0, y: 600 }, { x: 2, y: 900 }, { x: 4, y: 650 }, { x: 6, y: 700 }, { x: 9, y: 600 }]
}, {
'color': 'blue',
'data': [{ x: 0, y: 400 }, { x: 2, y: 300 }, { x: 4, y: 450 }, { x: 6, y: 900 }, { x: 9, y: 400 }]
}, {
'color': 'yellow',
'data': [{ x: 0, y: 200 }, { x: 2, y: 100 }, { x: 4, y: 550 }, { x: 6, y: 600 }, { x: 9, y: 400 }]
}]
//let domain = d3.domain([ d3.minValue(dataset, 'x'), d3.maxValue(dataset, 'x') ])
console.log(d3.minValue(dataset, 'x'), d3.maxValue(dataset, 'x')) // 0, 9
console.log(d3.minValue(dataset, 'y'), d3.maxValue(dataset, 'y')) // 100, 900
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
The question related to CanvasJS, but probably any expert in pure javascript could help.
I need a button to hide/unhide all elements in canvasjs graph.
There is a working code that can hide element using array index:
chart.options.data[0].visible = !chart.options.data[0].visible;
I'm trying to go through array, but it doesn't work, obviously my code is wrong:
chart.options.data.forEach(visible = !visible);
How should I fix it?
The full code snippet is:
var chart = new CanvasJS.Chart("chartContainer",
{
title:{
text: "Test Button to Hide All Series"
},
legend: {
cursor: "pointer",
itemclick: function (e) {
//console.log("legend click: " + e.dataPointIndex);
//console.log(e);
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
} else {
e.dataSeries.visible = true;
}
e.chart.render();
}
},
data: [
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 5 },
{ x: 20, y: 9},
{ x: 30, y: 17 },
{ x: 40, y: 32 },
{ x: 50, y: 22 },
{ x: 60, y: 14 },
{ x: 70, y: 25 },
{ x: 80, y: 18 },
{ x: 90, y: 20}
]
},
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 31 },
{ x: 20, y: 35},
{ x: 30, y: 30 },
{ x: 40, y: 35 },
{ x: 50, y: 35 },
{ x: 60, y: 38 },
{ x: 70, y: 38 },
{ x: 80, y: 34 },
{ x: 90, y: 44}
]
},
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 25 },
{ x: 20, y: 30},
{ x: 30, y: 20 },
{ x: 40, y: 45 },
{ x: 50, y: 30 },
{ x: 60, y: 10 },
{ x: 70, y: 15 },
{ x: 80, y: 18 },
{ x: 90, y: 20}
]
}
]
});
chart.render();
document.getElementById("showAllSeries").onclick = function(){
//Works for a single element using index:
chart.options.data[0].visible = !chart.options.data[0].visible;
//Doesn't work, need to modify
//chart.options.data.forEach(visible = !visible);
chart.render();
};
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<br/>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
<center><button id= "showAllSeries" style= "margin: 10px;">Show/Hide All series</button></center>
UP:
Found solution with for loop:
for (var i = 0; i < chart.options.data.length; i++) {
chart.options.data[i].visible = !chart.options.data[i].visible;
}
But still interesting how should it work with foreach
forEach is an Array method that you can use to execute a function on each element in an array. On the other hand for is a loop that is more flexible.
In your case, you can hide all dataSeries onclick of button either using for or forEach. Check the code below:
var chart = new CanvasJS.Chart("chartContainer", {
title:{
text: "Test Button to Hide All Series"
},
legend: {
cursor: "pointer",
itemclick: function (e) {
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
} else {
e.dataSeries.visible = true;
}
e.chart.render();
}
},
data: [
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 5 },
{ x: 20, y: 9 },
{ x: 30, y: 17 },
{ x: 40, y: 32 },
{ x: 50, y: 22 },
{ x: 60, y: 14 },
{ x: 70, y: 25 },
{ x: 80, y: 18 },
{ x: 90, y: 20 }
]
},
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 31 },
{ x: 20, y: 35 },
{ x: 30, y: 30 },
{ x: 40, y: 35 },
{ x: 50, y: 35 },
{ x: 60, y: 38 },
{ x: 70, y: 38 },
{ x: 80, y: 34 },
{ x: 90, y: 44 }
]
},
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 25 },
{ x: 20, y: 30 },
{ x: 30, y: 20 },
{ x: 40, y: 45 },
{ x: 50, y: 30 },
{ x: 60, y: 10 },
{ x: 70, y: 15 },
{ x: 80, y: 18 },
{ x: 90, y: 20 }
]
}
]
});
chart.render();
document.getElementById("showAllSeries").onclick = function(){
chart.options.data.forEach(function(dataSeries) {
if (typeof (dataSeries.visible) === "undefined" || dataSeries.visible) {
dataSeries.visible = false;
} else {
dataSeries.visible = true;
}
});
/*var dataSeries;
for(var i = 0; i < chart.data.length; i++){
dataSeries = chart.options.data[i];
if (typeof (dataSeries.visible) === "undefined" || dataSeries.visible) {
dataSeries.visible = false;
} else {
dataSeries.visible = true;
}
}*/
chart.render();
};
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 260px; width: 100%;"></div>
<center><button id= "showAllSeries" style= "margin: 10px;">Show/Hide All series</button></center>
Thanks to Vishwas for detailed answer. Generally - yes, both for & forEach are fine usable here. I will mark it as correct, but it helped me to get more concise solution using forEach that I expected:
document.getElementById(""showAllSeries"").onclick = function(){
chart.options.data.forEach(function(dataSeries) {
dataSeries.visible = !dataSeries.visible })
chart.render();
};
Will leave it here for a history also:
var chart = new CanvasJS.Chart("chartContainer",
{
title:{
text: "Test Button to Hide All Series"
},
legend: {
cursor: "pointer",
itemclick: function (e) {
//console.log("legend click: " + e.dataPointIndex);
//console.log(e);
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
} else {
e.dataSeries.visible = true;
}
e.chart.render();
}
},
data: [
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 5 },
{ x: 20, y: 9},
{ x: 30, y: 17 },
{ x: 40, y: 32 },
{ x: 50, y: 22 },
{ x: 60, y: 14 },
{ x: 70, y: 25 },
{ x: 80, y: 18 },
{ x: 90, y: 20}
]
},
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 31 },
{ x: 20, y: 35},
{ x: 30, y: 30 },
{ x: 40, y: 35 },
{ x: 50, y: 35 },
{ x: 60, y: 38 },
{ x: 70, y: 38 },
{ x: 80, y: 34 },
{ x: 90, y: 44}
]
},
{
showInLegend: true,
type: "line",
dataPoints: [
{ x: 10, y: 25 },
{ x: 20, y: 30},
{ x: 30, y: 20 },
{ x: 40, y: 45 },
{ x: 50, y: 30 },
{ x: 60, y: 10 },
{ x: 70, y: 15 },
{ x: 80, y: 18 },
{ x: 90, y: 20}
]
}
]
});
chart.render();
document.getElementById("showAllSeries").onclick=function(){
chart.options.data.forEach(function(dataSeries){
dataSeries.visible = !dataSeries.visible
})
chart.render();
};
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<br/>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
<center><button id= "showAllSeries" style= "margin: 10px;">Show/Hide All series</button></center>
Is there a way to add title to the axis? Typically, it is useful to have the y-axis display units. For example: http://code.shutterstock.com/rickshaw/examples/y_axis.html has just numbers, but in any kind of plot you would need to specify: %, $, km/s, etc. How to do that?
Thank you!
var graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
renderer: 'line',
height: 300,
width: 800,
series: [
{
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"
}, {
data: [ { x: 0, y: 200 }, { x: 1, y: 390 }, { x: 2, y: 1000 }, { x: 3, y: 200 }, { x: 4, y: 230 } ],
color: "#6060c0"
}
]
} );
var y_ticks = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
element: document.getElementById('y_axis'),
} );
graph.render();