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