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.
- 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
|