lib/lilygraph.rb in lilygraph-0.4.4 vs lib/lilygraph.rb in lilygraph-0.5.0

- old
+ new

@@ -17,11 +17,13 @@ DEFAULT_OPTIONS = { :height => '100%', :width => '100%', :indent => 2, :padding => 14, + :legend => :right, :bar_text => true, + :type => :bar, :viewbox => { :width => 800, :height => 600 }, :margin => { :top => 50, :left => 50, :right => 50, :bottom => 100 } @@ -137,24 +139,24 @@ # Lines xml.g 'font-size' => '10px' do |xml| line_x1 = @options[:margin][:left] + 1 line_x2 = @options[:viewbox][:width] - @options[:margin][:right] - 1 - text_x = @options[:margin][:left] - 25 + text_x = @options[:margin][:left] - 5 - xml.text 0, :x => text_x, :y => (@options[:viewbox][:height] - @options[:margin][:bottom] + 4), 'stroke-width' => 0.5 + xml.text 0, :x => text_x, :y => (@options[:viewbox][:height] - @options[:margin][:bottom] + 4), 'stroke-width' => 0.5, 'text-anchor' => 'end' - 1.upto((max / 10) - 1) do |line_number| + 1.upto((max / division) - 1) do |line_number| y = (@options[:margin][:top] + (line_number * dy)).round xml.line :x1 => line_x1, :y1 => y, :x2 => line_x2, :y2 => y, :stroke => '#666666' - xml.text max - line_number * 10, :x => text_x, :y => y + 4, 'stroke-width' => 0.5 + xml.text max - line_number * division, :x => text_x, :y => y + 4, 'stroke-width' => 0.5, 'text-anchor' => 'end' # Smaller Line xml.line(:x1 => line_x1, :y1 => y + (0.5 * dy), :x2 => line_x2, :y2 => y + (0.5 * dy), :stroke => '#999999') if max < 55 end - xml.text max, :x => text_x, :y => @options[:margin][:top] + 4, 'stroke-width' => 0.5 + xml.text max, :x => text_x, :y => @options[:margin][:top] + 4, 'stroke-width' => 0.5, 'text-anchor' => 'end' # Smaller Line 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 end # Labels @@ -166,10 +168,12 @@ end end # Bars xml.g 'font-size' => '10px', 'stroke-width' => 0.3 do |xml| + last_spot = [] + @data.each_with_index do |data, data_index| data = Array(data) width = dx - @options[:padding] bar_width = (width / Float(data.size)).round @@ -179,34 +183,54 @@ data.each_with_index do |number, number_index| color = if @colors.respond_to? :call @colors.call(data_index, number_index, @data.size, data.size) elsif @colors.class == Array first = @colors[data_index % (@colors.size)] - + if first.class == Array first[number_index % (first.size)] else first end else @colors end - height = ((dy / 10.0) * number).round + height = ((dy / division) * number).round bar_x = (x + ((dx - width) / 2.0) + (number_index * bar_width)).round bar_y = @options[:viewbox][:height] - @options[:margin][:bottom] - height - xml.rect :fill => color, :stroke => color, 'stroke-width' => 0, :x => bar_x, :width => bar_width, :y => bar_y, :height => height - 1 + + case @options[:type] + when :bar then + xml.rect :fill => color, :stroke => color, 'stroke-width' => 0, :x => bar_x, :width => bar_width, :y => bar_y, :height => height - 1 + when :line then + if last_spot[number_index] + xml.line(:x1 => last_spot[number_index][:x], :y1 => last_spot[number_index][:y], :x2 => bar_x, :y2 => bar_y, + :fill => color, :stroke => color, 'stroke-width' => 2.0) + end + xml.circle :cx => bar_x, :cy => bar_y, :fill => color, :stroke => color, :r => bar_width * 1.5 + end + + last_spot[number_index] = { :x => bar_x, :y => bar_y } end + end + @data.each_with_index do |data, data_index| + data = Array(data) + width = dx - @options[:padding] + bar_width = (width / Float(data.size)).round + + x = (@options[:margin][:left] + (dx * data_index)).round + # Text if @options[:bar_text] last_bar_height = false data.each_with_index do |number, number_index| if number > 0 - height = ((dy / 10.0) * number).round + height = ((dy / division) * number).round bar_x = (x + ((dx - width) / 2.0) + (number_index * bar_width)).round text_x = (bar_x + (bar_width / 2.0)).round bar_y = @options[:viewbox][:height] - @options[:margin][:bottom] - height @@ -228,11 +252,15 @@ end end # Legend if @legend - legend_x = @options[:viewbox][:width] - (3 * @options[:margin][:right]) + if @options[:legend] == :right + legend_x = @options[:viewbox][:width] - (3 * @options[:margin][:right]) + else + legend_x = (@options[:margin][:left] * 1.5).round + end legend_y = (@options[:margin][:top] / 2) + @options[:margin][:top] xml.rect :fill => '#ffffff', :stroke => '#000000', 'stroke-width' => 2, :x => legend_x, :y => legend_y, :width => (2.5 * @options[:margin][:right]), :height => (@legend.size * 15) + 16 @legend.sort.each_with_index do |data, index| color, label = data @@ -251,14 +279,22 @@ output end private + def data_max + @data.map do |num| + num.respond_to?(:max) ? num.max : num + end.max || 0 + end + + def division + (10 ** Math.log10(data_max).floor) / 10 + end + def max - ((((@data.map do |num| - num.respond_to?(:max) ? num.max : num - end.max || 0) + 1) / 10.0).ceil * 10).round + (((data_max + (division / 10)) / Float(division)).ceil * Float(division)).round end def graph_height @options[:viewbox][:height] - (@options[:margin][:top] + @options[:margin][:bottom]) end @@ -274,8 +310,8 @@ def dx graph_width / Float(number_of_slots) end def dy - (graph_height * 10.0) / Float(max) + (graph_height * division) / Float(max) end end