svg-graph 1.0.5 → 2.0.1

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