svg-graph 2.0.2 → 2.1.0.beta1

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
  SHA1:
3
- metadata.gz: 7101e9e0d576c758450907b8f9d30bf2b8c787ee
4
- data.tar.gz: c370f0c3b179587d0e4bf34d4862f4c1a0366dce
3
+ metadata.gz: 0cd53b929ddc82314e5a2f5905ee19e6945f4a7c
4
+ data.tar.gz: 95968148c4ec92b65c88f8dc1b0796fa95a645b7
5
5
  SHA512:
6
- metadata.gz: da39453fcbd961e3b8758da1b7a5ed49f9fa6142f598151de6625e7294ca3ffc2689aca19110841a6f598bf23305ab85daaf2f5b2d59a03f29b3204d96c2ecc2
7
- data.tar.gz: 58a9de11f45ce90ffbf7600b4d82a0b26b27f4b6598e016221bc838fa074cd7aaaecad537aa7cd69fbcae33d03f4c6da432883b890775dfd9db24900c1c39f3e
6
+ metadata.gz: d08b2f7ec8271044779fb858cb79262a1d8e69a86b76181c7dc4fa0b8c02aec6c5a2e248ab2b90d07774456dbc9e77754a50a62e944d313426678fc216af9dc2
7
+ data.tar.gz: c4ec0861d565c824cc5aed3ce3d4eef79ce85093a730e630fd4255b8797559825f6fb1dfd2e68ff47a267704bffc28eba45579e81089dd997ea695e3f4686500
@@ -2,6 +2,12 @@ TODO / Backlog
2
2
  * add unit tests for all types of graphs
3
3
  * refactor various hardcoded constant pixel offsets in Graph class to use named constants or variables
4
4
 
5
+ === 2.1.0 / 2017-02-12 [lumean]
6
+ * change behavior for number format, Strings axis labels will never be formatted
7
+ previously, when containing numbers they were formatted with the number_format template
8
+ * added options to change x-axis and y-axis position :x_axis_position and :y_axis_position
9
+ * x_guidelines and y_guidelines can now be drawn independently of show_x_labels and show_y_labels,
10
+ before they were only drawn if show_x_labels resp show_y_labels was true
5
11
 
6
12
  === 2.0.2 / 2016-10-24 [lumean]
7
13
  * fix axis-title positioning
@@ -24,7 +30,7 @@ TODO / Backlog
24
30
  * all ruby files in the test directory now run on ruby >2.0 and write output to files [lumean]
25
31
  * changed from autoload to static loading due to issues with unit-testing when the gem is not installed [lumean]
26
32
  * begin transition to minitest for tests [lumean]
27
- * merged fix for 100% pie graphs from https://github.com/endersstocker/svg-graph
33
+ * merged fix for 100% pie graphs from https://github.com/endersstocker/svg-graph
28
34
  * fix wrong margins for labels after merge of number formatting [lumean]
29
35
  * Add new option for locations for the axis titles (at the end of the axis instead of below / left from it) [lumean]
30
36
  * improved x-axis label location when x-axis marks are vertical and long [lumean]
@@ -46,5 +52,3 @@ TODO / Backlog
46
52
  * Max values and improved Time data handling.
47
53
  * Merge pull request #1 from thinkingbox/master
48
54
  * Adding scattered plot support with :show_lines =>false Rounding values to integers in popups can be disabled with :round_popups => false Optional description gets shown in popup
49
-
50
-
@@ -103,29 +103,29 @@ module SVG
103
103
 
104
104
  bar_width = fieldwidth - bargap
105
105
  bar_width /= @data.length if stack == :side
106
-
106
+
107
107
  bottom = @graph_height
108
108
 
109
109
  field_count = 0
110
110
  @config[:fields].each_index { |i|
111
111
  dataset_count = 0
112
112
  for dataset in @data
113
-
113
+
114
114
  # cases (assume 0 = +ve):
115
115
  # value min length
116
116
  # +ve +ve value - min
117
117
  # +ve -ve value - 0
118
118
  # -ve -ve value.abs - 0
119
-
119
+
120
120
  value = dataset[:data][i]/@y_scale_division
121
-
121
+
122
122
  left = (fieldwidth * field_count)
123
-
123
+
124
124
  length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
125
125
  # top is 0 if value is negative
126
126
  top = bottom - (((value < 0 ? 0 : value) - minvalue) * unit_size)
127
127
  left += bar_width * dataset_count if stack == :side
128
-
128
+
129
129
  @graph.add_element( "rect", {
130
130
  "x" => left.to_s,
131
131
  "y" => top.to_s,
@@ -134,7 +134,8 @@ module SVG
134
134
  "class" => "fill#{dataset_count+1}"
135
135
  })
136
136
 
137
- make_datapoint_text(left + bar_width/2.0, top - font_size/2, dataset[:data][i].to_s)
137
+ make_datapoint_text(left + bar_width/2.0, top - font_size/2, dataset[:data][i])
138
+ # number format shall not apply to popup (use .to_s conversion)
138
139
  add_popup(left + bar_width/2.0, top , dataset[:data][i].to_s)
139
140
  dataset_count += 1
140
141
  end
@@ -4,43 +4,43 @@ require_relative 'BarBase'
4
4
  module SVG
5
5
  module Graph
6
6
  # === Create presentation quality SVG horitonzal bar graphs easily
7
- #
7
+ #
8
8
  # = Synopsis
9
- #
9
+ #
10
10
  # require 'SVG/Graph/BarHorizontal'
11
- #
11
+ #
12
12
  # fields = %w(Jan Feb Mar)
13
13
  # data_sales_02 = [12, 45, 21]
14
- #
14
+ #
15
15
  # graph = SVG::Graph::BarHorizontal.new({
16
16
  # :height => 500,
17
17
  # :width => 300,
18
18
  # :fields => fields,
19
19
  # })
20
- #
20
+ #
21
21
  # graph.add_data({
22
22
  # :data => data_sales_02,
23
23
  # :title => 'Sales 2002',
24
24
  # })
25
- #
25
+ #
26
26
  # print "Content-type: image/svg+xml\r\n\r\n"
27
27
  # print graph.burn
28
- #
28
+ #
29
29
  # = Description
30
- #
30
+ #
31
31
  # This object aims to allow you to easily create high quality
32
32
  # SVG horitonzal bar graphs. You can either use the default style sheet
33
33
  # or supply your own. Either way there are many options which can
34
34
  # be configured to give you control over how the graph is
35
35
  # generated - with or without a key, data elements at each point,
36
36
  # title, subtitle etc.
37
- #
37
+ #
38
38
  # = Examples
39
- #
39
+ #
40
40
  # * http://germane-software.com/repositories/public/SVG/test/test.rb
41
- #
41
+ #
42
42
  # = See also
43
- #
43
+ #
44
44
  # * SVG::Graph::Graph
45
45
  # * SVG::Graph::Bar
46
46
  # * SVG::Graph::Line
@@ -62,14 +62,14 @@ module SVG
62
62
  # [show_y_guidelines] false
63
63
  def set_defaults
64
64
  super
65
- init_with(
65
+ init_with(
66
66
  :rotate_y_labels => true,
67
67
  :show_x_guidelines => true,
68
68
  :show_y_guidelines => false
69
69
  )
70
70
  # self.right_align = self.right_font = 1
71
71
  end
72
-
72
+
73
73
  protected
74
74
 
75
75
  def get_x_labels
@@ -110,14 +110,14 @@ module SVG
110
110
  bar_height = fieldheight - bargap
111
111
  bar_height /= @data.length if stack == :side
112
112
  y_mod = (bar_height / 2) + (font_size / 2)
113
-
113
+
114
114
  field_count = 1
115
115
  @config[:fields].each_index { |i|
116
116
  dataset_count = 0
117
117
  for dataset in @data
118
118
  value = dataset[:data][i]
119
-
120
- top = @graph_height - (fieldheight * field_count)
119
+
120
+ top = @graph_height - (fieldheight * field_count) + bargap
121
121
  top += (bar_height * dataset_count) if stack == :side
122
122
  # cases (assume 0 = +ve):
123
123
  # value min length left
@@ -135,9 +135,8 @@ module SVG
135
135
  "class" => "fill#{dataset_count+1}"
136
136
  })
137
137
 
138
- make_datapoint_text(
139
- left+length+5, top+y_mod, dataset[:data][i].to_s, "text-anchor: start; "
140
- )
138
+ make_datapoint_text(left+length+5, top+y_mod, dataset[:data][i], "text-anchor: start; ")
139
+ # number format shall not apply to popup (use .to_s conversion)
141
140
  add_popup(left+length, top+y_mod , dataset[:data][i].to_s)
142
141
  dataset_count += 1
143
142
  end
@@ -13,14 +13,14 @@ module SVG
13
13
  # fields = %w(Jan Feb);
14
14
  # myarr1_mean = 10
15
15
  # myarr1_confidence = 1
16
- #
16
+ #
17
17
  # myarr2_mean = 20
18
18
  # myarr2_confidence = 2
19
- #
19
+ #
20
20
  # data= [myarr1_mean, myarr2_mean]
21
- #
21
+ #
22
22
  # err_mesure = [myarr1_confidence, myarr2_confidence]
23
- #
23
+ #
24
24
  # graph = SVG::Graph::ErrBar.new(
25
25
  # :height => 500,
26
26
  # :width => 600,
@@ -28,7 +28,7 @@ module SVG
28
28
  # :errorBars => err_mesure,
29
29
  # :scale_integers => true,
30
30
  # )
31
- #
31
+ #
32
32
  # graph.add_data(
33
33
  # :data => data,
34
34
  # :title => 'Sales 2002'
@@ -71,10 +71,10 @@ module SVG
71
71
  def initialize config
72
72
  raise "fields was not supplied or is empty" unless config[:errorBars] &&
73
73
  config[:errorBars].kind_of?(Array) &&
74
- config[:errorBars].length > 0
74
+ config[:errorBars].length > 0
75
75
  super
76
- end
77
- # Array of confidence values for each item in :fields. A range from
76
+ end
77
+ # Array of confidence values for each item in :fields. A range from
78
78
  # value[i]-errorBars[i] to value[i]+errorBars[i] is drawn into the graph.
79
79
  attr_accessor :errorBars
80
80
 
@@ -103,7 +103,7 @@ module SVG
103
103
  end
104
104
 
105
105
  rv = []
106
- maxvalue = maxvalue%@y_scale_division == 0 ?
106
+ maxvalue = maxvalue%@y_scale_division == 0 ?
107
107
  maxvalue : maxvalue + @y_scale_division
108
108
  minvalue.step( maxvalue, @y_scale_division ) {|v| rv << v}
109
109
  return rv
@@ -122,31 +122,31 @@ module SVG
122
122
 
123
123
  bar_width = fieldwidth - (bargap *2)
124
124
  bar_width /= @data.length if stack == :side
125
-
125
+
126
126
  bottom = @graph_height
127
127
 
128
128
  field_count = 0
129
129
  @config[:fields].each_index { |i|
130
130
  dataset_count = 0
131
131
  for dataset in @data
132
-
132
+
133
133
  # cases (assume 0 = +ve):
134
134
  # value min length
135
135
  # +ve +ve value - min
136
136
  # +ve -ve value - 0
137
137
  # -ve -ve value.abs - 0
138
-
138
+
139
139
  value = dataset[:data][i].to_f/@y_scale_division
140
-
140
+
141
141
  left = (fieldwidth * field_count)
142
142
  left += bargap
143
-
144
-
143
+
144
+
145
145
  length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
146
146
  # top is 0 if value is negative
147
147
  top = bottom - (((value < 0 ? 0 : value) - minvalue) * unit_size)
148
148
  left += bar_width * dataset_count if stack == :side
149
-
149
+
150
150
  @graph.add_element( "rect", {
151
151
  "x" => left.to_s,
152
152
  "y" => top.to_s,
@@ -160,7 +160,7 @@ module SVG
160
160
  upperErr = top+threshold
161
161
  bottomErr = top-threshold
162
162
  withthErr = bar_width/4
163
-
163
+
164
164
  @graph.add_element( "line", {
165
165
  "x1" => middlePointErr.to_s,
166
166
  "y1" => upperErr.to_s,
@@ -168,7 +168,7 @@ module SVG
168
168
  "y2" => bottomErr.to_s,
169
169
  "style" => "stroke:rgb(0,0,0);stroke-width:1"
170
170
  })
171
-
171
+
172
172
  @graph.add_element( "line", {
173
173
  "x1" => (middlePointErr-withthErr).to_s,
174
174
  "y1" => upperErr.to_s,
@@ -183,15 +183,16 @@ module SVG
183
183
  "y2" => bottomErr.to_s,
184
184
  "style" => "stroke:rgb(0,0,0);stroke-width:1"
185
185
  })
186
-
187
- make_datapoint_text(left + bar_width/2.0, top - 6, dataset[:data][i].to_s)
186
+
187
+ make_datapoint_text(left + bar_width/2.0, top - 6, dataset[:data][i])
188
+ # number format shall not apply to popup (use .to_s conversion)
188
189
  add_popup(left + bar_width/2.0, top , dataset[:data][i].to_s)
189
190
  dataset_count += 1
190
191
  end
191
192
  field_count += 1
192
193
  } # config[:fields].each_index
193
194
  end # draw_data
194
-
195
+
195
196
  end # ErrBar
196
197
  end
197
198
  end
@@ -10,7 +10,7 @@ module SVG
10
10
  module Graph
11
11
 
12
12
  # === Base object for generating SVG Graphs
13
- #
13
+ #
14
14
  # == Synopsis
15
15
  #
16
16
  # This class is only used as a superclass of specialized charts. Do not
@@ -28,9 +28,9 @@ module SVG
28
28
  # * file:test/single.rb
29
29
  # * file:test/test.rb
30
30
  # * file:test/timeseries.rb
31
- #
31
+ #
32
32
  # == Description
33
- #
33
+ #
34
34
  # This package should be used as a base for creating SVG graphs.
35
35
  #
36
36
  # == Acknowledgements
@@ -39,7 +39,7 @@ module SVG
39
39
  # port is based on.
40
40
  #
41
41
  # Stephen Morgan for creating the TT template and SVG.
42
- #
42
+ #
43
43
  # == See
44
44
  #
45
45
  # * SVG::Graph::BarHorizontal
@@ -63,6 +63,8 @@ module SVG
63
63
  # instantiate this class directly; see the subclass for options.
64
64
  # [width] 500
65
65
  # [height] 300
66
+ # [x_axis_position] nil
67
+ # [y_axis_position] nil
66
68
  # [show_x_guidelines] false
67
69
  # [show_y_guidelines] true
68
70
  # [show_data_values] true
@@ -98,7 +100,7 @@ module SVG
98
100
  # [key_font_size] 10
99
101
  # [no_css] false
100
102
  # [add_popups] false
101
- # [number_format] '%.2f'
103
+ # [number_format] '%.2f'
102
104
  def initialize( config )
103
105
  @config = config
104
106
  @data = []
@@ -112,6 +114,9 @@ module SVG
112
114
  :show_y_guidelines => true,
113
115
  :show_data_values => true,
114
116
 
117
+ :x_axis_position => nil,
118
+ :y_axis_position => nil,
119
+
115
120
  :min_scale_value => nil,
116
121
 
117
122
  :show_x_labels => true,
@@ -138,7 +143,7 @@ module SVG
138
143
  :graph_title => 'Graph Title',
139
144
  :show_graph_subtitle => false,
140
145
  :graph_subtitle => 'Graph Sub Title',
141
- :key => true,
146
+ :key => true,
142
147
  :key_position => :right, # bottom or right
143
148
 
144
149
  :font_size =>12,
@@ -149,27 +154,27 @@ module SVG
149
154
  :x_title_font_size =>14,
150
155
  :y_title_font_size =>14,
151
156
  :key_font_size =>10,
152
-
157
+
153
158
  :no_css =>false,
154
159
  :add_popups =>false,
155
- :number_format => '%.2f'
160
+ :number_format => '%.2f'
156
161
  })
157
162
  set_defaults if self.respond_to? :set_defaults
158
163
  init_with config
159
164
  end
160
165
 
161
-
166
+
162
167
  # This method allows you do add data to the graph object.
163
168
  # It can be called several times to add more data sets in.
164
169
  #
165
170
  # data_sales_02 = [12, 45, 21];
166
- #
171
+ #
167
172
  # graph.add_data({
168
173
  # :data => data_sales_02,
169
174
  # :title => 'Sales 2002'
170
175
  # })
171
176
  def add_data conf
172
- @data = [] unless (defined? @data and !@data.nil?)
177
+ @data = [] unless (defined? @data and !@data.nil?)
173
178
 
174
179
  if conf[:data] and conf[:data].kind_of? Array
175
180
  @data << conf
@@ -183,7 +188,7 @@ module SVG
183
188
  # reuse it to create a new graph but with the same config options.
184
189
  #
185
190
  # graph.clear_data
186
- def clear_data
191
+ def clear_data
187
192
  @data = []
188
193
  end
189
194
 
@@ -193,12 +198,12 @@ module SVG
193
198
  #
194
199
  # This method will croak unless at least one data set has
195
200
  # been added to the graph object.
196
- #
201
+ #
197
202
  # print graph.burn
198
- #
203
+ #
199
204
  def burn
200
205
  raise "No data available" unless @data.size > 0
201
-
206
+
202
207
  start_svg
203
208
  calculate_graph_dimensions
204
209
  @foreground = Element.new( "g" )
@@ -223,14 +228,14 @@ module SVG
223
228
  data << "<!-- Ruby Zlib not available for SVGZ -->";
224
229
  end
225
230
  end
226
-
231
+
227
232
  return data
228
233
  end
229
-
230
- # Burns the graph but returns only the <svg> node as String without the
234
+
235
+ # Burns the graph but returns only the <svg> node as String without the
231
236
  # Doctype and XML Declaration. This allows easy integration into
232
237
  # existing xml documents.
233
- #
238
+ #
234
239
  # @return [String] the SVG node which represents the Graph
235
240
  def burn_svg_only
236
241
  # initialize all instance variables by burning the graph
@@ -260,6 +265,19 @@ module SVG
260
265
  attr_accessor :style_sheet
261
266
  # (Bool) Show the value of each element of data on the graph
262
267
  attr_accessor :show_data_values
268
+ # By default (nil/undefined) the x-axis is at the bottom of the graph.
269
+ # With this property a custom position for the x-axis can be defined.
270
+ # Valid values are between :min_scale_value and maximum value of the
271
+ # data.
272
+ # Default: nil
273
+ attr_accessor :x_axis_position
274
+ # By default (nil/undefined) the y-axis is the left border of the graph.
275
+ # With this property a custom position for the y-axis can be defined.
276
+ # Valid values are any values in the range of x-values (in case of a
277
+ # Plot) or any of the :fields values (in case of Line/Bar Graphs, note
278
+ # the '==' operator is used to find at which value to draw the axis).
279
+ # Default: nil
280
+ attr_accessor :y_axis_position
263
281
  # The point at which the Y axis starts, defaults to nil,
264
282
  # if set to nil it will default to the minimum data value.
265
283
  attr_accessor :min_scale_value
@@ -268,17 +286,17 @@ module SVG
268
286
  attr_accessor :show_x_labels
269
287
  # This puts the X labels at alternative levels so if they
270
288
  # are long field names they will not overlap so easily.
271
- # Default it false, to turn on set to true.
289
+ # Default is false, to turn on set to true.
272
290
  attr_accessor :stagger_x_labels
273
291
  # This puts the Y labels at alternative levels so if they
274
292
  # are long field names they will not overlap so easily.
275
- # Default it false, to turn on set to true.
293
+ # Default is false, to turn on set to true.
276
294
  attr_accessor :stagger_y_labels
277
295
  # This turns the X axis labels by 90 degrees.
278
- # Default it false, to turn on set to true.
296
+ # Default is false, to turn on set to true.
279
297
  attr_accessor :rotate_x_labels
280
298
  # This turns the Y axis labels by 90 degrees.
281
- # Default it true, to turn on set to false.
299
+ # Default is true, to turn on set to false.
282
300
  attr_accessor :rotate_y_labels
283
301
  # How many "steps" to use between displayed X axis labels,
284
302
  # a step of one means display every label, a step of two results
@@ -286,7 +304,7 @@ module SVG
286
304
  # a step of three results in every third label being displayed
287
305
  # (label <gap> <gap> label <gap> <gap> label) and so on.
288
306
  attr_accessor :step_x_labels
289
- # Whether to (when taking "steps" between X axis labels) step from
307
+ # Whether to (when taking "steps" between X axis labels) step from
290
308
  # the first label (i.e. always include the first label) or step from
291
309
  # the X axis origin (i.e. start with a gap if step_x_labels is greater
292
310
  # than one).
@@ -295,7 +313,7 @@ module SVG
295
313
  # to true, set to false if you want to turn them off.
296
314
  attr_accessor :show_y_labels
297
315
  # Ensures only whole numbers are used as the scale divisions.
298
- # Default it false, to turn on set to true. This has no effect if
316
+ # Default is false, to turn on set to true. This has no effect if
299
317
  # scale divisions are less than 1.
300
318
  attr_accessor :scale_integers
301
319
  # This defines the gap between markers on the Y axis,
@@ -315,7 +333,7 @@ module SVG
315
333
  # Whether to show the title under the Y axis labels,
316
334
  # default is false, set to true to show.
317
335
  attr_accessor :show_y_title
318
- # Aligns writing mode for Y axis label.
336
+ # Aligns writing mode for Y axis label.
319
337
  # Defaults to :bt (Bottom to Top).
320
338
  # Change to :tb (Top to Bottom) to reverse.
321
339
  attr_accessor :y_title_text_direction
@@ -383,7 +401,7 @@ module SVG
383
401
 
384
402
 
385
403
  protected
386
-
404
+
387
405
  # implementation of quicksort
388
406
  # used for Schedule and Plot
389
407
  def sort( *arrys )
@@ -411,7 +429,7 @@ module SVG
411
429
  # Check size of Y labels
412
430
  @border_left += max_y_label_width_px
413
431
  if (show_y_title && (y_title_location ==:middle))
414
- @border_left += y_title_font_size + 5
432
+ @border_left += y_title_font_size + 5
415
433
  end
416
434
  end
417
435
 
@@ -439,12 +457,12 @@ module SVG
439
457
  @border_right = 7
440
458
  if key and key_position == :right
441
459
  val = keys.max { |a,b| a.length <=> b.length }
442
- @border_right += val.length * key_font_size * 0.6
460
+ @border_right += val.length * key_font_size * 0.6
443
461
  @border_right += KEY_BOX_SIZE
444
462
  @border_right += 10 # Some padding around the box
445
463
  end
446
464
  if (x_title_location == :end)
447
- @border_right = [@border_right, x_title.length * x_title_font_size * 0.6].max
465
+ @border_right = [@border_right, x_title.length * x_title_font_size * 0.6].max
448
466
  end
449
467
  end
450
468
 
@@ -483,16 +501,16 @@ module SVG
483
501
  (x+txt_width > width ? "text-anchor: end;" : "text-anchor: start;")
484
502
  t.text = label.to_s
485
503
  t.attributes["id"] = t.object_id.to_s
486
-
504
+
487
505
  # add a circle to catch the mouseover
488
506
  @foreground.add_element( "circle", {
489
507
  "cx" => x.to_s,
490
508
  "cy" => y.to_s,
491
509
  "r" => "#{popup_radius}",
492
510
  "style" => "opacity: 0",
493
- "onmouseover" =>
511
+ "onmouseover" =>
494
512
  "document.getElementById(#{t.object_id}).setAttribute('visibility', 'visible' )",
495
- "onmouseout" =>
513
+ "onmouseout" =>
496
514
  "document.getElementById(#{t.object_id}).setAttribute('visibility', 'hidden' )",
497
515
  })
498
516
  end # if add_popups
@@ -501,16 +519,16 @@ module SVG
501
519
  # returns the longest label from an array of labels as string
502
520
  # each object in the array must support .to_s
503
521
  def get_longest_label(arry)
504
- longest_label = arry.max{|a,b|
522
+ longest_label = arry.max{|a,b|
505
523
  # respect number_format
506
- a = @number_format % a if numeric?(a)
524
+ a = @number_format % a if numeric?(a)
507
525
  b = @number_format % b if numeric?(b)
508
526
  a.to_s.length <=> b.to_s.length
509
527
  }
510
528
  longest_label = @number_format % longest_label if numeric?(longest_label)
511
529
  return longest_label
512
530
  end
513
-
531
+
514
532
  # Override this (and call super) to change the margin to the bottom
515
533
  # of the plot area. Results in @border_bottom being set.
516
534
  #
@@ -526,13 +544,13 @@ module SVG
526
544
  @border_bottom += x_title_font_size + 5
527
545
  end
528
546
  end
529
-
547
+
530
548
  # returns the maximum height of the labels respect the rotation or 0 if
531
549
  # the labels are not shown
532
550
  def max_x_label_height_px
533
551
  return 0 if !show_x_labels
534
-
535
- if rotate_x_labels
552
+
553
+ if rotate_x_labels
536
554
  max_height = get_longest_label(get_x_labels).to_s.length * x_label_font_size * 0.6
537
555
  else
538
556
  max_height = x_label_font_size + 3
@@ -557,32 +575,92 @@ module SVG
557
575
  "class" => "graphBackground"
558
576
  })
559
577
 
560
- # Axis
578
+ draw_x_axis
579
+ draw_y_axis
580
+
581
+ draw_x_labels
582
+ draw_y_labels
583
+ end
584
+
585
+ # draws the x-axis; can be overridden by child classes
586
+ def draw_x_axis
587
+ # relative position on y-axis (hence @graph_height is our axis length)
588
+ relative_position = calculate_rel_position(get_y_labels, field_height, @x_axis_position, @graph_height)
589
+ # X-Axis
590
+ y_offset = (1 - relative_position) * @graph_height
561
591
  @graph.add_element( "path", {
562
- "d" => "M 0 0 v#@graph_height",
592
+ "d" => "M 0 #{y_offset} h#@graph_width",
563
593
  "class" => "axis",
564
- "id" => "xAxis"
594
+ "id" => "yAxis"
565
595
  })
596
+ end
597
+
598
+ # draws the y-axis; can be overridden by child classes
599
+ def draw_y_axis
600
+ # relative position on x-axis (hence @graph_width is our axis length)
601
+ relative_position = calculate_rel_position(get_x_labels, field_width, @y_axis_position, @graph_width)
602
+ # Y-Axis
603
+ x_offset = relative_position * @graph_width
566
604
  @graph.add_element( "path", {
567
- "d" => "M 0 #@graph_height h#@graph_width",
605
+ "d" => "M #{x_offset} 0 v#@graph_height",
568
606
  "class" => "axis",
569
- "id" => "yAxis"
607
+ "id" => "xAxis"
570
608
  })
571
-
572
- draw_x_labels
573
- draw_y_labels
574
609
  end
575
610
 
611
+ # calculates the relative position betewen 0 and 1 of a value on the axis
612
+ # can be multiplied with either @graph_height or @graph_width to get the
613
+ # absolute position in pixels.
614
+ # If labels are strings, checks if one of label matches with the value
615
+ # and returns this position.
616
+ # If labels are numeric, compute relative position between first and last value
617
+ # If nothing else applies or the value is nil, the relative position is 0
618
+ # @param labels [Array] the array of x or y labels, see {#get_x_labels} or {#get_y_labels}
619
+ # @param segment_px [Float] number of pixels per label, see {#field_width} or {#field_height}
620
+ # @param value [Numeric, String] the value for which the relative position is computed
621
+ # @param axis_length [Numeric] either @graph_width or @graph_height
622
+ # @return [Float] relative position between 0 and 1, returns 0
623
+ def calculate_rel_position(labels, segment_px, value, axis_length)
624
+ # default value, y-axis on the left side, or x-axis at bottom
625
+ # puts "calculate_rel_position:"
626
+ # p labels
627
+ # p segment_px
628
+ # p value
629
+ # p axis_length
630
+ relative_position = 0
631
+ if !value.nil? # only
632
+ if (labels[0].is_a? Numeric) && (labels[-1].is_a? Numeric) && (value.is_a? Numeric)
633
+ # labels are numeric, compute relative position between first and last value
634
+ range = labels[-1] - labels[0]
635
+ position = value - labels[0]
636
+ # compute how many segments long the offset is
637
+ relative_to_segemts = position/range * (labels.size - 1)
638
+ # convert from segments to relative position on the axis axis,
639
+ # the number of segments (i.e. relative_to_segemts >= 1)
640
+ relative_position = relative_to_segemts * segment_px / axis_length
641
+ elsif labels[0].is_a? String
642
+ # labels are strings, see if one of label matches with the position
643
+ # and place the axis there
644
+ index = labels.index(value)
645
+ if !index.nil? # index would be nil if label is not found
646
+ offset_px = segment_px * index
647
+ relative_position = offset_px/axis_length # between 0 and 1
648
+ end
649
+ end
650
+ end # value.nil?
651
+ return relative_position
652
+ end
576
653
 
577
654
  # Where in the X area the label is drawn
578
655
  # Centered in the field, should be width/2. Start, 0.
579
656
  def x_label_offset( width )
580
657
  0
581
658
  end
582
-
659
+
583
660
  # check if an object can be converted to float
584
661
  def numeric?(object)
585
- true if Float(object) rescue false
662
+ # true if Float(object) rescue false
663
+ object.is_a? Numeric
586
664
  end
587
665
 
588
666
  # adds the datapoint text to the graph only if the config option is set
@@ -604,7 +682,7 @@ module SVG
604
682
  "y" => y.to_s,
605
683
  "class" => "dataPointLabel",
606
684
  "style" => "#{style} stroke: #fff; stroke-width: 2;"
607
- }).text = textStr
685
+ }).text = textStr
608
686
  # actual label
609
687
  text = @foreground.add_element( "text", {
610
688
  "x" => x.to_s,
@@ -615,60 +693,60 @@ module SVG
615
693
  text.attributes["style"] = style if style.length > 0
616
694
  end
617
695
  end
618
-
619
696
 
620
- # Draws the X axis labels
697
+
698
+ # Draws the X axis labels. The x-axis (@graph_width) is diveded into
699
+ # {#get_x_labels.length} equal sections. The (center) x-coordinate for a
700
+ # label hence is label_index * width_of_section
621
701
  def draw_x_labels
622
702
  stagger = x_label_font_size + 5
623
- if show_x_labels
624
- label_width = field_width
703
+ label_width = field_width
704
+ count = 0
705
+ x_axis_already_drawn = false
706
+ for label in get_x_labels
707
+ if step_include_first_x_label == true then
708
+ step = count % step_x_labels
709
+ else
710
+ step = (count + 1) % step_x_labels
711
+ end
712
+ # only draw every n-th label as defined by step_x_labels
713
+ if step == 0 && show_x_labels then
714
+ textStr = label.to_s
715
+ if( numeric?(label) )
716
+ textStr = @number_format % label
717
+ end
718
+ text = @graph.add_element( "text" )
719
+ text.attributes["class"] = "xAxisLabels"
720
+ text.text = textStr
625
721
 
626
- count = 0
627
- for label in get_x_labels
628
- if step_include_first_x_label == true then
629
- step = count % step_x_labels
630
- else
631
- step = (count + 1) % step_x_labels
722
+ x = count * label_width + x_label_offset( label_width )
723
+ y = @graph_height + x_label_font_size + 3
724
+ #t = 0 - (font_size / 2)
725
+
726
+ if stagger_x_labels and count % 2 == 1
727
+ y += stagger
728
+ @graph.add_element( "path", {
729
+ "d" => "M#{x} #@graph_height v#{stagger}",
730
+ "class" => "staggerGuideLine"
731
+ })
632
732
  end
633
733
 
634
- if step == 0 then
635
- label = label.to_s
636
- if( numeric?(label) )
637
- label = @number_format % label
638
- end
639
- text = @graph.add_element( "text" )
640
- text.attributes["class"] = "xAxisLabels"
641
- text.text = label.to_s
642
-
643
- x = count * label_width + x_label_offset( label_width )
644
- y = @graph_height + x_label_font_size + 3
645
- #t = 0 - (font_size / 2)
646
-
647
- if stagger_x_labels and count % 2 == 1
648
- y += stagger
649
- @graph.add_element( "path", {
650
- "d" => "M#{x} #@graph_height v#{stagger}",
651
- "class" => "staggerGuideLine"
652
- })
653
- end
654
-
655
- text.attributes["x"] = x.to_s
656
- text.attributes["y"] = y.to_s
657
- if rotate_x_labels
658
- text.attributes["transform"] =
659
- "rotate( 90 #{x} #{y-x_label_font_size} )"+
660
- " translate( 0 -#{x_label_font_size/4} )"
661
- text.attributes["style"] = "text-anchor: start"
662
- else
663
- text.attributes["style"] = "text-anchor: middle"
664
- end
734
+ text.attributes["x"] = x.to_s
735
+ text.attributes["y"] = y.to_s
736
+ if rotate_x_labels
737
+ text.attributes["transform"] =
738
+ "rotate( 90 #{x} #{y-x_label_font_size} )"+
739
+ " translate( 0 -#{x_label_font_size/4} )"
740
+ text.attributes["style"] = "text-anchor: start"
741
+ else
742
+ text.attributes["style"] = "text-anchor: middle"
665
743
  end
744
+ end # if step == 0 && show_x_labels
666
745
 
667
- draw_x_guidelines( label_width, count ) if show_x_guidelines
668
- count += 1
669
- end
670
- end
671
- end
746
+ draw_x_guidelines( label_width, count ) if show_x_guidelines
747
+ count += 1
748
+ end # for label in get_x_labels
749
+ end # draw_x_labels
672
750
 
673
751
 
674
752
  # Where in the Y area the label is drawn
@@ -681,17 +759,17 @@ module SVG
681
759
  # must return the array of labels for the x-axis
682
760
  def get_x_labels
683
761
  end
684
-
762
+
685
763
  # override this method in child class
686
764
  # must return the array of labels for the y-axis
687
765
  # this method defines @y_scale_division
688
766
  def get_y_labels
689
767
  end
690
-
768
+
691
769
  # space in px between x-labels
692
770
  def field_width
693
771
  # -1 is to use entire x-axis
694
- # otherwise there is always 1 division unused
772
+ # otherwise there is always 1 division unused
695
773
  @graph_width.to_f / ( get_x_labels.length - 1 )
696
774
  end
697
775
 
@@ -704,21 +782,20 @@ module SVG
704
782
 
705
783
 
706
784
  # Draws the Y axis labels, the Y-Axis (@graph_height) is divided equally into #get_y_labels.lenght sections
707
- # So the y coordinate for an arbitrary value is calculated as follows:
785
+ # So the y coordinate for an arbitrary value is calculated as follows:
708
786
  # y = @graph_height equals the min_value
709
- # #normalize value of a single scale_division:
710
- # count = value /(@y_scale_division)
711
- # y = @graph_height - count * field_height
712
- #
787
+ # #normalize value of a single scale_division:
788
+ # count = value /(@y_scale_division)
789
+ # y = @graph_height - count * field_height
790
+ #
713
791
  def draw_y_labels
714
792
  stagger = y_label_font_size + 5
715
- if show_y_labels
716
- label_height = field_height
717
-
718
- count = 0
719
- y_offset = @graph_height + y_label_offset( label_height )
720
- y_offset += font_size/1.2 unless rotate_y_labels
721
- for label in get_y_labels
793
+ label_height = field_height
794
+ count = 0
795
+ y_offset = @graph_height + y_label_offset( label_height )
796
+ y_offset += font_size/1.2 unless rotate_y_labels
797
+ for label in get_y_labels
798
+ if show_y_labels
722
799
  y = y_offset - (label_height * count)
723
800
  x = rotate_y_labels ? 0 : -3
724
801
 
@@ -748,14 +825,14 @@ module SVG
748
825
  text.attributes["y"] = (y - (y_label_font_size/2)).to_s
749
826
  text.attributes["style"] = "text-anchor: end"
750
827
  end
751
- draw_y_guidelines( label_height, count ) if show_y_guidelines
752
- count += 1
753
- end
754
- end
755
- end
828
+ end # if show_y_labels
829
+ draw_y_guidelines( label_height, count ) if show_y_guidelines
830
+ count += 1
831
+ end # for label in get_y_labels
832
+ end # draw_y_labels
756
833
 
757
834
 
758
- # Draws the X axis guidelines
835
+ # Draws the X axis guidelines, parallel to the y-axis
759
836
  def draw_x_guidelines( label_height, count )
760
837
  if count != 0
761
838
  @graph.add_element( "path", {
@@ -766,7 +843,7 @@ module SVG
766
843
  end
767
844
 
768
845
 
769
- # Draws the Y axis guidelines
846
+ # Draws the Y axis guidelines, parallel to the x-axis
770
847
  def draw_y_guidelines( label_height, count )
771
848
  if count != 0
772
849
  @graph.add_element( "path", {
@@ -788,7 +865,7 @@ module SVG
788
865
  end
789
866
 
790
867
  if show_graph_subtitle
791
- y_subtitle = show_graph_title ?
868
+ y_subtitle = show_graph_title ?
792
869
  title_font_size + subtitle_font_size + 5 :
793
870
  subtitle_font_size
794
871
  @root.add_element("text", {
@@ -840,7 +917,7 @@ module SVG
840
917
  end
841
918
  end # draw_titles
842
919
 
843
- def keys
920
+ def keys
844
921
  i = 0
845
922
  return @data.collect{ |d| i+=1; d[:title] || "Serie #{i}" }
846
923
  end
@@ -893,7 +970,7 @@ module SVG
893
970
  sort_multiple(arrys, lo, p-1)
894
971
  sort_multiple(arrys, p+1, hi)
895
972
  end
896
- arrys
973
+ arrys
897
974
  end
898
975
 
899
976
  def partition( arrys, lo, hi )
@@ -955,11 +1032,11 @@ module SVG
955
1032
  def add_defs defs
956
1033
  end
957
1034
 
958
- # Creates the XML document and adds the root svg element with
1035
+ # Creates the XML document and adds the root svg element with
959
1036
  # the width, height and viewBox attributes already set.
960
- # The element is stored as @root.
1037
+ # The element is stored as @root.
961
1038
  #
962
- # In addition a rectangle background of the same size as the
1039
+ # In addition a rectangle background of the same size as the
963
1040
  # svg is added.
964
1041
  #
965
1042
  def start_svg
@@ -1096,7 +1173,7 @@ module SVG
1096
1173
  .staggerGuideLine{
1097
1174
  fill: none;
1098
1175
  stroke: #000000;
1099
- stroke-width: 0.5px;
1176
+ stroke-width: 0.5px;
1100
1177
  }
1101
1178
 
1102
1179
  #{get_css}
@@ -3,47 +3,47 @@ require_relative 'Graph'
3
3
  module SVG
4
4
  module Graph
5
5
  # === Create presentation quality SVG line graphs easily
6
- #
6
+ #
7
7
  # = Synopsis
8
- #
8
+ #
9
9
  # require 'SVG/Graph/Line'
10
- #
10
+ #
11
11
  # fields = %w(Jan Feb Mar);
12
12
  # data_sales_02 = [12, 45, 21]
13
13
  # data_sales_03 = [15, 30, 40]
14
- #
14
+ #
15
15
  # graph = SVG::Graph::Line.new({
16
16
  # :height => 500,
17
17
  # :width => 300,
18
18
  # :fields => fields,
19
19
  # })
20
- #
20
+ #
21
21
  # graph.add_data({
22
22
  # :data => data_sales_02,
23
23
  # :title => 'Sales 2002',
24
24
  # })
25
- #
25
+ #
26
26
  # graph.add_data({
27
27
  # :data => data_sales_03,
28
28
  # :title => 'Sales 2003',
29
29
  # })
30
- #
30
+ #
31
31
  # print "Content-type: image/svg+xml\r\n\r\n";
32
32
  # print graph.burn();
33
- #
33
+ #
34
34
  # = Description
35
- #
35
+ #
36
36
  # This object aims to allow you to easily create high quality
37
37
  # SVG line graphs. You can either use the default style sheet
38
38
  # or supply your own. Either way there are many options which can
39
39
  # be configured to give you control over how the graph is
40
40
  # generated - with or without a key, data elements at each point,
41
41
  # title, subtitle etc.
42
- #
42
+ #
43
43
  # = Examples
44
- #
44
+ #
45
45
  # http://www.germane-software/repositories/public/SVG/test/single.rb
46
- #
46
+ #
47
47
  # = Notes
48
48
  # Only number of fileds datapoints will be drawn, additional data values
49
49
  # are ignored. Nil values in data are skipped and
@@ -54,9 +54,9 @@ module SVG
54
54
  # additional settings for the extra data sets. You will know
55
55
  # if you go over 10 data sets as they will have no style and
56
56
  # be in black.
57
- #
57
+ #
58
58
  # = See also
59
- #
59
+ #
60
60
  # * SVG::Graph::Graph
61
61
  # * SVG::Graph::BarHorizontal
62
62
  # * SVG::Graph::Bar
@@ -75,14 +75,14 @@ module SVG
75
75
  # Show a small circle on the graph where the line
76
76
  # goes from one point to the next.
77
77
  attr_accessor :show_data_points
78
- # Accumulates each data set. (i.e. Each point increased by sum of
78
+ # Accumulates each data set. (i.e. Each point increased by sum of
79
79
  # all previous series at same point). Default is 0, set to '1' to show.
80
80
  attr_accessor :stacked
81
81
  # Fill in the area under the plot if true
82
82
  attr_accessor :area_fill
83
83
 
84
84
  # The constructor takes a hash reference, :fields (the names for each
85
- # field on the X axis) MUST be set, all other values are defaulted to
85
+ # field on the X axis) MUST be set, all other values are defaulted to
86
86
  # those shown above - with the exception of style_sheet which defaults
87
87
  # to using the internal style sheet.
88
88
  def initialize config
@@ -112,7 +112,7 @@ module SVG
112
112
  max = 0
113
113
  if stacked
114
114
  sums = Array.new(@config[:fields].length).fill(0)
115
-
115
+
116
116
  @data.each do |data|
117
117
  sums.each_index do |i|
118
118
  sums[i] += data[:data][i].to_f
@@ -125,7 +125,7 @@ module SVG
125
125
  x[:data].compact.max
126
126
  }.max
127
127
  end
128
-
128
+
129
129
  return max
130
130
  end
131
131
 
@@ -167,7 +167,7 @@ module SVG
167
167
 
168
168
  @y_scale_division = scale_divisions || (scale_range / 10.0)
169
169
  @y_offset = 0
170
-
170
+
171
171
  if scale_integers
172
172
  @y_scale_division = @y_scale_division < 1 ? 1 : @y_scale_division.round
173
173
  @y_offset = (minvalue.to_f - minvalue.floor).to_f
@@ -201,10 +201,10 @@ module SVG
201
201
  for data in @data.reverse
202
202
  lpath = ""
203
203
  apath = ""
204
-
204
+
205
205
  # reset cum_sum if we are not in a stacked graph
206
206
  if not stacked then cum_sum.fill(nil) end
207
-
207
+
208
208
  # only consider as many datapoints as we have fields
209
209
  @config[:fields].each_index do |i|
210
210
  next if data[:data][i].nil?
@@ -216,33 +216,33 @@ module SVG
216
216
  c = calc_coords(i, cum_sum[i], fieldwidth, fieldheight)
217
217
  lpath << "#{c[:x]} #{c[:y]} "
218
218
  end
219
-
219
+
220
220
  if area_fill
221
221
  if stacked then
222
222
  (prev_sum.length - 1).downto 0 do |i|
223
223
  next if prev_sum[i].nil?
224
224
  c = calc_coords(i, prev_sum[i], fieldwidth, fieldheight)
225
-
225
+
226
226
  apath << "#{c[:x]} #{c[:y]} "
227
227
  end
228
-
228
+
229
229
  c = calc_coords(0, prev_sum[0], fieldwidth, fieldheight)
230
230
  else
231
231
  apath = "V#@graph_height"
232
232
  c = calc_coords(0, -@y_offset, fieldwidth, fieldheight)
233
233
  end
234
-
234
+
235
235
  @graph.add_element("path", {
236
236
  "d" => "M#{c[:x]} #{c[:y]} L" + lpath + apath + "Z",
237
237
  "class" => "fill#{line}"
238
238
  })
239
239
  end
240
-
240
+
241
241
  @graph.add_element("path", {
242
242
  "d" => "M0 #@graph_height L" + lpath,
243
243
  "class" => "line#{line}"
244
244
  })
245
-
245
+
246
246
  if show_data_points || show_data_values || add_popups
247
247
  cum_sum.each_index do |i|
248
248
  # skip datapoint if nil
@@ -258,7 +258,8 @@ module SVG
258
258
  end
259
259
 
260
260
  make_datapoint_text( c[:x], c[:y] - font_size/2, cum_sum[i] + minvalue)
261
- add_popup(c[:x], c[:y], cum_sum[i] + minvalue)
261
+ # number format shall not apply to popup (use .to_s conversion)
262
+ add_popup(c[:x], c[:y], (cum_sum[i] + minvalue).to_s)
262
263
  end
263
264
  end
264
265
 
@@ -274,62 +275,62 @@ module SVG
274
275
  .line1{
275
276
  fill: none;
276
277
  stroke: #ff0000;
277
- stroke-width: 1px;
278
+ stroke-width: 1px;
278
279
  }
279
280
  .line2{
280
281
  fill: none;
281
282
  stroke: #0000ff;
282
- stroke-width: 1px;
283
+ stroke-width: 1px;
283
284
  }
284
285
  .line3{
285
286
  fill: none;
286
287
  stroke: #00ff00;
287
- stroke-width: 1px;
288
+ stroke-width: 1px;
288
289
  }
289
290
  .line4{
290
291
  fill: none;
291
292
  stroke: #ffcc00;
292
- stroke-width: 1px;
293
+ stroke-width: 1px;
293
294
  }
294
295
  .line5{
295
296
  fill: none;
296
297
  stroke: #00ccff;
297
- stroke-width: 1px;
298
+ stroke-width: 1px;
298
299
  }
299
300
  .line6{
300
301
  fill: none;
301
302
  stroke: #ff00ff;
302
- stroke-width: 1px;
303
+ stroke-width: 1px;
303
304
  }
304
305
  .line7{
305
306
  fill: none;
306
307
  stroke: #00ffff;
307
- stroke-width: 1px;
308
+ stroke-width: 1px;
308
309
  }
309
310
  .line8{
310
311
  fill: none;
311
312
  stroke: #ffff00;
312
- stroke-width: 1px;
313
+ stroke-width: 1px;
313
314
  }
314
315
  .line9{
315
316
  fill: none;
316
317
  stroke: #ccc6666;
317
- stroke-width: 1px;
318
+ stroke-width: 1px;
318
319
  }
319
320
  .line10{
320
321
  fill: none;
321
322
  stroke: #663399;
322
- stroke-width: 1px;
323
+ stroke-width: 1px;
323
324
  }
324
325
  .line11{
325
326
  fill: none;
326
327
  stroke: #339900;
327
- stroke-width: 1px;
328
+ stroke-width: 1px;
328
329
  }
329
330
  .line12{
330
331
  fill: none;
331
332
  stroke: #9966FF;
332
- stroke-width: 1px;
333
+ stroke-width: 1px;
333
334
  }
334
335
  /* default fill styles */
335
336
  .fill1{
@@ -396,62 +397,62 @@ module SVG
396
397
  .key1,.dataPoint1{
397
398
  fill: #ff0000;
398
399
  stroke: none;
399
- stroke-width: 1px;
400
+ stroke-width: 1px;
400
401
  }
401
402
  .key2,.dataPoint2{
402
403
  fill: #0000ff;
403
404
  stroke: none;
404
- stroke-width: 1px;
405
+ stroke-width: 1px;
405
406
  }
406
407
  .key3,.dataPoint3{
407
408
  fill: #00ff00;
408
409
  stroke: none;
409
- stroke-width: 1px;
410
+ stroke-width: 1px;
410
411
  }
411
412
  .key4,.dataPoint4{
412
413
  fill: #ffcc00;
413
414
  stroke: none;
414
- stroke-width: 1px;
415
+ stroke-width: 1px;
415
416
  }
416
417
  .key5,.dataPoint5{
417
418
  fill: #00ccff;
418
419
  stroke: none;
419
- stroke-width: 1px;
420
+ stroke-width: 1px;
420
421
  }
421
422
  .key6,.dataPoint6{
422
423
  fill: #ff00ff;
423
424
  stroke: none;
424
- stroke-width: 1px;
425
+ stroke-width: 1px;
425
426
  }
426
427
  .key7,.dataPoint7{
427
428
  fill: #00ffff;
428
429
  stroke: none;
429
- stroke-width: 1px;
430
+ stroke-width: 1px;
430
431
  }
431
432
  .key8,.dataPoint8{
432
433
  fill: #ffff00;
433
434
  stroke: none;
434
- stroke-width: 1px;
435
+ stroke-width: 1px;
435
436
  }
436
437
  .key9,.dataPoint9{
437
438
  fill: #cc6666;
438
439
  stroke: none;
439
- stroke-width: 1px;
440
+ stroke-width: 1px;
440
441
  }
441
442
  .key10,.dataPoint10{
442
443
  fill: #663399;
443
444
  stroke: none;
444
- stroke-width: 1px;
445
+ stroke-width: 1px;
445
446
  }
446
447
  .key11,.dataPoint11{
447
448
  fill: #339900;
448
449
  stroke: none;
449
- stroke-width: 1px;
450
+ stroke-width: 1px;
450
451
  }
451
452
  .key12,.dataPoint12{
452
453
  fill: #9966FF;
453
454
  stroke: none;
454
- stroke-width: 1px;
455
+ stroke-width: 1px;
455
456
  }
456
457
  EOL
457
458
  end
@@ -1,6 +1,6 @@
1
1
  module SVG
2
2
  module Graph
3
- VERSION = '2.0.2'
3
+ VERSION = '2.1.0.beta1'
4
4
  end
5
5
  end
6
6
  require_relative 'SVG/Graph/DataPoint'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svg-graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Russell
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2016-10-26 00:00:00.000000000 Z
15
+ date: 2017-02-13 00:00:00.000000000 Z
16
16
  dependencies: []
17
17
  description: "Gem version of SVG:::Graph. SVG:::Graph is a pure Ruby library for generating
18
18
  charts, \nwhich are a type of graph where the values of one axis are not scalar.
@@ -67,12 +67,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
67
67
  version: '0'
68
68
  required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  requirements:
70
- - - ">="
70
+ - - ">"
71
71
  - !ruby/object:Gem::Version
72
- version: '0'
72
+ version: 1.3.1
73
73
  requirements: []
74
74
  rubyforge_project:
75
- rubygems_version: 2.6.7
75
+ rubygems_version: 2.6.10
76
76
  signing_key:
77
77
  specification_version: 4
78
78
  summary: SVG:::Graph is a pure Ruby library for generating charts, which are a type