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.
Related
I am using LightningChart JS and would like to implement a virtual measurement device, where I can click on point A and then drag to point B and obtain the x,y values of both point A and point B.
As far as I have looked into the event handlers they just return a mouse event with start and stop positions in terms of screen positions. Please, correct me if I'm wrong. Also please suggest an efficient way to do this.
Thanks in advance.
The mouse events return the mouse coordinates in the same coordinate space as normal JS mouse events. To get the click location in the series coordinate space, a couple of steps need to be taken.
First the mouse coordinates need to be converted to the engine coordinate space. The engine coordinate space is the canvas area with 0,0 on the bottom left of the canvas. This can be done with chart.engine.clientLocation2Engine(ev.clientX,ev.clientY). This returns the event coordinate in the engine coordinate space using the chart engine scale.
This needs to be then converted to the series coordinate. This can be done with translatePoint method. translatePoint can be used to convert points between two different scales. Scale in LightningChart JS is basically a coordinate space.
const m = chart.engine.clientLocation2Engine(ev.clientX, ev.clientY)
const translated = translatePoint(m, chart.engine.scale, lineSeries.scale)
Now the translated variable contains the click location in the series coordinate space.
See a full code snippet below where you can drag on the series area and when drag is stopped markers are placed to the start and end locations of the drag.
const {
lightningChart,
SolidLine,
SolidFill,
ColorRGBA,
AxisTickStrategies,
UIOrigins,
DataPatterns,
translatePoint,
ColorHEX
} = lcjs
const chart = lightningChart().ChartXY()
const diesel = [
{ x: 0, y: 1.52 },
{ x: 1, y: 1.52 },
{ x: 2, y: 1.52 },
{ x: 3, y: 1.58 },
{ x: 4, y: 2.00 },
{ x: 5, y: 2.00 },
{ x: 6, y: 2.00 },
{ x: 7, y: 2.00 },
{ x: 8, y: 2.26 },
{ x: 9, y: 1.90 },
{ x: 10, y: 1.90 },
{ x: 11, y: 1.90 },
{ x: 12, y: 1.90 },
{ x: 13, y: 1.60 },
{ x: 14, y: 1.60 },
{ x: 15, y: 1.60 },
{ x: 16, y: 1.00 },
{ x: 17, y: 1.00 },
{ x: 18, y: 1.00 },
{ x: 19, y: 1.74 },
{ x: 20, y: 1.47 },
{ x: 21, y: 1.47 },
{ x: 22, y: 1.47 },
{ x: 23, y: 1.74 },
{ x: 24, y: 1.74 },
{ x: 25, y: 1.74 },
{ x: 27, y: 1.5 },
{ x: 28, y: 1.5 },
{ x: 29, y: 1.5 }
]
const gasoline = [
{ x: 0, y: 1.35 },
{ x: 1, y: 1.35 },
{ x: 2, y: 1.35 },
{ x: 3, y: 1.35 },
{ x: 4, y: 1.90 },
{ x: 5, y: 1.90 },
{ x: 6, y: 1.90 },
{ x: 7, y: 1.92 },
{ x: 8, y: 1.50 },
{ x: 9, y: 1.50 },
{ x: 10, y: 1.3 },
{ x: 11, y: 1.3 },
{ x: 12, y: 1.3 },
{ x: 13, y: 1.3 },
{ x: 14, y: 1.3 },
{ x: 15, y: 1.32 },
{ x: 16, y: 1.40 },
{ x: 17, y: 1.44 },
{ x: 18, y: 1.02 },
{ x: 19, y: 1.02 },
{ x: 20, y: 1.02 },
{ x: 21, y: 1.02 },
{ x: 22, y: 1.02 },
{ x: 23, y: 1.02 },
{ x: 24, y: 1.02 },
{ x: 25, y: 1.02 },
{ x: 27, y: 1.30 },
{ x: 28, y: 1.30 },
{ x: 29, y: 1.30 }
]
const lineSeries = chart.addLineSeries({ dataPattern: DataPatterns.horizontalProgressive })
const lineSeries2 = chart.addLineSeries({ dataPattern: DataPatterns.horizontalProgressive })
lineSeries2.add(diesel.map((point) => ({ x: point.x, y: point.y })))
lineSeries.add(gasoline.map((point) => ({ x: point.x, y: point.y })))
const markerA = chart.addChartMarkerXY()
.setPointMarker((marker) => marker.setFillStyle((f => f.setColor(ColorHEX('#f00')))))
.setMouseInteractions(false)
const markerB = chart.addChartMarkerXY()
.setPointMarker((marker) => marker.setFillStyle((f => f.setColor(ColorHEX('#0f0')))))
.setMouseInteractions(false)
function getClickInSeriesScale(point, scale) {
const m = chart.engine.clientLocation2Engine(point.x, point.y)
return translatePoint(m, chart.engine.scale, scale)
}
chart.onSeriesBackgroundMouseDragStop((obj, ev, b, start) => {
let pointA = getClickInSeriesScale(start, lineSeries.scale)
let pointB = getClickInSeriesScale({x:ev.clientX,y:ev.clientY}, lineSeries.scale)
// move markes to start and end points
markerA.setPosition(pointA)
markerB.setPosition(pointB)
})
<script src="https://unpkg.com/#arction/lcjs#1.3.1/dist/lcjs.iife.js"></script>
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>
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/
I'm trying to add a PolyLine. Why doesn't this work?
this.addLine = function(vertices)
{
var geometry = new THREE.Geometry();
for (var i = 0; i < vertices.length; i++)
{
geometry.vertices.push(new THREE.Vector3(
vertices[i].X,
vertices[i].Y,
vertices[i].Z));
}
var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({}));
line.width = 199.9;
scope.scene.add(line);
};
using it like this:
var objects = [
{ X: 216939.73, Y: 6595308.75, Z: 547.92 },
{ X: 216927.30, Y: 6595310.31, Z: 547.92 },
{ X: 216929.54, Y: 6595328.01, Z: 547.92 },
{ X: 216941.93, Y: 6595326.46, Z: 547.92 },
{ X: 216939.73, Y: 6595308.75, Z: 547.92 },
{ X: 209160.61, Y: 6589441.50, Z: 547.92 },
{ X: 209163.06, Y: 6589460.77, Z: 547.92 },
{ X: 209185.80, Y: 6589457.87, Z: 547.92 },
{ X: 209183.25, Y: 6589438.52, Z: 547.92 },
{ X: 209160.61, Y: 6589441.50, Z: 547.92 },
{ X: 220745.54, Y: 6593881.96, Z: 547.92 },
{ X: 220762.77, Y: 6593892.37, Z: 547.92 },
{ X: 220767.23, Y: 6593885.00, Z: 547.92 },
{ X: 220750.01, Y: 6593874.55, Z: 547.92 },
{ X: 220745.54, Y: 6593881.96, Z: 547.92 },
];
viewer.addLine(objects);
When I add lower points, like -10, 10, 0, it will render a line
near the grid, but while using real coordinates, it does not work. What's happening?