About
ApexCharts.RB is a ruby charting library that's going to give your ruby app beautiful,
interactive, and responsive charts powered by ApexCharts.JS. On top of those sweet
advantages, you'll also get extra features that you can't get by just including ApexCharts.JS
to your ruby app, namely view/template helpers for creating charts, options shortcuts,
application wide default options, reusable custom theme palette, and so on.
Trusted By
Organization/Company | Use Case |
---|
| Reports/charts related to Operating Room utilization statistics |
| Enterprise dashboards to visualize account receivables data |
| Ticket sales for clients (visitor attractions and tour operators) |
If your organization/company uses ApexCharts.RB in production, please comment on
this discussion.
README Versions
This README might not be for the version you use.
Choose the right README:
v0.2.0 | v0.1.11 | v0.1.10 | v0.1.9 | v0.1.8 | v0.1.7 |
v0.1.6 | v0.1.5 | v0.1.4 | v0.1.3 | v0.1.2 | v0.1.1
Table of Contents
Usage
Cartesian Charts
Example series used for cartesian charts:
<% series = [
{name: "Inactive", data: @inactive_properties},
{name: "Active", data: @active_properties}
] %>
To build the data, you can use gem groupdate.
In my case, it was:
@inactive_properties = Property.inactive.group_by_week(:created_at).count
@active_properties = Property.active.group_by_week(:created_at).count
and I'll get the data in this format:
{
Sun, 29 Jul 2018=>1,
Sun, 05 Aug 2018=>6,
..
}
PS: Property
can be any model you have and inactive
and active
are just some normal ActiveRecord scopes. Keep scrolling down to see
accepted data formats.
Example options used for cartesian charts:
<% options = {
title: 'Properties Growth',
subtitle: 'Grouped Per Week',
xtitle: 'Week',
ytitle: 'Properties',
stacked: true
} %>
Line Chart
<%= line_chart(series, options) %>
Stepline Chart
<%= line_chart(series, {**options, theme: 'palette7', curve: 'stepline'}) %>
Area Chart
<%= area_chart(series, {**options, theme: 'palette5'}) %>
Column Chart
<%= column_chart(series, {**options, theme: 'palette4'}) %>
Bar Chart
<%= bar_chart(series, {**options, xtitle: 'Properties', ytitle: 'Week', height: 800, theme: 'palette7'}) %>
Range Bar Chart
<% range_bar_series = [{
name: "Series A",
data: {
'A' => [1, 5],
'B' => [4, 6],
'C' => [5, 8],
'D' => [3, 11]
}
}, {
name: "Series B",
data: {
'A' => [2, 6],
'B' => [1, 3],
'C' => [7, 8],
'D' => [5, 9]
}
}]
%>
<%= range_bar_chart(range_bar_series, theme: 'palette3') %>
Scatter Chart
<%= scatter_chart(series, {**options, theme: 'palette3'}) %>
Candlestick Chart
Candlestick chart is typically used to illustrate movements in the price of a
financial instrument over time. This chart is also popular by the name "ohlc chart".
That's why you can call it with ohlc_chart
too.
So, here's how you make it.
Given:
<%
require 'date'
def candlestick_data
@acc = rand(6570..6650)
60.times.map {|i| [Date.today - 60 + i, ohlc] }.to_h
end
def ohlc
open = @acc + rand(-20..20)
high = open + rand(0..100)
low = open - rand(0..100)
@acc = close = open + rand(-((high-low)/3)..((high-low)/2))
[open, high, low, close]
end
candlestick_options = {
plot_options: {
candlestick: {
colors: {
upward: '#3C90EB',
downward: '#DF7D46'
}
}
}
}
%>
You can make candlestick chart with this:
<%= candlestick_chart(candlestick_data, candlestick_options) %>
Box Plot Chart
Given:
<%
require 'date'
def box_plot_data
20.times.map {|i| [Date.today - 20 + i, box_plot_datum] }.to_h
end
def box_plot_datum
level = 1000
max = level + rand(50..300)
min = level - rand(50..300)
q1 = min + rand(10..50)
q3 = max - rand(10..50)
median = (min + q1 + q3 + max)/4
[min, q1, median, q3, max]
end
box_plot_options = {
plot_options: {
boxPlot: {
colors: {
upper: '#aaffaa',
lower: '#ffaaFF'
}
}
}
}
%>
You can make box plot chart with this:
<%= box_plot_chart(box_plot_data, box_plot_options) %>
Mixed Charts
You can mix charts by using mixed_charts
or combo_charts
methods.
For example, given that:
@total_properties = Property.group_by_week(:created_at).count
and
<% total_series = {
name: "Total", data: @total_properties
} %>
you can do this:
<%= combo_charts({**options, theme: 'palette4', stacked: false, data_labels: false}) do %>
<% line_chart(total_series) %>
<% area_chart(series.last) %>
<% column_chart(series.first) %>
<% end %>
Syncing Charts
You can synchronize charts by using syncing_charts
or synchronized_charts
methods. For
example:
<%= syncing_charts(chart: {toolbar: false}, height: 250, style: 'display: inline-block; width: 32%;') do %>
<% mixed_charts(theme: 'palette4', data_labels: false) do %>
<% line_chart({name: "Total", data: @total_properties}) %>
<% area_chart({name: "Active", data: @active_properties}) %>
<% end %>
<% area_chart({name: "Active", data: @active_properties}, theme: 'palette6') %>
<% line_chart({name: "Inactive", data: @active_properties}, theme: 'palette8') %>
<% end %>
Brush Chart
<%= area_chart(total_series, {
**options, chart_id: 'the-chart', xtitle: nil, theme: 'palette2'
}) %>
<%= mixed_charts(brush_target: 'the-chart', theme: 'palette7') do %>
<% column_chart(series.first) %>
<% line_chart(series.last) %>
<% end %>
Annotations
All cartesian charts can have annotations, for example:
<%= area_chart(series, {**options, theme: 'palette9'}) do %>
<% x_annotation(value: ('2019-01-06'..'2019-02-24'), text: "Busy Time", color: 'green') %>
<% y_annotation(value: 29, text: "Max Properties", color: 'blue') %>
<% point_annotation(value: ['2018-10-07', 24], text: "First Peak", color: 'magenta') %>
<% end %>
Multiple Y-Axes
There's no fancy shortcut for multiple Y axes yet, but it is allowed. Here is an example
for that.
<% series = [
{
name: 'Income',
type: 'column',
data: [1.4, 2, 2.5, 1.5, 2.5, 2.8, 3.8, 4.6]
},
{
name: 'Cashflow',
type: 'column',
data: [1.1, 3, 3.1, 4, 4.1, 4.9, 6.5, 8.5]
},
{
name: 'Revenue',
data: [20, 29, 37, 36, 44, 45, 50, 58]
}
]
xaxis = {
title: {text: 'Year'},
categories: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016]
}
yaxis = [
{title: {text: "Income"}},
{
title: {text: "Operating Cashflow"},
opposite: true,
seriesName: 'Cashflow'
},
{
title: {text: "Revenue"},
opposite: true,
seriesName: 'Revenue'
}
]
%>
<%= line_chart(series, xaxis: xaxis, yaxis: yaxis) %>
Heatmap Chart
<% heatmap_series = 17.downto(10).map do |n|
{
name: "#{n}:00",
data: 15.times.map do |i|
["W#{i+1}", rand(90)]
end.to_h
}
end %>
<%= heatmap_chart(heatmap_series) %>
Radar Chart
<% radar_series = [
{
name: "What it should be",
data: { "Code review"=>10, "Issues"=>5, "Pull request"=>25, "Commits"=>60 }
},
{
name: "What it really is",
data: { "Code review"=>1, "Issues"=>3, "Pull request"=>7, "Commits"=>89 }
}
] %>
<%= radar_chart(
radar_series,
{title: "GitHub Radar", markers: {size: 4}, theme: 'palette4'}
) %>
Bubble Chart
<% bubble_series = (1..4).map do |n|
{
name: "Bubble#{n}",
data: 20.times.map{[rand(750),rand(10..60),rand(70)]}
}
end %>
<%= bubble_chart(bubble_series, data_labels: false, theme: 'palette6') %>
Polar Charts
Pie Chart
<%= pie_chart([
{name: "Series A", data: 25},
{name: "Series B", data: 100},
{name: "Series C", data: 200},
{name: "Series D", data: 125}
], legend: "left") %>
Donut Chart
<%= donut_chart([25, 100, 200, 125], theme: 'palette4') %>
Radial Bar Chart
Also called circle_chart
.
<%= radial_bar_chart([
{name: "Circle A", data: 25},
{name: "Circle B", data: 40},
{name: "Circle C", data: 80},
{name: "Circle D", data: 45}
], legend: true) %>
Data Formats
Cartesian Charts
The data format for line, stepline, area, column, bar, and scatter
charts should be in following format per-series:
{
<x value> => <y value>,
<x value> => <y value>,
...
}
or this:
[
[<x value>, <y value>],
[<x value>, <y value>],
...
]
Candlestick Chart
Candlestick chart is just like other cartesian charts, only the y value is
an array of 4 members which called the OHLC (Open-High-Low-Close):
{
<x value> => [<Open>, <High>, <Low>, <Close>],
<x value> => [<Open>, <High>, <Low>, <Close>],
...
}
or this:
[
[<x value>, [<Open>, <High>, <Low>, <Close>]],
[<x value>, [<Open>, <High>, <Low>, <Close>]],
...
]
Box Plot Chart
Box plot chart is similar to candlestick chart, only the y value is
an array of 5 members (Minimum-First Quartile-Median-Third Quartile-Maximum):
{
<x value> => [<Min>, <Q1>, <Median>, <Q3>, <Max>],
<x value> => [<Min>, <Q1>, <Median>, <Q3>, <Max>],
...
}
or this:
[
[<x value>, [<Min>, <Q1>, <Median>, <Q3>, <Max>]],
[<x value>, [<Min>, <Q1>, <Median>, <Q3>, <Max>]],
...
]
Heatmap Chart
The data format for heatmap chart per-series is similar to cartesian
charts. But instead of y values they are heat values. The series names will
be the y values.
{
<x value> => <heat value>,
<x value> => <heat value>,
...
}
or this:
[
[<x value>, <heat value>],
[<x value>, <heat value>],
...
]
Radar Chart
The data format for radar chart per-series is also similar but instead
of x values they are variables and instead of y values they are the only
values for the variables with type of Numeric.
{
<variable> => <value>,
<variable> => <value>,
...
}
or this:
[
[<variable>, <value>],
[<variable>, <value>],
...
]
Bubble Chart
Bubble chart is similar to scatter chart, only they have one more value
for bubble size:
[
[<x value>, <bubble size>, <y value>],
[<x value>, <bubble size>, <y value>],
...
]
Polar Charts
The data format for donut, pie, and radial bar are the simplest. They are
just any single value of type Numeric.
Options
ApexCharts.RB supports all options from ApexCharts.JS,
but instead of camelCase, you can write them in snake_case.
ApexCharts.RB also provides shortcuts to some ApexCharts.JS options, such as title
. In
ApexCharts.JS you would have to write
title: { text: "Some title" }
In ApexCharts.RB you can write
title: "Some title"
if you just want to add the text.
xtitle
and ytitle
are even greater shortcuts. Instead of
xaxis: { title: { text: "x title" } }
you can write
xtitle: "x title"
options = {
animations: false,
chart: {
fontFamily: "Helvetica, Arial, sans-serif",
toolbar: {
show: false
}
},
curve: "straight",
markers: {
size: 5,
},
tooltip: false,
xtitle: "Boars per capita"
}
These options can be passed to any chart helper like <%= line_chart(series, options) %>
.
Global Options
To use default options globally, you can specify config for default options before calling
your charts. In Rails, put it in initializers
directory. For example:
ApexCharts.config.default_options = {
data_labels: false,
tootip: true,
theme: 'my-theme'
}
All charts will then automatically pick up these global options, which can be overwritten
individually by any options passed to the relevant chart helper.
Formatter Function
To use a simple formatter function (e.g. formatter in tooltip
, data_labels
, and labels
),
you can add functionable-json to your Gemfile and
use it like so:
<%= area_chart series, tooltip: {y: {formatter: function(val) { return '$' + parseFloat(val).toLocaleString() }}} %>
Or, without the functionable-json gem, use function as object as follows:
<%= area_chart series, tooltip: {y: {formatter: {function: {args: "val", body: "return '$' + parseFloat(val).toLocaleString();"}} }} %>
Defer Chart Rendering
It's possible to defer chart rendering by passing the argument defer: true
as option.
<%= line_chart series, defer: true %>
Render with a script whose type is module
The charts are rendered by inserting a use the
option module: true
.
<%= line_chart series, module: true %>
Reusable Custom Palette
To create palettes to be used anywhere on your any parts of your app, you can use
ApexCharts::Theme.create
.
For example, in rails app, you would write it in initializers:
ApexCharts::Theme.create "rainbow", ["#ff0000", "#00ff00", "#0000ff"]
and later somewhere in your app views:
...
= line_chart chart_data, theme: "rainbow"
...
If later for some reason I don't know you want to destroy the palette you can use:
ApexCharts::Theme.destroy "rainbow"
Use Alongside Other Charting Libraries
You can prefix the helper methods name with your chosen words to avoid name clashing with
other charting libraries (e.g. chartkick, google_charts, etc.) you already use. Just set
the APEXCHARTS_PREFIX
environment variable to a string before you start your app server,
say, 'awesome_' and then on your views/templates use the chart helpers as awesome_line_chart
,
awesome_area_chart
, and so on.
Besides setting the environtment variable, if you just want a quick prefix, you can instead
do this on your Gemfile:
gem 'apexcharts', require: 'apex_charts/prefix_with_apex'
and you'll get apex_line_chart
, apex_area_chart
, etc.
The prefix you set only applies to the outer chart helpers. The inner chart helpers is not
prefixed. For example:
<%= awesome_syncing_chart(syncing_options) do %>
<% combo_chart(mixed_options) do %>
<% line_chart(line_series) %>
<% area_chart(area_series) %>
<% end %>
<% end %>
Alongside Chartkick
Given:
<% series = [
{name: 'Verified', data: @verified_users},
{name: 'Unverified', data: @unverified_users}
] %>
<% options = {
legend: 'bottom', title: 'Users Grouped By Week For The Last 1 Year',
ytitle: 'Users', width: '100%', height: '300px'
} %>
Chartkick (Chart.js) and ApexCharts
<div style="display: inline-block; width: 48%;">
<%= area_chart(series, {**options, adapter: 'chartjs'}) %>
</div>
<div style="display: inline-block; width: 48%;">
<%= apex_area_chart(series, options) %>
</div>
Chartkick (Google Charts) and ApexCharts
<div style="display: inline-block; width: 48%;">
<%= area_chart(series, {**options, adapter: 'google'}) %>
</div>
<div style="display: inline-block; width: 48%;">
<%= apex_area_chart(series, options) %>
</div>
Chartkick (Highcharts) and ApexCharts
<div style="display: inline-block; width: 48%;">
<%= area_chart(series, {**options, adapter: 'highcharts'}) %>
</div>
<div style="display: inline-block; width: 48%;">
<%= apex_area_chart(series, options) %>
</div>
Installation
Add this line to your application's Gemfile:
gem 'groupdate'
gem 'apexcharts'
And then execute:
$ bundle
Web Support
Rails
Require it in your app/assets/javascripts/application.js
.
Or, if you use webpacker
, you can run:
$ yarn add apexcharts
and then require it in your app/javascript/packs/application.js
.
window.ApexCharts = require("apexcharts")
import ApexCharts from 'apexcharts'
window.ApexCharts = ApexCharts
Sinatra
Require it after you require 'sinatra/base'
and add helper Sinatra::ApexCharts
in the
class that inherits from Sinatra::Base
.
require 'sinatra/base'
require 'apexcharts'
class SimpleApp < Sinatra::Base
helpers Sinatra::ApexCharts
end
To add the asset (ApexCharts.JS), include a script tag in your template
as follows:
template :index do
<<~INDEX
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<% series = {...} %>
<%= pie_chart(series, legend: "left") %>
INDEX
end
For more details, see example.
Plain HTML+ERB (Without Framework)
Insert this to the top of your .html.erb files:
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<% require 'apexcharts' %>
<% include ApexCharts::Helper %>
You can then generate the static html page with e.g.
$ erb sample.html.erb > sample.html
Contributing
Everyone is encouraged to help improve this project by:
- Reporting bugs
- Fixing bugs and submiting pull requests
- Fixing documentation
- Suggesting new features
License
The gem is available as open source under the terms of the
MIT License.
Articles