I've got an unlisted Fusion Table with sample election data and vote counts by Wisconsin county, and I'm building a maps display page for election night. I'd like to conditionally style the county polygons depending on which candidate has a higher vote count, but I can't seem to do any styling based on a WHERE clause which directly compares column values. Instead, the default styling takes effect and the where clauses never kick in.
My reading of the FT "SQL-ish" syntax makes me think that it doesn't allow a WHERE clause which directly compares two columns, so maybe that's what's stopping me ... but man, I'd very much like to. Is there a technique I'm missing?
Vote counts for candidate 1 are in "1_Vote_Count" and for candidate 2 in "2_Vote_Count".
<script type="text/javascript">
function initialize () {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(44.824708,-89.780273),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: false,
mapTypeControl: false,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
panControl: false,
});
var layer = new google.maps.FusionTablesLayer({
query: {
select: 'geometry',
from: '173CovMDpzEwyBBtF2fwkxHB5nt6zETzBzG-3YLE',
where: "Office_ID = 'G' AND FIPS_Code > 0"
},
styles: [{
polygonOptions: {
fillColor: "#00FF00",
fillOpacity: 0.3,
strokeWeight: 0.5
}
}, {
where: "'1_Vote_Count' < '2_Vote_Count'",
polygonOptions: {
fillColor: "#DD0000"
}
}, {
where: "'2_Vote_Count' < '1_Vote_Count'",
polygonOptions: {
fillColor: "#0000DD"
}
}]
});
layer.setMap(map);
}
</script>
There's no technique that you're missing. I recommend opening a feature request, as Eric noted.
http://code.google.com/p/fusion-tables/issues/list?q=Type%3DFeature_Request
Related
I would like to display only the first and the last label on my xAxis. This would give enough of a »frame« for the user. However, I don't succeed in it. I am working with a synchronized chart, which can be found here. Is the second and third »column« of (smaller) graphs, I am targeting at.
I tried to work with »startOnTick« and »endOnTick«, but it won't do it.
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
visible: i === 1,
showFirstlabel: true,
showLastlabel: true,
startOnTick: true,
endOnTick: true,
labels: {
step: 500,
format: '{value}'
}
},
What is the correct way to force Highcharts to display only first and last label?
Here is a short fiddle (don't know why the line does not appear; it shows the values with mouseover...).
Thanks for any hints.
You can use the xAxis.labels.formatter callback to show wanted ticks:
Demo: https://jsfiddle.net/BlackLabel/m2Ln8sdg/
xAxis: {
tickAmount: 10,
labels: {
formatter() {
if(this.isFirst || this.isLast) {
return this.value
} else {
return ''
}
}
}
},
API: https://api.highcharts.com/highcharts/xAxis.labels.formatter
If you want to have more control about it (like hide label and tick) you can use the load callback method and proper logic to hide/show ticks:
Demo: https://jsfiddle.net/BlackLabel/fbcdskmv/
chart: {
events: {
load() {
let chart = this;
for (let i in chart.xAxis[0].ticks) {
//hide all
chart.xAxis[0].ticks[i].label.hide()
chart.xAxis[0].ticks[i].mark.hide()
// show first and last tick
if (chart.xAxis[0].ticks[i].isFirst || chart.xAxis[0].ticks[i].isLast) {
chart.xAxis[0].ticks[i].mark.show()
chart.xAxis[0].ticks[i].label.show()
}
}
}
}
API: https://api.highcharts.com/highcharts/chart.events.load
Or use the tickPositioner callback to achieve it: https://api.highcharts.com/highcharts/xAxis.tickPositioner
The above answers are good, but i just wanted to show another approach which works just fine.
In my styling i do this;
.highcharts-xaxis-labels > text:not(:first-child):not(:last-child) {
visibility: hidden !important;
}
Summing up #luftikus143 and #Sebastian Wędzel comments:
const data = [
['Jan 2020', 167],
['Feb 2020', 170],
['Mar 2020', 172]
];
xAxis: {
type: 'category',
tickPositions: [0, data.length - 1]
}
Will output only the first and last labels. #martinethyl's workaround answer might need some extra tweaks specially if you have multiple data points. Suggestions (might not work well with smaller media types):
xAxis: {
type: 'category',
labels: {
rotation: 0,
x: 5, // Optional: moves labels along the x-axis
style: {
textOverflow: 'none', // Removes ellipsis
whiteSpace: 'nowrap', // Gets the label text in one line
},
},
So I built a Highcharts application which looks somewhat like this:
https://codesandbox.io/s/angular-opcho
the chart looks like this:
export class ChartComponent implements OnInit {
title = "app";
chart;
updateFromInput = false;
Highcharts = Highcharts;
chartConstructor = "chart";
chartCallback;
data1;
data2;
chartOptions = {
title: {
text: "Global temperature change"
},
subtitle: {
text: "Data input from CSV"
},
plotOptions: {
series: {
marker: {
enabled: false
}
}
},
series: []
}
A highcharts application where you can upload csv data.
If you put in csv data which looks similar to this:
"runs","numbers",differences
"run1","1123",21
"run2","222",7200
"run3","31112",60
"run4","412312",32
you will have a nice graph with x and y axis.
Now, what i am trying to do is to build in a range selector for the y axis so i can sort out really high values and have a better view on the lower values.
My problem is, i can only find range selectors that have something to do with date and time. Is there any range selector for my specific problem?
The basic range selector uses setExtremes method, so you can do the same on yAxis:
var chart = Highcharts.chart('container', {
series: [{
type: 'column',
data: [1, 2, 3, 1, 3, 999, 888, 979]
}]
});
document.getElementById('low').addEventListener('click', function() {
chart.yAxis[0].setExtremes(0, 10);
});
document.getElementById('high').addEventListener('click', function() {
chart.yAxis[0].setExtremes(850, 1000);
});
Live demo: http://jsfiddle.net/BlackLabel/hbf2smoc/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
I’ve got two series in my chart. I have data coming every day. I register two kinds of information for every data in both series. There are five points in the first series but four in the second one. It is vital for both to have a point for every data. I want the absent point in the second series to be filled by the average of its two neighbor points.
Does highstock have any solution for that?
example:
<script src="jquery.js"></script>
<script src="highstock.js"></script>
<script type="text/javascript">
jQuery(function(){
var $ = jQuery;
Highcharts.stockChart('chart', {
chart: {
panning: false,
},
plotOptions:{
series:{
dataGrouping: {
forced: true,
units: [['day', [1]]]
},
}
},
series: [{
type: 'line',
color:'#23bdbd',
data: [
[1558224000000,8197.68969113999992259778082370758056640625],
[1558310400000,7978.3090724399999089655466377735137939453125],
[1558396800000,7963.3277791099999376456253230571746826171875],
[1558483200000,7680.06654589000027044676244258880615234375],
[1558569600000,7881.846721050000269315205514430999755859375]
],
},
{
type: 'line',
color:'#ff5d5d',
data: [
[1558224000000,100],
[1558310400000,150],
[1558483200000,2300],
[1558569600000,5500]
],
}],
});
});
</script>
<div id="chart"></div>
You can achieve it by adding additional logic in the load event callback. Filter the data and find absent points, then add absent points using series.addPoint(). Check the code and demo posted below.
Code:
chart: {
panning: false,
events: {
load: function() {
const chart = this;
const absentPoints = chart.series[0].xData.filter(
data => chart.series[1].xData.indexOf(data) === -1
);
absentPoints.forEach(absentPoint => {
const index = chart.series[0].xData.indexOf(absentPoint);
const value =
(chart.series[1].yData[index] +
chart.series[1].yData[index - 1]) /
2;
chart.series[1].addPoint([absentPoint, value], false);
});
chart.redraw(false);
}
}
}
Demo:
https://jsfiddle.net/BlackLabel/91ntpmyr/
API reference:
https://api.highcharts.com/class-reference/Highcharts.Series#addPoint
I would like to make something like a dashboard (kinda like the one that you see in many financial site), using Highcharts.
I've got the hang of adding 1 chart to a page, using a container, so I told myself that many containers, duplicating the code for one graph, will do; but I can't get it to work.
I have at least 8 graph, and I would like to organize them either in 2X4 arrangement, or just stacked on top of each other.
Mainly my confusion is coming from the fact that I need a general options section (to group common options), but I also need to customize the graphs, and I need to load data from CSV, so the order in which you do what, is causing me some problems.
I tried to follow an example here, where it was suggested to use setOptions and jQuery.extend, but I was not successful in making it work.
Is there an example that show a skeleton of the webpage, so I can see where to put each function, in which order and what kind of code do I have to put in?
Here you can find example how to add multiple chart like a dashboard: http://www.highcharts.com/demo/sparkline
And copy&paste code:
$(function () {
/**
* Create a constructor for sparklines that takes some sensible defaults and merges in the individual
* chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine').
*/
Highcharts.SparkLine = function (options, callback) {
var defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 120,
height: 20,
style: {
overflow: 'visible'
},
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
title: {
text: null
},
startOnTick: false,
endOnTick: false,
tickPositions: []
},
yAxis: {
endOnTick: false,
startOnTick: false,
labels: {
enabled: false
},
title: {
text: null
},
tickPositions: [0]
},
legend: {
enabled: false
},
tooltip: {
backgroundColor: null,
borderWidth: 0,
shadow: false,
useHTML: true,
hideDelay: 0,
shared: true,
padding: 0,
positioner: function (w, h, point) {
return { x: point.plotX - w / 2, y: point.plotY - h};
}
},
plotOptions: {
series: {
animation: false,
lineWidth: 1,
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
marker: {
radius: 1,
states: {
hover: {
radius: 2
}
}
},
fillOpacity: 0.25
},
column: {
negativeColor: '#910000',
borderColor: 'silver'
}
}
};
options = Highcharts.merge(defaultOptions, options);
return new Highcharts.Chart(options, callback);
};
var start = +new Date(),
$tds = $("td[data-sparkline]"),
fullLen = $tds.length,
n = 0;
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length;
for (i = 0; i < len; i++) {
var $td = $($tds[i]),
stringdata = $td.data('sparkline'),
arr = stringdata.split('; '),
data = $.map(arr[0].split(', '), parseFloat),
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('th').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
n++;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
// Print a feedback on the performance
if (n === fullLen) {
$('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms');
}
}
}
doChunk();
});
For a more simplistic start to this problem, take a look at this example:
http://jsfiddle.net/jlbriggs/4GaVj/
It's a very simple set up that defines data arrays first (you can do this as part of your CSV parsing), then defines global options via Highcharts.setOptions(), and then defines the individual charts.
There are several different ways to go about this, from this simple example up to more complex, flexible and dynamic approaches. But if you're looking to start with the basics, this should help.
After upgrading for Highcharts 2.1.9 to 3.0.0 we found that it seems impossible to render more than 1000 points in one series.
If you add 1000 points to a series it renders ok.
If you add 1001 points to a series it does not render at all. If you interrogate the series afterwards the "data" array on the series is empty.
You can however render multiple series with 1000 points - so there does not seem to be a limitation in terms of the total number of points per chart.
Here is a jsFiddle which illustrates this: http://jsfiddle.net/YWVHx/47/
$(function () {
var series1Data = [];
for (var i = 0; i < 1000; i++) {
series1Data.push({
x: (new Date()).getTime() + i * 10000,
y: Math.random() * 100
});
}
var series2Data = [];
// If you change this back to 1000 the series gets rendered
for (var i = 0; i < 1001; i++) {
series2Data.push({
x: (new Date()).getTime() + i * 10000,
y: Math.random() * 100 + 100
});
}
$('#container').highcharts({
chart: {
type: 'line'
},
title: {
text: 'Foo'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: null
}
},
tooltip: {
crosshairs: true,
shared: true,
valueSuffix: '°C'
},
legend: {
enabled: true
},
series: [{
name: '1000 Points - I work ;-)',
data: series1Data
}, {
name: '1001 Points - I dont work :-(',
data: series2Data
}]
});
});
Is this a limitation that was imposed on purpose or is it a problem with v3?
You should set bigger turbothreshold: http://api.highcharts.com/highcharts#plotOptions.series.turboThreshold
For the other user's convenience , this is a complementary example that you can copy and paste:
plotOptions:{
series:{
turboThreshold:5000//set it to a larger threshold, it is by default to 1000
}
}
Check http://jsfiddle.net/YWVHx/339/ here for results