Does anyone know of a chart layout that functions like a schedule/timeline?
I currently have a chart that shows the on/off status of 3 valves over time.
It's a stacked line/area chart, it's works ok, but it's not the easiest to follow.
See linked screenshot of what I'm looking to achieve: Chart actual vs desired (Top is current chart, bottom is what I want to achieve).
Is this possible with apache echarts?
Thanks to #pthomson for pointing me in the right direction.
Here is what I've come up with: Codepen chart example
I'm still having some issues with the min/max values for the xAxis.
The min/max seems to be calculated on values in index 1, which is the end timestamp of each schedule piece, so not ideal.
var dom = document.getElementById('chart-container');
var myChart = echarts.init(dom, null, {
renderer: 'canvas',
useDirtyRect: false
});
var app = {};
var option;
const valveColors = [
"#f59527",
"#00e200",
"#2da8f3",
]
var data = [
{
"name": "Valve 1",
"value": [
1655647200000,
1657980000000,
0
]
},
{
"name": "Valve 3",
"value": [
1657980000000,
1659448800000,
2
]
},
{
"name": "Valve 1",
"value": [
1659448800000,
1660526144467,
0
]
},
{
"name": "Valve 2",
"value": [
1655647200000,
1660526144467,
1
]
}
];
option = {
xAxis: {
type: "time",
//Min is getting values from index 1, not sure why
min: range => range.min - (7 * 24 * 60 * 60 * 1000), //Subtract 7 days
},
yAxis: {
type: "category",
data: [ "Valve 3", "Valve 2", "Valve 1" ]
},
series: [
{
type: "custom",
renderItem: (params, api) => {
var catIndex = api.value(2);
var timeSpan = [api.value(0), api.value(1)];
var start = api.coord([timeSpan[0], 2 - catIndex]);
var end = api.coord([timeSpan[1], 2 -catIndex]);
var size = api.size([0,1]);
var height = size[1] * 0.6;
var rect = echarts.graphic.clipRectByRect(
{ x: start[0], y: start[1] - height / 2, width: end[0] - start[0], height: height},
{ x: params.coordSys.x, y: params.coordSys.y, width: params.coordSys.width, height: params.coordSys.height}
);
return (
rect && {
type: "rect",
transition: ["shape"],
shape: rect,
style: {
fill: valveColors[catIndex],
},
}
);
},
encode: {
x: [0,1],
y: 0,
},
data: data,
}
],
tooltip: {
show: true,
trigger: "item",
formatter: params => {
return `${params.data.name}<br/> ${params.data.value[0]} - ${params.data.value[1]}` //Unix timestamps should be converted to readable dates
}
},
dataZoom: [
{
type: "slider",
filterMode: "none"
},
],
}
if (option && typeof option === 'object') {
myChart.setOption(option);
}
window.addEventListener('resize', myChart.resize);
Related
I'm currently creating a chart whose data is dynamically fetch from a database. Based on this data, I want to create a Horizontal Stacked Bar Chart that has only one series. Would that be possible in AmCharts? Or do I need a different approach?
Here's what I'd like as final result:
Here's a sample of what I'm currently doing: Chart Sample
I'm also aware that using series.stacked = true; would make a column chart stacked but I think this needs to have multiple series which I want to avoid for now.
<html>
<head></head>
<style></style>
<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<body>
<div id="chartdiv" style="width: 600px;height: 200px;background:#c7cacb;margin: 0 auto;"></div>
<script>
am5.ready(function () {
var root = am5.Root.new("chartdiv");
root._logo.dispose();
root.setThemes([
am5themes_Animated.new(root)
]);
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: false,
wheelY: false,
layout: root.verticalLayout
}));
var data = [{
"year": "Payments",
"europe": 50,
"namerica": 0,
"asia": 0,
}, {
"year": "Invoiced",
"europe": 30,
"namerica": 0,
"asia": 0,
}, {
"year": "Other Adjustment Sum",
"europe": 40,
"namerica": 20,
"asia": 39,
}]
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: "year",
renderer: am5xy.AxisRendererY.new(root, {}),
tooltip: am5.Tooltip.new(root, {})
}));
yAxis.data.setAll(data);
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
min: 0,
renderer: am5xy.AxisRendererX.new(root, {})
}));
xAxis = chart.xAxes.push(
am5xy.ValueAxis.new(root, {
min: 0,
numberFormat: "''",
renderer: am5xy.AxisRendererX.new(root, {
strokeOpacity: 1,
strokeWidth: 1,
minGridDistance: 60
}),
})
);
let myRange = [
{
x: 20,
},
{
x: 40,
},
{
x: 60,
},
{
x: 80,
},
{
x: 100,
},
];
for (var i = 0; i < data.length + 2; i++) {
let value = myRange[i].x;
let rangeDataItem = xAxis.makeDataItem({
value: value,
});
let range = xAxis.createAxisRange(rangeDataItem);
rangeDataItem.get('label').setAll({
forceHidden: false,
text: value,
});
}
var legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.p50,
x: am5.p50
}));
function makeSeries(name, fieldName, color) {
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
name: name,
stacked: true,
xAxis: xAxis,
yAxis: yAxis,
baseAxis: yAxis,
fill: color,
valueXField: fieldName,
categoryYField: "year"
}));
series.columns.template.setAll({
tooltipText: "{name}, {categoryY}: {valueX}",
tooltipY: am5.percent(90)
});
series.data.setAll(data);
series.appear();
}
makeSeries("Europe", "europe", "#83cdf4");
makeSeries("North America", "namerica","#caa3ed");
makeSeries("Asia", "asia","#eec48b");
chart.appear(1000, 100);
});
</script>
</body>
</html>
I am using the react wrapper for high charts btw.
What I have currently.
What I'm aiming for with but stacked waterfall chart
Just started using high charts and I love it but this one has me stumped. I figured out the data that I need to put that but now I just need to be able to place it in there..
Possible avenues of approach:
Is there a way to add custom HTML only for the top series?
Could I alter the data set to maybe re-render with the top label?
Could I just make the labels show but add an additional label above with the points I wants and make the rest transparent?
import React from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import HC_more from "highcharts/highcharts-more";
HC_more(Highcharts);
let categories = ["bar 1", "bar 2", "bar 3", "bar 4", "total bar"];
let series = [
{
data: [
20,
10,
-15,
30,
{
isSum: true,
},
],
name: "custom series 1",
},
{
data: [
20,
50,
-25,
10,
{
isSum: true,
},
],
name: "custom series 2",
lineWidth: 0,
},
{
data: [
5,
10,
-5,
10,
{
isSum: true,
},
],
name: "custom series 3",
lineWidth: 0,
},
];
let grandTotal = true;
function _createLabelValuePairs(s, c) {
let collection = {};
//Step 0 - iterate over data to get the series
s.map((dataSet) => {
//since we have total bars. Something that shouldn't be calc into the dataset we still need to figure out how many series it has
//for all the set values
dataSet.data.map((item, idx) => {
if (typeof item == "number") {
if (collection[c[idx]]) {
collection[c[idx]]["values"].push(item);
} else {
collection[c[idx]] = {};
collection[c[idx]]["values"] = [];
collection[c[idx]]["values"].push(item);
}
}
});
});
//Step 1 - Get my totals for each dataset
for (const a in collection) {
collection[a]["barTotal"] = collection[a].values.reduce(
(partialSum, a) => partialSum + a,
0,
);
}
//Step 2 - Get grand total numbers of all datasets.
if (grandTotal) {
//Step 2a - Totals for each bar
let sum = 0;
for (const item in collection) {
sum = sum + collection[item].barTotal;
if (collection[c[c.length - 1]]) {
collection[c[c.length - 1]]["values"].push(collection[item].barTotal);
} else {
collection[c[c.length - 1]] = {};
collection[c[c.length - 1]]["values"] = [];
collection[c[c.length - 1]]["values"].push(collection[item].barTotal);
}
}
//grand total bar will be the last entry in the set you pass in
collection[c[c.length - 1]]["barTotal"] = sum;
//Step 2b - Totals for each series
options.series.map((item) => {
if (collection[c[c.length - 1]]["seriesTotal"]) {
collection[c[c.length - 1]]["seriesTotal"][
item["name"]
] = item.data.reduce((partialSum, a) => {
if (typeof partialSum == "number") {
return Number(partialSum) + a;
}
}, 0);
} else {
collection[c[c.length - 1]]["seriesTotal"] = {};
collection[c[c.length - 1]]["seriesTotal"][item["name"]] = 0;
collection[c[c.length - 1]]["seriesTotal"][
item["name"]
] = item.data.reduce((partialSum, a) => {
if (typeof partialSum == "number") {
return Number(partialSum) + a;
}
}, 0);
}
if (
collection[c[c.length - 1]]["seriesTotal"][item["name"]].indexOf(
"[object Object]",
)
) {
collection[c[c.length - 1]]["seriesTotal"][item["name"]] = Number(
collection[c[c.length - 1]]["seriesTotal"][item["name"]].split(
"[object Object]",
)[0],
);
}
});
}
return collection;
}
function _getDelta(key, sets) {
console.log(sets);
//not passing anything back into the datalabel
return null;
}
const options = {
chart: {
type: "waterfall",
className: "test",
showAxes: false,
},
colors: ["#00A9F4", "#B3B3B3", "#000000"],
legend: {
align: "right",
symbolRadius: 0,
verticalAlign: "top",
},
title: {
text: "Stacked waterfall example",
},
plotOptions: {
series: {
stacking: "normal",
},
waterfall: {
borderColor: "none",
dashStyle: "Solid",
dataLabels: {
useHTML: true,
className: "waterfall-label",
enabled: true,
formatter: function(a) {
return _getDelta(
this.key,
_createLabelValuePairs(series, categories),
);
},
inside: false,
},
states: {
hover: {
animation: {
duration: 0,
},
enabled: false,
},
inactive: {
enabled: false,
},
select: {
enabled: false,
},
},
},
},
xAxis: {
categories: categories,
labels: {
style: {
color: "#000000",
cursor: "default",
fontSize: "14px",
fontFamily: "Mckinsey Sans Regular",
width: "75px",
whiteSpace: "normal", //set to normal
},
},
},
yAxis: {
visible: false,
},
series: series,
credits: {
enabled: false,
},
tooltip: {
animation: false,
backgroundColor: "#333333",
borderColor: "inherit",
borderRadius: 0,
formatter: function() {
return this.x + ": " + this.y;
},
hideDelay: 0,
shadow: false,
style: {
color: "white",
},
},
};
function Waterfall() {
return <HighchartsReact highcharts={Highcharts} options={options} />;
}
export default Waterfall;
And if you want to know what all that code was for _createLabelPairs it's just to get the totals of the series and that of the bars as well( If I need to use those later). I can figure out the percentages with barTotals and total property in the total bar
result from _createLabelPairs function
I want to create a synchronized High chart with two charts and the 1st chart will have one series and 2nd chart will have 2 series.
this link contains the sync chart with two series each chart, but when I reduced data to my required condition crosshair did not work properly.
data for chart.
var activity = {
"xData": [1, 1056, 2161, 3215, 4267],
"datasets": [{
"name": "Chart 1 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 1 series 2",
"data": [23, 84, 22, 5, 75],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 2 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "%",
"type": "line",
"valueDecimals": 1
}]
You are going from 2 series on each chart to 2 series on the 1st chart and 1 series on the 2nd chart, so you will be getting an error while trying your updated activity data. You need to add a conditional check like this (comments in uppercase):
/*
The purpose of this demo is to demonstrate how multiple charts on the same page can be linked
through DOM and Highcharts events and API methods. It takes a standard Highcharts config with a
small variation for each data set, and a mouse/touch event handler to bind the charts together.
*/
$(function () {
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
$('#container').bind('mousemove touchmove', function (e) {
var chart,
points,
i;
for (i = 0; i < Highcharts.charts.length; i++) {
chart = Highcharts.charts[i];
e = chart.pointer.normalize(e); // Find coordinates within the chart
// CHECK IF WE HAVE 2:
if ( chart.series.length === 2 ){
points = [chart.series[0].searchPoint(e, true), chart.series[1].searchPoint(e, true)]; // Get the hovered point
if (points[0] && points[1]) {
points[0].onMouseOver(); // Show the hover marker
points[1].onMouseOver(); // Show the hover marker
chart.tooltip.refresh(points); // Show the tooltip
chart.xAxis[0].drawCrosshair(e, points[0]); // Show the crosshair
}
// CHECK IF WE HAVE 1 CHART:
} else {
points = [chart.series[0].searchPoint(e, true)]; // Get the hovered poi
if (points[0]) {
points[0].onMouseOver(); // Show the hover marker
chart.tooltip.refresh(points); // Show the tooltip
chart.xAxis[0].drawCrosshair(e, points[0]); // Show the crosshair
}
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function () {};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max);
}
}
});
}
// Get the data. The contents of the data file can be viewed at
// https://github.com/highslide-software/highcharts.com/blob/master/samples/data/activity.json
//$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function (activity) {
var activity = {
"xData": [1, 1056, 2161, 3215, 4267],
"datasets": [{
"name": "Chart 1 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 1 series 2",
"data": [23, 84, 22, 5, 75],
"unit": "ms",
"type": "line",
"valueDecimals": 1
}, {
"name": "Chart 2 series 1",
"data": [0, 10, 20, 30, 20],
"unit": "%",
"type": "line",
"valueDecimals": 1
}]
},
lastChart;
$.each(activity.datasets, function (i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function (val, i) {
return [activity.xData[i], val];
});
if(i%2 == 0) { //first series of chart
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20,
// zoomType: 'x'
// pinchType: null // Disable zoom on touch devices
},
title: {
text: dataset.name.slice(0,7),
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
shared: true,
headerFormat: '',
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
visible:true
}
}]
});
} else { //second series of chart
lastChart = Highcharts.charts[Highcharts.charts.length-1];
lastChart.addSeries({
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
});
}
});
//});
});
Working JSFiddle: http://jsfiddle.net/kostasx/kfwtv1zj/
I am using Highcharts to create a timeline chart which shows the flow of different "states" over time. The current implementation is at http://jsfiddle.net/hq1kdpmo/8/ and it looks like .
The current code is as follows:
Highcharts.chart('container', {
"chart": {
"type": "xrange"
},
"title": {
"text": "State Periods"
},
"xAxis": {
"type": "datetime"
},
"yAxis": [{
"title": {
"text": "Factions"
},
"categories": ["A", "B", "C", "D"],
"reversed": true
}],
"plotOptions": {
"xrange": {
"borderRadius": 0,
"borderWidth": 0,
"grouping": false,
"dataLabels": {
"align": "center",
"enabled": true,
"format": "{point.name}"
},
"colorByPoint": false
}
},
"tooltip": {
"headerFormat": "<span style=\"font-size: 0.85em\">{point.x} - {point.x2}</span><br/>",
"pointFormat": "<span style=\"color:{series.color}\">●</span> {series.name}: <b>{point.yCategory}</b><br/>"
},
"series": [{
"name": "State A",
"pointWidth": 20,
"data": [{
"x": 1540430613000,
"x2": 1540633768100,
"y": 0
}, {
"x": 1540191009000,
"x2": 1540633768100,
"y": 1
}, {
"x": 1540191009000,
"x2": 1540530613000,
"y": 2
}, {
"x": 1540530613000,
"x2": 1540633768100,
"y": 3
}]
}, {
"name": "State B",
"pointWidth": 20,
"data": [{
"x": 1540191009000,
"x2": 1540430613000,
"y": 0
}, {
"x": 1540530613000,
"x2": 1540633768100,
"y": 2
}, {
"x": 1540191009000,
"x2": 1540330613000,
"y": 3
}]
}, {
"name": "State C",
"pointWidth": 20,
"data": [{
"x": 1540330613000,
"x2": 1540530613000,
"y": 3
}]
}],
"exporting": {
"enabled": true,
"sourceWidth": 1200
}
});
Now what I am looking forward to is create something of this sort (pardon my paint skills).
Here the categories A to D are the only axis on y. But I would like to group a variable number of parallel ranges. The use case is that there can be multiple states at any point of time and the number of states at any point of time is variable. How do I go on about doing this?
To create such a chart you will have to add 12 yAxis (0-11) and set proper ticks and labels so that only A-D categories will be plotted. Additionally, adjust plotOptions.pointPadding and plotOptions.groupPadding properties to set points width automatically (series.pointWidth should be undefined then).
yAxis options:
yAxis: [{
title: {
text: "Factions"
},
categories: ["A", "B", "C", "D"],
tickPositions: [-1, 2, 5, 8, 11],
lineWidth: 0,
labels: {
y: -20,
formatter: function() {
var chart = this.chart,
axis = this.axis,
label;
if (!chart.yaxisLabelIndex) {
chart.yaxisLabelIndex = 0;
}
if (this.value !== -1) {
label = axis.categories[chart.yaxisLabelIndex];
chart.yaxisLabelIndex++;
if (chart.yaxisLabelIndex === 4) {
chart.yaxisLabelIndex = 0;
}
return label;
}
},
},
reversed: true
}]
Demo:
https://jsfiddle.net/wchmiel/s9qefg7t/1/
I have managed to solve this thanks to support from Highcharts themselves. The idea is to set the tick position on the load event and use the labels.formatter for formatting each individual label.
events: {
load() {
let labelGroup = document.querySelectorAll('.highcharts-yaxis-labels');
// nodeValue is distance from top
let ticks = document.querySelectorAll('.highcharts-yaxis-grid');
let tickPositions = Array.from(ticks[0].childNodes).map(
function(node){
return +node.attributes.d.nodeValue.split(" ")[2];
}
);
let labelPositions = [];
for(let i =1 ;i<tickPositions.length;i++){
labelPositions.push((tickPositions[i] + tickPositions[i-1])/2);
}
labelGroup[0].childNodes[0].attributes.y.nodeValue = labelPositions[0] + parseFloat(labelGroup[0].childNodes[0].style["font-size"], 10) / 2;
labelGroup[0].childNodes[1].attributes.y.nodeValue = labelPositions[1] + parseFloat(labelGroup[0].childNodes[1].style["font-size"], 10) / 2;
labelGroup[0].childNodes[2].attributes.y.nodeValue = labelPositions[2] + parseFloat(labelGroup[0].childNodes[2].style["font-size"], 10) / 2;
labelGroup[0].childNodes[3].attributes.y.nodeValue = labelPositions[3] + parseFloat(labelGroup[0].childNodes[3].style["font-size"], 10) / 2;
labelGroup[0].childNodes[4].attributes.y.nodeValue = labelPositions[4] + parseFloat(labelGroup[0].childNodes[4].style["font-size"], 10) / 2;
}
}
And the labels are formatted as:
labels: {
formatter: function() {
var chart = this.chart,
axis = this.axis,
label;
if (!chart.yaxisLabelIndex) {
chart.yaxisLabelIndex = 0;
}
if (this.value !== -1) {
label = axis.categories[chart.yaxisLabelIndex];
chart.yaxisLabelIndex++;
if (chart.yaxisLabelIndex === groups.length) {
chart.yaxisLabelIndex = 0;
}
return label;
}
},
}
Fiddle at https://jsfiddle.net/yvnp4su0/42/
As I suggested in the comment above it is a better idea to use Highcharts renderer and add custom labels than manipulate Dom elements as you did in the previous answer, because it is a much cleaner solution.
Disable default labels:
yAxis: [{
title: {
text: "Factions",
margin: 35
},
categories: ["A", "B", "C", "D", "E"],
tickPositions: tickPositions,
lineWidth: 0,
labels: {
enabled: false
},
reversed: true
}]
Add custom labels in proper positions using renderer:
chart: {
type: 'xrange',
height: 500,
marginLeft: 60,
events: {
load: function() {
this.customLabels = [];
},
render: function() {
var chart = this,
yAxis = chart.yAxis[0],
categories = yAxis.categories,
xOffset = 15,
yOffset = 20,
xPos = yAxis.left - xOffset,
tickPositions = yAxis.tickPositions,
text,
label,
yPos,
tick1Y,
tick2Y,
i;
for (i = 0; i < tickPositions.length - 1; i++) {
if (chart.customLabels[i]) {
chart.customLabels[i].destroy();
}
tick1Y = yAxis.toPixels(tickPositions[i]);
tick2Y = yAxis.toPixels(tickPositions[i + 1]);
yPos = (tick1Y + tick2Y) / 2 + yOffset;
text = categories[i];
label = chart.renderer.text(text, xPos, yPos)
.css({
color: '#ccc',
fontSize: '14px'
})
.add();
chart.customLabels[i] = label;
}
}
}
}
Demo: https://jsfiddle.net/wchmiel/vkz7o1hw/
Basically, am working with json objects however my skills are not that much because I am still a newbie in javascript and json or object literals. Am trying to achieve where I would like to push or insert a custom json object at the last element of the other xml/json file. Is there any on way how to do this? I've been trying to do it for quite some time now but could not make it work. Any idea how to make it work? because honestly, I don't have any left :-)
I use getJSON to request a JSON from my website. It works great, but I need to somehow insert another custom object literals at the end of the json is it possible?
By the way here is my code.
$(function() {
$.getJSON('https://some_link_from_a_server_that_produces_xml_file_or_json',
function(data) {
//var dataLength = data.length;
fillData();
function fillData() {
var jsonData = [{
"LastModification": "04:27:48",
"Symbol": "EURUSD",
"Bid": '1.20568',
"Ask": "1.21238",
"High": '1.21789',
"Low": '1.19253',
"Direction": "-1",
"InserTime": "\/Date(1358760600163)\/",
"volume": "0"
}];
for (var i = 0; i < jsonData.length; i++) {
data.push([
parseFloat(jsonData[i].Bid),
parseFloat(jsonData[i].High),
parseFloat(jsonData[i].Low),
parseFloat(jsonData[i].Ask),
parseInt(jsonData[i].InserTime.substr(6)),
parseInt(jsonData[i].volume)
]);
}
CreateChart();
} // end of function fillData()
function CreateChart() {
var chart = new Highcharts.stockChart('container2',
{
title: {
text: 'EUR/USD',
floating: true,
align: 'left',
x: 0,
y: 55
},
subtitle: {
text: 'highest: 1.23223 / lowest: 1.21774',
floating: true,
align: 'left',
x: 0,
y: 70
},
xAxis: {
gridLineWidth: 1
},
yAxis: {
gridLineWidth: 1
},
rangeSelector: {
buttons: [
{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}
],
selected: 1,
inputEnabled: true
},
series: [
{
name: 'EURUSD',
type: 'candlestick',
data: data,
tooltip: {
valueDecimals: 5
}
}
]
}); // end of highcharts.stockchart
}
});
});
I think you are making a array of JSON which looks like [{...}, {...}]
However, in your code you are making an array of array which looks like [[...], [...]].
Try :
let data = [];
const func = function(data) {
fillData();
function fillData() {
var jsonData = [{
"LastModification": "04:27:48",
"Symbol": "EURUSD",
"Bid": '1.20568',
"Ask": "1.21238",
"High": '1.21789',
"Low": '1.19253',
"Direction": "-1",
"InserTime": "\/Date(1358760600163)\/",
"volume": "0"
}];
for (var i = 0; i < jsonData.length; i++) {
data.push({
Bid :parseFloat(jsonData[i].Bid),
High : parseFloat(jsonData[i].High),
Low : parseFloat(jsonData[i].Low),
Ask : parseFloat(jsonData[i].Ask),
InserTime : parseInt(jsonData[i].InserTime.substr(6)),
Volume :parseInt(jsonData[i].volume)
});
}
console.log(data);
} // end of function fillData()
}
func(data);