minichart 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0574d786b6188b0f2ed6977760ad85bbd2f2487a6d010de8e7be7f50127d51a3
4
- data.tar.gz: 5b138c614099b58ff7365a38246641a586417c0fdccb6e1e2677494603f01eb8
3
+ metadata.gz: 6109cfc57cb909c2ba0a9df4e184bc4319220399b774ff2098b728bf4a41f57e
4
+ data.tar.gz: 32cd8ff3c3260d08f81106c3ac74037e36990d4601eb8ff7e40c8840d44b3ca3
5
5
  SHA512:
6
- metadata.gz: 49471660072528ec03c129fb0b549b88f3a2a9f3f5286b969579402ddfb9233c7eb617f1fa64821273a43a88042a724432324bad8f7f0d0143d5825778f4d5fb
7
- data.tar.gz: 23d208d26569d432380615d0e5e479a92dfa61492841cbd9c9211dd8c94c036f5be467f5710de49a66b58cffa92a2c3066f9a4a2bf6933fea72ba69c59b9e811
6
+ metadata.gz: 63e01d19bd4539ccf1283a98bee8f941a7e270ee0f1a2956aed20ecbab21661e7923420588c28f0aa90027cfc6fadc88f5f90b5776ff8dfa3523c9faf85c03ba
7
+ data.tar.gz: 1861ffff3d852e85fbf9b8c334d091f6dd40ce823086ae4215edb95c96f20a5f9e79e4da5caaf51b35956a8da92ca9de054ee35aae67c84884c02ad5f59af628
data/README.md CHANGED
@@ -1,16 +1,36 @@
1
- Minichart - SVG Chart Generator
2
- ==================================================
1
+ # Minichart - SVG Chart Generator
3
2
 
4
3
  ---
5
4
 
6
5
  Create SVG mini charts with Ruby
7
6
 
7
+ ![demo](examples/multiple.svg)
8
+
8
9
  ---
9
10
 
10
- Install
11
- --------------------------------------------------
11
+ * [Install](#install)
12
+ * [Usage](#usage)
13
+ * [Chart Types](#chart-types)
14
+ * [Line Chart](#line-chart)
15
+ * [Bar Chart](#bar-chart)
16
+ * [Area Chart](#area-chart)
17
+ * [Horizontal Bar Meter](#horizontal-bar-meter)
18
+ * [Vertical Bar Meter](#vertical-bar-meter)
19
+ * [Configuration](#configuration)
20
+ * [Class-level default options](#class-level-default-options)
21
+ * [Instance initialization options](#instance-initialization-options)
22
+ * [Instance-level options](#instance-level-options)
23
+ * [Options Reference](#options-reference)
24
+ * [Basic Options](#basic-options)
25
+ * [Meter Options](#meter-options)
26
+ * [Examples](#examples)
12
27
 
13
- ```
28
+
29
+ ---
30
+
31
+ ## Install
32
+
33
+ ```shell
14
34
  $ gem install minichart
15
35
  ```
16
36
 
@@ -20,20 +40,230 @@ Or with bundler:
20
40
  gem 'minichart'
21
41
  ```
22
42
 
23
- Example
24
- --------------------------------------------------
43
+ ## Usage
44
+
45
+ Require and optionally include the library:
25
46
 
26
47
  ```ruby
27
48
  require 'minichart'
28
49
  include Minichart
50
+ ```
51
+
52
+ Initialize a chart with data, and optional options:
53
+
54
+ ```ruby
55
+ data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9]
56
+ chart = AreaChart.new data, color: 'blue'
57
+ ```
58
+
59
+ Get the full SVG output by calling `#render`:
60
+
61
+ ```ruby
62
+ puts chart.render
63
+ #=> <?xml version="1.0" standalone="no"?>
64
+ # <svg> ... </svg>
65
+ ```
66
+
67
+ Save it to file, by calling `#save`:
68
+
69
+ ```ruby
70
+ chart.save "my-chart.svg"
71
+ ```
72
+
73
+ Get its inner SVG string by calling `#to_s`:
74
+
75
+ ```ruby
76
+ puts chart.to_s
77
+ #=> <polyline fill="blue" stroke="blue" stroke-width="2" points="..."/>
78
+ ```
79
+
80
+
81
+ The objects returned from all the mini chart classes are [Victor::SVG][2] objects, so they support all methods supported by it as well.
82
+
83
+ ## Chart Types
84
+
85
+ ### Line Chart
86
+
87
+ <img src='examples/line_chart.svg' align='right' width=300>
88
+
89
+ ```ruby
90
+ LineChart.new data, height: 50, background: '#eee',
91
+ aspect_ratio: 5, color: 'green'
92
+ ```
93
+
94
+ ### Bar Chart
95
+
96
+ <img src='examples/bar_chart.svg' align='right' width=300>
97
+
98
+ ```ruby
99
+ BarChart.new data, height: 50, background: '#eee',
100
+ aspect_ratio: 5, color: 'green'
101
+ ```
102
+
103
+ ### Area Chart
104
+
105
+ <img src='examples/area_chart.svg' align='right' width=300>
106
+
107
+ ```ruby
108
+ AreaChart.new data, height: 50, background: '#eee',
109
+ aspect_ratio: 5, color: 'green'
110
+ ```
111
+
112
+ ### Horizontal Bar Meter
113
+
114
+ <img src='examples/multiple_horizontal_bars.svg' align='right'>
115
+
116
+ ```ruby
117
+ positive = HorizontalBarMeter.new 70,
118
+ height: 20, width: 250, background: '#9f9', color: 'green'
119
+
120
+ negative = HorizontalBarMeter.new -80,
121
+ height: 20, width: 250, background: '#f99', color: 'red'
122
+
123
+ dual = HorizontalBarMeter.new 80,
124
+ height: 20, width: 250, background: '#99f', color: 'blue',
125
+ mode: :dual, zero_line: true
126
+ ```
127
+
128
+ Meter charts support [additional options](#meter-options).
129
+
130
+ ### Vertical Bar Meter
131
+
132
+ <img src='examples/multiple_vertical_bars.svg' align='right'>
133
+
134
+ ```ruby
135
+ positive = VerticalBarMeter.new 70,
136
+ width: 20, height: 250, background: '#9f9', color: 'green'
137
+
138
+ negative = VerticalBarMeter.new -80,
139
+ width: 20, height: 250, background: '#f99', color: 'red'
140
+
141
+ dual = VerticalBarMeter.new 80,
142
+ width: 20, height: 250, background: '#99f', color: 'blue',
143
+ mode: :dual, zero_line: true
144
+ ```
29
145
 
30
- plot = LineChart.new
31
- plot.aspect_ratio = 2
32
- plot.data = [10, 30, 20, 40, 30]
33
- plot.save 'line'
146
+ Meter charts support [additional options](#meter-options).
147
+
148
+
149
+ ## Configuration
150
+
151
+ Chart options can be set in one of three ways.
152
+
153
+ ### Class-level default options
154
+
155
+ See or set default options for any chart class by calling its `::options` method:
156
+
157
+ ```ruby
158
+ # See all options
159
+ p AreaChart.options
160
+ #=> {:background=>"white", :height=>100, :width=>300, :stroke=>2, :style=>{}, :color=>"#66f"}
161
+
162
+ # Set a single default option
163
+ AreaChart.options[:color] = '#333'
164
+
165
+ # Set multiple options at once
166
+ AreaChart.options background: 'black', color: 'green'
34
167
  ```
35
168
 
169
+ ### Instance initialization options
170
+
171
+ Set options by providing a hash as the second argument on initialization:
172
+
173
+ ```ruby
174
+ chart = AreaChart.new data, height: 120, width: 500
175
+ ```
176
+
177
+ ### Instance-level options
178
+
179
+ After initialization, you can still update individual options:
180
+
181
+ ```ruby
182
+ chart = AreaChart.new data
183
+ chart.options[:background] = 'yellow'
184
+ ```
185
+
186
+ ## Options Reference
187
+
188
+ ### Basic Options
189
+
190
+ #### background
191
+
192
+ Chart background color.
193
+
194
+ #### color
195
+
196
+ Chart color.
197
+
198
+ #### height
199
+
200
+ Chart height in pixels.
201
+
202
+ #### width
203
+
204
+ Chart width in pixels.
205
+
206
+ #### stroke
207
+
208
+ Line stroke width. This has a different effect in different chart types.
209
+
210
+ #### style
211
+
212
+ CSS Style hash to apply to the entire SVG.
213
+
214
+
215
+ ### Meter Options
216
+
217
+ Meter charts support these options in additon to the basic options:
218
+
219
+ #### mode
220
+
221
+ Display mode. Can be `:positive`, `:negative`, `:dual` or `:auto` (default).
222
+
223
+ The `:auto` mode will switch between `:positive` and `:negative` based on the
224
+ value.
225
+
226
+ #### max
227
+
228
+ The absolute maximum value. This number should be positive even for negative
229
+ charts.
230
+
231
+ #### notches
232
+
233
+ An array of one or more levels to place a notch marker. Use positive values
234
+ only.
235
+
236
+ #### notch_thickness
237
+
238
+ Thickness of the notch markers.
239
+
240
+ #### notch_color
241
+
242
+ Color of the notch markers.
243
+
244
+ #### clipping_indicator
245
+
246
+ If true, show a marker when the value exceeds the range.
247
+
248
+ #### clipping_indicator_thickness
249
+
250
+ Thickness of the clipping indicator.
251
+
252
+ #### clipping_indicator_color
253
+
254
+ Color of the clipping indicator.
255
+
256
+ ## Examples
257
+
36
258
  See more examples (code and SVG output) in the [examples folder][1].
37
259
 
260
+ ## Contributing / Support
261
+
262
+ If you experience any issue, have a question or a suggestion, or if you wish
263
+ to contribute, feel free to [open an issue][issues].
264
+
265
+ ---
38
266
 
39
267
  [1]: https://github.com/DannyBen/minichart/tree/master/examples#examples
268
+ [2]: https://github.com/DannyBen/victor
269
+ [issues]: https://github.com/DannyBen/minichart/issues
@@ -1,4 +1,12 @@
1
1
  require 'victor'
2
- require 'minichart/chart'
3
- require 'minichart/line_chart'
4
- require 'minichart/bar_chart'
2
+ require 'minichart/id_generator'
3
+ require 'minichart/base'
4
+ require 'minichart/charts/chart'
5
+ require 'minichart/charts/line_chart'
6
+ require 'minichart/charts/bar_chart'
7
+ require 'minichart/charts/area_chart'
8
+ require 'minichart/meters/meter'
9
+ require 'minichart/meters/vertical_bar_meter'
10
+ require 'minichart/meters/horizontal_bar_meter'
11
+
12
+ require 'byebug' if ENV['BYEBUG']
@@ -0,0 +1,63 @@
1
+ module Minichart
2
+ # Base class for all Minichart classes
3
+ class Base < Victor::SVGBase
4
+ attr_reader :data, :options
5
+
6
+ class << self
7
+ def master_defaults
8
+ {
9
+ background: 'white',
10
+ height: 100,
11
+ width: 300,
12
+ stroke: 2,
13
+ style: {},
14
+ color: '#66f'
15
+ }
16
+ end
17
+
18
+ # For subclasses to define
19
+ def defaults
20
+ {}
21
+ end
22
+
23
+ def options(update_hash = nil)
24
+ @options ||= master_defaults.merge defaults
25
+ @options.merge! update_hash if update_hash
26
+ @options
27
+ end
28
+ end
29
+
30
+ def initialize(data, user_options = {})
31
+ @data = data
32
+ @options = self.class.options.merge user_options
33
+
34
+ super viewBox: viewbox, style: options[:style]
35
+ element :rect, x: 0, y: 0,
36
+ width: options[:width], height: options[:height],
37
+ fill: options[:background], stroke_width: 0
38
+
39
+ clip_path_id = IDGenerator.next
40
+ setup_clip_path clip_path_id
41
+
42
+ element :g, clip_path: "url(##{clip_path_id})" do
43
+ build
44
+ end
45
+ end
46
+
47
+ def setup_clip_path(id)
48
+ element :defs do
49
+ element :clipPath, id: id do
50
+ element :rect, width: options[:width], height: options[:height]
51
+ end
52
+ end
53
+ end
54
+
55
+ def viewbox
56
+ "0 0 #{options[:width]} #{options[:height]}"
57
+ end
58
+
59
+ def build
60
+ raise NotImplementedError, "#build is not implemented"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,27 @@
1
+ module Minichart
2
+ class AreaChart < Chart
3
+ def build
4
+ element :polyline, fill: options[:color],
5
+ stroke: options[:color],
6
+ stroke_width: options[:stroke],
7
+ stroke_linejoin: :round,
8
+ points: points
9
+ end
10
+
11
+ protected
12
+
13
+ def points
14
+ result = ["0,#{options[:height]}"]
15
+
16
+ inverted_points.each do |point|
17
+ x = options[:width] *point[0]
18
+ y = options[:height] * point[1]
19
+ result << "#{x},#{y}"
20
+ end
21
+
22
+ result << "#{options[:width]},#{options[:height]}"
23
+
24
+ result
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ module Minichart
2
+ class BarChart < Chart
3
+ def build
4
+ opts = { x_point_count: data.size }
5
+
6
+ inverted_points(opts).each do |x, y|
7
+ element :rect, bar_options(x, y)
8
+ end
9
+ end
10
+
11
+ protected
12
+
13
+ def bar_width
14
+ @bar_width ||= options[:width] / data.size
15
+ end
16
+
17
+ def bar_options(x, y)
18
+ y = y * options[:height]
19
+ bar_height = options[:height] - y
20
+ {
21
+ x: x * options[:width],
22
+ y: y,
23
+ width: bar_width,
24
+ height: bar_height,
25
+ style: {
26
+ fill: options[:color],
27
+ stroke_width: options[:stroke],
28
+ stroke: options[:background]
29
+ }
30
+ }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ module Minichart
2
+ # Base class for charts with data series
3
+ class Chart < Base
4
+
5
+ protected
6
+
7
+ def inverted_points(opts={})
8
+ normalized_points(opts).map { |point| [point[0], 1-point[1]] }
9
+ end
10
+
11
+ def normalized_points(opts={})
12
+ x_point_count = opts[:x_point_count] || data.count-1
13
+
14
+ range = (data.max - data.min).to_f
15
+ x_width = 1 / (x_point_count).to_f
16
+ result = []
17
+
18
+ data.each_with_index do |y, index|
19
+ x = index*x_width
20
+ y = (y - data.min) / range
21
+ result << [x,y]
22
+ end
23
+
24
+ result
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ module Minichart
2
+ class LineChart < Chart
3
+ def build
4
+ element :polyline, fill: :none,
5
+ stroke: options[:color],
6
+ stroke_width: options[:stroke],
7
+ stroke_linejoin: :round,
8
+ points: points
9
+ end
10
+
11
+ protected
12
+
13
+ def points
14
+ result = []
15
+ inverted_points.each do |point|
16
+ x = options[:width] * point[0]
17
+ y = options[:height] * point[1]
18
+ result << "#{x},#{y}"
19
+ end
20
+ result
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module Minichart
2
+ module IDGenerator
3
+ class << self
4
+ def next
5
+ @id ||= 0
6
+ "minichart-#{@id += 1}"
7
+ end
8
+
9
+ def reset
10
+ @id = 0
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,80 @@
1
+ module Minichart
2
+ class HorizontalBarMeter < Meter
3
+ class << self
4
+ def defaults
5
+ meter_defaults.merge width: 300, height: 50
6
+ end
7
+ end
8
+
9
+ def build
10
+ draw_bar
11
+ draw_notches if options[:notches]
12
+ draw_clipping_indicator if options[:clipping_indicator] and clipping?
13
+ end
14
+
15
+ protected
16
+
17
+ def draw_bar
18
+ x1 = x_for 0
19
+ x2 = x_for clamped_value
20
+ x = [x1, x2].min
21
+
22
+ element :rect, x: x, y: 0, height: options[:height],
23
+ width: bar_width, style: style
24
+ end
25
+
26
+ def draw_notches
27
+ options[:notches].each do |notch|
28
+ draw_notch notch
29
+ draw_notch -notch if mode == :dual and notch != 0
30
+ end
31
+ end
32
+
33
+ def draw_notch(notch)
34
+ draw_vertical_line notch, stroke: options[:notch_thickness],
35
+ color: options[:notch_color]
36
+ end
37
+
38
+ def draw_clipping_indicator
39
+ draw_vertical_line clamped_value,
40
+ stroke: options[:clipping_indicator_thickness],
41
+ color: options[:clipping_indicator_color]
42
+ end
43
+
44
+ def draw_vertical_line(target_value, color:, stroke:)
45
+ x = x_for target_value
46
+
47
+ element :line, x1: x, x2: x, y1: 0, y2: options[:height],
48
+ stroke: color, stroke_width: stroke
49
+ end
50
+
51
+ def width_factor
52
+ options[:width] / options[:max].to_f
53
+ end
54
+
55
+ def half_width
56
+ options[:width] * 0.5
57
+ end
58
+
59
+ def bar_width
60
+ if mode == :dual
61
+ clamped_value.abs * width_factor * 0.5
62
+ else
63
+ clamped_value.abs * width_factor
64
+ end
65
+ end
66
+
67
+ def x_for(target_value)
68
+ result = target_value.abs / options[:max].to_f * options[:width]
69
+
70
+ case mode
71
+ when :positive
72
+ result
73
+ when :negative
74
+ options[:width] - result
75
+ when :dual
76
+ target_value / options[:max].to_f * half_width + half_width
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,65 @@
1
+ module Minichart
2
+ # Base class for charts with a single value
3
+ class Meter < Base
4
+
5
+ class << self
6
+ def meter_defaults
7
+ @meter_defaults ||= {
8
+ height: 50,
9
+ max: 100,
10
+ notches: [],
11
+ notch_thickness: 10,
12
+ notch_color: 'black',
13
+ clipping_indicator: false,
14
+ clipping_indicator_thickness: 20,
15
+ clipping_indicator_color: 'yellow',
16
+ }
17
+ end
18
+ end
19
+
20
+
21
+ protected
22
+
23
+ def value
24
+ data
25
+ end
26
+
27
+ def clipping?
28
+ value > options[:max] || value < -options[:max]
29
+ end
30
+
31
+ def mode
32
+ @mode ||= mode!
33
+ end
34
+
35
+ def mode!
36
+ options[:mode] ||= :auto
37
+
38
+ if options[:mode] == :auto
39
+ value >= 0 ? :positive : :negative
40
+ else
41
+ options[:mode].to_sym
42
+ end
43
+ end
44
+
45
+ def clamped_value
46
+ case mode
47
+ when :positive
48
+ value.clamp 0, options[:max]
49
+ when :negative
50
+ value.clamp -options[:max], 0
51
+ when :dual
52
+ value.clamp -options[:max], options[:max]
53
+ end
54
+ end
55
+
56
+ def style
57
+ {
58
+ fill: options[:color],
59
+ stroke_width: options[:stroke],
60
+ stroke: options[:background]
61
+ }
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,80 @@
1
+ module Minichart
2
+ class VerticalBarMeter < Meter
3
+ class << self
4
+ def defaults
5
+ meter_defaults.merge width: 50, height: 300
6
+ end
7
+ end
8
+
9
+ def build
10
+ draw_bar
11
+ draw_notches if options[:notches]
12
+ draw_clipping_indicator if options[:clipping_indicator] and clipping?
13
+ end
14
+
15
+ protected
16
+
17
+ def draw_bar
18
+ y1 = y_for 0
19
+ y2 = y_for clamped_value
20
+ y = [y1, y2].min
21
+
22
+ element :rect, x: 0, y: y, height: bar_height,
23
+ width: options[:width], style: style
24
+ end
25
+
26
+ def draw_notches
27
+ options[:notches].each do |notch|
28
+ draw_notch notch
29
+ draw_notch -notch if mode == :dual and notch != 0
30
+ end
31
+ end
32
+
33
+ def draw_notch(notch)
34
+ draw_horizontal_line notch, stroke: options[:notch_thickness],
35
+ color: options[:notch_color]
36
+ end
37
+
38
+ def draw_clipping_indicator
39
+ draw_horizontal_line clamped_value,
40
+ stroke: options[:clipping_indicator_thickness],
41
+ color: options[:clipping_indicator_color]
42
+ end
43
+
44
+ def draw_horizontal_line(target_value, color:, stroke:)
45
+ y = y_for target_value
46
+
47
+ element :line, x1: 0, x2: options[:width], y1: y, y2: y,
48
+ stroke: color, stroke_width: stroke
49
+ end
50
+
51
+ def height_factor
52
+ options[:height] / options[:max].to_f
53
+ end
54
+
55
+ def half_height
56
+ options[:height] * 0.5
57
+ end
58
+
59
+ def bar_height
60
+ if mode == :dual
61
+ clamped_value.abs * height_factor * 0.5
62
+ else
63
+ clamped_value.abs * height_factor
64
+ end
65
+ end
66
+
67
+ def y_for(target_value)
68
+ result = target_value.abs / options[:max].to_f * options[:height]
69
+
70
+ case mode
71
+ when :positive
72
+ options[:height] - result
73
+ when :negative
74
+ result
75
+ when :dual
76
+ options[:height] - (target_value / options[:max].to_f * half_height + half_height)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module Minichart
2
- VERSION = "0.1.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minichart
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-22 00:00:00.000000000 Z
11
+ date: 2020-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: victor
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.1'
19
+ version: '0.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.1'
26
+ version: '0.3'
27
27
  description: Generate mini charts with SVG
28
28
  email: db@dannyben.com
29
29
  executables: []
@@ -32,9 +32,15 @@ extra_rdoc_files: []
32
32
  files:
33
33
  - README.md
34
34
  - lib/minichart.rb
35
- - lib/minichart/bar_chart.rb
36
- - lib/minichart/chart.rb
37
- - lib/minichart/line_chart.rb
35
+ - lib/minichart/base.rb
36
+ - lib/minichart/charts/area_chart.rb
37
+ - lib/minichart/charts/bar_chart.rb
38
+ - lib/minichart/charts/chart.rb
39
+ - lib/minichart/charts/line_chart.rb
40
+ - lib/minichart/id_generator.rb
41
+ - lib/minichart/meters/horizontal_bar_meter.rb
42
+ - lib/minichart/meters/meter.rb
43
+ - lib/minichart/meters/vertical_bar_meter.rb
38
44
  - lib/minichart/version.rb
39
45
  homepage: https://github.com/DannyBen/minichart
40
46
  licenses:
@@ -48,14 +54,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
48
54
  requirements:
49
55
  - - ">="
50
56
  - !ruby/object:Gem::Version
51
- version: 2.0.0
57
+ version: 2.5.0
52
58
  required_rubygems_version: !ruby/object:Gem::Requirement
53
59
  requirements:
54
60
  - - ">="
55
61
  - !ruby/object:Gem::Version
56
62
  version: '0'
57
63
  requirements: []
58
- rubygems_version: 3.0.3
64
+ rubygems_version: 3.1.2
59
65
  signing_key:
60
66
  specification_version: 4
61
67
  summary: SVG Mini Charts
@@ -1,29 +0,0 @@
1
- module Minichart
2
- class BarChart < Chart
3
- def build
4
- opts = { x_point_count: data.size }
5
-
6
- inverted_points(opts).each do |x, y|
7
- svg.rect bar_options x, y
8
- end
9
- end
10
-
11
- private
12
-
13
- def bar_width
14
- @bar_width ||= width / data.size
15
- end
16
-
17
- def bar_options(x, y)
18
- y = y*height
19
- bar_height = height-y
20
- {
21
- x: x*width,
22
- y: y,
23
- width: bar_width,
24
- height: bar_height,
25
- style: { fill: color, stroke_width: stroke, stroke: background }
26
- }
27
- end
28
- end
29
- end
@@ -1,67 +0,0 @@
1
- module Minichart
2
- class Chart
3
- attr_accessor :data, :aspect_ratio, :opts
4
-
5
- def initialize(opts={})
6
- @opts = opts
7
- end
8
-
9
- def save(name)
10
- svg.rect x: 0, y: 0, width: width, height: height, fill: background
11
- build
12
- svg.save name
13
- end
14
-
15
- def build
16
- raise NotImplementedError, "#build is not implemented"
17
- end
18
-
19
- def inverted_points(opts={})
20
- normalized_points(opts).map { |point| [point[0], 1-point[1]] }
21
- end
22
-
23
- def normalized_points(opts={})
24
- x_point_count = opts[:x_point_count] || data.count-1
25
-
26
- range = (data.max - data.min).to_f
27
- x_width = 1/(x_point_count).to_f
28
- result = []
29
-
30
- data.each_with_index do |y, index|
31
- x = index*x_width
32
- y = (y-data.min)/range
33
- result << [x,y]
34
- end
35
-
36
- result
37
- end
38
-
39
- def width
40
- @width ||= (aspect_ratio * height).round
41
- end
42
-
43
- def height
44
- 100
45
- end
46
-
47
- def svg
48
- @svg ||= Victor::SVG.new viewBox: "0 0 #{width} #{height}", style: style
49
- end
50
-
51
- def style
52
- @opts[:style] ||= {}
53
- end
54
-
55
- def background
56
- @opts[:background] ||= '#eee'
57
- end
58
-
59
- def color
60
- @opts[:color] || '#333'
61
- end
62
-
63
- def stroke
64
- @opts[:stroke] ||= 2
65
- end
66
- end
67
- end
@@ -1,19 +0,0 @@
1
- module Minichart
2
- class LineChart < Chart
3
- def build
4
- svg.polyline fill: :none, stroke: color, stroke_width: stroke, points: points
5
- end
6
-
7
- private
8
-
9
- def points
10
- result = []
11
- inverted_points.each do |point|
12
- x = width*point[0]
13
- y = height*point[1]
14
- result << "#{x},#{y}"
15
- end
16
- result
17
- end
18
- end
19
- end