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.
- checksums.yaml +7 -0
- data/History.txt +18 -0
- data/README.markdown +90 -6
- data/Rakefile +26 -14
- data/lib/SVG/Graph/Bar.rb +2 -2
- data/lib/SVG/Graph/BarBase.rb +25 -24
- data/lib/SVG/Graph/BarHorizontal.rb +1 -1
- data/lib/SVG/Graph/ErrBar.rb +189 -0
- data/lib/SVG/Graph/Graph.rb +141 -64
- data/lib/SVG/Graph/Line.rb +1 -1
- data/lib/SVG/Graph/Pie.rb +76 -49
- data/lib/SVG/Graph/Plot.rb +2 -2
- data/lib/SVG/Graph/Schedule.rb +18 -19
- data/lib/SVG/Graph/TimeSeries.rb +26 -22
- data/lib/svggraph.rb +12 -10
- data/test/test_svg_graph.rb +48 -6
- metadata +41 -136
- data.tar.gz.sig +0 -2
- data/Manifest.txt +0 -56
- data/build.xml +0 -143
- data/dist.xml.in +0 -46
- data/images/bar.png +0 -0
- data/images/bar.svg +0 -76
- data/images/bar.svgz +0 -0
- data/images/barhorizontal.png +0 -0
- data/images/barhorizontal.svg +0 -76
- data/images/barhorizontal.svgz +0 -0
- data/images/line.png +0 -0
- data/images/line.svg +0 -80
- data/images/line.svgz +0 -0
- data/images/pie.png +0 -0
- data/images/pie.svg +0 -70
- data/images/pie.svgz +0 -0
- data/images/plot.png +0 -0
- data/images/plot.svg +0 -131
- data/images/plot.svgz +0 -0
- data/images/schedule.png +0 -0
- data/images/schedule.svg +0 -67
- data/images/timeseries.png +0 -0
- data/images/timeseries.svg +0 -179
- data/images/timeseries.svgz +0 -0
- data/index.xml +0 -281
- data/install.rb +0 -161
- data/screenshots.xml +0 -148
- data/style/common.xsl +0 -37
- data/style/release_html.xsl +0 -169
- data/style/release_txt.xsl +0 -25
- data/svg-graph.gemspec +0 -58
- data/test/data.txt +0 -4
- data/test/plot.rb +0 -51
- data/test/schedule.rb +0 -43
- data/test/single.rb +0 -33
- data/test/test.rb +0 -54
- data/test/test_data_point.rb +0 -67
- data/test/test_plot.rb +0 -282
- data/test/timeseries.rb +0 -58
- metadata.gz.sig +0 -1
data/lib/SVG/Graph/Graph.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
begin
|
2
2
|
require 'zlib'
|
3
|
-
@@__have_zlib = true
|
4
3
|
rescue
|
5
|
-
|
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 =
|
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
|
109
|
+
:height => 300,
|
108
110
|
:show_x_guidelines => false,
|
109
111
|
:show_y_guidelines => true,
|
110
112
|
:show_data_values => true,
|
111
113
|
|
112
|
-
|
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
|
-
|
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
|
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
|
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
|
313
|
-
#
|
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
|
372
|
-
max_y_label_height_px =
|
373
|
-
|
374
|
-
get_y_labels.
|
375
|
-
|
376
|
-
|
377
|
-
@border_left += max_y_label_height_px if
|
378
|
-
@border_left += max_y_label_height_px + 10 if
|
379
|
-
@border_left += y_title_font_size + 5 if
|
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
|
-
|
451
|
-
|
452
|
-
get_x_labels.
|
453
|
-
|
454
|
-
|
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 =
|
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 =
|
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
|
-
|
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 +
|
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
|
676
|
-
y
|
677
|
-
|
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
|
-
|
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
|
699
|
-
|
700
|
-
|
701
|
-
|
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
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
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
|
data/lib/SVG/Graph/Line.rb
CHANGED
data/lib/SVG/Graph/Pie.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
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
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
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
|
-
|
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
|
-
"
|
261
|
+
"class" => "fill#{count+1}"
|
253
262
|
})
|
254
|
-
end
|
255
263
|
|
256
|
-
|
257
|
-
tx =
|
258
|
-
ty =
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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
|
-
|
265
|
-
|
266
|
-
|
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
|