To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / .svn / pristine / 6d / 6da4657cfa69c954a9a2eba694b2e889d7bbf4f1.svn-base @ 1297:0a574315af3e
History | View | Annotate | Download (4.26 KB)
| 1 |
require 'rexml/document' |
|---|---|
| 2 |
require 'SVG/Graph/Graph' |
| 3 |
require 'SVG/Graph/BarBase' |
| 4 |
|
| 5 |
module SVG |
| 6 |
module Graph |
| 7 |
# === Create presentation quality SVG bar graphs easily |
| 8 |
# |
| 9 |
# = Synopsis |
| 10 |
# |
| 11 |
# require 'SVG/Graph/Bar' |
| 12 |
# |
| 13 |
# fields = %w(Jan Feb Mar); |
| 14 |
# data_sales_02 = [12, 45, 21] |
| 15 |
# |
| 16 |
# graph = SVG::Graph::Bar.new( |
| 17 |
# :height => 500, |
| 18 |
# :width => 300, |
| 19 |
# :fields => fields |
| 20 |
# ) |
| 21 |
# |
| 22 |
# graph.add_data( |
| 23 |
# :data => data_sales_02, |
| 24 |
# :title => 'Sales 2002' |
| 25 |
# ) |
| 26 |
# |
| 27 |
# print "Content-type: image/svg+xml\r\n\r\n" |
| 28 |
# print graph.burn |
| 29 |
# |
| 30 |
# = Description |
| 31 |
# |
| 32 |
# This object aims to allow you to easily create high quality |
| 33 |
# SVG[http://www.w3c.org/tr/svg bar graphs. You can either use the default |
| 34 |
# style sheet or supply your own. Either way there are many options which |
| 35 |
# can be configured to give you control over how the graph is generated - |
| 36 |
# with or without a key, data elements at each point, title, subtitle etc. |
| 37 |
# |
| 38 |
# = Notes |
| 39 |
# |
| 40 |
# The default stylesheet handles upto 12 data sets, if you |
| 41 |
# use more you must create your own stylesheet and add the |
| 42 |
# additional settings for the extra data sets. You will know |
| 43 |
# if you go over 12 data sets as they will have no style and |
| 44 |
# be in black. |
| 45 |
# |
| 46 |
# = Examples |
| 47 |
# |
| 48 |
# * http://germane-software.com/repositories/public/SVG/test/test.rb |
| 49 |
# |
| 50 |
# = See also |
| 51 |
# |
| 52 |
# * SVG::Graph::Graph |
| 53 |
# * SVG::Graph::BarHorizontal |
| 54 |
# * SVG::Graph::Line |
| 55 |
# * SVG::Graph::Pie |
| 56 |
# * SVG::Graph::Plot |
| 57 |
# * SVG::Graph::TimeSeries |
| 58 |
class Bar < BarBase |
| 59 |
include REXML |
| 60 |
|
| 61 |
# See Graph::initialize and BarBase::set_defaults |
| 62 |
def set_defaults |
| 63 |
super |
| 64 |
self.top_align = self.top_font = 1 |
| 65 |
end |
| 66 |
|
| 67 |
protected |
| 68 |
|
| 69 |
def get_x_labels |
| 70 |
@config[:fields] |
| 71 |
end |
| 72 |
|
| 73 |
def get_y_labels |
| 74 |
maxvalue = max_value |
| 75 |
minvalue = min_value |
| 76 |
range = maxvalue - minvalue |
| 77 |
|
| 78 |
top_pad = range == 0 ? 10 : range / 20.0 |
| 79 |
scale_range = (maxvalue + top_pad) - minvalue |
| 80 |
|
| 81 |
scale_division = scale_divisions || (scale_range / 10.0) |
| 82 |
|
| 83 |
if scale_integers |
| 84 |
scale_division = scale_division < 1 ? 1 : scale_division.round |
| 85 |
end |
| 86 |
|
| 87 |
rv = [] |
| 88 |
maxvalue = maxvalue%scale_division == 0 ? |
| 89 |
maxvalue : maxvalue + scale_division |
| 90 |
minvalue.step( maxvalue, scale_division ) {|v| rv << v}
|
| 91 |
return rv |
| 92 |
end |
| 93 |
|
| 94 |
def x_label_offset( width ) |
| 95 |
width / 2.0 |
| 96 |
end |
| 97 |
|
| 98 |
def draw_data |
| 99 |
minvalue = min_value |
| 100 |
fieldwidth = field_width |
| 101 |
|
| 102 |
unit_size = (@graph_height.to_f - font_size*2*top_font) / |
| 103 |
(get_y_labels.max - get_y_labels.min) |
| 104 |
bargap = bar_gap ? (fieldwidth < 10 ? fieldwidth / 2 : 10) : 0 |
| 105 |
|
| 106 |
bar_width = fieldwidth - bargap |
| 107 |
bar_width /= @data.length if stack == :side |
| 108 |
x_mod = (@graph_width-bargap)/2 - (stack==:side ? bar_width/2 : 0) |
| 109 |
|
| 110 |
bottom = @graph_height |
| 111 |
|
| 112 |
field_count = 0 |
| 113 |
@config[:fields].each_index { |i|
|
| 114 |
dataset_count = 0 |
| 115 |
for dataset in @data |
| 116 |
|
| 117 |
# cases (assume 0 = +ve): |
| 118 |
# value min length |
| 119 |
# +ve +ve value - min |
| 120 |
# +ve -ve value - 0 |
| 121 |
# -ve -ve value.abs - 0 |
| 122 |
|
| 123 |
value = dataset[:data][i] |
| 124 |
|
| 125 |
left = (fieldwidth * field_count) |
| 126 |
|
| 127 |
length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size |
| 128 |
# top is 0 if value is negative |
| 129 |
top = bottom - (((value < 0 ? 0 : value) - minvalue) * unit_size) |
| 130 |
left += bar_width * dataset_count if stack == :side |
| 131 |
|
| 132 |
@graph.add_element( "rect", {
|
| 133 |
"x" => left.to_s, |
| 134 |
"y" => top.to_s, |
| 135 |
"width" => bar_width.to_s, |
| 136 |
"height" => length.to_s, |
| 137 |
"class" => "fill#{dataset_count+1}"
|
| 138 |
}) |
| 139 |
|
| 140 |
make_datapoint_text(left + bar_width/2.0, top - 6, value.to_s) |
| 141 |
dataset_count += 1 |
| 142 |
end |
| 143 |
field_count += 1 |
| 144 |
} |
| 145 |
end |
| 146 |
end |
| 147 |
end |
| 148 |
end |