svg-graph 1.0.5 → 2.0.1

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +18 -0
  3. data/README.markdown +90 -6
  4. data/Rakefile +26 -14
  5. data/lib/SVG/Graph/Bar.rb +2 -2
  6. data/lib/SVG/Graph/BarBase.rb +25 -24
  7. data/lib/SVG/Graph/BarHorizontal.rb +1 -1
  8. data/lib/SVG/Graph/ErrBar.rb +189 -0
  9. data/lib/SVG/Graph/Graph.rb +141 -64
  10. data/lib/SVG/Graph/Line.rb +1 -1
  11. data/lib/SVG/Graph/Pie.rb +76 -49
  12. data/lib/SVG/Graph/Plot.rb +2 -2
  13. data/lib/SVG/Graph/Schedule.rb +18 -19
  14. data/lib/SVG/Graph/TimeSeries.rb +26 -22
  15. data/lib/svggraph.rb +12 -10
  16. data/test/test_svg_graph.rb +48 -6
  17. metadata +41 -136
  18. data.tar.gz.sig +0 -2
  19. data/Manifest.txt +0 -56
  20. data/build.xml +0 -143
  21. data/dist.xml.in +0 -46
  22. data/images/bar.png +0 -0
  23. data/images/bar.svg +0 -76
  24. data/images/bar.svgz +0 -0
  25. data/images/barhorizontal.png +0 -0
  26. data/images/barhorizontal.svg +0 -76
  27. data/images/barhorizontal.svgz +0 -0
  28. data/images/line.png +0 -0
  29. data/images/line.svg +0 -80
  30. data/images/line.svgz +0 -0
  31. data/images/pie.png +0 -0
  32. data/images/pie.svg +0 -70
  33. data/images/pie.svgz +0 -0
  34. data/images/plot.png +0 -0
  35. data/images/plot.svg +0 -131
  36. data/images/plot.svgz +0 -0
  37. data/images/schedule.png +0 -0
  38. data/images/schedule.svg +0 -67
  39. data/images/timeseries.png +0 -0
  40. data/images/timeseries.svg +0 -179
  41. data/images/timeseries.svgz +0 -0
  42. data/index.xml +0 -281
  43. data/install.rb +0 -161
  44. data/screenshots.xml +0 -148
  45. data/style/common.xsl +0 -37
  46. data/style/release_html.xsl +0 -169
  47. data/style/release_txt.xsl +0 -25
  48. data/svg-graph.gemspec +0 -58
  49. data/test/data.txt +0 -4
  50. data/test/plot.rb +0 -51
  51. data/test/schedule.rb +0 -43
  52. data/test/single.rb +0 -33
  53. data/test/test.rb +0 -54
  54. data/test/test_data_point.rb +0 -67
  55. data/test/test_plot.rb +0 -282
  56. data/test/timeseries.rb +0 -58
  57. metadata.gz.sig +0 -1
@@ -1,8 +1,7 @@
1
1
  begin
2
2
  require 'zlib'
3
- @@__have_zlib = true
4
3
  rescue
5
- @@__have_zlib = false
4
+ # No Zlib.
6
5
  end
7
6
 
8
7
  require 'rexml/document'
@@ -78,9 +77,11 @@ module SVG
78
77
  # [scale_integers] false
79
78
  # [show_x_title] false
80
79
  # [x_title] 'X Field names'
80
+ # [x_title_location] :middle | :end
81
81
  # [show_y_title] false
82
- # [y_title_text_direction] :bt
82
+ # [y_title_text_direction] :bt | :tb
83
83
  # [y_title] 'Y Scale'
84
+ # [y_title_location] :middle | :end
84
85
  # [show_graph_title] false
85
86
  # [graph_title] 'Graph Title'
86
87
  # [show_graph_subtitle] false
@@ -97,19 +98,20 @@ module SVG
97
98
  # [key_font_size] 10
98
99
  # [no_css] false
99
100
  # [add_popups] false
101
+ # [number_format] '%.2f'
100
102
  def initialize( config )
101
103
  @config = config
102
- @data = nil
104
+ @data = []
103
105
  self.top_align = self.top_font = self.right_align = self.right_font = 0
104
106
 
105
107
  init_with({
106
108
  :width => 500,
107
- :height => 300,
109
+ :height => 300,
108
110
  :show_x_guidelines => false,
109
111
  :show_y_guidelines => true,
110
112
  :show_data_values => true,
111
113
 
112
- # :min_scale_value => 0,
114
+ :min_scale_value => nil,
113
115
 
114
116
  :show_x_labels => true,
115
117
  :stagger_x_labels => false,
@@ -124,10 +126,12 @@ module SVG
124
126
 
125
127
  :show_x_title => false,
126
128
  :x_title => 'X Field names',
129
+ :x_title_location => :middle, # or :end
127
130
 
128
131
  :show_y_title => false,
129
- :y_title_text_direction => :bt,
132
+ :y_title_text_direction => :bt, # other option is :tb
130
133
  :y_title => 'Y Scale',
134
+ :y_title_location => :middle, # or :end
131
135
 
132
136
  :show_graph_title => false,
133
137
  :graph_title => 'Graph Title',
@@ -142,12 +146,12 @@ module SVG
142
146
  :x_label_font_size =>12,
143
147
  :y_label_font_size =>12,
144
148
  :x_title_font_size =>14,
145
- :y_label_font_size =>12,
146
149
  :y_title_font_size =>14,
147
150
  :key_font_size =>10,
148
151
 
149
152
  :no_css =>false,
150
153
  :add_popups =>false,
154
+ :number_format => '%.2f'
151
155
  })
152
156
  set_defaults if self.respond_to? :set_defaults
153
157
  init_with config
@@ -164,7 +168,7 @@ module SVG
164
168
  # :title => 'Sales 2002'
165
169
  # })
166
170
  def add_data conf
167
- @data = [] unless (defined? @data and !@data.nil?)
171
+ @data = [] unless (defined? @data and !@data.nil?)
168
172
 
169
173
  if conf[:data] and conf[:data].kind_of? Array
170
174
  @data << conf
@@ -209,7 +213,7 @@ module SVG
209
213
  @doc.write( data, 0 )
210
214
 
211
215
  if @config[:compress]
212
- if @@__have_zlib
216
+ if defined?(Zlib)
213
217
  inp, out = IO.pipe
214
218
  gz = Zlib::GzipWriter.new( out )
215
219
  gz.write data
@@ -222,6 +226,21 @@ module SVG
222
226
 
223
227
  return data
224
228
  end
229
+
230
+ # Burns the graph but returns only the <svg> node as String without the
231
+ # Doctype and XML Declaration. This allows easy integration into
232
+ # existing xml documents.
233
+ #
234
+ # @return [String] the SVG node which represents the Graph
235
+ def burn_svg_only
236
+ # initialize all instance variables by burning the graph
237
+ burn
238
+ f = REXML::Formatters::Pretty.new(0)
239
+ f.compact = true
240
+ out = ''
241
+ f.write(@root, out)
242
+ return out
243
+ end
225
244
 
226
245
 
227
246
  # Set the height of the graph box, this is the total height
@@ -241,7 +260,7 @@ module SVG
241
260
  attr_accessor :style_sheet
242
261
  # (Bool) Show the value of each element of data on the graph
243
262
  attr_accessor :show_data_values
244
- # The point at which the Y axis starts, defaults to '0',
263
+ # The point at which the Y axis starts, defaults to nil,
245
264
  # if set to nil it will default to the minimum data value.
246
265
  attr_accessor :min_scale_value
247
266
  # Whether to show labels on the X axis or not, defaults
@@ -290,6 +309,9 @@ module SVG
290
309
  attr_accessor :show_x_title
291
310
  # What the title under X axis should be, e.g. 'Months'.
292
311
  attr_accessor :x_title
312
+ # Where the x_title should be positioned, either in the :middle of the axis or
313
+ # at the :end of the axis. Defaults to :middle
314
+ attr_accessor :x_title_location
293
315
  # Whether to show the title under the Y axis labels,
294
316
  # default is false, set to true to show.
295
317
  attr_accessor :show_y_title
@@ -299,6 +321,9 @@ module SVG
299
321
  attr_accessor :y_title_text_direction
300
322
  # What the title under Y axis should be, e.g. 'Sales in thousands'.
301
323
  attr_accessor :y_title
324
+ # Where the y_title should be positioned, either in the :middle of the axis or
325
+ # at the :end of the axis. Defaults to :middle
326
+ attr_accessor :y_title_location
302
327
  # Whether to show a title on the graph, defaults
303
328
  # to false, set to true to show.
304
329
  attr_accessor :show_graph_title
@@ -309,40 +334,51 @@ module SVG
309
334
  attr_accessor :show_graph_subtitle
310
335
  # What the subtitle on the graph should be.
311
336
  attr_accessor :graph_subtitle
312
- # Whether to show a key, defaults to false, set to
313
- # true if you want to show it.
337
+ # Whether to show a key (legend), defaults to true, set to
338
+ # false if you want to hide it.
314
339
  attr_accessor :key
315
340
  # Where the key should be positioned, defaults to
316
341
  # :right, set to :bottom if you want to move it.
317
342
  attr_accessor :key_position
318
- # Set the font size (in points) of the data point labels
343
+ # Set the font size (in points) of the data point labels.
344
+ # Defaults to 12.
319
345
  attr_accessor :font_size
320
- # Set the font size of the X axis labels
346
+ # Set the font size of the X axis labels.
347
+ # Defaults to 12.
321
348
  attr_accessor :x_label_font_size
322
- # Set the font size of the X axis title
349
+ # Set the font size of the X axis title.
350
+ # Defaults to 14.
323
351
  attr_accessor :x_title_font_size
324
- # Set the font size of the Y axis labels
352
+ # Set the font size of the Y axis labels.
353
+ # Defaults to 12.
325
354
  attr_accessor :y_label_font_size
326
- # Set the font size of the Y axis title
355
+ # Set the font size of the Y axis title.
356
+ # Defaults to 14.
327
357
  attr_accessor :y_title_font_size
328
- # Set the title font size
358
+ # Set the title font size.
359
+ # Defaults to 16.
329
360
  attr_accessor :title_font_size
330
- # Set the subtitle font size
361
+ # Set the subtitle font size.
362
+ # Defaults to 14.
331
363
  attr_accessor :subtitle_font_size
332
- # Set the key font size
364
+ # Set the key font size.
365
+ # Defaults to 10.
333
366
  attr_accessor :key_font_size
334
- # Show guidelines for the X axis
367
+ # Show guidelines for the X axis, default is false
335
368
  attr_accessor :show_x_guidelines
336
- # Show guidelines for the Y axis
369
+ # Show guidelines for the Y axis, default is true
337
370
  attr_accessor :show_y_guidelines
338
371
  # Do not use CSS if set to true. Many SVG viewers do not support CSS, but
339
372
  # not using CSS can result in larger SVGs as well as making it impossible to
340
373
  # change colors after the chart is generated. Defaults to false.
341
374
  attr_accessor :no_css
342
- # Add popups for the data points on some graphs
375
+ # Add popups for the data points on some graphs, default is false.
343
376
  attr_accessor :add_popups
344
377
  # Customize popup radius
345
378
  attr_accessor :popup_radius
379
+ # Number format values and Y axis representation like 1.2345667 represent as 1.23,
380
+ # defaults to '%.2f'
381
+ attr_accessor :number_format
346
382
 
347
383
 
348
384
  protected
@@ -368,15 +404,15 @@ module SVG
368
404
  # of the plot area. Results in @border_left being set.
369
405
  def calculate_left_margin
370
406
  @border_left = 7
371
- # Check for Y labels
372
- max_y_label_height_px = @rotate_y_labels ?
373
- @y_label_font_size :
374
- get_y_labels.max{|a,b|
375
- a.to_s.length<=>b.to_s.length
376
- }.to_s.length * @y_label_font_size * 0.6
377
- @border_left += max_y_label_height_px if @show_y_labels
378
- @border_left += max_y_label_height_px + 10 if @stagger_y_labels
379
- @border_left += y_title_font_size + 5 if @show_y_title
407
+ # Check size of Y labels
408
+ max_y_label_height_px = y_label_font_size
409
+ if !rotate_y_labels
410
+ max_y_label_height_px = get_longest_label(get_y_labels).to_s.length * y_label_font_size * 0.6
411
+ end
412
+
413
+ @border_left += max_y_label_height_px if show_y_labels
414
+ @border_left += max_y_label_height_px + 10 if stagger_y_labels
415
+ @border_left += y_title_font_size + 5 if (show_y_title && (y_title_location ==:middle))
380
416
  end
381
417
 
382
418
 
@@ -397,6 +433,9 @@ module SVG
397
433
  @border_right += KEY_BOX_SIZE
398
434
  @border_right += 10 # Some padding around the box
399
435
  end
436
+ if (x_title_location == :end)
437
+ @border_right = [@border_right, x_title.length * x_title_font_size * 0.6].max
438
+ end
400
439
  end
401
440
 
402
441
 
@@ -404,7 +443,7 @@ module SVG
404
443
  # of the plot area. Results in @border_top being set.
405
444
  def calculate_top_margin
406
445
  @border_top = 5
407
- @border_top += title_font_size if show_graph_title
446
+ @border_top += [title_font_size, y_title_font_size].max if (show_graph_title || (y_title_location ==:end))
408
447
  @border_top += 5
409
448
  @border_top += subtitle_font_size if show_graph_subtitle
410
449
  end
@@ -437,6 +476,18 @@ module SVG
437
476
 
438
477
  end
439
478
 
479
+ # returns the longest label from an array of labels as string
480
+ # each object in the array must support .to_s
481
+ def get_longest_label(arry)
482
+ longest_label = arry.max{|a,b|
483
+ # respect number_format
484
+ a = @number_format % a if numeric?(a)
485
+ b = @number_format % b if numeric?(b)
486
+ a.to_s.length <=> b.to_s.length
487
+ }
488
+ longest_label = @number_format % longest_label if numeric?(longest_label)
489
+ return longest_label
490
+ end
440
491
 
441
492
  # Override this (and call super) to change the margin to the bottom
442
493
  # of the plot area. Results in @border_bottom being set.
@@ -447,15 +498,15 @@ module SVG
447
498
  @border_bottom += 10
448
499
  end
449
500
  if show_x_labels
450
- max_x_label_height_px = (not rotate_x_labels) ?
451
- x_label_font_size :
452
- get_x_labels.max{|a,b|
453
- a.to_s.length<=>b.to_s.length
454
- }.to_s.length * x_label_font_size * 0.6
501
+ max_x_label_height_px = x_label_font_size
502
+ if rotate_x_labels
503
+ max_x_label_height_px = get_longest_label(get_x_labels).to_s.length * x_label_font_size * 0.6
504
+ end
505
+
455
506
  @border_bottom += max_x_label_height_px
456
507
  @border_bottom += max_x_label_height_px + 10 if stagger_x_labels
457
508
  end
458
- @border_bottom += x_title_font_size + 5 if show_x_title
509
+ @border_bottom += x_title_font_size + 5 if (show_x_title && (x_title_location ==:middle))
459
510
  end
460
511
 
461
512
 
@@ -496,21 +547,30 @@ module SVG
496
547
  def x_label_offset( width )
497
548
  0
498
549
  end
550
+
551
+ # check if an object can be converted to float
552
+ def numeric?(object)
553
+ true if Float(object) rescue false
554
+ end
499
555
 
500
556
  def make_datapoint_text( x, y, value, style="" )
501
557
  if show_data_values
558
+ textStr = value
559
+ if( numeric?(value) )
560
+ textStr = @number_format % value
561
+ end
502
562
  @foreground.add_element( "text", {
503
563
  "x" => x.to_s,
504
564
  "y" => y.to_s,
505
565
  "class" => "dataPointLabel",
506
566
  "style" => "#{style} stroke: #fff; stroke-width: 2;"
507
- }).text = value.to_s
567
+ }).text = textStr
508
568
  text = @foreground.add_element( "text", {
509
569
  "x" => x.to_s,
510
570
  "y" => y.to_s,
511
571
  "class" => "dataPointLabel"
512
572
  })
513
- text.text = value.to_s
573
+ text.text = textStr
514
574
  text.attributes["style"] = style if style.length > 0
515
575
  end
516
576
  end
@@ -611,7 +671,11 @@ module SVG
611
671
  "y" => y.to_s,
612
672
  "class" => "yAxisLabels"
613
673
  })
614
- text.text = label.to_s
674
+ textStr = label.to_s
675
+ if( numeric?(label) )
676
+ textStr = @number_format % label
677
+ end
678
+ text.text = textStr
615
679
  if rotate_y_labels
616
680
  text.attributes["transform"] = "translate( -#{font_size} 0 ) "+
617
681
  "rotate( 90 #{x} #{y} ) "
@@ -661,7 +725,7 @@ module SVG
661
725
 
662
726
  if show_graph_subtitle
663
727
  y_subtitle = show_graph_title ?
664
- title_font_size + 10 :
728
+ title_font_size + subtitle_font_size + 5 :
665
729
  subtitle_font_size
666
730
  @root.add_element("text", {
667
731
  "x" => (width / 2).to_s,
@@ -672,11 +736,16 @@ module SVG
672
736
 
673
737
  if show_x_title
674
738
  y = @graph_height + @border_top + x_title_font_size
675
- if show_x_labels
676
- y += x_label_font_size + 5 if stagger_x_labels
677
- y += x_label_font_size + 5
739
+ if (x_title_location == :end)
740
+ y = y - x_title_font_size/2.0
741
+ x = width - x_title.length * x_title_font_size * 0.6/2.0
742
+ else
743
+ x = width / 2
744
+ if show_x_labels
745
+ y += x_label_font_size + 5 if stagger_x_labels
746
+ y += x_label_font_size + 5
747
+ end
678
748
  end
679
- x = width / 2
680
749
 
681
750
  @root.add_element("text", {
682
751
  "x" => x.to_s,
@@ -687,21 +756,29 @@ module SVG
687
756
 
688
757
  if show_y_title
689
758
  x = y_title_font_size + (y_title_text_direction==:bt ? 3 : -3)
690
- y = height / 2
691
-
759
+ if (y_title_location == :end)
760
+ x = y_title.length * y_title_font_size * 0.6/2.0 # positioning is not optimal but ok for now
761
+ y = @border_top - y_title_font_size/2.0
762
+ else
763
+ y = height / 2
764
+ end
692
765
  text = @root.add_element("text", {
693
766
  "x" => x.to_s,
694
767
  "y" => y.to_s,
695
768
  "class" => "yAxisTitle",
696
769
  })
697
770
  text.text = y_title.to_s
698
- if y_title_text_direction == :bt
699
- text.attributes["transform"] = "rotate( -90, #{x}, #{y} )"
700
- else
701
- text.attributes["transform"] = "rotate( 90, #{x}, #{y} )"
771
+ # only rotate text if it is at the middle left of the y-axis
772
+ # ignore the text_direction if y_title_location is set to :end
773
+ if (y_title_location != :end)
774
+ if y_title_text_direction == :bt
775
+ text.attributes["transform"] = "rotate( -90, #{x}, #{y} )"
776
+ else
777
+ text.attributes["transform"] = "rotate( 90, #{x}, #{y} )"
778
+ end
702
779
  end
703
780
  end
704
- end
781
+ end # draw_titles
705
782
 
706
783
  def keys
707
784
  i = 0
@@ -739,11 +816,11 @@ module SVG
739
816
  x_offset = @border_left + 20
740
817
  y_offset = @border_top + @graph_height + 5
741
818
  if show_x_labels
742
- max_x_label_height_px = (not rotate_x_labels) ?
743
- x_label_font_size :
744
- get_x_labels.max{|a,b|
745
- a.to_s.length<=>b.to_s.length
746
- }.to_s.length * x_label_font_size * 0.6
819
+ max_x_label_height_px = (not rotate_x_labels) ?
820
+ x_label_font_size :
821
+ get_x_labels.max{|a,b|
822
+ a.to_s.length<=>b.to_s.length
823
+ }.to_s.length * x_label_font_size * 0.6
747
824
  x_label_font_size
748
825
  y_offset += max_x_label_height_px
749
826
  y_offset += max_x_label_height_px + 5 if stagger_x_labels
@@ -973,8 +1050,8 @@ module SVG
973
1050
  }
974
1051
  /* End copy for external style sheet */
975
1052
  EOL
976
- end
1053
+ end # get_style
977
1054
 
978
- end
979
- end
980
- end
1055
+ end # class Graph
1056
+ end # module Graph
1057
+ end # module SVG
@@ -1,4 +1,4 @@
1
- require 'SVG/Graph/Graph'
1
+ require_relative 'Graph'
2
2
 
3
3
  module SVG
4
4
  module Graph
data/lib/SVG/Graph/Pie.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'SVG/Graph/Graph'
1
+ require_relative 'Graph'
2
2
 
3
3
  module SVG
4
4
  module Graph
@@ -205,9 +205,9 @@ module SVG
205
205
 
206
206
  total = 0
207
207
  max_value = 0
208
- @data.each {|x|
208
+ @data.each {|x|
209
209
  max_value = max_value < x ? x : max_value
210
- total += x
210
+ total += x
211
211
  }
212
212
  percent_scale = 100.0 / total
213
213
 
@@ -216,56 +216,85 @@ module SVG
216
216
  @config[:fields].each_index { |count|
217
217
  value = @data[count]
218
218
  percent = percent_scale * value
219
-
220
219
  radians = prev_percent * rad_mult
221
- x_start = radius+(Math.sin(radians) * radius)
222
- y_start = radius-(Math.cos(radians) * radius)
223
- radians = (prev_percent+percent) * rad_mult
224
- x_end = radius+(Math.sin(radians) * radius)
225
- x_end -= 0.00001 if @data.length == 1
226
- y_end = radius-(Math.cos(radians) * radius)
227
- path = "M#{radius},#{radius} L#{x_start},#{y_start} "+
228
- "A#{radius},#{radius} "+
229
- "0, #{percent >= 50 ? '1' : '0'},1, "+
230
- "#{x_end} #{y_end} Z"
231
-
232
-
233
- wedge = @foreground.add_element( "path", {
234
- "d" => path,
235
- "class" => "fill#{count+1}"
236
- })
237
-
238
- translate = nil
239
- tx = 0
240
- ty = 0
241
- half_percent = prev_percent + percent / 2
242
- radians = half_percent * rad_mult
243
-
244
- if show_shadow
245
- shadow = background.add_element( "path", {
246
- "d" => path,
247
- "filter" => "url(#dropshadow)",
248
- "style" => "fill: #ccc; stroke: none;"
220
+
221
+ if percent == 100.0
222
+ @foreground.add_element( "circle", {
223
+ "cx" => radius.to_s,
224
+ "cy" => radius.to_s,
225
+ "r" => radius.to_s,
226
+ "class" => "fill1"
249
227
  })
250
- clear = midground.add_element( "path", {
228
+
229
+ if show_shadow
230
+ shadow = background.add_element( "circle", {
231
+ "cx" => radius.to_s,
232
+ "cy" => radius.to_s,
233
+ "r" => radius.to_s,
234
+ "filter" => "url(#dropshadow)",
235
+ "style" => "fill: #ccc; stroke: none;"
236
+ })
237
+ clear = midground.add_element( "circle", {
238
+ "cx" => radius.to_s,
239
+ "cy" => radius.to_s,
240
+ "r" => radius.to_s,
241
+ "style" => "fill: #fff; stroke: none;"
242
+ })
243
+ shadow.attributes["transform"] =
244
+ "translate( #{shadow_offset} #{shadow_offset} )"
245
+ end
246
+ else
247
+ x_start = radius+(Math.sin(radians) * radius)
248
+ y_start = radius-(Math.cos(radians) * radius)
249
+ radians = (prev_percent+percent) * rad_mult
250
+ x_end = radius+(Math.sin(radians) * radius)
251
+ x_end -= 0.00001 if @data.length == 1
252
+ y_end = radius-(Math.cos(radians) * radius)
253
+ path = "M#{radius},#{radius} L#{x_start},#{y_start} "+
254
+ "A#{radius},#{radius} "+
255
+ "0, #{percent >= 50 ? '1' : '0'},1, "+
256
+ "#{x_end} #{y_end} Z"
257
+
258
+
259
+ wedge = @foreground.add_element( "path", {
251
260
  "d" => path,
252
- "style" => "fill: #fff; stroke: none;"
261
+ "class" => "fill#{count+1}"
253
262
  })
254
- end
255
263
 
256
- if expanded or (expand_greatest && value == max_value)
257
- tx = (Math.sin(radians) * expand_gap)
258
- ty = -(Math.cos(radians) * expand_gap)
259
- translate = "translate( #{tx} #{ty} )"
260
- wedge.attributes["transform"] = translate
261
- clear.attributes["transform"] = translate if clear
262
- end
264
+ translate = nil
265
+ tx = 0
266
+ ty = 0
267
+ half_percent = prev_percent + percent / 2
268
+ radians = half_percent * rad_mult
269
+
270
+ if show_shadow
271
+ shadow = background.add_element( "path", {
272
+ "d" => path,
273
+ "filter" => "url(#dropshadow)",
274
+ "style" => "fill: #ccc; stroke: none;"
275
+ })
276
+ clear = midground.add_element( "path", {
277
+ "d" => path,
278
+ "style" => "fill: #fff; stroke: none;"
279
+ })
280
+ end
263
281
 
264
- if show_shadow
265
- shadow.attributes["transform"] =
266
- "translate( #{tx+shadow_offset} #{ty+shadow_offset} )"
282
+ if expanded or (expand_greatest && value == max_value)
283
+ tx = (Math.sin(radians) * expand_gap)
284
+ ty = -(Math.cos(radians) * expand_gap)
285
+ translate = "translate( #{tx} #{ty} )"
286
+ wedge.attributes["transform"] = translate
287
+ clear.attributes["transform"] = translate if clear
288
+ end
289
+
290
+ if show_shadow
291
+ shadow.attributes["transform"] =
292
+ "translate( #{tx+shadow_offset} #{ty+shadow_offset} )"
293
+ end
294
+
295
+ prev_percent += percent
267
296
  end
268
-
297
+
269
298
  if show_data_labels and value != 0
270
299
  label = ""
271
300
  label += @config[:fields][count] if show_key_data_labels
@@ -293,11 +322,9 @@ module SVG
293
322
  "class" => "dataPointLabel",
294
323
  }).text = label.to_s
295
324
  end
296
-
297
- prev_percent += percent
298
325
  }
299
326
  end
300
-
327
+
301
328
 
302
329
  def round val, to
303
330
  up = 10**to.to_f