lib/sparklines.rb in sparklines-0.2.4 vs lib/sparklines.rb in sparklines-0.2.5

- old
+ new

@@ -20,10 +20,12 @@ {Geoffrey Grosenbach}[mailto:boss@topfunky.com] -- http://nubyonrails.topfunky.com -- Conversion to module and addition of functions for using with Rails. Also changed functions to use Rails-style option hashes for parameters. ===Tangent regarding RMagick +The easiest way to use RMagick on Mac OS X is to use darwinports. There are packages for libpng, freetype, and all the other libraries you need. + I had a heck of a time getting RMagick to work on my system so in the interests of saving other people the trouble here's a little set of instructions on how to get RMagick working properly and with the right image formats. 1. Install the zlib[http://www.libpng.org/pub/png/libpng.html] library 2. With zlib in the same directory as the libpng[http://www.libpng.org/pub/png/libpng.html] library, install libpng 3. Option step: Install the {jpeg library}[ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz] (You need it to use jpegs and you might want to have it) @@ -68,10 +70,11 @@ area discrete pie smooth + bar (results will be normalized, i.e. scaled to take up the full height of the graph) General Defaults: :type => 'smooth' :height => 14px @@ -86,11 +89,11 @@ Licensed under the MIT license. =end module Sparklines - $VERSION = '0.2.3' + $VERSION = '0.2.5' # Does the actually plotting of the graph. Calls the appropriate function based on the :type value passed. Defaults to 'smooth.' def Sparklines.plot(results=[], options={}) defaults = { :type => 'smooth', :height => 14, @@ -113,29 +116,20 @@ :has_last => false } # This symbol->string->symbol is kind of awkward. Is there a more elegant way? - # Convert all symbol keys to strings - defaults.keys.reverse.each do |key| - defaults[key.to_s] = defaults[key] - end options.keys.reverse.each do |key| - options[key.to_s] = options[key] - end - - options = defaults.merge(options) - - # Convert options string keys back to symbols - options.keys.reverse.each do |key| options[key.to_sym] = options[key] end - + options = defaults.merge(options) + # Minimal normalization + maximum_value = self.get_max_value(results).to_f + # Call the appropriate function for actual plotting - #self.send('smooth', results, options) - self.send(options[:type], results, options) + self.send(options[:type], results, options, maximum_value) end # Writes a graph to disk with the specified filename, or "Sparklines.png" def Sparklines.plot_to_file(filename="sparklines.png", results=[], options={}) File.open( filename, 'wb' ) do |png| @@ -152,11 +146,11 @@ # :diameter - An integer that determines what the size of the sparkline will be. Defaults to 20 # # :share_color - A string or color code representing the color to draw the share of the pie represented by percent. Defaults to blue. # # :remain_color - A string or color code representing the color to draw the pie not taken by the share color. Defaults to lightgrey. - def self.pie(results=[],options={}) + def self.pie(results=[],options={}, maximum_value=100.0) diameter = options[:diameter].to_i share_color = options[:share_color] remain_color = options[:remain_color] percent = results[0] @@ -224,27 +218,29 @@ # :upper - An integer that determines the threshold for colorization purposes. Any value less than upper will be colored using below_color, anything above and equal to upper will use above_color. Defaults to 50. # # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red. # # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray. - def self.discrete(results=[], options = {}) + def self.discrete(results=[], options = {}, maximum_value=100.0) height = options[:height].to_i upper = options[:upper].to_i below_color = options[:below_color] above_color = options[:above_color] img = Magick::Image.new(results.size * 2 - 1, height) {self.background_color = options[:background_color]} img.format = "PNG" draw = Magick::Draw.new - i=0 + i = 0 results.each do |r| - color = (r >= upper) && above_color || below_color + color = (r >= upper) ? above_color : below_color draw.stroke(color) - draw.line(i, (img.rows - r/(101.0/(height-4))-4).to_i,i,(img.rows - r/(101.0/(height-4))).to_i) - i+=2 + draw.line(i, (img.rows - r/(101.0/(height-4))-4).to_i, + i, (img.rows - r/(101.0/(height-4))).to_i) + + i += 2 end draw.draw(img) img.to_blob end @@ -274,11 +270,11 @@ # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red. # # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red. # # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray. - def self.area(results=[], options={}) + def self.area(results=[], options={}, maximum_value=100.0) step = options[:step].to_i height = options[:height].to_i upper = options[:upper].to_i @@ -369,11 +365,11 @@ # :min_color - A string or color code representing the color that the dot drawn at the smallest value will be displayed as. Defaults to blue. # # :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green. # # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red. - def self.smooth(results, options) + def self.smooth(results, options, maximum_value=100.0) step = options[:step].to_i height = options[:height].to_i min_color = options[:min_color] max_color = options[:max_color] @@ -442,6 +438,46 @@ draw.draw(img) img.to_blob end + + # Draws a bar graph, normalized. + # + # BUG: Last column never goes all the way to the bottom. + def self.bar(results=[], options = {}, maximum_value=100.0) + step = options[:step].to_i + height = options[:height].to_f + upper = options[:upper].to_i + below_color = options[:below_color] + above_color = options[:above_color] + + img = Magick::Image.new((results.size) * step + 1, height) { + self.background_color = options[:background_color] + } + img.format = "PNG" + draw = Magick::Draw.new + + i = 1 + results.each_with_index do |r, index| + color = (r >= upper) ? above_color : below_color + draw.stroke('transparent') + draw.fill(color) + draw.rectangle( i, img.rows, + i + step - 2, img.rows - ((r / maximum_value) * img.rows) ) + i += step + end + + draw.draw(img) + img.to_blob + end + + + def self.get_max_value(values=[]) + max_value = 0 + values.each do |value| + max_value = (value > max_value) ? value : max_value + end + return max_value + end + end