minichart 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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