Amcharts 5 - Smoothed line chart - two line charts - javascript

Im dealing with this problem.
I have smoothed line chart from amcharts v5.
And everything is working properly until i want to add second line to the chart. It only displays one line chart. And i need to add second line to the same chart.
If I change data values to another chart. It is working fine but same problem, only one line.
So my question is, how to add second line into same chart.
am5.ready(function() {
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root)
]);
// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: true,
panY: true,
wheelX: "panX",
wheelY: "zoomX",
pinchZoomX:true
}));
// Add cursor
// https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/
var cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
behavior: "none"
}));
cursor.lineY.set("visible", false);
function generateDataInvestice(roky,investice) {
value = investice;
return {
date: roky,
value: value
};
}
function generateDatasInvestice(count,i) {
var data = [];
var investice = 5;
for (var i = 1; i < count; ++i) {
data.push(generateDataInvestice(i,investice));
}
return data;
}
//generate uver
function generateDataUver(roky,uver) {
value = uver;
return {
date: roky,
value: value
};
}
function generateDatasUver(count,i) {
var data = [];
var uver = 1;
for (var i = 1; i < count; ++i) {
data.push(generateDataUver(i,uver));
}
return data;
}
// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
maxDeviation: 1,
baseInterval: {
count: 1
},
renderer: am5xy.AxisRendererX.new(root, {
pan:"zoom"
}),
tooltip: am5.Tooltip.new(root, {})
}));
var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
maxDeviation:1,
renderer: am5xy.AxisRendererY.new(root, {
pan:"zoom"
})
}));
// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var series = chart.series.push(am5xy.SmoothedXLineSeries.new(root, {
name: "Series",
xAxis: xAxis,
yAxis: yAxis,
valueYField: "value",
valueXField: "date",
tooltip: am5.Tooltip.new(root, {
labelText: "{valueY}"
})
}));
series.fills.template.setAll({
visible: true,
fillOpacity: 0.2
});
series.bullets.push(function() {
return am5.Bullet.new(root, {
locationY: 0,
sprite: am5.Circle.new(root, {
radius: 4,
stroke: root.interfaceColors.get("background"),
strokeWidth: 2,
fill: series.get("fill")
})
});
});
var data = generateDatasInvestice(30,0);
var data_uver = generateDatasUver(30,0);
series.data.setAll(data,data_uver);
series.appear(30);
chart.appear(1000, 100);
}); // end am5.ready()
Here is working soluiton on codepen: https://codepen.io/tom-august/pen/KKQLgbm
Thanks a lot.

In your data, you should have several value fields like so:
var data = [
{
date: new Date("2022-12-27").getTime(),
value1: 10,
value2: 20
},
{
date: new Date("2022-12-28").getTime(),
value1: 20,
value2: 30
},
{
date: new Date("2022-12-29").getTime(),
value1: 10,
value2: 20
}
];
Then you need to create a series for each line that you want to display, associating each series with the corresponding value field. This can be done using a function:
function createSeries(name, field) {
var series = chart.series.push(am5xy.SmoothedXLineSeries.new(root, {
name: name,
xAxis: xAxis,
yAxis: yAxis,
valueXField: "date",
valueYField: field
}));
series.data.setAll(data);
}
createSeries("Series 1", "value1");
createSeries("Series 2", "value2");
am5.ready(function() {
var root = am5.Root.new("chartdiv");
var chart = root.container.children.push(am5xy.XYChart.new(root, {}));
var data = [
{
date: new Date("2022-12-27").getTime(),
value1: 10,
value2: 20
},
{
date: new Date("2022-12-28").getTime(),
value1: 20,
value2: 30
},
{
date: new Date("2022-12-29").getTime(),
value1: 10,
value2: 20
}
];
var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
baseInterval: { timeUnit: "day", count: 1 },
renderer: am5xy.AxisRendererX.new(root, {}),
}));
var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererY.new(root, {})
}));
function createSeries(name, field) {
var series = chart.series.push(am5xy.SmoothedXLineSeries.new(root, {
name: name,
xAxis: xAxis,
yAxis: yAxis,
valueXField: "date",
valueYField: field
}));
series.data.setAll(data);
}
createSeries("Series 1", "value1");
createSeries("Series 2", "value2");
});
#chartdiv {
width: 100%;
height: 350px;
}
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<div id="chartdiv"></div>

Related

Issue with json data mapping with Highcharts

I'm trying to implement highcharts, but having difficulties in mapping the JSON data correctly.
Fiddle: https://jsfiddle.net/AndreasBren/vux52sL4/11/
var endpoint = '/api/chart/data/'
var label = []
var start = []
var end = []
var werk = []
$.ajax({
method: 'GET',
url: endpoint,
success: function(data) {
labels = data.label
start = data.start
end = data.end
uplant = data.werk
const forstart = start;
const newstart = forstart.map((str) => {
const [year, month, date] = str.split("-");
return `${date}.${month}.${year}`;
});
// console.log(newstart); "01.01.2019"
var dates = newstart.map(function(str) {
return new Date(str);
});
var sdates_ms = dates.map(function(date) {
return date.getTime();
});
const forend = end;
const newend = forend.map((str) => {
const [year, month, date] = str.split("-");
return `${date}.${month}.${year}`;
});
// console.log(newend); // "03.01.2019"
var dates = newend.map(function(str) {
return new Date(str);
});
var edates_ms = dates.map(function(date) {
return date.getTime();
});
var obj = {}
var finalArray = []
for (var i = 1; i <= start.length; i++) {
var first = {
name: uplant[i]
}
obj = {
...obj,
...first
}
var data = {
start: sdates_ms[i - 1],
end: edates_ms[i - 1],
name: labels[i],
y: 0
}
if (obj.data) {
obj.data.push(data)
} else {
obj.data = [data]
}
finalArray.push(obj)
}
day = 1000 * 60 * 60 * 24
var chart = Highcharts.ganttChart('container', {
chart: {
spacingLeft: 1,
scrollablePlotArea: {
minWidth: 700,
scrollPositionX: 0
}
},
title: {
text: 'Gantt Visualisation'
},
subtitle: {
text: ''
},
plotOptions: {
series: {
animation: true,
dragDrop: {
draggableX: true,
draggableY: true,
dragPrecisionX: day / 3
},
dataLabels: {
enabled: false,
format: '{point.name}',
style: {
cursor: 'default',
pointerEvents: 'none'
}
},
allowPointSelect: true,
}
},
scrollbar: {
enabled: true
},
yAxis: {
type: 'category',
categories: uplant,
},
xAxis: {
currentDateIndicator: true,
},
tooltip: {
xDateFormat: '%a %b %d, %H:%M'
},
series: finalArray,
scrollbar: {
enabled: true,
barBackgroundColor: 'gray',
barBorderRadius: 7,
barBorderWidth: 0,
buttonBackgroundColor: 'gray',
buttonBorderWidth: 0,
buttonArrowColor: 'yellow',
buttonBorderRadius: 7,
rifleColor: 'yellow',
trackBackgroundColor: 'white',
trackBorderWidth: 1,
trackBorderColor: 'silver',
trackBorderRadius: 7
}
});
},
error: function(error_data) {
console.log("error")
console.log(error_data)
}
});
Result:
One row contains all plants and all orders
Row 1 > Plant 1, Plant 2, ... > Order 1, Order 2, ...
Expected Result:
Each row stands for one plant and contains the orders of this plant
Row 1 > Plant 1 > Order 1
Row 2 > Plant 2 > Order 2
....
Fiddle: https://jsfiddle.net/AndreasBren/vux52sL4/11/
Thank you very much for any help!
There is a lot of confusion in your code. The main reason that all the orders appear to the first row, is because you're setting the y:0 inside the data binding loop. Also you start the for loop index from 1 which is unnecessary and leads to unwanted behavior. There is a much more cleaner and simple way to make the data object like this:
labels = ["Workorder1","Workorder2"]
start = ["2001.02.01","2002.02.10"]
end = ["2001.03.02","2002.03.10"]
uplant = ["Plant A","Plant B"]
const makeDate = str => {
const [year, month, date] = str.split(".")
return new Date(`${month}.${date}.${year}`).getTime()
}
const finalArray = start.map((s, i) => ({
name: labels[i],
start: makeDate(s),
end: makeDate(end[i]),
y: i
}))
define the yAxis like this:
yAxis: {
type: 'category',
categories: uplant,
min: 0,
max: uplant.length - 1
},
and the series like this:
series: [{ data: finalArray }]
Check my working fiddle: https://jsfiddle.net/lytrax/hyq206xt/26/

Draw a Line Chart with both solid and dotted line in it with angular nvd3js directive?

I'm using angular-nvd3 directive for making a custom line chart display counting number of guest in specific period time range as follow :
current Time - 2 --> current Time : will be display as straight line
current Time --> current Time + 2 : will be display as dotted line .
Here is my implementation code with only straight line:
var app = angular.module('plunker', ['nvd3']);
app.controller('MainCtrl', function($scope) {
$scope.options = {
chart: {
type: 'lineChart',
tooltips: false,
height: 450,
margin : {
top: 20,
right: 20,
bottom: 40,
left: 55
},
x: function(d){ return d.x; },
y: function(d){ return d.y; },
useInteractiveGuideline: false,
dispatch: {
stateChange: function(e){ console.log("stateChange"); },
changeState: function(e){ console.log("changeState"); },
tooltipShow: function(e){ console.log("tooltipShow"); },
tooltipHide: function(e){ console.log("tooltipHide"); }
},
xAxis: {
axisLabel: 'Time (ms)'
},
yAxis: {
axisLabel: 'Voltage (v)',
tickFormat: function(d){
return d3.format('.02f')(d);
},
axisLabelDistance: 30
},
callback: function(chart){
console.log("!!! lineChart callback !!!");
}
},
title: {
enable: true,
text: 'Title for Line Chart'
}
};
$scope.data = sinAndCos();
/*Random Data Generator */
function sinAndCos() {
var sin = [],sin2 = [],
cos = [];
//Data is represented as an array of {x,y} pairs.
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: Math.sin(i/10)});
sin2.push({x: i, y: i % 10 == 5 ? null : Math.sin(i/10) *0.25 + 0.5});
cos.push({x: i, y: .5 * Math.cos(i/10+ 2) + Math.random() / 10});
}
//Line chart data should be sent as an array of series objects.
return [
{
values: [{x:7,y:100},{x:8,y:40},{x:9,y:70}],
key: 'Sine Wave', //key - the name of the series.
color: '#ff7f0e', //color - optional: choose your own line color.
strokeWidth: 2
},
{
values: [{x:7,y:200},{x:8,y:140},{x:9,y:170},{x:10,y:120},{x:11,y:180}],
key: 'Cosine Wave',
color: '#2ca02c'
},
{
values: [{x:7,y:300},{x:8,y:240},{x:9,y:270},{x:10,y:220},{x:11,y:280}],
key: 'Another sine wave',
color: '#7777ff'
}
];
};
});
Here is the plunker for this : http://plnkr.co/edit/lBKFld?p=preview
Anyone can provide some help that would get my great appreciate.
Thanks
{
values: [{x:7,y:200},{x:8,y:140},{x:9,y:170},{x:10,y:120},{x:11,y:180}],
key: 'Cosine Wave',
color: '#2ca02c',
classed: 'dashed' // <-- Now use CSS to make the line dashed
}
STYLE!!!
.dashed {
stroke-dasharray: 5,5;
}

Updating highcharts live data not working

I have some UV Sensors (currently running on Thingspeak) - but I need to have multiple series on the same chart, so I made a sample .php page on my website.
I have the basic chart working nicely, but I have not been able to get it to do live updates - my coding skills are very lacking & I would appreciate any help I can get!
The sample chart is here: http://www.sesupply.co.nz/test.php
I have the code on JSFiddle here: https://jsfiddle.net/SESupply/9xn65qrL/9/
// variables for the first series
var series_1_channel_id = 43330;
var series_1_field_number = 4;
var series_1_read_api_key = '7ZPHNX2SXPM0CA1K';
var series_1_results = 480;
var series_1_color = '#d62020';
var series_1_name = 'Zims Sensor';
// variables for the second series
var series_2_channel_id = 45473;
var series_2_field_number = 2;
var series_2_read_api_key = 'N12T3CWQB5IWJAU9';
var series_2_results = 480;
var series_2_color = '#00aaff';
var series_2_name = 'UVM30A';
// chart title
var chart_title = 'UV Sensors Zim / UVM30A';
// y axis title
var y_axis_title = 'UV Index';
// user's timezone offset
var my_offset = new Date().getTimezoneOffset();
// chart variable
var my_chart;
// when the document is ready
$(document).on('ready', function () {
// add a blank chart
addChart();
// add the first series
addSeries(series_1_channel_id, series_1_field_number, series_1_read_api_key, series_1_results, series_1_color, series_1_name);
// add the second series
addSeries(series_2_channel_id, series_2_field_number, series_2_read_api_key, series_2_results, series_2_color, series_2_name);
});
// add the base chart
function addChart() {
// variable for the local date in milliseconds
var localDate;
// specify the chart options
var chartOptions = {
chart: {
renderTo: 'chart-container',
defaultSeriesType: 'spline',
zoomType: 'x', // added here
panning: true,
panKey: 'shift',
backgroundColor: '#ffffff',
events: {
load: addSeries
}
},
title: {
text: chart_title
},
subtitle: {
text: 'Click and drag to zoom in. Hold down shift key to pan.'
},
plotOptions: {
series: {
marker: {
radius: 2
},
animation: true,
step: false,
borderWidth: 0,
turboThreshold: 0
}
},
scrollbar: {
enabled: true
// barBackgroundColor: 'gray',
// barBorderRadius: 7,
// barBorderWidth: 0,
// buttonBackgroundColor: 'gray',
// buttonBorderWidth: 0,
// buttonArrowColor: 'yellow',
// buttonBorderRadius: 7,
// rifleColor: 'yellow',
// trackBackgroundColor: 'white',
// trackBorderWidth: 1,
// trackBorderColor: 'silver',
// trackBorderRadius: 7
},
tooltip: {
// reformat the tooltips so that local times are displayed
formatter: function () {
var d = new Date(this.x + (my_offset * 60000));
var n = (this.point.name === undefined) ? '' : '<br>' + this.point.name;
return this.series.name + ':<b>' + this.y + '</b>' + n + '<br>' + d.toDateString() + '<br>' + d.toTimeString().replace(/\(.*\)/, "");
}
},
xAxis: {
type: 'datetime',
title: {
text: 'Date'
}
},
rangeSelector: {
enabled: true,
buttons: [{
type: 'minute',
count: 60,
text: 'Hour'
}, {
type: 'day',
count: 1,
text: 'Day'
}, {
type: 'week',
count: 1,
text: 'Week'
}, {
type: 'all',
text: 'All'
}]
},
yAxis: {
title: {
text: y_axis_title
}
},
exporting: {
enabled: true
},
legend: {
enabled: true
},
credits: {
text: 'ThingSpeak.com',
href: 'https://thingspeak.com/',
style: {
color: '#D62020'
}
}
};
// draw the chart
my_chart = new Highcharts.Chart(chartOptions);
}
// add a series to the chart
function addSeries(channel_id, field_number, api_key, results, color, name) {
var field_name = 'field' + field_number;
// get the data with a webservice call
$.getJSON('https://api.thingspeak.com/channels/' + channel_id + '/fields/' + field_number + '.json?offset=0&round=2&results=' + results + '&api_key=' + api_key, function (data) {
// blank array for holding chart data
var chart_data = [];
// iterate through each feed
$.each(data.feeds, function () {
var point = new Highcharts.Point();
// set the proper values
var value = this[field_name];
point.x = getChartDate(this.created_at);
point.y = parseFloat(value);
// add location if possible
if (this.location) {
point.name = this.location;
}
// if a numerical value exists add it
if (!isNaN(parseInt(value))) {
chart_data.push(point);
}
});
// add the chart data
my_chart.addSeries({
data: chart_data,
name: name,
color: color
});
});
setTimeout(addSeries, 1000);
}
cache: false;
// converts date format from JSON
function getChartDate(d) {
// offset in minutes is converted to milliseconds and subtracted so that chart's x-axis is correct
return Date.parse(d) - (my_offset * 60000);
}
I have tried following the livedata example but seem to be failing miserably. The sensors update about every 60 seconds (only during the day - as there is no UV at night, I put the sensors into "sleep" mode to save battery power)

Highcharts error #15: www.highcharts.com/errors/15

I'm trying to use yahoo finance data to generate a Highcharts candlestick chart like this http://www.highcharts.com/stock/demo/candlestick-and-volume. But I keep getting this error: http://www.highcharts.com/errors/15
Highcharts Error #15
Highcharts expects data to be sorted
This happens when you are trying to create a line series or a stock chart where the data is not sorted in ascending X order. For performance reasons, Highcharts does not sort the data, instead it is required that the implementer pre-sorts the data.
My code is as follows.
$(function () {
$.getJSON('http://websitescraper.heroku.com/?url=http://ichart.finance.yahoo.com/table.csv?s=000338.sz&callback=?', function (csvdata) {
//console.log(csvdata);
var arr = csvdata.split('\n').slice(1);
var data = [];
for (var i = arr.length-1; i >= 0; --i) {
//console.log(arr[i]);
var line = arr[i].split(',');
line[0] = Date.parse(line[0]);
line = $.map(line, function(v) {
return parseFloat(v);
});
line = line.slice(0,6);
//var j = JSON.stringify(line.slice(0,0+6));
console.log(line);
data.push(line);
}
data = JSON.stringify(data.slice(1));
console.log(data);
run(data);
});
});
function run(data) {
// split the data set into ohlc and volume
var ohlc = [],
volume = [],
dataLength = data.length,
// set the allowed units for data grouping
/*groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]],*/
i = 0;
for (i; i < dataLength; i += 1) {
ohlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
]);
}
// create the chart
$('#container2').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: 'Shanghai Composite Index Historical'
},
yAxis: [{
labels: {
align: 'right',
x: -3
},
title: {
text: 'OHLC'
},
height: '60%',
lineWidth: 2
}, {
labels: {
align: 'right',
x: -3
},
title: {
text: 'Volume'
},
top: '65%',
height: '35%',
offset: 0,
lineWidth: 2
}],
series: [{
type: 'candlestick',
upLineColor: 'red',
downLineColor: 'green',
name: 'SSE',
data: ohlc,
/*dataGrouping: {
units: groupingUnits
}*/
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1
/*dataGrouping: {
units: groupingUnits
}*/
}]
});
}
Can somebody help? Thanks a lot!
The problem is the data = JSON.stringify(data.slice(1));. It turns the array to a string, therefore Highstock doesn't recognize it. Remove JSON.stringify and it will work fine:
data = data.slice(1);
Here's the DEMO.

How to place pie charts instead of markers in kendo ui maps

I need to create a map widget using kendo map UI .I have to replace the markers with pie chart like this . Is it possible to create a map widget using kendo ??? , If it is possible how can I do that .I dont know how to make this I'm new to Kendo. Please Help me...
I found a solution for my problem.
Step 1: First create a kendo map
$("#geoMap").kendoMap({
renderAs: "canvas",
center: [39.6924, -97.3370],
zoom: 4,
controls: {
attribution: false,
navigator: false,
zoom: false
},
layers: [{
type: "shape",
dataSource: {
type: "geojson",
transport: {
read: "/Scripts/kendo/us.geo.json"
}
},
style: {
stroke: {
color: "#A3A396"
},
fill: {
color: "#E6E6D4"
}
}
}],
shapeCreated: onShapeCreated,
reset: reset
});
Create a function named onShapeCreated, this function will call each time after the shape created in Kendo map
function onShapeCreated(event)
{
.......
}
Step 2 : If you want to create a map on a state then you need to find the position of that state to find that use the below function
function getShapePositions(event)
{
var result = {};
var segments = event.shape.segments;
result.minX = Number.MAX_VALUE;
result.maxX = Number.MIN_VALUE;
result.minY = Number.MAX_VALUE;
result.maxY = Number.MIN_VALUE;
if (segments) {
for (var i = 0; i < segments.length; i++) {
var anchor = segments[i].anchor();
result.minX = Math.min(result.minX, anchor.x);
result.maxX = Math.max(result.maxX, anchor.x);
result.minY = Math.min(result.minY, anchor.y);
result.maxY = Math.max(result.maxY, anchor.y);
}
}
result.width = result.maxX - result.minX;
result.height = result.maxY - result.minY;
return result;
}
Step 3: To create the pie chart on map, first we need to create a container div and append it to the map to do that use the following code
var chartDiv = $("<div id=" + event.shape.dataItem.properties.code + " class='state-code-label'></div>")
.appendTo(event.sender.scrollElement);
Step 4. After creating the container, create a pie chart using that container
function createPieChart(chartDiv)
{
$(chartDiv).kendoChart({
renderAs: "canvas",
title: {
visible: false
},
transitions: false,
legend: {
visible: false
},
chartArea: {
height: 100,
width: 100,
background: ""
},
data: [{
category: "Test",
value: 53.8,
color: "#9de219"
},{
category: "Test1",
value: 3.6,
color: "#033939"
}]
}],
seriesDefaults: {
labels: {
visible: false
},
overLay: {
gradient: null
}
},
seriesColors: ["#8F0000", "#CCCCCC"],
series: [{
type: "pie",
field: "Amount",
categoryField: "Category"
}],
tooltip: {
visible: false
}
});
}
Step 5 : Finally use the position object for placing the chart on map correctly.
chartDiv.css({
top: position.minY + position.height / 2 - chartDiv.height() / 2,
left: position.minX + position.width / 2 - chartDiv.width() / 2
});
Now The onShapeCreated function will look like this
function onShapeCreated(event)
{
var position = getShapePositions(event);
var chartDiv = $("<div id=" + event.shape.dataItem.properties.code + " class='state-code-label'></div>")
.appendTo(event.sender.scrollElement);
createPieChart(chartDiv);
chartDiv.css({
top: position.minY + position.height / 2 - chartDiv.height() / 2,
left: position.minX + position.width / 2 - chartDiv.width() / 2
});
}

Categories