prawn-graph 0.9.10 → 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -10
- data/README.md +35 -75
- data/Rakefile +0 -6
- data/lib/prawn/graph/charts/base.rb +1 -1
- data/lib/prawn/graph/charts/legacy/base.rb +3 -1
- data/lib/prawn/graph/charts/legacy/grid.rb +1 -1
- data/lib/prawn/graph/extension.rb +8 -39
- data/lib/prawn/graph/series.rb +7 -64
- data/lib/prawn/graph/theme.rb +6 -23
- data/lib/prawn/graph/version.rb +1 -1
- data/lib/prawn-graph.rb +0 -6
- data/prawn-graph.gemspec +3 -8
- metadata +7 -30
- data/lib/prawn/graph/calculations/layout_calculator.rb +0 -109
- data/lib/prawn/graph/calculations.rb +0 -1
- data/lib/prawn/graph/chart_components/canvas.rb +0 -139
- data/lib/prawn/graph/chart_components/series_renderer.rb +0 -339
- data/lib/prawn/graph/chart_components.rb +0 -2
- data/test.pdf +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84da9cfac88ce76e053409afd8ea057d8fb165b6
|
4
|
+
data.tar.gz: 0dc84a38ede9e63fae98301613f57c89c9d4970b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d7a8b4568f6cd91c062d2811cca83d077b086ea76d71e38ac0c5f2cb660636fd1043f2f3c68b3fb1bedd204629fb746a368daa3074afee9088b1c964d361a1c
|
7
|
+
data.tar.gz: 98609b55fe0f6cca079bf8b3421ee6fbd9315f1737c2278c0ec4c6e099ecdae658a9f8c37b8e9411c3198830695311eea9b682fca7bd6c44fcb17742549f6b8e
|
data/.travis.yml
CHANGED
@@ -1,17 +1,7 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
3
|
- 2.0.0
|
4
|
-
- 2.1.0-p0
|
5
4
|
- 2.1.8
|
6
|
-
- 2.2.0-p0
|
7
5
|
- 2.2.4
|
8
6
|
- 2.3.0
|
9
|
-
- jruby-9.0.5.0
|
10
|
-
- rbx-3.19
|
11
|
-
matrix:
|
12
|
-
allow_failures:
|
13
|
-
- rvm: rbx-3.19
|
14
7
|
before_install: gem install bundler -v 1.11.2
|
15
|
-
addons:
|
16
|
-
code_climate:
|
17
|
-
repo_token: 9646aae52d1d1670d545c46bd94f5d86b92d516c5e3cb9890fcef62acc3a34b6
|
data/README.md
CHANGED
@@ -2,11 +2,6 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/prawn-graph.svg)](https://badge.fury.io/rb/prawn-graph)
|
4
4
|
[![License](http://img.shields.io/:license-mit-blue.svg)](http://sujrd.mit-license.org)
|
5
|
-
[![Code Climate](https://codeclimate.com/github/HHRy/prawn-graph/badges/gpa.svg)](https://codeclimate.com/github/HHRy/prawn-graph)
|
6
|
-
[![Test Coverage](https://codeclimate.com/github/HHRy/prawn-graph/badges/coverage.svg)](https://codeclimate.com/github/HHRy/prawn-graph/coverage)
|
7
|
-
[![Build Status](https://travis-ci.org/HHRy/prawn-graph.svg?branch=master)](https://travis-ci.org/HHRy/prawn-graph)
|
8
|
-
[![security](https://hakiri.io/github/HHRy/prawn-graph/master.svg)](https://hakiri.io/github/HHRy/prawn-graph/master)
|
9
|
-
![Maintained: yes](https://img.shields.io/badge/maintained-yes-brightgreen.png)
|
10
5
|
|
11
6
|
An extension for the [prawn pdf library][5] which adds the ability to draw graphs (or charts if
|
12
7
|
you perfer) in PDF documents.
|
@@ -18,52 +13,42 @@ are dramatic.
|
|
18
13
|
|
19
14
|
By default, graphs are drawn in monochrome, as that's likely how they will be printed.
|
20
15
|
|
21
|
-
This is free and open source software released under ther terms of the [MIT Licence](http://opensource.org/licenses/MIT).
|
22
|
-
|
23
|
-
Its copyright is held by Ryan Stenhouse and the [other contributors][8] and it was first released in
|
24
|
-
2010.
|
25
|
-
|
26
16
|
## Compatibility
|
27
17
|
|
28
|
-
|
18
|
+
The gem is only tested against Ruby version 2.0 and greater. Older Ruby versions may work but are not
|
29
19
|
officially supported. We aim for compatibilty with 1.x and 2.x series of prawn. Any incomaptibilities
|
30
|
-
|
31
|
-
|
32
|
-
We build automatically using Travis CI. Our [.travis.yml][9] file targets the same Ruby versions as
|
33
|
-
[prawn itself][5] does.
|
20
|
+
should be treated as bugs and added to the [issue tracker][2].
|
34
21
|
|
22
|
+
Unlike previous version of prawn-graph, this version does not at this time include a theme api or the
|
23
|
+
ability to change the colors used to render the graph.
|
35
24
|
|
36
|
-
### Legacy support and deprecation notices.
|
37
25
|
|
38
|
-
|
39
|
-
and `line_graph` (aliased as `line_chart`) methods as part of its interface which function the same as their
|
40
|
-
equivalents in version `0.0.4`. These methods are, however, deprecated and **will** be removed when version
|
41
|
-
`1.0.0` is released. Using these methods will result in a `warn` level message from Ruby.
|
26
|
+
## IMPORTANT - READ THIS BEFORE USING
|
42
27
|
|
43
|
-
|
44
|
-
|
45
|
-
|
28
|
+
prawn-graph is currently being rewritten to have its internal components replaced with new, properly
|
29
|
+
test-driven bits of code to draw the various cool graphs and charts that people would like to use in
|
30
|
+
their PDFs.
|
46
31
|
|
47
|
-
|
48
|
-
|
32
|
+
Right now, the "legacy" drawing code is what is ultimately being used to render any graphs being
|
33
|
+
generated. The newness instead is that project is compatible with all modern versions of prawn and
|
34
|
+
therefore are useful again.
|
49
35
|
|
50
|
-
|
36
|
+
This means that for now any existing rendering bugs still remain. If you find any, please be
|
37
|
+
[a good citizen][2] and [report them][2].
|
51
38
|
|
52
|
-
To use prawn-graph, you can add the following to your `Gemfile`:
|
39
|
+
To use prawn-graph with these caveats, you can add the following to your `Gemfile`:
|
53
40
|
|
54
41
|
```Gemfile
|
55
|
-
gem 'prawn-graph', '
|
42
|
+
gem 'prawn-graph', '1.0.0.pre1'
|
56
43
|
```
|
57
44
|
|
58
|
-
Alternatively, you can use Rubygems directly: `gem install prawn-graph`.
|
45
|
+
Alternatively, you can use Rubygems directly: `gem install prawn-graph --pre`.
|
59
46
|
|
60
47
|
## Acknowledgements
|
61
48
|
|
62
49
|
With thanks to [株式会社アルム][3] ([Allm Inc][4]) for allowing Ryan Stenhouse the time to rebuild this version of
|
63
50
|
prawn-graph. This updated version of prawn-graph was inspired and guided by [prawn-svg][1] by [Roger Nesbitt][6].
|
64
|
-
|
65
|
-
Prawn Graph was originally sponsored by and built for use at [Purchasing Card Consultancy Ltd][7] while
|
66
|
-
Ryan Stenhouse was employed there.
|
51
|
+
It also uses some of [prawn-svg][1]'s document size calculation code.
|
67
52
|
|
68
53
|
## Supported graph / chart types
|
69
54
|
|
@@ -77,64 +62,39 @@ adventurous - please add it!
|
|
77
62
|
|
78
63
|
## Using prawn-graph
|
79
64
|
|
80
|
-
Graphs can be created by calling the `graph` or its alias, `chart` method with an array of
|
81
|
-
`Prawn::Graph::Series` objects representing the data you would like to plot and how it should
|
82
|
-
be displayed. It will also take a hash of options, and block which will have the graph yeilded
|
83
|
-
to it.
|
84
|
-
|
85
65
|
```ruby
|
86
|
-
graph
|
66
|
+
require 'prawn-graph'
|
67
|
+
|
68
|
+
data = [ ['A', 10], ['B', 11], ['C', 12] ]
|
69
|
+
|
70
|
+
Prawn::Document.generate('test.pdf') do
|
71
|
+
text 'Graph Example'
|
72
|
+
bar_graph data
|
73
|
+
end
|
87
74
|
```
|
88
75
|
|
89
76
|
When called with just a set of data, prawn-graph will do its best to make the graph fit in the
|
90
77
|
available space. For a little more control over how the graphs are rendered in the document
|
91
|
-
you can pass the following options
|
78
|
+
you can pass the following options:
|
92
79
|
|
93
80
|
Option | Data type | Description
|
94
81
|
----------- | --------- | -----------
|
95
82
|
:at | [integer, integer] | Specify the location on the page you want the graph to appear.
|
96
83
|
:width | integer | Desired width of the graph. Defaults to horizontal space available.
|
97
84
|
:height | integer | Desired height of the graph. Defaults to vertical space available.
|
98
|
-
:title | string | The overall title for your chart
|
99
|
-
:series_key | boolean | Should we render the series key for multi series graphs? Defaults to true.
|
100
85
|
|
101
|
-
|
102
|
-
themselves are made up of an array of data points to plot, and a series of options.
|
103
|
-
|
104
|
-
```ruby
|
105
|
-
Prawn::Graph::Series.new [1,2,3,4], options = {}
|
106
|
-
```
|
107
|
-
|
108
|
-
Valid `options` are:
|
109
|
-
|
110
|
-
Option | Data type | Description
|
111
|
-
------------- | --------- | -----------
|
112
|
-
:mark_average | boolean | Should we mark a line showing the average value of the series? Defaults to false.
|
113
|
-
:mark_minimum | boolean | Should we mark the minimum value of the series? Defaults to false.
|
114
|
-
:mark_maximum | boolean | Should we mark the maximum value of the series? Defaults to false.
|
115
|
-
:title | string | The title of this series, which will be shown in the series key.
|
116
|
-
:type | symbol | How this series should be rendered. Defaults to `:bar`, valid options are `:bar`, `:line`.
|
117
|
-
|
118
|
-
### Show me some code!
|
86
|
+
### Example
|
119
87
|
|
120
88
|
```ruby
|
121
89
|
require 'prawn-graph'
|
122
90
|
|
123
|
-
|
124
|
-
series << Prawn::Graph::Series.new([4,9,3,2,1,6,2,8,2,3,4,9,2], title: "A label for a series", type: :bar)
|
125
|
-
series << Prawn::Graph::Series.new([5,4,3,2,7,9,2,8,7,5,4,9,2], title: "Another label", type: :line, mark_average: true, mark_minimum: true)
|
126
|
-
series << Prawn::Graph::Series.new([1,2,3,4,5,9,6,4,5,6,3,2,11], title: "Yet another label", type: :bar)
|
127
|
-
series << Prawn::Graph::Series.new([1,2,3,4,5,12,6,4,5,6,3,2,9].shuffle, title: "One final label", type: :line, mark_average: true, mark_maximum: true)
|
128
|
-
|
129
|
-
xaxis_labels = ['0900', '1000', '1100', '1200', '1300', '1400', '1500', '1600', '1700', '1800', '1900', '2000', '2100']
|
91
|
+
data = [ ['A', 10], ['B', 11], ['C', 12] ]
|
130
92
|
|
131
93
|
Prawn::Document.generate('test.pdf') do
|
132
|
-
|
94
|
+
text 'Graph Example'
|
95
|
+
bar_graph data, at: [10,20], width: 200
|
133
96
|
end
|
134
|
-
```
|
135
|
-
|
136
|
-
### Output
|
137
|
-
<img src="http://prawn-graph.ryanstenhouse.jp/img/prawn-graph-output.png" alt="Prawn Graph Example Output" width="933" height="420">
|
97
|
+
```
|
138
98
|
|
139
99
|
## Development
|
140
100
|
|
@@ -151,6 +111,9 @@ Bug reports and pull requests are welcome [on GitHub][2]. This project is intend
|
|
151
111
|
safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org)
|
152
112
|
code of conduct.
|
153
113
|
|
114
|
+
## License
|
115
|
+
|
116
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
154
117
|
|
155
118
|
|
156
119
|
[1]: https://github.com/mogest/prawn-svg/
|
@@ -158,7 +121,4 @@ code of conduct.
|
|
158
121
|
[3]: http://www.allm.net/
|
159
122
|
[4]: http://www.allm.net/en/
|
160
123
|
[5]: http://github.com/prawnpdf/prawn/
|
161
|
-
[6]: https://github.com/mogest/
|
162
|
-
[7]: http://www.pccl.co.uk/
|
163
|
-
[8]: https://github.com/HHRy/prawn-graph/blob/master/CONTRIBUTORS.md
|
164
|
-
[9]: https://github.com/HHRy/prawn-graph/blob/master/.travis.yml
|
124
|
+
[6]: https://github.com/mogest/
|
data/Rakefile
CHANGED
@@ -16,6 +16,7 @@ module Prawn
|
|
16
16
|
@colour = false
|
17
17
|
@document = document
|
18
18
|
@theme = Prawn::Graph::Theme::Default
|
19
|
+
off = 20
|
19
20
|
@grid = Prawn::Graph::Charts::Legacy::Grid.new(grid_x_start, grid_y_start, grid_width, grid_height, opts[:spacing], document, Prawn::Graph::Theme::Default)
|
20
21
|
end
|
21
22
|
|
@@ -95,7 +96,8 @@ module Prawn
|
|
95
96
|
# method, which does the actual real heavy lifting of drawing the graph.
|
96
97
|
#
|
97
98
|
def plot_values
|
98
|
-
raise
|
99
|
+
raise Prawn::Errors::NoPlotValuesMethod, 'subclasses of Prawn::Chart::Base must implement '
|
100
|
+
+ 'their own plot_values method.'
|
99
101
|
end
|
100
102
|
|
101
103
|
def reset
|
@@ -23,7 +23,7 @@ module Prawn
|
|
23
23
|
#
|
24
24
|
def draw
|
25
25
|
@document.stroke_color @theme.markers
|
26
|
-
if @theme.
|
26
|
+
if @theme.stroke_grid_markers
|
27
27
|
(@height / @spacing).times do |x|
|
28
28
|
offset = @spacing * (x + 1)
|
29
29
|
@document.move_to [@point.first, (@point.last + offset)]
|
@@ -2,63 +2,32 @@ module Prawn
|
|
2
2
|
module Graph
|
3
3
|
module Extension
|
4
4
|
|
5
|
-
#
|
6
|
-
# Draws a bar graph into the PDF using the legacy graph stuff. Please avoid.
|
5
|
+
# Draws a bar graph into the PDF
|
7
6
|
#
|
8
7
|
# Example:
|
9
8
|
#
|
10
9
|
# bar_graph [ ["A", 1], ["B", 2], ["C", 3] ], at: [10,10]
|
11
10
|
#
|
12
11
|
def bar_graph(data, options = {}, &block)
|
13
|
-
|
14
|
-
|
12
|
+
graph = Prawn::Graph::Charts::Bar.new(data, self, options, &block)
|
13
|
+
graph.draw
|
14
|
+
{warnings: [], width: graph.prawn.bounds.width, height: graph.prawn.bounds.height}
|
15
15
|
end
|
16
16
|
alias bar_chart bar_graph
|
17
17
|
|
18
|
-
#
|
19
|
-
# Draws a line graph into the PDF using the legacy graph stuff. Please avoid.
|
18
|
+
# Draws a line graph into the PDF
|
20
19
|
#
|
21
20
|
# Example:
|
22
21
|
#
|
23
22
|
# line_graph [ ["A", 1], ["B", 2], ["C", 3] ], at: [10,10]
|
24
23
|
#
|
25
24
|
def line_graph(data, options = {}, &block)
|
26
|
-
|
27
|
-
|
25
|
+
graph = Prawn::Graph::Charts::Line.new(data, self, options, &block)
|
26
|
+
graph.draw
|
27
|
+
{warnings: [], width: graph.prawn.bounds.width, height: graph.prawn.bounds.height}
|
28
28
|
end
|
29
29
|
alias line_chart line_graph
|
30
30
|
|
31
|
-
|
32
|
-
# Plots one or more Prawn::Graph::Series on a chart. Expects an array-like object of
|
33
|
-
# Prawn::Graph::Series objects and some options for positioning the sizing the
|
34
|
-
# rendered graph
|
35
|
-
#
|
36
|
-
# @param series [Array] of Prawn::Graph::Series objects
|
37
|
-
# @param options [Hash] of options, which can be:
|
38
|
-
# `:width` - The overall width of the graph to be drawn. `<Integer>`
|
39
|
-
# `:height` - The overall height of the graph to be drawn. `<Integer>`
|
40
|
-
# `:at` - The point from where the graph will be drawn. `[<Integer>x, <Integer>y]`
|
41
|
-
# `:title` - The title for this chart. Must be a string. `<String>`
|
42
|
-
# `:series_key` - Should we render the key to series in this chart? `<Boolean>`
|
43
|
-
#
|
44
|
-
def graph(series, options = {}, &block)
|
45
|
-
canvas = Prawn::Graph::ChartComponents::Canvas.new(series, self, options, &block)
|
46
|
-
canvas.draw
|
47
|
-
{warnings: [], width: self.bounds.width, height: self.bounds.height}
|
48
|
-
end
|
49
|
-
alias chart graph
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def draw_graph(klass, data, options, &block)
|
54
|
-
graph = klass.new(data, self, options, &block)
|
55
|
-
graph.draw
|
56
|
-
{warnings: [], width: self.bounds.width, height: self.bounds.height}
|
57
|
-
end
|
58
|
-
|
59
|
-
def deprecate(method)
|
60
|
-
warn "[DEPRECATION] #{method} is deprecated and will be removed in future versions of prawn-graph. Use chart or graph instead."
|
61
|
-
end
|
62
31
|
end
|
63
32
|
end
|
64
33
|
end
|
data/lib/prawn/graph/series.rb
CHANGED
@@ -5,90 +5,33 @@ module Prawn
|
|
5
5
|
# on a chart.
|
6
6
|
#
|
7
7
|
class Series
|
8
|
-
attr_accessor :values, :
|
8
|
+
attr_accessor :values, :title, :type
|
9
|
+
VALID_TYPES = [ :bar, :line ]
|
9
10
|
|
10
|
-
|
11
|
-
title: nil,
|
12
|
-
type: :bar,
|
13
|
-
mark_average: false,
|
14
|
-
mark_minimum: false,
|
15
|
-
mark_maximum: false,
|
16
|
-
}
|
17
|
-
|
18
|
-
def initialize(values = [], options = {})
|
11
|
+
def initialize(values = [], title = nil, type = :bar)
|
19
12
|
@values = values
|
20
|
-
@
|
21
|
-
|
22
|
-
|
23
|
-
# @return [String] The value of +options.title+.
|
24
|
-
#
|
25
|
-
def title
|
26
|
-
options.title
|
13
|
+
@title = title
|
14
|
+
@type = type
|
27
15
|
end
|
28
16
|
|
29
|
-
# @return [Symbol] The value of +options.type+.
|
30
|
-
#
|
31
|
-
def type
|
32
|
-
options.type
|
33
|
-
end
|
34
|
-
|
35
|
-
# @param value [Object] a value to be added to the series. Must be of the same kind as other +values+.
|
36
|
-
# @return [Array] The modified +values+ object.
|
37
|
-
#
|
38
17
|
def <<(value)
|
39
18
|
@values << value
|
40
19
|
end
|
41
20
|
|
42
|
-
# @return [Numeric] The smallest value stored in the +values+ of this Series.
|
43
|
-
#
|
44
21
|
def min
|
45
|
-
|
46
|
-
0
|
47
|
-
else
|
48
|
-
values.sort.collect{ |x| x unless x.zero? }.compact.first
|
49
|
-
end
|
22
|
+
@values.min || 0
|
50
23
|
end
|
51
24
|
|
52
|
-
# @return [Numeric] The largest value stored in the +values+ of this Series.
|
53
|
-
#
|
54
25
|
def max
|
55
26
|
@values.max || 0
|
56
27
|
end
|
57
28
|
|
58
|
-
# @return [Numeric] The average value stored in the +values+ of this Series.
|
59
|
-
#
|
60
|
-
def avg
|
61
|
-
if size > 0
|
62
|
-
@values.inject(:+) / size
|
63
|
-
else
|
64
|
-
0
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# @return [Numeric] The size of the +values+ stored in this Series.
|
69
|
-
#
|
70
29
|
def size
|
71
30
|
@values.size
|
72
31
|
end
|
73
32
|
|
74
|
-
def mark_average?
|
75
|
-
options.mark_average == true
|
76
|
-
end
|
77
|
-
|
78
|
-
def mark_minimum?
|
79
|
-
options.mark_minimum == true
|
80
|
-
end
|
81
|
-
|
82
|
-
def mark_maximum?
|
83
|
-
options.mark_maximum == true
|
84
|
-
end
|
85
|
-
|
86
|
-
# @deprecated Provided to allow for tempory backwards compatibilty with legacy graph drawing. Do not use.
|
87
|
-
# @return [Array] Series represented as an array in the format [ title, val1, val2... ]
|
88
|
-
#
|
89
33
|
def to_a
|
90
|
-
|
91
|
-
[options.title, @values].compact.flatten
|
34
|
+
[title, @values].compact.flatten
|
92
35
|
end
|
93
36
|
end
|
94
37
|
end
|
data/lib/prawn/graph/theme.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
1
3
|
module Prawn
|
2
4
|
module Graph
|
3
5
|
module Theme
|
@@ -8,33 +10,14 @@ module Prawn
|
|
8
10
|
'85929E',
|
9
11
|
'34495E',
|
10
12
|
'1B2631',
|
11
|
-
'EBEDEF',
|
12
|
-
'D6DBDF',
|
13
|
-
'85929E',
|
14
|
-
'34495E',
|
15
|
-
'1B2631',
|
16
|
-
'EBEDEF',
|
17
|
-
'D6DBDF',
|
18
|
-
'85929E',
|
19
|
-
'34495E',
|
20
|
-
'1B2631',
|
21
13
|
],
|
22
|
-
title: '
|
14
|
+
title: '000000',
|
23
15
|
background: 'FFFFFF',
|
24
16
|
grid: 'F2F4F4',
|
25
17
|
axes: '17202A',
|
26
|
-
markers: '
|
27
|
-
|
28
|
-
default: '
|
29
|
-
average: '34495E',
|
30
|
-
max: '17202A',
|
31
|
-
min: '17202A',
|
32
|
-
font_sizes: OpenStruct.new({
|
33
|
-
default: 8,
|
34
|
-
main_title: 10,
|
35
|
-
axis_labels: 5,
|
36
|
-
series_key: 8,
|
37
|
-
}),
|
18
|
+
markers: '17202A',
|
19
|
+
stroke_grid_markers: true,
|
20
|
+
default: '000000',
|
38
21
|
})
|
39
22
|
end
|
40
23
|
end
|
data/lib/prawn/graph/version.rb
CHANGED
data/lib/prawn-graph.rb
CHANGED
@@ -1,11 +1,5 @@
|
|
1
|
-
require "ostruct"
|
2
|
-
require "bigdecimal"
|
3
1
|
require "prawn"
|
4
2
|
require "prawn/graph/version"
|
5
|
-
require "prawn/graph/calculations"
|
6
|
-
|
7
|
-
require "prawn/graph/chart_components"
|
8
|
-
|
9
3
|
require "prawn/graph/theme"
|
10
4
|
require "prawn/graph/series"
|
11
5
|
require "prawn/graph/charts"
|
data/prawn-graph.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
|
18
18
|
spec.summary = %q{Easily add graphs to Prawn PDF documents}
|
19
19
|
spec.description = %q{Prawn::Graph adds straightforward native graph drawing to Prawn without the need to depend on anything else. All generated graphs are pure PDF Vector Images. It results in smaller document sizes and less complication.}
|
20
|
-
spec.homepage = "
|
20
|
+
spec.homepage = "https://ryanstenhouse.jp"
|
21
21
|
spec.license = "MIT"
|
22
22
|
|
23
23
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -28,15 +28,10 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_development_dependency "bundler", "~> 1.11"
|
29
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
30
30
|
spec.add_development_dependency "rspec", "~> 3.0"
|
31
|
-
spec.add_development_dependency "
|
32
|
-
|
31
|
+
spec.add_development_dependency "simplecov"
|
32
|
+
|
33
33
|
|
34
34
|
spec.required_ruby_version = '>= 2.0.0'
|
35
35
|
|
36
36
|
spec.add_runtime_dependency "prawn", ">= 0.11.1", "< 3"
|
37
|
-
|
38
|
-
spec.metadata = {
|
39
|
-
"issue_tracker" => "https://github.com/HHRy/prawn-graph/issues",
|
40
|
-
"source_code" => "https://github.com/HHRy/prawn-graph"
|
41
|
-
}
|
42
37
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prawn-graph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Stenhouse
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-07
|
12
|
+
date: 2016-06-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -54,21 +54,7 @@ dependencies:
|
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '3.0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
58
|
-
requirement: !ruby/object:Gem::Requirement
|
59
|
-
requirements:
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: '0'
|
63
|
-
type: :development
|
64
|
-
prerelease: false
|
65
|
-
version_requirements: !ruby/object:Gem::Requirement
|
66
|
-
requirements:
|
67
|
-
- - ">="
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
|
-
- !ruby/object:Gem::Dependency
|
71
|
-
name: yard
|
57
|
+
name: simplecov
|
72
58
|
requirement: !ruby/object:Gem::Requirement
|
73
59
|
requirements:
|
74
60
|
- - ">="
|
@@ -125,11 +111,6 @@ files:
|
|
125
111
|
- bin/console
|
126
112
|
- bin/setup
|
127
113
|
- lib/prawn-graph.rb
|
128
|
-
- lib/prawn/graph/calculations.rb
|
129
|
-
- lib/prawn/graph/calculations/layout_calculator.rb
|
130
|
-
- lib/prawn/graph/chart_components.rb
|
131
|
-
- lib/prawn/graph/chart_components/canvas.rb
|
132
|
-
- lib/prawn/graph/chart_components/series_renderer.rb
|
133
114
|
- lib/prawn/graph/charts.rb
|
134
115
|
- lib/prawn/graph/charts/bar.rb
|
135
116
|
- lib/prawn/graph/charts/base.rb
|
@@ -144,13 +125,10 @@ files:
|
|
144
125
|
- lib/prawn/graph/theme.rb
|
145
126
|
- lib/prawn/graph/version.rb
|
146
127
|
- prawn-graph.gemspec
|
147
|
-
|
148
|
-
homepage: http://prawn-graph.ryanstenhouse.jp
|
128
|
+
homepage: https://ryanstenhouse.jp
|
149
129
|
licenses:
|
150
130
|
- MIT
|
151
|
-
metadata:
|
152
|
-
issue_tracker: https://github.com/HHRy/prawn-graph/issues
|
153
|
-
source_code: https://github.com/HHRy/prawn-graph
|
131
|
+
metadata: {}
|
154
132
|
post_install_message:
|
155
133
|
rdoc_options: []
|
156
134
|
require_paths:
|
@@ -162,9 +140,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
140
|
version: 2.0.0
|
163
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
142
|
requirements:
|
165
|
-
- - "
|
143
|
+
- - ">"
|
166
144
|
- !ruby/object:Gem::Version
|
167
|
-
version:
|
145
|
+
version: 1.3.1
|
168
146
|
requirements: []
|
169
147
|
rubyforge_project:
|
170
148
|
rubygems_version: 2.5.1
|
@@ -172,4 +150,3 @@ signing_key:
|
|
172
150
|
specification_version: 4
|
173
151
|
summary: Easily add graphs to Prawn PDF documents
|
174
152
|
test_files: []
|
175
|
-
has_rdoc:
|
@@ -1,109 +0,0 @@
|
|
1
|
-
module Prawn
|
2
|
-
module Graph
|
3
|
-
module Calculations
|
4
|
-
|
5
|
-
class LayoutCalculator
|
6
|
-
attr_reader :bounds
|
7
|
-
attr_reader :series_key_area, :title_area, :graph_area, :canvas_width, :canvas_height
|
8
|
-
|
9
|
-
class Dimensions < OpenStruct
|
10
|
-
def renderable?
|
11
|
-
width > 0 && height > 0
|
12
|
-
end
|
13
|
-
|
14
|
-
def point
|
15
|
-
[x, y]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(bounds, attributes = nil, theme = Prawn::Graph::Theme::Default)
|
20
|
-
@bounds = bounds
|
21
|
-
@graph_area = Dimensions.new({ width: 0, height: 0, x: 0, y: 0 })
|
22
|
-
@title_area = Dimensions.new({ width: 0, height: 0, x: 0, y: 0 })
|
23
|
-
@series_key_area = Dimensions.new({ width: 0, height: 0, x: 0, y: 0 })
|
24
|
-
@theme = theme
|
25
|
-
set_from_attributes(attributes) if attributes
|
26
|
-
end
|
27
|
-
|
28
|
-
def calculate
|
29
|
-
calculate_width_and_height_of_canvas
|
30
|
-
calculate_key_area
|
31
|
-
calculate_title_area
|
32
|
-
calculate_graph_area
|
33
|
-
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
def hpadding
|
38
|
-
((BigDecimal(canvas_width) / 100) * 2).round
|
39
|
-
end
|
40
|
-
|
41
|
-
def vpadding
|
42
|
-
((BigDecimal(canvas_height) / 100) * 2).round
|
43
|
-
end
|
44
|
-
|
45
|
-
def invalid?
|
46
|
-
canvas_width > bounds[0] || canvas_height > bounds[1]
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def set_from_attributes(attributes)
|
52
|
-
@canvas_width = BigDecimal(attributes[:width], 10) rescue 0
|
53
|
-
@canvas_height = BigDecimal(attributes[:height], 10) rescue 0
|
54
|
-
@num_series = attributes[:series_count] || 1
|
55
|
-
@title = attributes[:title]
|
56
|
-
@show_series_key = !attributes[:show_series_key].nil? ? attributes[:show_series_key] : true
|
57
|
-
end
|
58
|
-
|
59
|
-
def calculate_width_and_height_of_canvas
|
60
|
-
if @canvas_width.zero? && @canvas_height.zero?
|
61
|
-
@canvas_width = BigDecimal(bounds[0], 10)
|
62
|
-
@canvas_height = BigDecimal(bounds[1], 10)
|
63
|
-
elsif !@canvas_width.zero? && @canvas_height.zero?
|
64
|
-
@canvas_height = (@canvas_width / bounds_aspect_ratio).round
|
65
|
-
elsif !@canvas_height.zero? && @canvas_width.zero?
|
66
|
-
@canvas_width = (@canvas_height * bounds_aspect_ratio).round
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def bounds_aspect_ratio
|
71
|
-
BigDecimal(bounds[0], 10) / BigDecimal(bounds[1], 10)
|
72
|
-
end
|
73
|
-
|
74
|
-
def calculate_title_area
|
75
|
-
unless @title.nil?
|
76
|
-
@title_area[:width] = (canvas_width - @series_key_area[:width] - (2*hpadding))
|
77
|
-
@title_area[:x] = hpadding
|
78
|
-
@title_area[:height] = @theme.font_sizes.main_title + vpadding
|
79
|
-
@title_area[:y] = canvas_height + vpadding
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def calculate_key_area
|
84
|
-
if @num_series > 1 && @show_series_key
|
85
|
-
@series_key_area[:width] = ( (canvas_width / 100) * 25 ).round
|
86
|
-
@series_key_area[:x] = (canvas_width - @series_key_area[:width] - hpadding)
|
87
|
-
@series_key_area[:y] = canvas_height + vpadding
|
88
|
-
@series_key_area[:height] = (canvas_height - vpadding)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def calculate_graph_area
|
93
|
-
@graph_area[:width] = (canvas_width - @series_key_area[:width] - (2*hpadding))
|
94
|
-
@graph_area[:x] = hpadding
|
95
|
-
|
96
|
-
if !@title_area.renderable?
|
97
|
-
@graph_area[:y] = canvas_height + vpadding
|
98
|
-
@graph_area[:height] = (canvas_height - vpadding)
|
99
|
-
else
|
100
|
-
@graph_area[:y] = (@title_area[:y] - @title_area[:height])
|
101
|
-
@graph_area[:height] = (canvas_height - vpadding - @title_area[:height])
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require_relative "calculations/layout_calculator"
|
@@ -1,139 +0,0 @@
|
|
1
|
-
module Prawn
|
2
|
-
module Graph
|
3
|
-
module ChartComponents
|
4
|
-
# A Prawn::Graph::Canvas represents the area on which a graph will be drawn. Think of it
|
5
|
-
# as the container in which your chart / graph will be sized to fit within.
|
6
|
-
#
|
7
|
-
class Canvas
|
8
|
-
attr_reader :layout, :series, :prawn, :theme, :options
|
9
|
-
|
10
|
-
# @param series [Array[Prawn::Graph::Series]]
|
11
|
-
# @param prawn [Prawn::Document]
|
12
|
-
# @param options [Hash]
|
13
|
-
# @return [Prawn::Graph::Canvas] a canvas ready to be drawn on the provided +prawn+ document.
|
14
|
-
#
|
15
|
-
def initialize(series, prawn, options = {}, &block)
|
16
|
-
@series = series
|
17
|
-
verify_series_are_ok!
|
18
|
-
@options = {xaxis_labels: []}.merge(options.merge({ series_count: series.size }))
|
19
|
-
@prawn = prawn
|
20
|
-
@theme = Prawn::Graph::Theme::Default
|
21
|
-
@layout = Prawn::Graph::Calculations::LayoutCalculator.new([prawn.bounds.width, prawn.bounds.height], @options, @theme).calculate
|
22
|
-
|
23
|
-
yield self if block_given?
|
24
|
-
end
|
25
|
-
|
26
|
-
# Fires off the actual drawing of the chart on the provided canvas.
|
27
|
-
# @return [nil]
|
28
|
-
#
|
29
|
-
def draw
|
30
|
-
prawn.bounding_box(position, :width => layout.canvas_width, :height => layout.canvas_height, padding: 0) do
|
31
|
-
prawn.save_graphics_state do
|
32
|
-
apply_theme!
|
33
|
-
render_title_area!
|
34
|
-
render_series_keys!
|
35
|
-
render_graph_area!
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# The coordinates which the canvas will be drawn at
|
41
|
-
# @return [Array] [X-Coord, Y-Coord]
|
42
|
-
#
|
43
|
-
def position
|
44
|
-
@options[:at] || [0,0]
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def apply_theme!
|
50
|
-
prawn.fill_color @theme.default
|
51
|
-
prawn.stroke_color @theme.default
|
52
|
-
prawn.font_size @theme.font_sizes.default
|
53
|
-
end
|
54
|
-
|
55
|
-
def plot_series!
|
56
|
-
bar_charts = series.collect{ |s| s if s.type == :bar }.compact
|
57
|
-
others = series - bar_charts
|
58
|
-
|
59
|
-
BarChartRenderer.render(bar_charts, self, theme.series[0..(bar_charts.size - 1)]) unless bar_charts.empty?
|
60
|
-
|
61
|
-
i = bar_charts.size
|
62
|
-
others.each do |series|
|
63
|
-
SeriesRenderer.render(series, self, theme.series[i])
|
64
|
-
i+=1
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def render_graph_area!
|
69
|
-
if layout.graph_area.renderable?
|
70
|
-
prawn.bounding_box layout.graph_area.point, width: layout.graph_area.width, height: layout.graph_area.height do
|
71
|
-
plot_series!
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def render_title_area!
|
77
|
-
if layout.title_area.renderable?
|
78
|
-
prawn.text_box "<color rgb=\"#{@theme.title}\">#{@options[:title]}</color>", at: layout.title_area.point, inline_format: true,
|
79
|
-
valign: :center, align: :center, size: @theme.font_sizes.main_title, width: layout.title_area.width, height: layout.title_area.height
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def render_series_keys!
|
84
|
-
if layout.series_key_area.renderable?
|
85
|
-
prawn.bounding_box layout.series_key_area.point, width: layout.series_key_area.width, height: layout.series_key_area.height do
|
86
|
-
series.each_with_index do |series, i|
|
87
|
-
series_offset = i + 1
|
88
|
-
|
89
|
-
prawn.save_graphics_state do
|
90
|
-
prawn.stroke_color = theme.axes
|
91
|
-
prawn.line_width = 0.5
|
92
|
-
prawn.fill_color = theme.series[i]
|
93
|
-
|
94
|
-
|
95
|
-
series_offset = series_offset * theme.font_sizes.series_key
|
96
|
-
|
97
|
-
title = series.title || "Series #{series_offset}"
|
98
|
-
top_position = (prawn.bounds.top - (series_offset * 3))
|
99
|
-
|
100
|
-
|
101
|
-
prawn.fill_and_stroke_rectangle([ theme.font_sizes.series_key, top_position ], theme.font_sizes.series_key, theme.font_sizes.series_key)
|
102
|
-
|
103
|
-
prawn.fill_color = theme.axes
|
104
|
-
prawn.text_box title, at: [ (theme.font_sizes.series_key * 3), top_position ], size: theme.font_sizes.series_key, height: (series_offset * 2)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Verifies that we provide an array-like object of Prawn::Graph::Series instances to
|
112
|
-
# the Canvas, for later rendering.
|
113
|
-
#
|
114
|
-
def verify_series_are_ok!
|
115
|
-
if @series.respond_to?(:each) && @series.respond_to?(:collect)
|
116
|
-
classes = @series.collect{ |c| c.is_a?(Prawn::Graph::Series) }.uniq
|
117
|
-
if classes.size > 1 || classes[0] != true
|
118
|
-
raise RuntimeError.new("All of the items provided must be instances of Prawn::Graph::Series")
|
119
|
-
end
|
120
|
-
else
|
121
|
-
raise RuntimeError.new("Series provided must be an Array (or Array-like) object.")
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# From prawn-svg - creates a cipped retangle, which we will then use to draw the graphs
|
126
|
-
# upon.
|
127
|
-
#
|
128
|
-
def clip_graph_to_bounds(x, y, width, height)
|
129
|
-
prawn.move_to x, y
|
130
|
-
prawn.line_to x + width, y
|
131
|
-
prawn.line_to x + width, y + height
|
132
|
-
prawn.line_to x, y + height
|
133
|
-
prawn.close_path
|
134
|
-
prawn.add_content "W n"
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
@@ -1,339 +0,0 @@
|
|
1
|
-
module Prawn
|
2
|
-
module Graph
|
3
|
-
module ChartComponents
|
4
|
-
|
5
|
-
# The Prawn::Graph::ChartComponents::SeriesRenderer is used to plot indivdual Prawn::Graph::Series on
|
6
|
-
# a Prawn::Graph::ChartComponents::Canvas and its associated Prawn::Document.
|
7
|
-
#
|
8
|
-
module SeriesRenderer
|
9
|
-
class << self
|
10
|
-
# @param series [Prawn::Graph::Series]
|
11
|
-
# @param canvas [Prawn::Graph::ChartComponents::Canvas]
|
12
|
-
#
|
13
|
-
def render(series, canvas, color = '000000')
|
14
|
-
raise ArgumentError.new("series must be a Prawn::Graph::Series") unless series.is_a?(Prawn::Graph::Series)
|
15
|
-
raise ArgumentError.new("canvas must be a Prawn::Graph::ChartComponents::Canvas") unless canvas.is_a?(Prawn::Graph::ChartComponents::Canvas)
|
16
|
-
|
17
|
-
@series = series
|
18
|
-
@canvas = canvas
|
19
|
-
@prawn = canvas.prawn
|
20
|
-
@color = color
|
21
|
-
|
22
|
-
@graph_area = @canvas.layout.graph_area
|
23
|
-
|
24
|
-
@plot_area_width = @graph_area.width - 25
|
25
|
-
@plot_area_height = @graph_area.height - 20
|
26
|
-
|
27
|
-
render_line_chart
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def render_line_chart
|
33
|
-
prawn.bounding_box [@graph_area.point[0] + 5, @graph_area.point[1] - 20], width: @plot_area_width, height: @plot_area_height do
|
34
|
-
j = 2
|
35
|
-
prawn.save_graphics_state do
|
36
|
-
max_marked = false
|
37
|
-
min_marked = false
|
38
|
-
|
39
|
-
@series.values.each_with_index do |v, i|
|
40
|
-
next if i == 0
|
41
|
-
|
42
|
-
width_per_point = (@plot_area_width / @series.size).round(2).to_f
|
43
|
-
spacing = width_per_point
|
44
|
-
|
45
|
-
prawn.line_width = 2
|
46
|
-
prawn.fill_color = @color
|
47
|
-
prawn.stroke_color = @color
|
48
|
-
|
49
|
-
|
50
|
-
previous_value = @series.values[i - 1]
|
51
|
-
this_value = v
|
52
|
-
|
53
|
-
previous_y = (point_height_percentage(previous_value) * @plot_area_height) - 5
|
54
|
-
this_y = (point_height_percentage(this_value) * @plot_area_height) - 5
|
55
|
-
|
56
|
-
previous_x_offset = ((spacing * (j - 1)) - spacing) + (spacing / 2.0)
|
57
|
-
this_x_offset = ((spacing * j) - spacing) + (spacing / 2.0)
|
58
|
-
|
59
|
-
|
60
|
-
prawn.stroke_line([previous_x_offset, previous_y], [ this_x_offset, this_y ]) unless previous_value.zero? || this_value.zero?
|
61
|
-
|
62
|
-
prawn.fill_color = @canvas.theme.markers
|
63
|
-
prawn.fill_ellipse([ ( previous_x_offset), previous_y ], 1) unless previous_value.zero? || this_value.zero?
|
64
|
-
prawn.fill_ellipse([ ( this_x_offset), this_y ], 1) unless previous_value.zero? || this_value.zero?
|
65
|
-
|
66
|
-
if @series.mark_minimum? && min_marked == false && previous_value != 0 && previous_value == @series.min
|
67
|
-
prawn.save_graphics_state do
|
68
|
-
prawn.fill_color = @canvas.theme.min
|
69
|
-
prawn.stroke_color = @canvas.theme.min
|
70
|
-
prawn.line_width = 1
|
71
|
-
|
72
|
-
prawn.dash(2)
|
73
|
-
prawn.stroke_line([previous_x_offset, 0], [previous_x_offset, previous_y])
|
74
|
-
prawn.undash
|
75
|
-
|
76
|
-
prawn.fill_ellipse([ ( previous_x_offset), previous_y ], 2)
|
77
|
-
min_marked = true
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
if @series.mark_maximum? && max_marked == false && previous_value != 0 && previous_value == @series.max
|
82
|
-
prawn.save_graphics_state do
|
83
|
-
prawn.fill_color = @canvas.theme.max
|
84
|
-
prawn.stroke_color = @canvas.theme.max
|
85
|
-
prawn.line_width = 1
|
86
|
-
|
87
|
-
prawn.dash(2)
|
88
|
-
prawn.stroke_line([previous_x_offset, 0], [previous_x_offset, previous_y])
|
89
|
-
prawn.undash
|
90
|
-
|
91
|
-
prawn.fill_ellipse([ ( previous_x_offset), previous_y ], 2)
|
92
|
-
max_marked = true
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
if @series.mark_minimum? && min_marked == false && this_value != 0 && this_value == @series.min
|
98
|
-
prawn.save_graphics_state do
|
99
|
-
prawn.fill_color = @canvas.theme.min
|
100
|
-
prawn.stroke_color = @canvas.theme.min
|
101
|
-
prawn.line_width = 1
|
102
|
-
|
103
|
-
prawn.dash(2)
|
104
|
-
prawn.stroke_line([this_x_offset, 0], [this_x_offset, this_y])
|
105
|
-
prawn.undash
|
106
|
-
|
107
|
-
prawn.fill_ellipse([ ( this_x_offset), this_y ], 2)
|
108
|
-
min_marked = true
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
if @series.mark_maximum? && max_marked == false && this_value != 0 && this_value == @series.max
|
113
|
-
prawn.save_graphics_state do
|
114
|
-
prawn.fill_color = @canvas.theme.max
|
115
|
-
prawn.stroke_color = @canvas.theme.max
|
116
|
-
prawn.line_width = 1
|
117
|
-
|
118
|
-
prawn.dash(2)
|
119
|
-
prawn.stroke_line([this_x_offset, 0], [this_x_offset, this_y])
|
120
|
-
prawn.undash
|
121
|
-
|
122
|
-
prawn.fill_ellipse([ ( this_x_offset), this_y ], 2)
|
123
|
-
max_marked = true
|
124
|
-
end
|
125
|
-
end
|
126
|
-
j += 1
|
127
|
-
end
|
128
|
-
|
129
|
-
if @series.mark_average?
|
130
|
-
average_y_coordinate = (point_height_percentage(@series.avg) * @plot_area_height) - 5
|
131
|
-
prawn.line_width = 1
|
132
|
-
prawn.stroke_color = @color
|
133
|
-
prawn.dash(2)
|
134
|
-
prawn.stroke_line([0, average_y_coordinate], [ @plot_area_width, average_y_coordinate ])
|
135
|
-
prawn.undash
|
136
|
-
end
|
137
|
-
end
|
138
|
-
render_axes
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def render_axes
|
143
|
-
prawn.stroke_color = @canvas.theme.axes
|
144
|
-
prawn.fill_color = @canvas.theme.axes
|
145
|
-
prawn.stroke_horizontal_line(0, @plot_area_width, at: 0)
|
146
|
-
prawn.stroke_vertical_line(0, @plot_area_height, at: 0)
|
147
|
-
prawn.fill_and_stroke_ellipse [ 0,0], 1
|
148
|
-
|
149
|
-
max = @series.max || 0
|
150
|
-
min = @series.min || 0
|
151
|
-
avg = @series.avg || 0
|
152
|
-
mid = (min + max) / 2 rescue 0
|
153
|
-
|
154
|
-
max_y = (point_height_percentage(max) * @plot_area_height)
|
155
|
-
min_y = (point_height_percentage(min) * @plot_area_height)
|
156
|
-
mid_y = (point_height_percentage(mid) * @plot_area_height)
|
157
|
-
avg_y = (point_height_percentage(avg) * @plot_area_height)
|
158
|
-
|
159
|
-
prawn.text_box "#{max}", at: [-14, max_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless max.zero?
|
160
|
-
prawn.text_box "#{mid}", at: [-14, mid_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless mid.zero?
|
161
|
-
prawn.text_box "#{avg}", at: [-14, avg_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless avg.zero?
|
162
|
-
prawn.text_box "#{min}", at: [-14, min_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless min.zero?
|
163
|
-
|
164
|
-
return if @canvas.options[:xaxis_labels].size.zero?
|
165
|
-
|
166
|
-
width_of_each_label = (@plot_area_width / @canvas.options[:xaxis_labels].size) - 1
|
167
|
-
@canvas.options[:xaxis_labels].each_with_index do |label, i|
|
168
|
-
offset = i + 1
|
169
|
-
position = ((offset * width_of_each_label) - width_of_each_label) + 1
|
170
|
-
|
171
|
-
prawn.text_box label, at: [ position, -2 ], width: width_of_each_label, height: 6, valign: :center, align: :right,
|
172
|
-
overflow: :shrink_to_fit
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
# Calculates the relative height of a given point based on the maximum value present in
|
177
|
-
# the series.
|
178
|
-
#
|
179
|
-
def point_height_percentage(value)
|
180
|
-
((BigDecimal(value, 10)/BigDecimal(@canvas.series.collect(&:max).max, 10)) * BigDecimal(1)).round(2) rescue 0
|
181
|
-
end
|
182
|
-
|
183
|
-
def prawn
|
184
|
-
@prawn
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
# The Prawn::Graph::ChartComponents::BarChartRenderer is used to plot one or more bar charts
|
192
|
-
# in a sensible way on a a Prawn::Graph::ChartComponents::Canvas and its associated
|
193
|
-
# Prawn::Document.
|
194
|
-
#
|
195
|
-
module BarChartRenderer
|
196
|
-
class << self
|
197
|
-
# @param series [Prawn::Graph::Series]
|
198
|
-
# @param canvas [Prawn::Graph::ChartComponents::Canvas]
|
199
|
-
#
|
200
|
-
def render(series, canvas, colors)
|
201
|
-
@series = series
|
202
|
-
@canvas = canvas
|
203
|
-
@prawn = canvas.prawn
|
204
|
-
@colors = colors
|
205
|
-
|
206
|
-
|
207
|
-
@graph_area = @canvas.layout.graph_area
|
208
|
-
|
209
|
-
@plot_area_width = @graph_area.width - 25
|
210
|
-
@plot_area_height = @graph_area.height - 20
|
211
|
-
|
212
|
-
render_bar_charts
|
213
|
-
end
|
214
|
-
|
215
|
-
private
|
216
|
-
|
217
|
-
def render_bar_charts
|
218
|
-
prawn.bounding_box [@graph_area.point[0] + 5, @graph_area.point[1] - 20], width: @plot_area_width, height: @plot_area_height do
|
219
|
-
|
220
|
-
prawn.save_graphics_state do
|
221
|
-
num_points = @series[0].size
|
222
|
-
width_per_point = (@plot_area_width / num_points)
|
223
|
-
width = (((width_per_point * 0.9) / @series.size).round(2)).to_f
|
224
|
-
min_marked = false
|
225
|
-
max_marked = false
|
226
|
-
|
227
|
-
num_points.times do |point|
|
228
|
-
|
229
|
-
@series.size.times do |series_index|
|
230
|
-
series_offset = series_index + 1
|
231
|
-
prawn.fill_color = @colors[series_index]
|
232
|
-
prawn.stroke_color = @colors[series_index]
|
233
|
-
prawn.line_width = width
|
234
|
-
|
235
|
-
starting = (prawn.bounds.left + (point * width_per_point))
|
236
|
-
|
237
|
-
x_position = ( (starting + (series_offset * width) ).to_f - (width / 2.0))
|
238
|
-
y_position = ((point_height_percentage(@series[series_index].values[point]) * @plot_area_height) - 5).to_f
|
239
|
-
|
240
|
-
prawn.fill_and_stroke_line([ x_position ,0], [x_position ,y_position]) unless @series[series_index].values[point].zero?
|
241
|
-
|
242
|
-
if @series[series_index].mark_average?
|
243
|
-
average_y_coordinate = (point_height_percentage(@series[series_index].avg) * @plot_area_height) - 5
|
244
|
-
prawn.line_width = 1
|
245
|
-
prawn.stroke_color = @colors[series_index]
|
246
|
-
prawn.dash(2)
|
247
|
-
prawn.stroke_line([0, average_y_coordinate], [ @plot_area_width, average_y_coordinate ])
|
248
|
-
prawn.undash
|
249
|
-
end
|
250
|
-
|
251
|
-
if @series[series_index].mark_minimum? && min_marked == false && !@series[series_index].values[point].zero? && @series[series_index].values[point] == @series[series_index].min
|
252
|
-
prawn.save_graphics_state do
|
253
|
-
prawn.fill_color = @canvas.theme.min
|
254
|
-
prawn.stroke_color = @canvas.theme.min
|
255
|
-
prawn.line_width = 1
|
256
|
-
|
257
|
-
prawn.dash(2)
|
258
|
-
prawn.stroke_line([x_position, 0], [x_position, y_position])
|
259
|
-
prawn.undash
|
260
|
-
|
261
|
-
prawn.fill_ellipse([x_position, y_position ], 2)
|
262
|
-
min_marked = true
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
if @series[series_index].mark_maximum? && max_marked == false && @series[series_index].values[point] == @series[series_index].max
|
267
|
-
prawn.save_graphics_state do
|
268
|
-
prawn.fill_color = @canvas.theme.max
|
269
|
-
prawn.stroke_color = @canvas.theme.max
|
270
|
-
prawn.line_width = 1
|
271
|
-
|
272
|
-
prawn.dash(2)
|
273
|
-
prawn.stroke_line([x_position, 0], [x_position, y_position])
|
274
|
-
prawn.undash
|
275
|
-
|
276
|
-
prawn.fill_ellipse([x_position, y_position ], 2)
|
277
|
-
max_marked = true
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
end
|
283
|
-
|
284
|
-
end
|
285
|
-
render_axes
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
def render_axes
|
290
|
-
prawn.stroke_color = @canvas.theme.axes
|
291
|
-
prawn.fill_color = @canvas.theme.axes
|
292
|
-
prawn.stroke_horizontal_line(0, @plot_area_width, at: 0)
|
293
|
-
prawn.stroke_vertical_line(0, @plot_area_height, at: 0)
|
294
|
-
prawn.fill_and_stroke_ellipse [ 0,0], 1
|
295
|
-
|
296
|
-
max = @series.collect(&:max).max || 0
|
297
|
-
min = @series.collect(&:min).min || 0
|
298
|
-
avg = ((BigDecimal(@series.collect(&:avg).inject(:+), 10) / @series.collect(&:avg).size).round(2)).to_f || 0
|
299
|
-
mid = (min + max) / 2 || 0
|
300
|
-
|
301
|
-
max_y = (point_height_percentage(max) * @plot_area_height)
|
302
|
-
min_y = (point_height_percentage(min) * @plot_area_height)
|
303
|
-
mid_y = (point_height_percentage(mid) * @plot_area_height)
|
304
|
-
avg_y = (point_height_percentage(avg) * @plot_area_height)
|
305
|
-
|
306
|
-
prawn.text_box "#{max}", at: [-14, max_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless max.zero?
|
307
|
-
prawn.text_box "#{mid}", at: [-14, mid_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless mid.zero?
|
308
|
-
prawn.text_box "#{avg}", at: [-14, avg_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless avg.zero?
|
309
|
-
prawn.text_box "#{min}", at: [-14, min_y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right unless min.zero?
|
310
|
-
|
311
|
-
return if @canvas.options[:xaxis_labels].size.zero?
|
312
|
-
|
313
|
-
width_of_each_label = (@plot_area_width / @canvas.options[:xaxis_labels].size) - 1
|
314
|
-
@canvas.options[:xaxis_labels].each_with_index do |label, i|
|
315
|
-
offset = i + 1
|
316
|
-
position = ((offset * width_of_each_label) - width_of_each_label) + 1
|
317
|
-
|
318
|
-
prawn.text_box label, at: [ position, -2 ], width: width_of_each_label, height: 6, valign: :center, align: :right,
|
319
|
-
overflow: :shrink_to_fit
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
# Calculates the relative height of a given point based on the maximum value present in
|
324
|
-
# the series.
|
325
|
-
#
|
326
|
-
def point_height_percentage(value)
|
327
|
-
pc = ((BigDecimal(value, 10)/BigDecimal(@series.collect(&:max).max, 10)) * BigDecimal(1)).round(2)
|
328
|
-
pc = 0 if pc.nan?
|
329
|
-
pc
|
330
|
-
end
|
331
|
-
|
332
|
-
def prawn
|
333
|
-
@prawn
|
334
|
-
end
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
data/test.pdf
DELETED
Binary file
|