class Scruffy::Graph

Scruffy Graphs

Author

Brasten Sager

Date

August 5th, 2006

Graphs vs. Layers (Graph Types)

Scruffy::Graph is the primary class you will use to generate your graphs. A Graph does not define a graph type nor does it directly hold any data. Instead, a Graph object can be thought of as a canvas on which other graphs are draw. (The actual graphs themselves are subclasses of Scruffy::Layers::Base) Despite the technical distinction, we will refer to Scruffy::Graph objects as 'graphs' and Scruffy::Layers as 'layers' or 'graph types.'

Creating a Graph

You can begin building a graph by instantiating a Graph object and optionally passing a hash of properties.

graph = Scruffy::Graph.new

OR

graph = Scruffy::Graph.new(:title => "Monthly Profits", :theme => Scruffy::Themes::RubyBlog.new)

Once you have a Graph object, you can set any Graph-level properties (title, theme, etc), or begin adding graph layers. You can add a graph layer to a graph by using the Scruffy::Helpers::LayerContainer#add or Graph#<< methods. The two methods are identical and used to accommodate syntax preferences.

graph.add(:line, 'John', [100, -20, 30, 60])
graph.add(:line, 'Sara', [120, 50, -80, 20])

OR

graph << Scruffy::Layers::Line.new(:title => 'John', :points => [100, -20, 30, 60])
graph << Scruffy::Layers::Line.new(:title => 'Sara', :points => [120, 50, -80, 20])

Now that we've created our graph and added a layer to it, we're ready to render! You can render the graph directly to SVG or any other image format (supported by RMagick) with the #render method:

graph.render    # Renders a 600x400 SVG graph

OR

graph.render(:width => 1200)

# For image formats other than SVG:
graph.render(:width => 1200, :as => 'PNG')

# To render directly to a file:
graph.render(:width => 5000, :to => '<filename>')

graph.render(:width => 700, :as => 'PNG', :to => '<filename>')

And that's your basic Scruffy graph! Please check the documentation for the various methods and classes you'll be using, as there are a bunch of options not demonstrated here.

A couple final things worth noting:

Attributes

layout[R]
renderer[R]

Public Class Methods

new(*args) click to toggle source

Returns a new Graph. You can optionally pass in a default graph type and an options hash.

Graph.new           # New graph
Graph.new(:line)    # New graph with default graph type of Line
Graph.new({...})    # New graph with options.

Options:

title

Graph's title

x_legend

Title for X Axis

y_legend

Title for Y Axis

theme

A theme object to use when rendering graph

layers

An array of Layers for this graph to use

default_type

A symbol indicating the default type of Layer for this graph

value_formatter

Sets a formatter used to modify marker values prior to rendering

point_markers

Sets the x-axis marker values

point_markers_rotation

Sets the angle of rotation for x-axis marker values

point_markers_ticks

Sets a small tick mark above each marker value. Helful when used with rotation.

rasterizer

Sets the rasterizer to use when rendering to an image format. Defaults to RMagick.

# File lib/scruffy/graph.rb, line 111
def initialize(*args)
  self.default_type   = args.shift if args.first.is_a?(Symbol)
  options             = args.shift.dup if args.first.is_a?(Hash)
  raise ArgumentError, "The arguments provided are not supported." if args.size > 0

  options ||= {}
  
  
  self.theme = Scruffy::Themes::Standard.new
  self.renderer = Scruffy::Renderers::Standard.new
  self.rasterizer = Scruffy::Rasterizers::MiniMagickRasterizer.new
  self.value_formatter = Scruffy::Formatters::Number.new
  self.key_formatter = Scruffy::Formatters::Number.new

  %w(title x_legend y_legend theme layers default_type value_formatter point_markers point_markers_rotation point_markers_ticks rasterizer key_formatter).each do |arg|
    self.send("#{arg}=".to_sym, options.delete(arg.to_sym)) unless options[arg.to_sym].nil?
  end
  
  raise ArgumentError, "Some options provided are not supported: #{options.keys.join(' ')}." if options.size > 0
end

Public Instance Methods

component(id) click to toggle source
# File lib/scruffy/graph.rb, line 191
def component(id)
  renderer.component(id)
end
remove(id) click to toggle source
# File lib/scruffy/graph.rb, line 195
def remove(id)
  renderer.remove(id)
end
render(options = {}) click to toggle source

Renders the graph in it's current state to an SVG object.

Options:

size

An array indicating the size you wish to render the graph. ( [x, y] )

width

The width of the rendered graph. A height is calculated at 3/4th of the width.

theme

Theme used to render graph for this render only.

min_value

Overrides the calculated minimum value used for the graph.

max_value

Overrides the calculated maximum value used for the graph.

renderer

Provide a Renderer object to use instead of the default.

For other image formats:

as

File format to render to ('PNG', 'JPG', etc)

to

Name of file to save graph to, if desired. If not provided, image is returned as blob/string.

# File lib/scruffy/graph.rb, line 145
def render(options = {})
  options[:theme]               ||= theme
  options[:value_formatter]     ||= value_formatter
  options[:key_formatter]       ||= key_formatter
  options[:point_markers]       ||= point_markers
  options[:point_markers_rotation]       ||= point_markers_rotation
  options[:point_markers_ticks]       ||= point_markers_ticks
  options[:size]                ||= (options[:width] ? [options[:width], (options.delete(:width) * 0.6).to_i] : [600, 360])
  options[:title]               ||= title
  options[:x_legend]               ||= x_legend
  options[:y_legend]               ||= y_legend
  options[:layers]              ||= layers
  options[:min_value]           ||= bottom_value(options[:padding] ? options[:padding] : nil)
  options[:max_value]           ||= top_value(options[:padding] ? options[:padding] : nil)
  options[:min_key]             ||= bottom_key
  options[:max_key]             ||= top_key
  options[:graph]               ||= self

  # Removed for now.
  # Added for making smaller fonts more legible, but may not be needed after all.
  #
  # if options[:as] && (options[:size][0] <= 300 || options[:size][1] <= 200)
  #   options[:actual_size] = options[:size]
  #   options[:size] = [800, (800.to_f * (options[:actual_size][1].to_f / options[:actual_size][0].to_f))]
  # end
  
  svg = ( options[:renderer].nil? ? self.renderer.render( options ) : options[:renderer].render( options ) )
  
  # SVG to file.
  if options[:to] && options[:as].nil?
    File.open(options[:to], 'w') { |file|
      file.write(svg)
    }
  end
  
  options[:as] ? rasterizer.rasterize(svg, options) : svg
end
renderer=(val) click to toggle source
# File lib/scruffy/graph.rb, line 183
def renderer=(val)
  raise ArgumentError, "Renderer must include a #render(options) method." unless (val.respond_to?(:render) && val.method(:render).arity.abs > 0)
  
  @renderer = val
end