I'm using Kendo Data viz and am passing JSON to an .NET MVC page to initialise the chart:
<div class="k-chart" id="SummaryWeekImportChart"></div>
$("#SummaryWeekImportChart").kendoChart(
#Html.Raw(Model.KendoLineChartJson));
The JSON (important bits):
"dataSource":{
"schema":{
"model":{
"fields":{
"TotalValue":{
"type":"number"
},
"SuccessValue":{
"type":"number"
},
"ErrorValue":{
"type":"number"
},
"Date":{
"type":"date"
},
"Category":{
"type":"string"
},
"ToolTip":{
"editable":false,
"type":"string"
}
}
}
},
"data":[
{
"TotalValue":0,
"SuccessValue":0,
"ErrorValue":0,
"Date":"2013-10-18T00:00:00",
"Category":"18/10/2013",
"ToolTip":"18/10/2013"
},
{
"TotalValue":0,
"SuccessValue":0,
"ErrorValue":0,
"Date":"2013-10-19T00:00:00",
"Category":"19/10/2013",
"ToolTip":"19/10/2013"
},
{
"TotalValue":0,
"SuccessValue":0,
"ErrorValue":0,
"Date":"2013-10-20T00:00:00",
"Category":"20/10/2013",
"ToolTip":"20/10/2013"
},
{
"TotalValue":0,
"SuccessValue":0,
"ErrorValue":0,
"Date":"2013-10-21T00:00:00",
"Category":"21/10/2013",
"ToolTip":"21/10/2013"
},
{
"TotalValue":1,
"SuccessValue":0,
"ErrorValue":1,
"Date":"2013-10-22T00:00:00",
"Category":"22/10/2013",
"ToolTip":"22/10/2013"
},
{
"TotalValue":68,
"SuccessValue":68,
"ErrorValue":0,
"Date":"2013-10-23T00:00:00",
"Category":"23/10/2013",
"ToolTip":"23/10/2013"
},
{
"TotalValue":96,
"SuccessValue":96,
"ErrorValue":0,
"Date":"2013-10-24T00:00:00",
"Category":"24/10/2013",
"ToolTip":"24/10/2013"
}
]
I'm using javascript to poll the server every x seconds:
$.get("/Dash/GetLineChartData", { searchDateString: searchDateForm },
function (incomingData) {
console.log("GetLineChartData back...", incomingData);
// Replace the data in the pie chart with the new data
var chart = $('#SummaryWeekImportChart').data("kendoChart");
var currSource = chart.dataSource;
currSource.data(incomingData.dataSource.data);
chart.refresh();
});
The data is loading ok but the labels across the x axis break.
Does anyone know how to update a line chart's data without messing up the labels?
you can add categoryAxis property inside the for the kendo chart like
categoryAxis: {
field: "Date",
labels: {
rotation: -65
},
majorGridLines: {
visible: false
}
},
Related
I am trying to poll my data in HighCharts. The graph in this link is what I am trying to achieve. I am using Ajax request to retrieve my data. Here is my code:
setInterval(RefreshGraph, 3000);
...
...
function RefreshGraph() {
var options = {
chart: {
type: 'spline'
},
title: {
text: 'Text'
},
xAxis: {
title: {
text: 'TIMEFRAME'
},
categories: ['-4m', '-3m', '-2m', '-1m', 'Now']
},
yAxis: {
title: {
text: 'NUMBER'
},
},
tooltip: {
crosshairs: true,
shared: true
},
plotOptions: {
spline: {
marker: {
radius: 4,
lineColor: '#666666',
lineWidth: 2
}
}
},
series: [{}]
};
Highcharts.ajax({
url: "/Home/GetData",
success: function (data) {
var formattedData = FormatData(data);
//Graph 1
options.series[0] = formattedData[0];
//Graph 2
options.series[1] = formattedData[1];
Highcharts.chart("container", options);
}
});
}
However, the entire graph gets redrawn with my above code. How can I enable live polling for the above code?
You create a chart every time data is received. You need to create a chart and then update it. Example:
const options = {...};
const chart = Highcharts.chart("container", options);
function RefreshGraph() {
Highcharts.ajax({
url: "/Home/GetData",
success: function(data) {
var formattedData = FormatData(data);
chart.update({
series: [formattedData[0], formattedData[1]]
});
}
});
}
setInterval(RefreshGraph, 3000);
Live demo: http://jsfiddle.net/BlackLabel/6d5stjab/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Chart#update
I would like to do map drilldown using Highcharts by following this US Map Drilldown example : US Map Drilldown Highcharts
This is the sample of my drilldown javascript file
var data = Highcharts.geojson(Highcharts.maps['countries/my/my-all']),
separators = Highcharts.geojson(Highcharts.maps['countries/my/my-all'], 'mapline'),
// Some responsiveness
small = $('#container').width() < 400;
// Set drilldown pointers
$.each(data, function (i) {
this.drilldown = this.properties['hc-key'];
this.value = i; // Non-random bogus data
});
// Instantiate the map
Highcharts.mapChart('container', {
chart: {
events: {
drilldown: function (e) {
if (!e.seriesOptions) {
var chart = this,
mapKey = 'countries/my/' + e.point.drilldown + '-all',
// Handle error, the timeout is cleared on success
fail = setTimeout(function () {
if (!Highcharts.maps[mapKey]) {
chart.showLoading('<i class="icon-frown"></i> Failed loading ' + e.point.name);
fail = setTimeout(function () {
chart.hideLoading();
}, 1000);
}
}, 3000);
// Show the spinner
chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>'); // Font Awesome spinner
// Load the drilldown map
$.getScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', function () {
data = Highcharts.geojson(Highcharts.maps[mapKey]);
// Set a non-random bogus value
$.each(data, function (i) {
this.value = i;
});
// Hide loading and add series
chart.hideLoading();
clearTimeout(fail);
chart.addSeriesAsDrilldown(e.point, {
name: e.point.name,
data: data,
dataLabels: {
enabled: true,
format: '{point.name}'
}
});
});
}
this.setTitle(null, { text: e.point.name });
},
drillup: function () {
this.setTitle(null, { text: '' });
}
}
This is sample code for states.json
"features": [
{
"type": "Feature",
"id": "MY.SA",
"properties": {
"hc-group": "admin1",
"hc-middle-x": 0.32,
"hc-middle-y": 0.6,
"hc-key": "my-sa",
"hc-a2": "SA",
"labelrank": "6",
"hasc": "MY.SA",
"alt-name": "North Borneo",
"woe-id": "2346310",
"subregion": null,
"fips": "MY16",
"postal-code": "SA",
"name": "Sabah",
"country": "Malaysia",
"type-en": "State",
"region": null,
"longitude": "117.095",
"woe-name": "Sabah",
"latitude": "5.31115",
"woe-label": "Sabah, MY, Malaysia",
"type": "State"
},
This is sample code for district in district.json
{
"type": "Feature",
"properties": {
"GID_0": "MYS",
"NAME_0": "Malaysia",
"GID_1": "MYS.13_1",
"NAME_1": "Sabah",
"NL_NAME_1": null,
"GID_2": "MYS.13.1_1",
"NAME_2": "Beaufort",
"VARNAME_2": null,
"NL_NAME_2": null,
"TYPE_2": "Daerah",
"ENGTYPE_2": "District",
"CC_2": null,
"HASC_2": "MY.SA.BF",
"ISO": "MY-12",
"ISO_district": "MY-12.1"
},
I need to use getJSON function right? Can someone help me how to do the declaration in the javascript file?
I'm drawing a pie chart using AmCharts V3 and am using the export plugin to export the data as a file. I'm displaying a percentage contibution of the sale in different countries and would like to also display this percentage when I export my data to a CSV or XLSX file, but I'm not able to do so.
Here is my code
var chart = AmCharts.makeChart("chartdivtaxes", {
type: "pie",
startDuration: 0,
theme: "light",
addClassNames: true,
labelText: "[[percents]]",
innerRadius: "30%",
labelFunction: function(value, valueText, valueAxis) {
valueText = parseFloat(valueText);
var percentageText = valueText
.toFixed(1)
.replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
return percentageText + "%";
},
defs: {
filter: [
{
id: "shadow",
width: "200%",
height: "200%",
feOffset: {
result: "offOut",
in: "SourceAlpha",
dx: 0,
dy: 0
},
feGaussianBlur: {
result: "blurOut",
in: "offOut",
stdDeviation: 5
},
feBlend: {
in: "SourceGraphic",
in2: "blurOut",
mode: "normal"
}
}
]
},
dataProvider: [
{
countryName: "India",
country: "sale in india:",
litres: "800.00"
},
{
countryName: "africa",
country: "sale in africa:",
litres: "800.00"
},
{
countryName: "UK",
country: "sale in UK:",
litres: "800.00"
},
{
countryName: "US",
country: "sale in US:",
litres: "800.00"
}
],
valueField: "litres",
titleField: "country",
balloon: {
fixedPosition: false,
color: "#ffffff",
fillAlpha: 0.9,
fillColor: "#00000"
},
export: {
enabled: true,
divId: "exportLevy",
columnNames: {
litres: "TotalSale",
countryName: "Name"
},
menu: [
{
class: "export-main",
label: "Export",
menu: [
{
format: "XLSX"
},
{
format: "CSV"
}
]
}
],
exportFields: ["countryName", "litres", "percents"]
}
});
There are two ways you can go about this - both of which involve using the processData callback offered by the export plugin.
1) Use processData to add a percent property in your data and manually trigger a download with toCSV or toXLSX. Note that you will need to throw an exception to prevent the plugin from triggering the download multiple times:
var chart = AmCharts.makeChart("...", {
// ...
export: {
// ...
processData: function(data, cfg) {
//only for CSV and XLSX export. Wrap in an ignore call to prevent infinite loop
if ((cfg.format === "CSV" || cfg.format === "XLSX") && !cfg.ignoreThatRequest) {
var sum = data.reduce(function(accumulator, currentDataValue) {
return accumulator + parseFloat(currentDataValue.TotalSale);
}, 0);
data.forEach(function(currentDataValue) {
currentDataValue.percents =
(parseFloat(currentDataValue.TotalSale) / sum * 100).toFixed(1) + "%";
});
//will map to this.toCSV or this.toXLSX
this["to" + cfg.format]({
data: JSON.parse(JSON.stringify(data)),
ignoreThatRequest: true, //set ignore flag as processData will execute again when this is called
exportFields: ["Name", "TotalSale", "percents"]
},
function(output) {
this.download(output, cfg.mimeType, cfg.fileName + "." + cfg.extension);
}
);
throw "Invoked – Use custom handler (stop multiple download)"; //throw an exception to stop the multi-download attempt
}
return data;
}
}
});
Demo of method #1
2) Alternatively, add a dummy percents property in your dataProvider with its value set to null and use processData to fill it in before exporting the chart. This is simpler and doesn't require an exception workaround to prevent multiple downloads:
var chart = AmCharts.makeChart("...", {
// ...
export: {
// ...
processData: function(data, cfg) {
var sum = data.reduce(function(accumulator, currentDataValue) {
return accumulator + parseFloat(currentDataValue.TotalSale);
}, 0);
data.forEach(function(currentDataValue) {
currentDataValue.percents =
(parseFloat(currentDataValue.TotalSale) / sum * 100).toFixed(1) + "%";
});
return data;
}
}
});
Demo of method #2
Is there way to fill space after one column was hidden by clicking on legend item?
<div id="container" style="height: 300px"></div>
<script src="http://code.highcharts.com/highcharts.src.js"></script>
var chart = new Highcharts.Chart({
chart: {
type: 'column',
renderTo: 'container'
},
"title":{
"text":"TITLE",
"align":"left"
},
"subtitle":{
"text":"Subtitle Text",
"align":"left",
"style":{
"paddingBottom":"20px"
}
},
"xAxis":{
"categories":[
"Category1",
"Category2",
"Category3",
"Category4",
"Category5"
],
"crosshair":true,
"title":{
},
"labels":{
"enabled":false,
"format":"{value}"
}
},
"yAxis":{
"min":0,
"title":{
"text":"Meters"
},
"labels":{
"format":"{value}"
}
},
"tooltip":{
"enabled":true,
"headerFormat":"<span style=\"font-size:10px\">{point.key}</span><br/>",
"shared":true,
"useHTML":true
},
"legend":{
"enabled":true,
"align":"left",
"useHTML":true
},
"plotOptions":{
"column":{
"pointPadding":0.2,
"borderWidth":0,
"dataLabels":{
"enabled":true,
"format":"{point.y:.2f} ",
"style":{
"textShadow":0
}
}
},
"series":{
"grouping":false
}
},
"series":[
{
"name":"Category1",
"data":[
{
"name":"Category1",
"y":45,
"x":0
}
]
},
{
"name":"Category2",
"data":[
{
"name":"Category2",
"y":43,
"x":1
}
]
},
{
"name":"Category3",
"data":[
{
"name":"Category3",
"y":43,
"x":2
}
]
},
{
"name":"Category4",
"data":[
{
"name":"Category4",
"y":42,
"x":3
}
]
},
{
"name":"Category5",
"data":[
{
"name":"Category5",
"y":42,
"x":4
}
]
},
{
"name":"",
"data":[
{
}
],
"visible":false,
"showInLegend":false,
"exporting":false
},
{
"name":"Bla bla bla",
"data":[
45,
43,
43,
42,
42
],
"showInLegend":false,
"visible":false,
"exporting":true
}
],
"exporting":{
"enabled":false,
"chartOptions":{
"legend":{
"enabled":true,
"maxHeight":null,
"itemStyle":{
"fontFamily":"Arial"
}
}
}
},
"loading":{
"style":{
"opacity":0.9
}
},
"drilldown":{
"drillUpButton":{
"theme":{
"style":{
"display":"none"
}
}
}
}
});
Here is live example.
When I click on first or last legend item, then chart are redrawing, but it doesn't happening when I clicked on a middle legend item? It's a bug or feature? And how I can change this behavior for middle legend items to they able also throw the event redrawing the chart?
Thanks advance
You could set and update breaks for xAxis to hide the empty space:
http://jsfiddle.net/a4vcye4p/1/
events: {
legendItemClick: function() {
var series = this,
seriesIndex = series._i,
xAxis = series.xAxis,
newBreaks = [];
if (series.visible) {
newBreaks = xAxis.options.breaks;
newBreaks.push({
from: seriesIndex,
to: seriesIndex + 1,
seriesIndex: seriesIndex
});
} else {
Highcharts.each(xAxis.options.breaks, function(br) {
if (br.seriesIndex !== seriesIndex) {
newBreaks.push(br);
}
});
}
xAxis.update({
breaks: newBreaks
});
}
}
The tooltips for my hacked gantt chart using highcharts doesnt seem to be working properly. I used the gantt chart provided by the highcharts team from here-:
http://jsfiddle.net/highcharts/r6emu/
I am using UnixTime and that seems to be somehow throwing off the tooltips. Here-:
http://jsfiddle.net/bootkick/NFS5M/
// Define tasks
var tasks = [{
"name": "a",
"intervals": [{
"from": 1366005607000,
"to": 1366006490000
}]
}, {
"name": "b",
"intervals": [{
"from": 1366059607000,
"to": 1366061858000
}, {
"from": 1366056006000,
"to": 1366058223000
}, {
"from": 1366047007000,
"to": 1366049299000
}, {
"from": 1366034407000,
"to": 1366036682000
}, {
"from": 1366030808000,
"to": 1366033050000
}, {
"from": 1366027208000,
"to": 1366029512000
}, {
"from": 1366018209000,
"to": 1366021296000
}]
}, {
"name": "c",
"intervals": [{
"from": 1366018209000,
"to": 1366019966000
}]
}, {
"name": "d",
"intervals": [{
"from": 1366005607000,
"to": 1366047612000
}, {
"from": 1366002007000,
"to": 1366002202000
}]
}];
// re-structure the tasks into line seriesvar series = [];
var series = [];
$.each(tasks.reverse(), function (i, task) {
var item = {
name: task.name,
data: []
};
$.each(task.intervals, function (j, interval) {
item.data.push({
x: interval.from,
y: i,
label: interval.label,
from: interval.from,
to: interval.to
}, {
x: interval.to,
y: i,
from: interval.from,
to: interval.to
});
// add a null value between intervals
if (task.intervals[j + 1]) {
item.data.push(
[(interval.to + task.intervals[j + 1].from) / 2, null]);
}
});
series.push(item);
});
// create the chart
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
title: {
text: 'Daily activities'
},
xAxis: {
type: 'datetime'
},
yAxis: {
tickInterval: 1,
labels: {
formatter: function () {
if (tasks[this.value]) {
return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Activity'
},
minPadding: 0.2,
maxPadding: 0.2
},
legend: {
enabled: false
},
tooltip: {
formatter: function () {
return '<b>' + tasks[this.y].name + '</b><br/>' + Highcharts.dateFormat('%H:%M', this.point.options.from) +
' - ' + Highcharts.dateFormat('%H:%M', this.point.options.to);
}
},
plotOptions: {
line: {
lineWidth: 9,
marker: {
enabled: false
},
dataLabels: {
enabled: true,
align: 'left',
formatter: function () {
return this.point.options && this.point.options.label;
}
}
}
},
series: series
});
I am relatively new to Javascript and Highcharts so pardon the obvious if any.
I figured it out. The problem was that the from,to timestamp pairs within a name/category are not in the ascending order. For the tooltip to work correctly, they need to be in the ascending order which is kinda weird.