I want to create a density map similar to the link below
http://www.guardian.co.uk/news/datablog/interactive/2011/jun/22/us-casualties-afghanistan-state
Can anyone please steps tell how such type of maps can be created.
thank you
They're using a FusionTablesLayer to do this.
Their maps-related JS in full from that page:
var center = new google.maps.LatLng(38.0000,-97.0000);
var zoom = 4;
var legend_width = '150px';
var tableid = 1038573;
var location_column = 'geo';
var columns = {
'Killed in action': [
{
'min': 0,
'max': 10,
'color': '#f4cccc'
},
{
'min': 10,
'max': 30,
'color': '#ea9999'
},
{
'min': 30,
'max': 60,
'color': '#cc0000'
},
{
'min': 60,
'max': 90,
'color': '#990000'
},
{
'min': 90,
'max': 130,
'color': '#660000'
}
],
'Killed, not in action': [
{
'min': 1,
'max': 10,
'color': '#f4cccc'
},
{
'min': 10,
'max': 20,
'color': '#ea9999'
},
{
'min': 20,
'max': 30,
'color': '#cc0000'
}
],
'Wounded in action': [
{
'min': 0,
'max': 100,
'color': '#f4cccc'
},
{
'min': 100,
'max': 200,
'color': '#ea9999'
},
{
'min': 200,
'max': 400,
'color': '#cc0000'
},
{
'min': 400,
'max': 600,
'color': '#990000'
},
{
'min': 600,
'max': 1000,
'color': '#660000'
}
],
'Total deaths in Afghanistan per 100,000 pop': [
{
'min': 0,
'max': 0.2,
'color': '#f4cccc'
},
{
'min': 0.2,
'max': 0.4,
'color': '#ea9999'
},
{
'min': 0.4,
'max': 0.6,
'color': '#cc0000'
},
{
'min': 0.6,
'max': 1,
'color': '#990000'
},
{
'min': 1,
'max': 2,
'color': '#660000'
}
],
'Wounded, per 100,000 pop': [
{
'min': 0,
'max': 2,
'color': '#f4cccc'
},
{
'min': 2,
'max': 3,
'color': '#ea9999'
},
{
'min': 3,
'max': 4,
'color': '#cc0000'
},
{
'min': 4,
'max': 5,
'color': '#990000'
},
{
'min': 5,
'max': 8,
'color': '#660000'
}
]
}
var map, layer;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: center,
zoom: zoom,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var style = [
{
featureType: 'administrative',
elementType: 'all',
stylers: [
{ visibility: 'off' }
]
}
];
var styledMapType = new google.maps.StyledMapType(style, {
map: map,
name: 'Styled Map'
});
map.mapTypes.set('map-style', styledMapType);
map.setMapTypeId('map-style');
layer = new google.maps.FusionTablesLayer({
query: {
select: location_column,
from: tableid
}
});
layer.setMap(map);
init_selectmenu();
addStyle(getKey());
}
function getKey() {
for(key in columns) {
return key;
}
}
// Initialize the drop-down menu
function init_selectmenu() {
var selectmenu = document.getElementById('selector');
for(column in columns) {
var option = document.createElement('option');
option.setAttribute('value', column);
option.innerHTML = column;
selectmenu.appendChild(option);
}
}
// Apply the style to the layer
function addStyle(column) {
var defined_styles = columns[column];
var styles = new Array();
for(defined_style in defined_styles) {
var style = defined_styles[defined_style];
styles.push({
where: generateWhere(column, style.min, style.max),
polygonOptions: {
fillColor: style.color,
fillOpacity: style.opacity ? style.opacity : 1
}
});
}
layer.set('styles', styles);
updateLegend(column);
}
// Create the where clause
function generateWhere(column_name, low, high) {
var whereClause = new Array();
whereClause.push("'");
whereClause.push(column_name);
whereClause.push("' >= ");
whereClause.push(low);
whereClause.push(" AND '");
whereClause.push(column_name);
whereClause.push("' < ");
whereClause.push(high);
return whereClause.join('');
}
// Create the legend with the corresponding colors
function updateLegend(column) {
var legendDiv = document.createElement('div');
var legend = new Legend(legendDiv, column);
legendDiv.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].pop();
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(legendDiv);
}
// Generate the content for the legend
function Legend(controlDiv, column) {
controlDiv.style.padding = '10px';
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '1px';
controlUI.style.width = legend_width;
controlUI.title = 'Legend';
controlDiv.appendChild(controlUI);
var controlText = document.createElement('div');
controlText.style.fontFamily = 'Arial,sans-serif';
controlText.style.fontSize = '12px';
controlText.style.paddingLeft = '4px';
controlText.style.paddingRight = '4px';
controlText.innerHTML = legendContent(column);
controlUI.appendChild(controlText);
}
function legendContent(column) {
var defined_styles = columns[column];
// Generate the content for the legend using colors from object
var controlTextList = new Array();
controlTextList.push('<p><b>');
controlTextList.push(column);
controlTextList.push('</b></p>');
for(defined_style in defined_styles) {
var style = defined_styles[defined_style];
controlTextList.push('<div style="background-color: ');
controlTextList.push(style.color);
controlTextList.push('; height: 20px; width: 20px; margin: 3px; float: left;"></div>');
controlTextList.push(style.min);
controlTextList.push(' - ');
controlTextList.push(style.max);
controlTextList.push('<br style="clear: both;"/>');
}
controlTextList.push('<br />');
return controlTextList.join('');
}
My addin for Excel does exactly this.
Related
I am new to using highcharts.js. I want to create an activity gauge chart using data from a json file or url. I have understood how they draw the chart but failed to understand the data format used in json to display the chart.
Here is my code
var options = {
chart: {
type: 'solidgauge',
marginTop: 50
},
title: {
text: 'Activity',
style: {
fontSize: '24px'
}
},
tooltip: {
borderWidth: 0,
backgroundColor: 'none',
shadow: false,
style: {
fontSize: '16px'
},
pointFormat: '{series.name}<br><span style="font-size:2em; color: {point.color}; font-weight: bold">{point.y}%</span>',
positioner: function (labelWidth, labelHeight) {
return {
x: 200 - labelWidth / 2,
y: 180
};
}
},
pane: {
startAngle: 0,
endAngle: 360,
background: [{ // Track for Move
outerRadius: '112%',
innerRadius: '88%',
backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0.3).get(),
borderWidth: 0
}, { // Track for Exercise
outerRadius: '87%',
innerRadius: '63%',
backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[1]).setOpacity(0.3).get(),
borderWidth: 0
}, { // Track for Stand
outerRadius: '62%',
innerRadius: '38%',
backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[2]).setOpacity(0.3).get(),
borderWidth: 0
}]
},
yAxis: {
min: 0,
max: 100,
lineWidth: 0,
tickPositions: []
},
plotOptions: {
solidgauge: {
borderWidth: '34px',
dataLabels: {
enabled: false
},
linecap: 'round',
stickyTracking: false
}
},
series: []
};
var gauge1;
$.getJSON('bryan.json', function(json){
console.log(json)
options.chart.renderTo = 'container';
options.series.data = json
gauge1 = new Highcharts.Chart(options);
});
/**
* In the chart load callback, add icons on top of the circular shapes
*/
function callback()
{
// Move icon
this.renderer.path(['M', -8, 0, 'L', 8, 0, 'M', 0, -8, 'L', 8, 0, 0, 8])
.attr({
'stroke': '#ffffff',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'stroke-width': 2,
'zIndex': 10
})
.translate(190, 26)
.add(this.series[2].group);
// Exercise icon
this.renderer.path(['M', -8, 0, 'L', 8, 0, 'M', 0, -8, 'L', 8, 0, 0, 8, 'M', 8, -8, 'L', 16, 0, 8, 8])
.attr({
'stroke': '#ffffff',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'stroke-width': 2,
'zIndex': 10
})
.translate(190, 61)
.add(this.series[2].group);
// Stand icon
this.renderer.path(['M', 0, 8, 'L', 0, -8, 'M', -8, 0, 'L', 0, -8, 8, 0])
.attr({
'stroke': '#ffffff',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'stroke-width': 2,
'zIndex': 10
})
.translate(190, 96)
.add(this.series[2].group);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container" style="width: 400px; height: 400px; margin: 0 auto">
</div>
And here is my json data which i thout might be rendered but it didnot.
data.json
First of all, instead of options.series.data = json, you need to create the first series and then populate its data array with your data. Also, set in each point different radius and innerRadius properties. Take a look at the example below.
API Reference:
http://api.highcharts.com/highcharts/series.solidgauge.data.radius
http://api.highcharts.com/highcharts/series.solidgauge.data.innerRadius
Example:
http://jsfiddle.net/x3cne1ng/
Pretty new to this stuff, so any help is greatly appreciated. To start off with, here is my JSON file's contents:
[
{
"drg": "NONSPECIFIC CEREBROVASCULAR DISORDERS W MCC",
"approved": 124,
"denied": 38
},
{
"drg": "SEIZURES WO MCC",
"approved": 138,
"denied": 26
},
{
"drg": "CHRONIC OBSTRUCTIVE PULMONARY DISEASE W CC",
"approved": 352,
"denied": 61
},
{
"drg": "CHEST PAIN",
"approved": 246,
"denied": 44
},
{
"drg": "TRANSIENT ISCHEMIA",
"approved": 205,
"denied": 37
},
{
"drg": "OTHER DISORDERS OF NERVOUS SYSTEM W CC",
"approved": 133,
"denied": 23
},
{
"drg": "DIABETES W MCC",
"approved": 151,
"denied": 27
},
{
"drg": "CARDIAC ARRHYTHMIA CONDUCTION DISORDERS W CC",
"approved": 336,
"denied": 55
},
{
"drg": "HYPERTENSION WO MCC",
"approved": 177,
"denied": 29
},
{
"drg": "POISONING TOXIC EFFECTS OF DRUGS WO MCC",
"approved": 144,
"denied": 24
}
]
My stacked bar chart, which worked fine with a CSV file, keeps ignoring the "denied" value. I suspect the issue has something to do with my formatting of the "processed_json.push()" portion of my code. It renders the approved value stacked on top of itself. Here is the script file:
<script>
$(document).ready(function() {
var processed_json = new Array();
$.getJSON('/dashboard-test-data/denied-percentage-2015-chart.json', function(data) {
for (i = 0; i < data.length; i++) {
processed_json.push([data[i].drg, data[i].approved, data[i].denied]);
}
$('#denied-percentage-2015-chart').highcharts({
chart: {
type: 'bar'
},
credits: {
text: 'Vortext Analytics',
href: 'http://www.vortextanalytics.com'
},
title: {
text: 'Top 10 DRG by Denial Percentage 2015'
},
xAxis: {
type: 'category',
},
navigation: {
menuStyle: {
border: '1px solid #ddd',
boxShadow: 'none',
},
menuItemStyle: {
padding: '5px 1.5rem',
},
menuItemHoverStyle: {
backgroundColor: '#f7f7f9',
color: '#666'
},
buttonOptions: {
height: 40,
width: 46,
symbolX: 23,
symbolY: 22,
x: 10,
y: -15,
symbolSize: 13,
}
},
yAxis: {
min: 0,
title: {
text: 'Total Records'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
},
formatter: function() {
return (this.axis.series[1].yData[this.x] / this.total * 100).toPrecision(2) + '%';
}
}
},
legend: {
align: 'left',
x: 0,
verticalAlign: 'bottom',
y: 22,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
reversed: true,
},
tooltip: {
shared: true,
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: {point.y:,0f} of {point.stackTotal:,0f} <b>({point.percentage:.1f}%)</b><br />',
},
plotOptions: {
series: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textOutline: 'none',
fontWeight: 'normal',
fontSize: '9px'
}
},
pointWidth: 20,
}
},
series: [{
name: 'approved',
color: '#55B4E4',
data: processed_json,
}, {
name: 'denied',
color: '#005079',
data: processed_json,
}],
});
});
});
</script>
Here is what the end product should produce (screen grab from my csv version):
Correct
And here is what I'm getting from the JSON file: incorrect
Any assistance or guidance is greatly appreciated. Thanks.
Have a look at highchart's stacked bar chart example. For each series, data contains the array of values for that series.
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
In your case, instead of creating the processed_json array of objects, you should create separate arrays containing each series' values.
Change the loop this way:
var xAxis = []
, approvedCount = []
, deniedCount = []
for (i = 0; i < data.length; i++) {
xAxis.push(data[i].drg);
approvedCount.push(data[i].approved);
deniedCount.push(data[i].denied);
Then adapt the chart's instantiation accordingly:
// (...)
xAxis: {
categories: xAxis
},
// (...)
series: [{
name: 'approved',
color: '#55B4E4',
data: approvedCount,
}, {
name: 'denied',
color: '#005079',
data: deniedCount,
}],
// (...)
I am trying to draw two lines using google combo charts, I am referring this link https://developers.google.com/chart/interactive/docs/gallery/combochart
but I am able to draw only one line!!!
function drawchart1(dataValues) {
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
var data = new google.visualization.DataTable();
data.addColumn('string', 'KPI_MONTH');
data.addColumn('number', 'DIE');
data.addColumn('number', 'DIE_TS');
data.addColumn('number', 'DIE_LL');
for (var i = 0; i < dataValues.length; i++) {
data.addRow([dataValues[i].KPI_MONTH, dataValues[i].DIE, dataValues[i].DIE_TS, dataValues[i].DIE_LL]);
}
// Instantiate and draw our chart, passing in some options
var chart = new google.visualization.ComboChart(document.getElementById('ColumnChart'));
//var chart1 = new google.visualization.PieChart(document.getElementById('piechart1'));
chart.draw(data,
{
title: "Column Chart of Google Chart in Asp.net",
position: "top",
fontsize: "14px",
seriesType: 'bars',
series: { 2: { type: 'line' } },
series: { 1: { type: 'line' } },
chartArea: { width: '50%' },
});
Only for the series 1 graph is getting generated like below.Only one line is geeting generated in this graph
The chart options should only have one key for series, which can have multiple series definitions.
series: {
1: { type: 'line' },
2: { type: 'line' }
},
Example...
google.load('visualization', '1', {
packages: ['corechart'],
callback: drawchart1
});
function drawchart1(dataValues) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'KPI_MONTH');
data.addColumn('number', 'DIE');
data.addColumn('number', 'DIE_TS');
data.addColumn('number', 'DIE_LL');
data.addRow(['Jan-15', 80, 90, 80]);
data.addRow(['Feb-15', null, 90, 80]);
data.addRow(['Mar-15', 100, 90, 80]);
data.addRow(['Apr-15', 100, 90, 80]);
data.addRow(['May-15', 20, 90, 80]);
data.addRow(['Jun-15', 30, 90, 80]);
data.addRow(['Jul-15', 10, 90, 80]);
data.addRow(['Aug-15', 50, 90, 80]);
data.addRow(['Sep-15', 30, 90, 80]);
data.addRow(['Oct-15', 10, 90, 80]);
data.addRow(['Nov-15', 20, 90, 80]);
data.addRow(['Dec-15', 100, 90, 80]);
var chart = new google.visualization.ComboChart(document.getElementById('ColumnChart'));
chart.draw(data,
{
title: "Column Chart of Google Chart in Asp.net",
position: "top",
fontsize: "14px",
seriesType: 'bars',
series: {
1: { type: 'line' },
2: { type: 'line' }
},
chartArea: { width: '50%' },
});
}
<script src="https://www.google.com/jsapi"></script>
<div id="ColumnChart"></div>
I am trying to read the data from csv and display it as a input to Speedometer but I am unable to get the chart. Please tell me where i am going wrong.
My code is:
$(document).ready(function() {
var options = {
chart: {
type: 'gauge',
plotBackgroundColor: null,
plotBackgroundImage: null,
plotBorderWidth: 0,
plotShadow: false
},
title: {
text: 'Speedometer'
},
pane: {
startAngle: -150,
endAngle: 150,
background: [{
backgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0, '#FFF'],
[1, '#333']
]
},
borderWidth: 0,
outerRadius: '109%'
}, {
backgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [
[0, '#333'],
[1, '#FFF']
]
},
borderWidth: 1,
outerRadius: '107%'
}, {
// default background
}, {
backgroundColor: '#DDD',
borderWidth: 0,
outerRadius: '105%',
innerRadius: '103%'
}]
},
// the value axis
yAxis: {
min: 0,
max: 100,
minorTickInterval: 'auto',
minorTickWidth: 1,
minorTickLength: 10,
minorTickPosition: 'inside',
minorTickColor: '#666',
tickPixelInterval: 30,
tickWidth: 2,
tickPosition: 'inside',
tickLength: 10,
tickColor: '#666',
labels: {
step: 2,
rotation: 'auto'
},
title: {
text: 'km/h'
},
plotBands: [{
from: 0,
to: 120,
color: '#55BF3B' // green
}, {
from: 120,
to: 160,
color: '#DDDF0D' // yellow
}, {
from: 160,
to: 200,
color: '#DF5353' // red
}]
},
series: []
};
$.get('data.csv', function(data) {
var series = {
data: [],
name: 'Speed',
tooltip: {
valueSuffix: ' km/h'
}
};
series.data.push(parseFloat(data));
options.series.push(series);
alert("data "+options.series);
var chart = new Highcharts.Chart(options);
});
});
and the csv file is simple
data.csv has only one value 30.
or incase it is
t1,30
t2,40
t3,60
how do i display 3 corresponding speedometers with respective speed.
Your help is greatly appreciated.
Thanks in advance.
In your case data your data (from ajax) is a single string, but you need to split elements and then choose which should be parsed to integer (parseFloat).
I have used the code available from http://codeblitz.wordpress.com/2009/06/22/jquery-charts/
It uses jqPlot. So I have the following sample code Default.html that works:
<script type="text/javascript">
var jsonObj = { "pageHits": [30, 60, 22, 5, 60, 88, 102], "rssHits": [33, 45, 121, 23, 55, 35, 77], "xAxis": ['Jan 2009', 'Feb 2009', 'Mar 2009', 'Apr 2009', 'May 2009', 'June 2009', 'Jul 2009'] };
$(function () {
$.jqplot('chartDiv', [jsonObj.pageHits, jsonObj.rssHits], CreateBarChartOptions());
});
function CreateBarChartOptions()
{
var optionsObj = {
title: 'Blog Statistics',
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: jsonObj.xAxis
}
},
series: [{label:'Page Hits'}, {label: 'RSS Hits'}],
legend: {
show: true,
location: 'nw'
},
seriesDefaults:{
shadow: true,
renderer:$.jqplot.BarRenderer,
rendererOptions:{
barPadding: 8,
barMargin: 10
}
},
highlighter: {
showTooltip: true,
tooltipFade: true
}
};
return optionsObj;
}
</script>
I have copied the code and put it into Default.aspx. The only thing I want to change is to be able to get the data from an external file, so now my code is:
<script type="text/javascript">
var jsonObj;
$.getJSON('example.json', function (response)
{
jsonObj = response;
alert(jsonObj.property);
});
$(function () {
$.jqplot('chartDiv', [jsonObj.pageHits, jsonObj.rssHits], CreateBarChartOptions());
});
function CreateBarChartOptions()
{
var optionsObj = {
title: 'Blog Statistics',
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: jsonObj.xAxis
}
},
series: [{ label: 'Page Hits' }, { label: 'RSS Hits'}],
legend: {
show: true,
location: 'nw'
},
seriesDefaults: {
shadow: true,
renderer: $.jqplot.BarRenderer,
rendererOptions: {
barPadding: 8,
barMargin: 10
}
},
highlighter: {
showTooltip: true,
tooltipFade: true
}
};
return optionsObj;
}
</script>
But jsonObj is always undefined, I'm presuming my file is not formatted properly. I have tried example.json to contain this:
{"pageHits": [30, 60, 22, 5, 60, 88, 102], "rssHits": [33, 45, 121, 23, 55, 35, 77], "xAxis": ['Jan 2009', 'Feb 2009', 'Mar 2009', 'Apr 2009', 'May 2009', 'June 2009', 'Jul 2009']}
and this:
{"pageHits": [30, 60, 22, 5, 60, 88, 102], "rssHits": [33, 45, 121, 23, 55, 35, 77], "xAxis": ["Jan 2009", "Feb 2009", "Mar 2009", "Apr 2009", "May 2009", "June 2009", "Jul 2009"]}
But to no avail. What am I doing wrong?
Thanks for any assistance,
Julian
You'd probably need to do something like:
$.getJSON('example.json', function (response)
{
var jsonObj = response;
$.jqplot('chartDiv', [jsonObj.pageHits, jsonObj.rssHits], CreateBarChartOptions());
});
The way you have it now your annon function to trigger jqplot will run 'inline', while the ajax loading will still be going on.