Kelsin-lilygraph 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/LICENSE +0 -0
  2. data/README +0 -0
  3. data/VERSION +1 -0
  4. data/lib/lilygraph.rb +176 -0
  5. data/lilygraph.gemspec +47 -0
  6. metadata +78 -0
data/LICENSE ADDED
File without changes
data/README ADDED
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,176 @@
1
+ # This is the main graphing class used for generating svg graphs.
2
+ #
3
+ # :author: Christopher Giroir <kelsin@valefor.com>
4
+
5
+ class Lilygraph
6
+ # Default options for the initializer
7
+ DEFAULT_OPTIONS = {
8
+ :height => '100%',
9
+ :width => '100%',
10
+ :indent => 2,
11
+ :padding => 14,
12
+ :viewbox => {
13
+ :width => 800,
14
+ :height => 600
15
+ },
16
+ :margin => { :top => 50, :left => 50, :right => 50, :bottom => 100 }
17
+ }
18
+
19
+ # An array of labels to use on the y axis. Make sure you have the right number
20
+ # of labels. The size of this array should = the size of the data array.
21
+ attr_accessor :labels
22
+
23
+ # This is the data for the graph. It should be an array where every item is
24
+ # either a number or an array of numbers.
25
+ #
26
+ # Examples:
27
+ # For a simple bar graph: data=[1,2,3]
28
+ # For a grouped bar graph: data=[[1,10],[2,20],[3,30]]
29
+ attr_accessor :data
30
+
31
+ # Returns a new graph creator with some default options and other options that you pass.
32
+ #
33
+ # The options has includes:
34
+ # :height - String to use as height parameter on the svg tag. Default is '100%'.
35
+ # :width - String to use as width parameter on the svg tag. Default is '100%'.
36
+ # :indent - Indent option to the XmlMarkup object. Defaults to 2.
37
+ # :padding - Number of svg units in between two bars.
38
+ # :viewbox - Hash of :height and :width keys to use for the viewbox parameter of the svg tag. Defaults to { :height => 600, :width => 800 }.
39
+ # :margin - Hash of margins to use for graph (in svg units). Defaults to { :top => 50, :left => 50, :right => 50, :bottom => 100 }.
40
+ def initialize(options = {})
41
+ @options = DEFAULT_OPTIONS.merge(options)
42
+ @data = []
43
+ @labels = []
44
+ end
45
+
46
+ # Updates the graph options with items from the passed in hash
47
+ def update_options(options = {})
48
+ @options = @options.merge(options)
49
+ end
50
+
51
+ # This returns a string of the graph as an svg. You can pass in a block in
52
+ # order to add your own items to the graph. Your block is passed the XmlMarkup
53
+ # object to use as well as the options hash in case you need to use some of
54
+ # that data.
55
+ def render
56
+ output = ""
57
+ xml = Builder::XmlMarkup.new(:target => output, :indent => @options[:indent])
58
+
59
+ # Output headers unless we specified otherwise
60
+ xml.instruct!
61
+ xml.declare! :DOCTYPE, :svg, :PUBLIC, "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
62
+
63
+ xml.svg(:viewBox => "0 0 #{@options[:viewbox][:width]} #{@options[:viewbox][:height]}",
64
+ :width => @options[:width], :height => @options[:height],
65
+ :xmlns => 'http://www.w3.org/2000/svg', :version => '1.1') do |xml|
66
+
67
+ xml.g(:fill => 'black', :stroke => 'black', 'stroke-width' => '2',
68
+ 'font-family' => 'Helvetica, Arial, sans-serif', 'font-size' => '10px', 'font-weight' => 'medium') do |xml|
69
+
70
+ # Outline
71
+ xml.rect(:x => @options[:margin][:left], :y => @options[:margin][:top],
72
+ :width => graph_width,
73
+ :height => graph_height,
74
+ :fill => 'lightgray')
75
+
76
+ xml.g 'stroke-width' => '1' do |xml|
77
+
78
+ # Title
79
+ xml.text(@options[:title], 'font-size' => '24px', :x => (@options[:viewbox][:width] / 2.0).round, :y => (@options[:subtitle] ? 24 : 32), 'text-anchor' => 'middle') if @options[:title]
80
+ xml.text(@options[:subtitle], 'font-size' => '18px', :x => (@options[:viewbox][:width] / 2.0).round, :y => 34, 'text-anchor' => 'middle') if @options[:subtitle]
81
+
82
+ # Lines
83
+ xml.g 'font-size' => '10px' do |xml|
84
+ line_x1 = @options[:margin][:left] + 1
85
+ line_x2 = @options[:viewbox][:width] - @options[:margin][:right] - 1
86
+
87
+ text_x = @options[:margin][:left] - 25
88
+
89
+ xml.text 0, :x => text_x, :y => (@options[:viewbox][:height] - @options[:margin][:bottom] + 4), 'stroke-width' => 0.5
90
+
91
+ 1.upto((max / 10) - 1) do |line_number|
92
+ y = (@options[:margin][:top] + (line_number * dy)).round
93
+ xml.line :x1 => line_x1, :y1 => y, :x2 => line_x2, :y2 => y, :stroke => '#666666'
94
+ xml.text max - line_number * 10, :x => text_x, :y => y + 4, 'stroke-width' => 0.5
95
+
96
+ # Smaller Line
97
+ xml.line(:x1 => line_x1, :y1 => y + (0.5 * dy), :x2 => line_x2, :y2 => y + (0.5 * dy), :stroke => '#999999') if max < 55
98
+ end
99
+
100
+ xml.text max, :x => text_x, :y => @options[:margin][:top] + 4, 'stroke-width' => 0.5
101
+ # Smaller Line
102
+ xml.line(:x1 => line_x1, :y1 => @options[:margin][:top] + (0.5 * dy), :x2 => line_x2, :y2 => @options[:margin][:top] + (0.5 * dy), :stroke => '#999999') if max < 55
103
+ end
104
+
105
+ # Labels
106
+ xml.g 'text-anchor' => 'end', 'font-size' => '12px', 'stroke-width' => 0.3 do |xml|
107
+ @labels.each_with_index do |label, index|
108
+ x = (@options[:margin][:left] + (dx * index) + (dx / 2.0)).round
109
+ y = @options[:viewbox][:height] - @options[:margin][:bottom] + 15
110
+ xml.text label, :x => x, :y => y, :transform => "rotate(-45 #{x} #{y})"
111
+ end
112
+ end
113
+
114
+ # Bars
115
+ xml.g 'font-size' => '8px', 'stroke-width' => 0.3 do |xml|
116
+ @data.each_with_index do |data, data_index|
117
+ data = Array(data)
118
+ width = dx - @options[:padding]
119
+ bar_width = (width / Float(data.size)).round
120
+
121
+ x = (@options[:margin][:left] + (dx * data_index)).round
122
+
123
+ data.each_with_index do |number, number_index|
124
+ color = Color::HSL.from_fraction(data_index * (1.0 / @data.size),1.0, 0.4 + (number_index * 0.2)).to_rgb
125
+ height = ((dy / 10.0) * number).round
126
+
127
+ bar_x = (x + ((dx - width) / 2.0) + (number_index * bar_width)).round
128
+ text_x = (bar_x + (bar_width / 2.0)).round
129
+
130
+ bar_y = @options[:viewbox][:height] - @options[:margin][:bottom] - height
131
+ text_y = bar_y - 3
132
+
133
+ xml.rect :fill => color.html, :stroke => color.html, 'stroke-width' => 0, :x => bar_x, :width => bar_width, :y => bar_y, :height => height - 1
134
+ xml.text number, :x => text_x, :y => text_y, 'text-anchor' => 'middle'
135
+ end
136
+ end
137
+ end
138
+
139
+ # Yield in case they want to do some custom drawing and have a block ready
140
+ yield xml, @options if block_given?
141
+
142
+ end
143
+ end
144
+ end
145
+
146
+ output
147
+ end
148
+
149
+ private
150
+
151
+ def max
152
+ (((@data.map do |num|
153
+ num.respond_to?(:max) ? num.max : num
154
+ end.max + 5) / 10.0).ceil * 10).round
155
+ end
156
+
157
+ def graph_height
158
+ @options[:viewbox][:height] - (@options[:margin][:top] + @options[:margin][:bottom])
159
+ end
160
+
161
+ def graph_width
162
+ @options[:viewbox][:width] - (@options[:margin][:left] + @options[:margin][:right])
163
+ end
164
+
165
+ def number_of_slots
166
+ @data.size
167
+ end
168
+
169
+ def dx
170
+ 700.0 / Float(number_of_slots)
171
+ end
172
+
173
+ def dy
174
+ 4500.0 / Float(max)
175
+ end
176
+ end
@@ -0,0 +1,47 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{lilygraph}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Christopher Giroir"]
12
+ s.date = %q{2009-08-19}
13
+ s.description = %q{Lilygraph is a Ruby library for creating svg charts and graphs based on XmlBuilder.}
14
+ s.email = %q{kelsin@valefor.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README"
18
+ ]
19
+ s.files = [
20
+ "LICENSE",
21
+ "README",
22
+ "VERSION",
23
+ "lib/lilygraph.rb",
24
+ "lilygraph.gemspec"
25
+ ]
26
+ s.homepage = %q{http://github.com/Kelsin/lilygraph}
27
+ s.rdoc_options = ["--charset=UTF-8"]
28
+ s.require_paths = ["lib"]
29
+ s.rubygems_version = %q{1.3.4}
30
+ s.summary = %q{Lilygraph is a Ruby library for creating svg charts and graphs based on XmlBuilder.}
31
+
32
+ if s.respond_to? :specification_version then
33
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
34
+ s.specification_version = 3
35
+
36
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
37
+ s.add_runtime_dependency(%q<builder>, [">= 2.1.2"])
38
+ s.add_runtime_dependency(%q<color-tools>, [">= 1.3.0"])
39
+ else
40
+ s.add_dependency(%q<builder>, [">= 2.1.2"])
41
+ s.add_dependency(%q<color-tools>, [">= 1.3.0"])
42
+ end
43
+ else
44
+ s.add_dependency(%q<builder>, [">= 2.1.2"])
45
+ s.add_dependency(%q<color-tools>, [">= 1.3.0"])
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Kelsin-lilygraph
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Giroir
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-19 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: builder
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.1.2
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: color-tools
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.0
34
+ version:
35
+ description: Lilygraph is a Ruby library for creating svg charts and graphs based on XmlBuilder.
36
+ email: kelsin@valefor.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README
44
+ files:
45
+ - LICENSE
46
+ - README
47
+ - VERSION
48
+ - lib/lilygraph.rb
49
+ - lilygraph.gemspec
50
+ has_rdoc: false
51
+ homepage: http://github.com/Kelsin/lilygraph
52
+ licenses:
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --charset=UTF-8
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Lilygraph is a Ruby library for creating svg charts and graphs based on XmlBuilder.
77
+ test_files: []
78
+