minichart 0.0.1 → 0.2.2
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 +5 -5
- data/README.md +150 -13
- data/lib/minichart.rb +11 -3
- data/lib/minichart/base.rb +67 -0
- data/lib/minichart/charts/area_chart.rb +27 -0
- data/lib/minichart/{bar_chart.rb → charts/bar_chart.rb} +29 -33
- data/lib/minichart/charts/chart.rb +28 -0
- data/lib/minichart/{line_chart.rb → charts/line_chart.rb} +23 -17
- data/lib/minichart/id_generator.rb +14 -0
- data/lib/minichart/meters/horizontal_bar_meter.rb +64 -0
- data/lib/minichart/meters/meter.rb +73 -0
- data/lib/minichart/meters/vertical_bar_meter.rb +72 -0
- data/lib/minichart/version.rb +1 -1
- metadata +15 -66
- data/lib/minichart/chart.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7debe086fa2ba7994f1362fa53ab2d5da5cc61a0010f6f08d6ca125cc447bc27
|
4
|
+
data.tar.gz: 77dd9cf342830795872c284befe937cba7caa9c2372bdae2b8a42a44e6d4bb13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a331fa46640d9bfb32759a5aa160680cd684bd7f57f194e212f7b0d0f5c2af61f03f8b526702de0421dbe608fbc70c39df8c219967b8c2de9fe647f04822e42
|
7
|
+
data.tar.gz: 2fede85eef059f2ac6980ff9ba6249b1e7b716edb38eacfe514cebace11488e0cb1ca4520ff4d7a3bf58934e746e846130026c9c98f7bc41419c4216a68c8734
|
data/README.md
CHANGED
@@ -1,17 +1,16 @@
|
|
1
|
-
Minichart - SVG Chart Generator
|
2
|
-
==================================================
|
3
|
-
|
1
|
+
# Minichart - SVG Chart Generator
|
4
2
|
|
5
3
|
---
|
6
4
|
|
7
5
|
Create SVG mini charts with Ruby
|
8
6
|
|
7
|
+

|
8
|
+
|
9
9
|
---
|
10
10
|
|
11
|
-
Install
|
12
|
-
--------------------------------------------------
|
11
|
+
## Install
|
13
12
|
|
14
|
-
```
|
13
|
+
```shell
|
15
14
|
$ gem install minichart
|
16
15
|
```
|
17
16
|
|
@@ -21,17 +20,155 @@ Or with bundler:
|
|
21
20
|
gem 'minichart'
|
22
21
|
```
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Require and optionally include the library:
|
26
26
|
|
27
27
|
```ruby
|
28
28
|
require 'minichart'
|
29
29
|
include Minichart
|
30
|
+
```
|
31
|
+
|
32
|
+
Initialize a chart with data, and optional options:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9]
|
36
|
+
chart = AreaChart.new data, color: 'blue'
|
37
|
+
```
|
38
|
+
|
39
|
+
Get the full SVG output by calling `#render`:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
puts chart.render
|
43
|
+
#=> <?xml version="1.0" standalone="no"?>
|
44
|
+
# <svg> ... </svg>
|
45
|
+
```
|
46
|
+
|
47
|
+
Save it to file, by calling `#save`:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
chart.save "my-chart.svg"
|
51
|
+
```
|
52
|
+
|
53
|
+
Get its inner SVG string by calling `#to_s`:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
puts chart.to_s
|
57
|
+
#=> <polyline fill="blue" stroke="blue" stroke-width="2" points="..."/>
|
58
|
+
```
|
59
|
+
|
60
|
+
|
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.
|
62
|
+
|
63
|
+
## Chart Types
|
64
|
+
|
65
|
+
### Line Chart
|
66
|
+
|
67
|
+
<img src='examples/line_chart.svg' align='right' width=300>
|
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' width=300>
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
BarChart.new data, height: 50, background: '#eee',
|
80
|
+
aspect_ratio: 5, color: 'green'
|
81
|
+
```
|
82
|
+
|
83
|
+
### Area Chart
|
30
84
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
85
|
+
<img src='examples/area_chart.svg' align='right' width=300>
|
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
|
35
106
|
```
|
36
107
|
|
37
|
-
|
108
|
+
Meter charts support [additional options](#meter-options).
|
109
|
+
|
110
|
+
### Vertical Bar Meter
|
111
|
+
|
112
|
+
<img src='examples/multiple_vertical_bars.svg' align='right'>
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
positive = VerticalBarMeter.new 70,
|
116
|
+
width: 20, height: 250, background: '#9f9', color: 'green'
|
117
|
+
|
118
|
+
negative = VerticalBarMeter.new -80,
|
119
|
+
width: 20, height: 250, background: '#f99', color: 'red'
|
120
|
+
|
121
|
+
dual = VerticalBarMeter.new 80,
|
122
|
+
width: 20, height: 250, background: '#99f', color: 'blue',
|
123
|
+
mode: :dual, zero_line: true
|
124
|
+
```
|
125
|
+
|
126
|
+
Meter charts support [additional options](#meter-options).
|
127
|
+
|
128
|
+
|
129
|
+
## Options
|
130
|
+
|
131
|
+
### Basic Options
|
132
|
+
|
133
|
+
All chart classes support a second hash argument for options
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
chart = LineChart.new data, options
|
137
|
+
```
|
138
|
+
|
139
|
+
| Option | Default | Description |
|
140
|
+
| -------------- | ----------------------------- | ------------------------------------------------------------ |
|
141
|
+
| `background` | `"white"` | Chart background color |
|
142
|
+
| `color` | `"#333"` | Chart color |
|
143
|
+
| `aspect_ratio` | `3` | Set automatic width |
|
144
|
+
| `height` | `100`<sup>*</sup> | Chart height in pixels |
|
145
|
+
| `width` | Calculated by `aspect_ratio`<sup>*</sup> | Chart width in pixels |
|
146
|
+
| `stroke` | `2` | Line stroke width.<br />In `BarChart` determines the gap between bars |
|
147
|
+
| `style` | *None* | Style hash for the SVG |
|
148
|
+
|
149
|
+
_* Default dimensions are reversed for horizontal meters - `width` defaults to 100, and `height` is calculated automatically._
|
150
|
+
|
151
|
+
### Meter Options
|
152
|
+
|
153
|
+
Meter charts support these options in additon to the basic options:
|
154
|
+
|
155
|
+
| Option | Default | Description |
|
156
|
+
| -------------------------- | --------- | ------------------------------------------------------------ |
|
157
|
+
| `mode` | `:auto` | Display mode.<br />Can be `:positive`, `:negative`, `:auto` or `:dual` |
|
158
|
+
| `max` | `100` | The absolute maximum value.<br />This number should be positive even for negative charts |
|
159
|
+
| `zero_line` | `false` | If true, mark the zero line |
|
160
|
+
| `zero_line_size` | `6` | Size of the zero line |
|
161
|
+
| `zero_line_color` | `"black"` | Color of the zero line |
|
162
|
+
| `clipping_indicator` | `false` | If true, show when the value exceeds the range |
|
163
|
+
| `clipping_indicator_size` | `6` | Size of the clipping indicator |
|
164
|
+
| `clipping_indicator_color` | `"yelow"` | Color of the clipping indicator |
|
165
|
+
|
166
|
+
## Examples
|
167
|
+
|
168
|
+
See more examples (code and SVG output) in the [examples folder][1].
|
169
|
+
|
170
|
+
---
|
171
|
+
|
172
|
+
|
173
|
+
[1]: https://github.com/DannyBen/minichart/tree/master/examples#examples
|
174
|
+
[2]: https://github.com/DannyBen/victor
|
data/lib/minichart.rb
CHANGED
@@ -1,4 +1,12 @@
|
|
1
1
|
require 'victor'
|
2
|
-
require 'minichart/
|
3
|
-
require 'minichart/
|
4
|
-
require 'minichart/
|
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,67 @@
|
|
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
|
+
super viewBox: viewbox, style: style
|
12
|
+
element :rect, x: 0, y: 0, width: width, height: height,
|
13
|
+
fill: background, stroke_width: 0
|
14
|
+
|
15
|
+
clip_path_id = IDGenerator.next
|
16
|
+
setup_clip_path clip_path_id
|
17
|
+
|
18
|
+
element :g, clip_path: "url(##{clip_path_id})" do
|
19
|
+
build
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup_clip_path(id)
|
24
|
+
element :defs do
|
25
|
+
element :clipPath, id: id do
|
26
|
+
element :rect, width: width, height: height
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def background
|
32
|
+
opts[:background] ||= 'white'
|
33
|
+
end
|
34
|
+
|
35
|
+
def aspect_ratio
|
36
|
+
opts[:aspect_ratio] ||= 3
|
37
|
+
end
|
38
|
+
|
39
|
+
def height
|
40
|
+
opts[:height] ||= 100
|
41
|
+
end
|
42
|
+
|
43
|
+
def width
|
44
|
+
opts[:width] ||= (aspect_ratio * height).round
|
45
|
+
end
|
46
|
+
|
47
|
+
def stroke
|
48
|
+
opts[:stroke] ||= 2
|
49
|
+
end
|
50
|
+
|
51
|
+
def style
|
52
|
+
opts[:style] ||= {}
|
53
|
+
end
|
54
|
+
|
55
|
+
def color
|
56
|
+
opts[:color] ||= '#333'
|
57
|
+
end
|
58
|
+
|
59
|
+
def viewbox
|
60
|
+
"0 0 #{width} #{height}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def build
|
64
|
+
raise NotImplementedError, "#build is not implemented"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Minichart
|
2
|
+
class AreaChart < Chart
|
3
|
+
def build
|
4
|
+
element :polyline, fill: color,
|
5
|
+
stroke: color,
|
6
|
+
stroke_width: stroke,
|
7
|
+
stroke_linejoin: :round,
|
8
|
+
points: points
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def points
|
14
|
+
result = ["0,#{height}"]
|
15
|
+
|
16
|
+
inverted_points.each do |point|
|
17
|
+
x = width*point[0]
|
18
|
+
y = height*point[1]
|
19
|
+
result << "#{x},#{y}"
|
20
|
+
end
|
21
|
+
|
22
|
+
result << "#{width},#{height}"
|
23
|
+
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,33 +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
|
-
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def
|
14
|
-
@
|
15
|
-
end
|
16
|
-
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
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,17 +1,23 @@
|
|
1
|
-
module Minichart
|
2
|
-
class LineChart < Chart
|
3
|
-
def build
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
result
|
15
|
-
|
16
|
-
|
17
|
-
|
1
|
+
module Minichart
|
2
|
+
class LineChart < Chart
|
3
|
+
def build
|
4
|
+
element :polyline, fill: :none,
|
5
|
+
stroke: color,
|
6
|
+
stroke_width: 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 = width*point[0]
|
17
|
+
y = height*point[1]
|
18
|
+
result << "#{x},#{y}"
|
19
|
+
end
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Minichart
|
2
|
+
class HorizontalBarMeter < Meter
|
3
|
+
def build
|
4
|
+
draw_bar
|
5
|
+
draw_zero_line if zero_line
|
6
|
+
draw_clipping_indicator if clipping_indicator and clipping?
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def draw_bar
|
12
|
+
x = if mode == :negative
|
13
|
+
width - bar_width
|
14
|
+
elsif mode == :dual
|
15
|
+
middle = width * 0.5
|
16
|
+
value >= 0 ? middle : middle - bar_width
|
17
|
+
else
|
18
|
+
0
|
19
|
+
end
|
20
|
+
|
21
|
+
element :rect, x: x, y: 0, height: height, width: bar_width, style: style
|
22
|
+
end
|
23
|
+
|
24
|
+
def draw_clipping_indicator
|
25
|
+
x = if mode == :positive or (mode == :dual and value > 0)
|
26
|
+
width - clipping_indicator_size
|
27
|
+
else
|
28
|
+
0
|
29
|
+
end
|
30
|
+
|
31
|
+
element :rect, x: x, y: 0,
|
32
|
+
height: height, width: clipping_indicator_size,
|
33
|
+
fill: clipping_indicator_color, stroke_width: 0
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def draw_zero_line
|
38
|
+
x = if mode == :negative
|
39
|
+
width - zero_line_size
|
40
|
+
elsif mode == :dual
|
41
|
+
width / 2 - zero_line_size / 2
|
42
|
+
else
|
43
|
+
0
|
44
|
+
end
|
45
|
+
|
46
|
+
element :rect, x: x, y: 0,
|
47
|
+
height: height, width: zero_line_size,
|
48
|
+
fill: zero_line_color, stroke_width: 0
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def width_factor
|
53
|
+
width / max.to_f
|
54
|
+
end
|
55
|
+
|
56
|
+
def bar_width
|
57
|
+
if mode == :dual
|
58
|
+
clamped_value.abs * width_factor * 0.5
|
59
|
+
else
|
60
|
+
clamped_value.abs * width_factor
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Minichart
|
2
|
+
# Base class for charts with a single value
|
3
|
+
class Meter < Base
|
4
|
+
|
5
|
+
protected
|
6
|
+
|
7
|
+
def value
|
8
|
+
data
|
9
|
+
end
|
10
|
+
|
11
|
+
def clipping?
|
12
|
+
value > max || value < -max
|
13
|
+
end
|
14
|
+
|
15
|
+
def mode
|
16
|
+
@mode ||= mode!
|
17
|
+
end
|
18
|
+
|
19
|
+
def mode!
|
20
|
+
opts[:mode] ||= :auto
|
21
|
+
|
22
|
+
if opts[:mode] == :auto
|
23
|
+
value >= 0 ? :positive : :negative
|
24
|
+
else
|
25
|
+
opts[:mode].to_sym
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def max
|
30
|
+
opts[:max] ||= 100
|
31
|
+
end
|
32
|
+
|
33
|
+
def zero_line
|
34
|
+
opts[:zero_line]
|
35
|
+
end
|
36
|
+
|
37
|
+
def zero_line_size
|
38
|
+
opts[:zero_line_size] ||= 6
|
39
|
+
end
|
40
|
+
|
41
|
+
def zero_line_color
|
42
|
+
opts[:zero_line_color] ||= 'black'
|
43
|
+
end
|
44
|
+
|
45
|
+
def clipping_indicator
|
46
|
+
opts[:clipping_indicator]
|
47
|
+
end
|
48
|
+
|
49
|
+
def clipping_indicator_size
|
50
|
+
opts[:clipping_indicator_size] ||= 6
|
51
|
+
end
|
52
|
+
|
53
|
+
def clipping_indicator_color
|
54
|
+
opts[:clipping_indicator_color] ||= 'yellow'
|
55
|
+
end
|
56
|
+
|
57
|
+
def clamped_value
|
58
|
+
case mode
|
59
|
+
when :positive
|
60
|
+
value.clamp 0, max
|
61
|
+
when :negative
|
62
|
+
value.clamp -max, 0
|
63
|
+
when :dual
|
64
|
+
value.clamp -max, max
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def style
|
69
|
+
{ fill: color, stroke_width: stroke, stroke: background }
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Minichart
|
2
|
+
class VerticalBarMeter < Meter
|
3
|
+
def build
|
4
|
+
draw_bar
|
5
|
+
draw_zero_line if zero_line
|
6
|
+
draw_clipping_indicator if clipping_indicator and clipping?
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def width
|
12
|
+
opts[:width] ||= 100
|
13
|
+
end
|
14
|
+
|
15
|
+
def height
|
16
|
+
opts[:height] ||= (aspect_ratio * width).round
|
17
|
+
end
|
18
|
+
|
19
|
+
def draw_bar
|
20
|
+
y = if mode == :positive
|
21
|
+
height - bar_height
|
22
|
+
elsif mode == :dual
|
23
|
+
middle = height * 0.5
|
24
|
+
value >= 0 ? middle - bar_height : middle
|
25
|
+
else
|
26
|
+
0
|
27
|
+
end
|
28
|
+
|
29
|
+
element :rect, x: 0, y: y, height: bar_height, width: width, style: style
|
30
|
+
end
|
31
|
+
|
32
|
+
def draw_clipping_indicator
|
33
|
+
y = if mode == :negative or (mode == :dual and value < 0)
|
34
|
+
height - clipping_indicator_size
|
35
|
+
else
|
36
|
+
0
|
37
|
+
end
|
38
|
+
|
39
|
+
element :rect, x: 0, y: y,
|
40
|
+
height: clipping_indicator_size, width: width,
|
41
|
+
fill: clipping_indicator_color, stroke_width: 0
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def draw_zero_line
|
46
|
+
y = if mode == :positive
|
47
|
+
height - zero_line_size
|
48
|
+
elsif mode == :dual
|
49
|
+
height / 2 - zero_line_size / 2
|
50
|
+
else
|
51
|
+
0
|
52
|
+
end
|
53
|
+
|
54
|
+
element :rect, x: 0, y: y,
|
55
|
+
height: zero_line_size, width: width,
|
56
|
+
fill: zero_line_color, stroke_width: 0
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def height_factor
|
61
|
+
height / max.to_f
|
62
|
+
end
|
63
|
+
|
64
|
+
def bar_height
|
65
|
+
if mode == :dual
|
66
|
+
clamped_value.abs * height_factor * 0.5
|
67
|
+
else
|
68
|
+
clamped_value.abs * height_factor
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/minichart/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.2
|
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:
|
11
|
+
date: 2020-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: victor
|
@@ -16,70 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
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.
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: runfile
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.8'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0.8'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: runfile-tasks
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0.4'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0.4'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: byebug
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '9.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '9.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: filewatcher
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0.5'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0.5'
|
26
|
+
version: '0.3'
|
83
27
|
description: Generate mini charts with SVG
|
84
28
|
email: db@dannyben.com
|
85
29
|
executables: []
|
@@ -88,9 +32,15 @@ extra_rdoc_files: []
|
|
88
32
|
files:
|
89
33
|
- README.md
|
90
34
|
- lib/minichart.rb
|
91
|
-
- lib/minichart/
|
92
|
-
- lib/minichart/
|
93
|
-
- lib/minichart/
|
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
|
94
44
|
- lib/minichart/version.rb
|
95
45
|
homepage: https://github.com/DannyBen/minichart
|
96
46
|
licenses:
|
@@ -104,15 +54,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
54
|
requirements:
|
105
55
|
- - ">="
|
106
56
|
- !ruby/object:Gem::Version
|
107
|
-
version: 2.
|
57
|
+
version: 2.5.0
|
108
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
59
|
requirements:
|
110
60
|
- - ">="
|
111
61
|
- !ruby/object:Gem::Version
|
112
62
|
version: '0'
|
113
63
|
requirements: []
|
114
|
-
|
115
|
-
rubygems_version: 2.6.6
|
64
|
+
rubygems_version: 3.1.2
|
116
65
|
signing_key:
|
117
66
|
specification_version: 4
|
118
67
|
summary: SVG Mini Charts
|
data/lib/minichart/chart.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Minichart
|
2
|
-
class Chart
|
3
|
-
attr_accessor :data, :aspect_ratio
|
4
|
-
|
5
|
-
def save(name)
|
6
|
-
svg.rect x: 0, y: 0, width: width, height: height, fill: '#ccc'
|
7
|
-
build
|
8
|
-
svg.save name
|
9
|
-
end
|
10
|
-
|
11
|
-
def build
|
12
|
-
raise "Subeclass needs to implement #build"
|
13
|
-
end
|
14
|
-
|
15
|
-
def inverted_points(opts={})
|
16
|
-
normalized_points(opts).map { |point| [point[0], 1-point[1]] }
|
17
|
-
end
|
18
|
-
|
19
|
-
def normalized_points(opts={})
|
20
|
-
x_point_count = opts[:x_point_count] || data.count-1
|
21
|
-
|
22
|
-
range = (data.max - data.min).to_f
|
23
|
-
x_width = 1/(x_point_count).to_f
|
24
|
-
result = []
|
25
|
-
|
26
|
-
data.each_with_index do |y, index|
|
27
|
-
x = index*x_width
|
28
|
-
y = (y-data.min)/range
|
29
|
-
result << [x,y]
|
30
|
-
end
|
31
|
-
|
32
|
-
result
|
33
|
-
end
|
34
|
-
|
35
|
-
def width
|
36
|
-
@width ||= (aspect_ratio * height).round
|
37
|
-
end
|
38
|
-
|
39
|
-
def height
|
40
|
-
100
|
41
|
-
end
|
42
|
-
|
43
|
-
def svg
|
44
|
-
@svg ||= SVG.new viewBox: "0 0 #{width} #{height}", style: { background: '#ddd' }
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|