We're working on a Highcharts Bubble Chart w/category axis and a lot of overlapping data points. Is there any way to control exactly how the bubbles are placed within the category? What we'd like to do is sort the bubbles ahead of time and then offset them from each other a bit. Some overlap is desirable so we'd prefer to not have to add additional categories to make sure there is no overlap.
Unfortunately we have no solution for controling positions of the bubbles. But you can request your propositin in our uservoice system http://highcharts.uservoice.com/
If you are using categories, your x values are the array index of the category for your value.
So to tweak the placement, you can tweak your x value by adding/subtracting small decimal amounts:
http://jsfiddle.net/yPLVP/10/
[-0.1,2,10]
Keeping in mind that +/- .5 is the center point between the categories - so for a value that falls within the 3rd category (x value 2), keep your x values between 1.55 and 2.45 (or so....)
I have the same problem, you can add this code:
function(chartObj) {
$.each(chartObj.series[0].data, function(i, point) {
var aux = 0;
if (i % 2 == 0)
aux = point.dataLabel.y + 6;
else
aux = point.dataLabel.y - 6;
point.dataLabel.attr({y:aux});
});
jsFiddle: http://jsfiddle.net/9m6wu/277/
Related
I'm making a sheet with details about a bunch of fictional characters, and one column I want to have is their height. I would also really like to use Conditional Formatting with a Color Scale to color-code the tallest and shortest characters, and everything in between.
Unfortunately, I live in the US, and am used to height expressed in feet and inches (e.g. 5'10''), which Google Sheets of course does not recognize as a number. Is there any way to remedy this, besides writing everything in terms of just inches (e.g. 60), such that I could apply conditional formatting directly to the column?
I've tried different formats (e.g. 5'10), and I considered having a hidden column with just the inch value and have conditional formatting work off of that row (doesn't work with Color Scale as far as I can tell, since you can't input a custom formula). One thought I had is somehow formatting things as an improper fraction with a denominator of 12, but hiding the denominator? But I have no idea how that would work. I've Googled as best I can, but I haven't found anything (everything's just about changing row height, which makes sense in hindsight).
I understand that you have two goals in mind. First of all, you should decide which unit length to use for managing heights. I have chosen inches, but you could work with feet if you need. This will simplify the scenario and will allow you to work easily with the data, but you could always create a function that translates inches to the foot/inches combo in order to show the data to a third party. This is the example table that I will use:
And this is my code, I will explain it at the bottom:
function main() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
data = sortTable(data);
sheet.getDataRange().setValues(data);
for (var i = 1; i < data.length; i++) {
data[i][2] = gradient(data.length, i);
}
for (var i = 1; i < data.length; i++) {
sheet.getRange(i, 2).setBackground("#" + data[i][2][0] + data[i][2][1] +
data[i][2][2]);
}
}
function sortTable(data) {
data.sort(function(a, b) {
return b[1] - a[1];
})
return data;
}
function gradient(arraySize, position) {
var relativePosition = position / arraySize;
var topColor = [parseInt("00", 16), parseInt("7A", 16), parseInt("33",
16)]; // Green
var bottomColor = [parseInt("FF", 16), parseInt("FF", 16), parseInt("FF",
16)]; // White
var positionColor = [0, 0, 0];
for (var i = 0; i < 3; i++) {
positionColor[i] = Math.floor(topColor[i] * (1 - relativePosition) +
bottomColor[i] * relativePosition).toString(16);
}
return positionColor;
}
First of all you have to read the data with a combination of getValues()/setValues(), and once you do that you can sort the table based on height so you can create the gradient later. Please notice how I separated the sorting function for better clarity.
After that you need the gradient color for setBackground(). To do so I developed a simple linear gradient function that calculates the RGB code from the top to the bottom. In my example the gradient fades from green to white, but you can change it. I also separated the gradient script into its own function. At this point you already have the sorted table and its gradient colors, so you only have to use setValues() and you are done. Feel free to leave any comment if you have doubts about this approach. This would be the final result:
UPDATE
Based in your comments I get that you need an imperial height format. For that case, you could use =INT(B2)&"' "&TRIM(TEXT(ROUND(MOD(B2,1)*12*16,0)/16,"# ??/??")&"""") (assuming that B2 contains the height). This approach will use Sheets Formulas to calculate the remainder part of the height, and its expression as an irreducible fraction. This is the final result:
I have a pie chart in Highcharts that reduces each slice to create a "fan" effect. Each slice is working great. However, the labels need to be handled as well. I tried the following:
new Highcharts.chart(div, pieOptions,
function(chartObj) {
var j = 0;
$.each(chartObj.series[0].data, function(i, point) {
point.labelDistance = j;
j -= 25;
});
});
This actually updates the label distance properly in the logged out data, but not in the visual itself. I've also tried reloading the chart each time.
Here is a jsfiddle: https://jsfiddle.net/s2pdroze/1/
Summary: I'm looking for each label on each slice to move slight more inward on each iteration.
I'd like to visualize the amount of steps taken over a day. Each datapoint looks simplified like this:
{
startDate: 1481029440000,
endDate: 1481029920000,
steps: 31
}
I'd like to plot it over an entire day and illustrate the duration but also the grow of step increase. Each datapoint is a separate series as I didn't want to have points connected to each other.
The result looks like what I want except for the styling which I have change. However the performance and zoom into the chart is extremely slow. Might there be a better way to use it?
Highcharts is optimised for managing many points, not many series (the work has been start on optimising series, though - as far as I know).
You can use one series with the null points as separators. By default connecting nulls is disabled.
data: (function (data) {
var d = [], i = 0, len = data.length, point;
for (; i < len; i++) {
point = data[i];
d.push([point.startDate, point.steps], [point.endDate, point.steps]);
if (i < len - 1) {d.push([point.endDate, null]);}
}
return d;
})(data)
example: http://jsfiddle.net/7vtd4fzm/
I have a dynamic data series like this
[1,0],[2,0],[3,0],[4,0],[5,0],[6,2],[7,5],[8,6],[9,6],[10,6],[11,7],[12,8],[13,8],[14,9]
The data grows automatically, so later on, an extra data point will be added e.g. [15,13]
I have an input field in which the user can select how many points from the end he wants to show.
For example if he inputs 5, only [10,6],[11,7],[12,8],[13,8],[14,9] should be visible. But when the additional point is added, this should become [11,7],[12,8],[13,8],[14,9],[15,13] automatically.
I think I have to use chart.xAxis[0].setExtremes() but I don't know what to enter as parameters... ?
You will have to "reapply" setExtremes when adding a point. The setExtremes function takes in these parameters (API):
setExtremes (Number min, Number max, [Boolean redraw], [Mixed animation])
You would have to use min and max to show the desired number of points, and have that include the last one. For example, you could do something like this:
var chart = $('#container').highcharts();
var numberOfPointsToShow = 5;
// Add new random point
chart.series[0].addPoint(Math.random() * 25);
// Get index of last point
var lastPoint = chart.series[0].data.length - 1;
// Set extremes to go from "min" (based on last point) to last point
chart.xAxis[0].setExtremes(
lastPoint - (numberOfPointsToShow - 1), // min
lastPoint); // max
See this JSFiddle example with dynamic adding of points.
I'm seeing some odd behavior in a Highcharts line chart. I have multiple series displayed, and need to let the user change what's called the "Map level" on the chart, which is a straight line across all time periods. Assuming that the correct series is
chart.series[i]
and that the new level that I want it set to is stored in var newMapLevel,
I'm changing that series' data like so:
data = chart.series[i].data;
for(j=0; j<data.length; j++){
data[j].y = newMapLevel;
}
chart.series[i].setData(data);
Calling this function has the desired effect UNLESS the new map level y_value is ONE greater than the highest y_value of all other series, in which case the y-axis scale blows up. In other words, if the y_axis scale is normally from 0 to 275,000, and the highest y_value of any of the other series is, say, 224,000, setting the new map level value to 224,001 causes the y_axis scale to become 0 to 27500M. Yes, that's 27.5 billion.
Might this be a bug in Highcharts? Or is there a better way to change the data in a series?
I've posted a fiddle: http://jsfiddle.net/earachefl/4FuNE/4/
I got my answer from the Highcharts forum:
http://highslide.com/forum/viewtopic.php?f=9&t=13594&p=59888#p59888
This doesn't work as smoothly as I'd like. When you go from 8 as your line to 2 as your line, the scale doesn't adjust back down until you enter another value. Perhaps it's a start in the right direction.
$(document).ready(function(){
$('#clickme').click(function(){
var newMapLevel = $('#newMAP').val();
if(newMapLevel){
for(i=0; i<chart.series.length; i++){
if(chart.series[i].name == 'Map Level'){
data = chart.series[i].data;
for(j=0; j<data.length; j++){
data[j].y = newMapLevel;
}
// get the extremes
var extremes = chart.yAxis[0].getExtremes();
//alert("dataMin: " + extremes.dataMin);
//alert("dataMax: " + extremes.dataMax);
// define a max YAxis value to use when setting the extremes
var myYMax = extremes.dataMax;
if (newMapLevel >= myYMax) {
myYMax = Number(newMapLevel) + 1; // number conversion required
}
if (myYMax > chart.yAxis[0].max) {
alert('cabbbie');
myYMax = chart.yAxis[0].max + 1;
}
//alert("myYMax: " + myYMax);
chart.yAxis[0].setExtremes(extremes.dataMin, myYMax)
// finally, set the line data
chart.series[i].setData(data);
}
}
}
}); });