minichart 0.2.0 → 0.2.1

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: 767c1bdbf55e5aedb689c5286535fb84d3c48cf2c1c054b01da97237dee3437a
4
- data.tar.gz: ea0b462ccfd166eea1df2e2a4ad08f32060c713a06f1aea36170079bc90a3671
3
+ metadata.gz: 144b47573abadc9f4bfe5e41dea006bb24705db37dc93767353ba62d389bdd1d
4
+ data.tar.gz: 7c4936f6947307fd106b1e0700fff88c9ad7f5721dfc50dfd23ca3051a79b7b5
5
5
  SHA512:
6
- metadata.gz: 57524a378c6ce4df0ad08d4edc134630d3ae6ebbb35e68638f11926ab61f4c3b3f6e8e0861d49213de54d619d52df2cb74c4813e2349409e9e444b0ddca2cb44
7
- data.tar.gz: 45820a40054e716bfe412d661ba814ea4fb8589b39145fbeff6a079841ea83990d2adbaf6733c328378627133eaaa5891f5e87d268f66abab69a412727cbc29a
6
+ metadata.gz: c66ae222164ccc21a98cd8eddd790f54d114897ed6374b7e36fd242d16364e49ccec532e580d3a180d094c48fd27853f7b01bd85c81e7b8a4af8254a595af191
7
+ data.tar.gz: 6d19ce05f98de008d26127b8046512b66e1c68af0972e3b66f15ce3a6bfe4ac8a99a6de76457757e34903e3012b757ba31eeba688a018393304ca8cff41a1e74
data/README.md CHANGED
@@ -33,15 +33,13 @@ Initialize a chart with data, and optional options:
33
33
 
34
34
  ```ruby
35
35
  data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9]
36
- line = LineChart.new data, color: 'blue'
37
- bars = BarChart.new data, color: 'blue'
38
- area = AreaChart.new data, color: 'blue'
36
+ chart = AreaChart.new data, color: 'blue'
39
37
  ```
40
38
 
41
39
  Get the full SVG output by calling `#render`:
42
40
 
43
41
  ```ruby
44
- puts area.render
42
+ puts chart.render
45
43
  #=> <?xml version="1.0" standalone="no"?>
46
44
  # <svg> ... </svg>
47
45
  ```
@@ -49,42 +47,105 @@ puts area.render
49
47
  Save it to file, by calling `#save`:
50
48
 
51
49
  ```ruby
52
- area.save "my-chart.svg"
50
+ chart.save "my-chart.svg"
53
51
  ```
54
52
 
55
53
  Get its inner SVG string by calling `#to_s`:
56
54
 
57
55
  ```ruby
58
- puts area.to_s
56
+ puts chart.to_s
59
57
  #=> <polyline fill="blue" stroke="blue" stroke-width="2" points="..."/>
60
58
  ```
61
59
 
62
60
 
63
61
  The objects returned from all the mini chart classes are [Victor::SVG][2] objects, so they support all methods supported by it as well.
64
62
 
63
+ ## Chart Types
64
+
65
+ ### Line Chart
66
+
67
+ <img src='examples/line_chart.svg' align='right'>
68
+
69
+ ```ruby
70
+ LineChart.new data, height: 50, background: '#eee',
71
+ aspect_ratio: 5, color: 'green'
72
+ ```
73
+
74
+ ### Bar Chart
75
+
76
+ <img src='examples/bar_chart.svg' align='right'>
77
+
78
+ ```ruby
79
+ BarChart.new data, height: 50, background: '#eee',
80
+ aspect_ratio: 5, color: 'green'
81
+ ```
82
+
83
+ ### Area Chart
84
+
85
+ <img src='examples/area_chart.svg' align='right'>
86
+
87
+ ```ruby
88
+ AreaChart.new data, height: 50, background: '#eee',
89
+ aspect_ratio: 5, color: 'green'
90
+ ```
91
+
92
+ ### Horizontal Bar Meter
93
+
94
+ <img src='examples/multiple_horizontal_bars.svg' align='right'>
95
+
96
+ ```ruby
97
+ positive = HorizontalBarMeter.new 70,
98
+ height: 20, width: 250, background: '#9f9', color: 'green'
99
+
100
+ negative = HorizontalBarMeter.new -80,
101
+ height: 20, width: 250, background: '#f99', color: 'red'
102
+
103
+ dual = HorizontalBarMeter.new 80,
104
+ height: 20, width: 250, background: '#99f', color: 'blue',
105
+ mode: :dual, zero_line: true
106
+ ```
107
+
108
+ Meter charts support [additional options](#meter-options).
109
+
65
110
  ## Options
66
111
 
67
- All minichart classes support a second hash argument for options
112
+ ### Basic Options
113
+
114
+ All chart classes support a second hash argument for options
68
115
 
69
116
  ```ruby
70
117
  chart = LineChart.new data, options
71
118
  ```
72
119
 
73
- | Option | Default | Description |
74
- | -------------- | ---------------------------- | ----------------------- |
75
- | `background` | *None* | Chart background color |
76
- | `color` | #333 | Chart color |
77
- | `aspect_ratio` | 3 | Set automatic width |
78
- | `height` | 100 | Chart height in pixels |
79
- | `width` | Calculated by `aspect_ratio` | Chart width in pixels |
80
- | `stroke` | 2 | Line stroke width |
81
- | `style` | *None* | Style hash for the SVG |
120
+ | Option | Default | Description |
121
+ | -------------- | ---------------------------- | ------------------------------------------------------------ |
122
+ | `background` | `"white"` | Chart background color |
123
+ | `color` | `"#333"` | Chart color |
124
+ | `aspect_ratio` | `3` | Set automatic width |
125
+ | `height` | `100` | Chart height in pixels |
126
+ | `width` | Calculated by `aspect_ratio` | Chart width in pixels |
127
+ | `stroke` | `2` | Line stroke width.<br />In `BarChart` determines the gap between bars |
128
+ | `style` | *None* | Style hash for the SVG |
129
+
130
+
131
+ ### Meter Options
82
132
 
133
+ Meter charts support these options in additon to the basic options:
134
+
135
+ | Option | Default | Description |
136
+ | ------------------ | --------- | ------------------------------------------------------------ |
137
+ | `mode` | `:auto` | Display mode.<br />Can be `:positive`, `:negative`, `:auto` or `:dual` |
138
+ | `max` | `100` | The absolute maximum value.<br />This number should be positive even for nengative charts |
139
+ | `zero_line` | `false` | If true, mark the zero line |
140
+ | `zero_line_stroke` | `4` | Width of the zero line |
141
+ | `zero_line_color` | `"black"` | Color of the zero line |
83
142
 
84
143
  ## Examples
85
144
 
86
145
  See more examples (code and SVG output) in the [examples folder][1].
87
146
 
147
+ ---
148
+
88
149
 
89
150
  [1]: https://github.com/DannyBen/minichart/tree/master/examples#examples
90
151
  [2]: https://github.com/DannyBen/victor
@@ -1,7 +1,11 @@
1
1
  require 'victor'
2
- require 'minichart/chart'
3
- require 'minichart/line_chart'
4
- require 'minichart/bar_chart'
5
- require 'minichart/area_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/horizontal_bar_meter'
6
10
 
7
11
  require 'byebug' if ENV['BYEBUG']
@@ -0,0 +1,65 @@
1
+ module Minichart
2
+ # Base class for all Minichart classes
3
+ class Base < Victor::SVGBase
4
+ attr_reader :aspect_ratio, :background, :color, :data,
5
+ :height, :stroke, :style, :width, :opts
6
+
7
+ def initialize(data, opts = {})
8
+ @data, @opts = data, opts
9
+
10
+ super height: height, width: width, style: style, viewBox: viewbox
11
+ element :rect, x: 0, y: 0, width: width, height: height, fill: background
12
+
13
+ clip_path_id = IDGenerator.next
14
+ setup_clip_path clip_path_id
15
+
16
+ element :g, clip_path: "url(##{clip_path_id})" do
17
+ build
18
+ end
19
+ end
20
+
21
+ def setup_clip_path(id)
22
+ element :defs do
23
+ element :clipPath, id: id do
24
+ element :rect, width: width, height: height
25
+ end
26
+ end
27
+ end
28
+
29
+ def background
30
+ opts[:background] ||= 'white'
31
+ end
32
+
33
+ def aspect_ratio
34
+ opts[:aspect_ratio] ||= 3
35
+ end
36
+
37
+ def height
38
+ opts[:height] ||= 100
39
+ end
40
+
41
+ def width
42
+ opts[:width] ||= (aspect_ratio * height).round
43
+ end
44
+
45
+ def stroke
46
+ opts[:stroke] ||= 2
47
+ end
48
+
49
+ def style
50
+ opts[:style] ||= {}
51
+ end
52
+
53
+ def color
54
+ opts[:color] ||= '#333'
55
+ end
56
+
57
+ def viewbox
58
+ "0 0 #{width} #{height}"
59
+ end
60
+
61
+ def build
62
+ raise NotImplementedError, "#build is not implemented"
63
+ end
64
+ end
65
+ end
@@ -1,7 +1,7 @@
1
1
  module Minichart
2
2
  class AreaChart < Chart
3
3
  def build
4
- polyline fill: color,
4
+ element :polyline, fill: color,
5
5
  stroke: color,
6
6
  stroke_width: stroke,
7
7
  stroke_linejoin: :round,
@@ -1,29 +1,29 @@
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
- rect bar_options x, y
8
- end
9
- end
10
-
11
- protected
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
+ 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 ||= 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
@@ -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
@@ -1,7 +1,7 @@
1
1
  module Minichart
2
2
  class LineChart < Chart
3
3
  def build
4
- polyline fill: :none,
4
+ element :polyline, fill: :none,
5
5
  stroke: color,
6
6
  stroke_width: stroke,
7
7
  stroke_linejoin: :round,
@@ -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,91 @@
1
+ module Minichart
2
+ class HorizontalBarMeter < Meter
3
+ def build
4
+ draw_bar
5
+ draw_zero_line if zero_line
6
+ end
7
+
8
+ protected
9
+
10
+ def draw_bar
11
+ x = if mode == :negative
12
+ width - bar_width
13
+ elsif mode == :dual
14
+ middle = width * 0.5
15
+ value >= 0 ? middle : middle - bar_width
16
+ else
17
+ 0
18
+ end
19
+
20
+ element :rect, x: x, y: 0, height: height, width: bar_width, style: style
21
+ end
22
+
23
+ def draw_zero_line
24
+ x = if mode == :negative
25
+ width-zero_line_stroke
26
+ elsif mode == :dual
27
+ width / 2 - zero_line_stroke / 2
28
+ else
29
+ 0
30
+ end
31
+
32
+ element :rect, x: x, y: 0,
33
+ height: height, width: zero_line_stroke,
34
+ fill: zero_line_color
35
+
36
+ end
37
+
38
+ def mode
39
+ opts[:mode] ||= :auto
40
+
41
+ if opts[:mode] == :auto
42
+ value >= 0 ? :positive : :negative
43
+ else
44
+ opts[:mode]
45
+ end
46
+ end
47
+
48
+ def max
49
+ opts[:max] ||= 100
50
+ end
51
+
52
+ def zero_line
53
+ opts[:zero_line]
54
+ end
55
+
56
+ def zero_line_stroke
57
+ opts[:zero_line_stroke] || 6
58
+ end
59
+
60
+ def zero_line_color
61
+ opts[:zero_line_color] || 'black'
62
+ end
63
+
64
+ def width_factor
65
+ width / max.to_f
66
+ end
67
+
68
+ def clamped_value
69
+ case mode
70
+ when :positive
71
+ value.clamp 0, max
72
+ when :negative
73
+ value.clamp -max, 0
74
+ when :dual
75
+ value.clamp -max, max
76
+ end
77
+ end
78
+
79
+ def bar_width
80
+ if mode == :dual
81
+ clamped_value.abs * width_factor * 0.5
82
+ else
83
+ clamped_value.abs * width_factor
84
+ end
85
+ end
86
+
87
+ def style
88
+ { fill: color, stroke_width: stroke, stroke: background }
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,8 @@
1
+ module Minichart
2
+ # Base class for charts with a single value
3
+ class Meter < Base
4
+ def value
5
+ data
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Minichart
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minichart
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
@@ -32,10 +32,14 @@ extra_rdoc_files: []
32
32
  files:
33
33
  - README.md
34
34
  - lib/minichart.rb
35
- - lib/minichart/area_chart.rb
36
- - lib/minichart/bar_chart.rb
37
- - lib/minichart/chart.rb
38
- - 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
39
43
  - lib/minichart/version.rb
40
44
  homepage: https://github.com/DannyBen/minichart
41
45
  licenses:
@@ -1,50 +0,0 @@
1
- module Minichart
2
- class Chart < Victor::SVG
3
- attr_reader :aspect_ratio, :background, :color, :data,
4
- :height, :stroke, :style, :width
5
-
6
- def initialize(data, opts = {})
7
- @data = data
8
- @background = opts[:background]
9
- @aspect_ratio = opts[:aspect_ratio] || 3
10
- @height = opts[:height] || 100
11
- @width = opts[:width] || (aspect_ratio * height).round
12
- @stroke = opts[:stroke] || 2
13
- @style = opts[:style] || {}
14
- @color = opts[:color] || '#333'
15
-
16
- super height: height, width: width, style: style,
17
- viewBox: "0 0 #{width} #{height}"
18
-
19
- rect x: 0, y: 0, width: width, height: height, fill: background if background
20
-
21
- build
22
- end
23
-
24
- def build
25
- raise NotImplementedError, "#build is not implemented"
26
- end
27
-
28
- protected
29
-
30
- def inverted_points(opts={})
31
- normalized_points(opts).map { |point| [point[0], 1-point[1]] }
32
- end
33
-
34
- def normalized_points(opts={})
35
- x_point_count = opts[:x_point_count] || data.count-1
36
-
37
- range = (data.max - data.min).to_f
38
- x_width = 1/(x_point_count).to_f
39
- result = []
40
-
41
- data.each_with_index do |y, index|
42
- x = index*x_width
43
- y = (y-data.min)/range
44
- result << [x,y]
45
- end
46
-
47
- result
48
- end
49
- end
50
- end