Kelsin-lilygraph 0.0.0

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