lib/prawn/graph/chart_components/bar_chart_renderer.rb
module Prawn
module Graph
module ChartComponents
# The Prawn::Graph::ChartComponents::BarChartRenderer is used to plot one or more bar charts
# in a sensible way on a a Prawn::Graph::ChartComponents::Canvas and its associated
# Prawn::Document.
#
class BarChartRenderer < SeriesRenderer
def render
render_the_chart
end
private
def mark_average_line(series_index)
if @series[series_index].mark_average?
average_y_coordinate = (point_height_percentage(@series[series_index].avg) * @plot_area_height) - 5
prawn.line_width = 1
prawn.stroke_color = @canvas.theme.color_for(@series[series_index]) # @color[series_index]
prawn.dash(2)
prawn.stroke_line([0, average_y_coordinate], [ @plot_area_width, average_y_coordinate ])
prawn.undash
end
end
def mark_maximum_point(series_index, point, max_marked, x_position, y_position)
if @series[series_index].mark_maximum? && max_marked == false && @series[series_index].values[point] == @series[series_index].max
max_marked = draw_marker_point(@canvas.theme.max, x_position, y_position)
end
max_marked
end
def mark_minimum_point(series_index, point, min_marked, x_position, y_position)
if @series[series_index].mark_minimum? && min_marked == false && !@series[series_index].values[point].zero? && @series[series_index].values[point] == @series[series_index].min
min_marked = draw_marker_point(@canvas.theme.min, x_position, y_position)
end
min_marked
end
def render_the_chart
prawn.bounding_box [@graph_area.point[0] + 5, @graph_area.point[1] - 20], width: @plot_area_width, height: @plot_area_height do
prawn.save_graphics_state do
num_points = @series[0].size
width_per_point = (@plot_area_width / num_points)
width = (((width_per_point * 0.9) / @series.size).round(2)).to_f
min_marked = false
max_marked = false
num_points.times do |point|
@series.size.times do |series_index|
series_offset = series_index + 1
prawn.fill_color = @canvas.theme.color_for(@series[series_index])
prawn.stroke_color = @canvas.theme.color_for(@series[series_index])
prawn.line_width = width
starting = (prawn.bounds.left + (point * width_per_point))
x_position = ( (starting + (series_offset * width) ).to_f - (width / 2.0))
y_position = ((point_height_percentage(@series[series_index].values[point]) * @plot_area_height) - 5).to_f
prawn.fill_and_stroke_line([ x_position ,0], [x_position ,y_position]) unless @series[series_index].values[point].zero?
mark_average_line(series_index)
max_marked = mark_maximum_point(series_index, point, max_marked, x_position, y_position)
min_marked = mark_minimum_point(series_index, point, min_marked, x_position, y_position)
end
end
end
render_axes
end
end
def max
@series.collect(&:max).max || 0
end
def min
@series.collect(&:min).min || 0
end
def avg
@series.collect(&:avg).inject(:+) / @series.size rescue 0
end
end
end
end
end