Mixed Chart Types using Chartkick/Highcharts on Rails - ruby-on-rails

I'm trying to create a mixed column/line chart using Highcharts.
I've been trying to use the library functionality to set one of my data series to be of type "line". I have tried a few different approaches, but I can't seem to figure out how to pass the type parameter of a given series using the Highcharts API.
<%= column_chart( ChartData.new(#forecast).revenue_and_net_income, library: {
title: {
text: "Revenue and Net Income"
},
series: [{
1 => {
type: "line"
}
}],
} ) %>
Where my data come from the following method:
def revenue_and_net_income
data = [
{
name: "Revenue",
data: revenue_by_year
},
{
name: "Net Income",
data: net_income_by_year,
}
]
end
Not sure what I'm doing wrong? I only seem to be able to access the Highcharts API methods listed under 'Chart', none of the series options etc. seem to work. Can anyone point me in the right direction for how to successfully get this to work?

you can try this way.
<%= line_chart [
{
name: "Amount", type: "column", data: #cause.donations.map {
|t| [t.user.name, t.amount]
}
},
{
name: "Test", type: "line", data: #cause.donations.map {
|t| [t.user.name, t.amount]
}
}
],
prefix: "$",
adapter: "highcharts"
%>
just don't care line_chart, column_chart or anythings... ONLY custom type in data. OK

Related

Highmaps display correctly mappoints but not maplines

I need to use Highmaps to display on a map some information such as points, lines...
Displaying the initial map and some mappoint (with latitude/longitude coordinates) works well.
But when I add a simple mapline (linestring) between 2 points already displayed on the map, the mapline is not drawn.
Here is an example : https://jsfiddle.net/vegaelce/4L928trp/
The 2 mappoints are correctly placed on the map with the following data :
data: [{
name: 'Paris',
geometry: {
type: 'Point',
coordinates: [2.34,48.86]
}
}, {
name: 'Orly',
geometry: {
type: 'Point',
coordinates: [2.40,48.75]
}
}]
But the mapline (named "road") added to link the 2 points is not displayed with the following data :
data: [{
geometry: {
type: 'LineString',
coordinates: [
[2.34,48.86], // Paris
[2.40,48.75] // Orly
]
}
}],
Do I need to add something else ?
If you use the TopoJSON maps, what you are trying to do works. https://jsfiddle.net/blaird/y1Ld6bgs/1/
(async () => {
const topology = await fetch(
'https://code.highcharts.com/mapdata/countries/fr/fr-idf-all.topo.json'
).then(response => response.json());
// Prepare demo data. The data is joined to map using value of 'hc-key'
// property by default. See API docs for 'joinBy' for more info on linking
// data and map.
var data = [
["fr-idf-se", 69699],
["fr-idf-hd", 14200],
["fr-idf-ss", 17301],
["fr-idf-vo", 14350],
["fr-idf-vm", 29728],
["fr-idf-vp", 28610],
["fr-idf-yv", 21667],
["fr-idf-es", 16494]
];
// Create the chart
Highcharts.mapChart('container', {
chart: {
map: topology
},
title: {
text: 'Highcharts Maps basic demo'
},
subtitle: {
text: 'Source map: Île-de-France'
},
series: [{
mapData: Highcharts.maps["countries/fr/fr-idf-all"],
data: data,
name: "States",
borderColor: "#ffffff",
joinBy: ["hc-key", "CODE_REGION"],
keys: ["CODE_REGION", "value"]
}, {
type: 'mapline',
data: [{
geometry: {
type: 'LineString',
coordinates: [
[2.34, 48.86], // Paris
[2.40, 48.75] // Orly
]
}
}],
showInLegend: true,
lineWidth: 2,
name: "Road",
nullColor: '#f00',
color: '#f00',
enableMouseTracking: false
}, {
type: 'mappoint',
color: '#333',
name: "Towns",
showInLegend: true,
data: [{
name: 'Paris',
geometry: {
type: 'Point',
coordinates: [2.34, 48.86]
}
}, {
name: 'Orly',
geometry: {
type: 'Point',
coordinates: [2.40, 48.75]
}
}],
enableMouseTracking: false
}]
});
})();
In the Adding Points and Lines doc: https://www.highcharts.com/docs/maps/adding-points-and-lines
Prior to v10, the coordinate system used in most of our maps was a
custom one, where both the X and Y values ranged from 0 to some
thousands. This still applies when loading GeoJSON maps rather than
TopoJSON maps from the Map Collection. With the support of the proj4js
library, points could be placed by the lon and lat options. Without
proj4.js, points were added as x, y pairs on the same coordinate
system as the map. Maplines however were given as paths.
It explains that if you don't use the Topo data, you'll have to either convert the coordinates, or use the same coordinate system as the map for lines.
P.S. Not sure why setting color of the line doesn't work, but setting nullColor does. But, that is what I had to do to make the line red
After digging into I think that it is a bug and I reported it on the Highcharts Github issue channel where you can follow this thread: https://github.com/highcharts/highcharts/issues/17086

highcharts lollipop/dumbbell chart change position/colour of positive and negative marker values

I am trying to create a lollipop chart where some values are negative, and some are positive, either side of zero, like this:
image
However the chart seemingly only allows the marker to be on the "high" end of the chart. Is there a way to control which end has the marker ?
I'm using these chart options:
chartOptions: {
chart: {
type: 'dumbbell',
inverted: true
},
title: {
text: 'lollipop chart'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'value'
}
},
series: [{
name: 'value',
data: [{
name: 'a',
low:0,
high:13,
}, {
name: 'b',
low:0,
high:26,
},{
name: 'c',
low:-43,
high:0
},{
name: 'd',
low:-83,
high:0
},{
name: 'e',
low:0,
high:113
}]
}]
}
The series which should be used in this case is a lollipop, but it seems that the array of objects configuration doesn't work. I reported it on the Highcharts Github issue channel, where you can follow this thread: https://github.com/highcharts/highcharts/issues/13202
As a solution in the dumbell series I suggest to find those graphics in the render callback and hide them.
Demo: https://jsfiddle.net/BlackLabel/3o7acsbt/
events: {
render() {
let chart = this;
chart.series[0].points.forEach(p => {
if (p.low >= 0){
p.lowerGraphic.hide()
} else {
p.upperGraphic.hide()
}
})
}
}
API: https://api.highcharts.com/highcharts/chart.events.render
EDIT
Under the GitHub link, the workaround showed up. Please check it, maybe will be fit better to your requirement.

How to show multiple sets in a Highcharts Venn chart?

I'd like to show two sets of Venn diagrams inside a single chart. So I have the following code for sets A and B:
Highcharts.chart('container', {
series: [{
type: 'venn',
data: [{
sets: ['A1'],
value: 188956
}, {
sets: ['A2'],
value: 211267
}, {
sets: ['A1', 'A2'],
value: 23085,
name: "overlap"
}, {
sets: ['B1'],
value: 10880
}, {
sets: ['B2'],
value: 10880
}, {
sets: ['B1', 'B2'],
value: 6389,
name: "overlap"
}]
}],
title: {
text: 'Sets A and B'
}
});
What's really nice about showing everything together is that the four circles are sized proportionately to each other. The problem is how they're laid out. I'd want to show set B on the right side of A with some spacing between them. I also want set B to be laid out horizontally like A is.
Is this doable and if so how?
Thanks!
Alvaro
That is not possible in one chart, but you can create multiple charts:
Highcharts.chart('container', {
...,
series: [{
type: 'venn',
data: [...]
}]
});
Highcharts.chart('container2', {
...,
series: [{
type: 'venn',
data: [...]
}]
});
Live demo: https://jsfiddle.net/BlackLabel/xy5dfq4s/
Docs: https://www.highcharts.com/docs/chart-and-series-types/venn-series

Drawing linear function by using Chartkick gem and Google chart

I am trying to draw a linear function(like y=ax+b) by using Chartkick gem and google chart on my rails application.
'a' and 'b' will be given as parameters.
The problem is that I am trying to achieve an infinite line graph using google chart out of slope 'a' and 'b' and I don't know how to achieve this in a proper way.
I came up with the solution of drawing a line chart with two points, (-b/a, 0) and (0, b) and give trendlines option onto it.
<!-- y = 0.55x floatify(2,#datas[4][2]) + 1.47 floatify(2,#datas[3][2]) -->
<%= line_chart [
{name: "targets",
data: [
["#{-(#datas[3][2].to_f/#datas[4][2].to_f).round(2)}",0],
[0,"#{#datas[3][2].to_f}"]
]
},
],
library: {
title: "#{#simplereg.variable_name}",
subtitle: "#{#simplereg.data_name}",
legend: "right",
vAxis: {title: 'average'},
trendlines: {
0: {
type: 'exponential',
visibleInLegend: true
}
}
}
%>
However, rails cannot read a '0' value as an option of trendlines unlike what google chart documentation says.
-> https://developers.google.com/chart/interactive/docs/gallery/trendlines
I have no clue how to fix this code to work.
Please help me... I don't mind throwing up this code and writing in completely different way.
Thanks ahead.
Use something like below
<%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
<%= line_chart [
{name: "targets",
data: [
["-2/3",0],
[0,"2"]
]
},
],
library: {
title: "ABC",
subtitle: "XYZ",
legend: "right",
vAxis: {title: 'average'},
trendlines: {
"0"=> {
type: 'exponential',
visibleInLegend: true
}
}
}
%>
basically instead of symbo 0: use "0" =>

Add annotations with Chartkick

I want to add annotations to my time series chart.
From Google's documentation:
data.addColumn({type:'string', role:'annotation'});
How can I pass these column properties through Chartkick?
<%= line_chart [{name: 'annotations', data: annotations_array},{name: 'numbers as a time series', data: 'numeric_array'}] %>
I created a pull request to the chartkick.js repo to add the functionality you're describing.
https://github.com/ankane/chartkick.js/pull/58
This is just for the JS library (chartkick.js), but the approach can be used in the ruby library by using the modified chartkick.js from this pull request and passing in the right role values (certainty, annotation, etc.) to the library options.
var data = [..., [Sat Mar 05 2016 17:13:22 GMT-0800 (PST), 1, false, "cool annotation"]];
new Chartkick.LineChart("chart-1", data, {
"library":
{"role":["certainty", "annotation"]}
});
If you're using chartjs-plugin-annotation.js:
https://github.com/chartjs/chartjs-plugin-annotation, then you need to use the library option which passes options from Chartkick through to the underlying chart provider, e.g. Chart.js.
Here's an example I got working to annotate a graph with a labelled vertical line:
<%=
line_chart profit_chart_path(staff), xtitle: 'Day', ytitle: 'Profit',
library: {
annotation: {
annotations: [
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 'May 2018',
label: {
content: 'My Vertical Line',
enabled: true
}
}
]
}
}
%>
If, for instance, you wanted a horizontal annotated line with e.g. a numerical value, use these values instead:
mode: 'horizontal',
scaleID: 'y-axis-0',
value: 20,
Ensure that you've registered the plugin first!
import ChartAnnotationsPlugin from 'chartjs-plugin-annotation';
Chart.plugins.register(ChartAnnotationsPlugin);
Try something like this (not tested):
<%= line_chart TABLE.group(XXX).where(XXX), library: {name: 'annotations', data: annotations_array, name: 'numbers as a time series', data: 'numeric_array', type:'string', role:'annotation'} %>
In 2022, with plugin version 1.4.0, working configuration is as follows:
library:
{
plugins:
{
annotation:
{
annotations:
{
line1:
{
type: 'line',
xMin: "2022-06-01",
xMax: "2022-06-01",
borderColor: 'rgb(255, 99, 132)',
borderWidth: 2
}
}
}
}
}
Without plugins key does not work.
You have to register a new plugin in app/javascript/application.js(if it is Rails app):
import { Chart } from 'chart.js';
// Make annotations for charts
import annotationPlugin from 'chartjs-plugin-annotation';
Chart.register(annotationPlugin);
an then in the view you can use it like this:
= line_chart #some_records, curve: false, prefix: "EUR ", thousands: "'", points: false,
library: {plugins: {annotation: {annotations: {line1: {type: 'line', xMin: Date.today.beginning_of_month.to_s, xMax: Date.today.beginning_of_month.to_s, borderColor: 'rgb(105,105,105)', borderWidth: 1}}}}}

Resources