SVG-Timeline

 view release on metacpan or  search on metacpan

lib/SVG/Timeline.pm  view on Meta::CPAN

  is      => 'ro',
  isa     => 'Str',
  default => '100%',
);

=item * height - the height of the output in any format used by SVG. The
default is 100%.

=cut

has height => (
  is      => 'ro',
  isa     => 'Str',
  default => '100%',
);

=item * aspect_ratio - the default is 16/9.

=cut

has aspect_ratio => (
  is => 'ro',
  isa => 'Num',
  default => 16/9,
);

=item * viewport - a viewport definition (which is a space separated list of
four integers. Unless you know what you're doing, it's probably best to leave
the class to work this out for you.

=cut

has viewbox => (
  is         => 'ro',
  isa        => 'Str',
  lazy_build => 1,
  clearer    => '_clear_viewbox',
);

sub _build_viewbox {
  my $self = shift;
  return join ' ',
    $self->min_year * $self->units_per_year,
    0,
    $self->years * $self->units_per_year,
    ($self->bar_height * $self->events_in_timeline) + $self->bar_height
    + (($self->count_events - 1) * $self->bar_height * $self->bar_spacing);
}

=item * svg - an instance of the SVG class that is used to generate the final
SVG output. Unless you're using a subclass of this class for some reason,
there is no reason to set this manually.

=cut

has svg => (
  is         => 'ro',
  isa        => 'SVG',
  lazy_build => 1,
  clearer    => '_clear_svg',
  handles    => [qw[xmlify line text rect cdata]],
);

sub _build_svg {
  my $self = shift;

  $_->{end} //= (localtime)[5] + 1900 foreach $self->all_events;

  return SVG->new(
    width   => $self->width,
    height  => $self->height,
    viewBox => $self->viewbox,
  );
}

=item * default_colour - the colour that is used to fill the timeline
blocks. This should be defined in the RGB format used by SVG. For example,
red would be 'RGB(255,0,0)'.

=cut

has default_colour => (
  is         => 'ro',
  isa        => 'Str',
  lazy_build => 1,
);

sub _build_default_colour {
  return 'rgb(255,127,127)';
}

=item * years_per_grid - the number of years between vertical grid lines
in the output. The default of 10 should be fine unless your timeline covers
a really long timespan.

=cut

# The number of years between vertical grid lines
has years_per_grid => (
  is      => 'ro',
  isa     => 'Int',
  default => 10, # One decade by default
);

=item * bar_height - the height of an individual timeline bar.

=cut

has bar_height => (
  is      => 'ro',
  isa     => 'Int',
  default => 50,
);

=item * bar_spacing - the height if the vertical space between bars (expresssed
as a decimal fraction of the bar height).

=cut

has bar_spacing => (
  is      => 'ro',

lib/SVG/Timeline.pm  view on Meta::CPAN

  # ... multiplied by the bar height...
  $calulated_height *= $self->bar_height;
  # .. add spacing.
  $calulated_height += $self->bar_height * $self->bar_spacing *
                       ($self->events_in_timeline - 1);

  return $calulated_height;
}

=head2 calculated_width

The width in "calulated units".

=cut

sub calculated_width {
  my $self = shift;

  return $self->calculated_height * $self->aspect_ratio;
}

=head2 units_per_year

The number of horizontal units that each year should take up.

=cut

sub units_per_year {
  my $self = shift;

  return $self->calculated_width / $self->years;
}

=head2 draw_grid

Method to draw the underlying grid.

=cut

sub draw_grid{
  my $self = shift;

  my $curr_year = $self->min_year;
  my $units_per_year = $self->units_per_year;

  # Draw the grid lines
  while ( $curr_year <= $self->max_year ) {
    unless ( $curr_year % $self->years_per_grid ) {
      $self->line(
        x1           => $curr_year * $units_per_year,
        y1           => 0,
        x2           => $curr_year * $units_per_year,
        y2           => $self->calculated_height,
        stroke       => $self->decade_line_colour,
        stroke_width => 1
      );
      $self->text(
        x           => ($curr_year + 1) * $units_per_year,
        y           => 20,
        'font-size' => $self->bar_height / 2
      )->cdata($curr_year);
    }
    $curr_year++;
  }

  $self->rect(
     x             => $self->min_year * $units_per_year,
     y             => 0,
     width         => $self->years * $units_per_year,
     height        => ($self->bar_height * ($self->events_in_timeline + 1))
                    + ($self->bar_height * $self->bar_spacing
                       * ($self->events_in_timeline - 1)),
     stroke        => $self->bar_outline_colour,
    'stroke-width' => 1,
    fill           => 'none',
  );

  return $self;
}

=head2 draw

Method to draw the timeline.

=cut

sub draw {
  my $self = shift;
  my %args = @_;

  croak "Can't draw a timeline with no events"
    unless $self->has_events;

  $self->draw_grid;

  my $curr_event_idx = 1;
  foreach ($self->all_events) {

    $_->draw_on($self);

    $curr_event_idx++;
  }

  return $self->xmlify;
}

=head2 min_year

Returns the minimum year from all the events in the timeline.

=cut

sub min_year {
  my $self = shift;
  return unless $self->has_events;
  my @years = map { $_->start_year } $self->all_events;
  return min(@years);
}

=head2 max_year



( run in 1.660 second using v1.01-cache-2.11-cpan-d06a3f9ecfd )