WithMap.pm
上传用户:shbosideng
上传日期:2013-05-04
资源大小:1555k
文件大小:5k
- package GIFgraph::WithMap;
- use strict;
- use vars qw (@ISA %fields $AUTOLOAD $VERSION);
- use Carp;
- use CGI;
- use MRP::BaseClass;
- $VERSION = 1.0;
- # use AUTOLOAD to pass everything that we can't do to _GIFgraph.
- # don't know if this is kosha. AHHHH.
- sub AUTOLOAD {
- my $thing = shift;
- my ($package, $function) = $AUTOLOAD =~ m/^(.*)::([^:]+)$/;
- if(ref($thing)) {
- my $delegate = $thing->_GIFgraph;
- $function = join '::', $delegate, $function;
- return $thing->$function(@_);
- }
- die "Could not find method $AUTOLOAD via $thing";
- }
- sub isa {
- my ($thing, $type) = @_;
- return $thing->_GIFgraph->isa($type) || $thing->SUPER::isa($type);
- }
- sub new {
- my $class = shift;
- my $GIFgraph = shift;
- my $baseClass = new MRP::BaseClass;
- my $self = $class->rebless($GIFgraph, $baseClass);
- $self->_GIFgraph(ref $GIFgraph);
- return $self;
- }
- sub draw_data {
- my ($self, $gd, $data) = @_;
- my $fuzz = $self->fuzz;
- my $map = "";
- my $mapname = $self->mapname || confess "You must set the name for this map before calling plot";
- my $seriesnames = $self->seriesnames;
- my $links = $self->links;
- my $delegateFunc = join '::', $self->_GIFgraph, 'draw_data';
- $self->$delegateFunc($gd, $data);
-
- $map = '<MAP NAME="' . $mapname . '">'."n";
- foreach my $series (1 .. $self->{numsets}) {
- my (@up, @down);
- foreach my $point (0 .. $self->{numpoints}) {
- next unless defined($$data[$series][$point]);
- my ($x, $y) = $self->val_to_pixel($point+1, $$data[$series][$point], $series);
- push @up, $x, $y+$fuzz;
- unshift @down, $x, $y-$fuzz;
- }
- my $seriesname = $seriesnames->[$series-1] || 'series '.$series;
- my $link = $links->[$series-1] || "#$seriesname";
- $map .= join("nt",
- '<AREA',
- 'alt="' . $seriesname . '"',
- 'href="' . $link . '"',
- 'onMouseOver="self.status=' . "'$seriesname'" . '; return true"',
- 'onMouseOut="self.status=' . "''" . '; return true"',
- 'shape=polygon',
- 'coords="' . join(', ', @up, @down) . '"',
- );
- $map .= ">n";
- }
- $map .= "</MAP>n";
- $self->map($map);
- }
- BEGIN {
- @ISA = qw (MRP::BaseClass);
- %fields = (
- 'fuzz' => 1,
- 'map' => undef,
- 'mapname' => undef,
- 'seriesnames' => [],
- 'links' => [],
- '_GIFgraph' => undef,
- );
- GIFgraph::WithMap->check4Clashes;
- }
- $VERSION;
- __END__
- =head1 NAME
- GIFgraph::WithMap - generates HTML map text while plotting graph
- =head1 DESCRIPTION
- Generates the html map block for a graph so that data series become
- 'clickable',
- =head1 SYNOPSIS
- This module extends GIFgraph objects such as GIFgraph::lines. You can
- do everything that you would with a GIFgraph object. In addition, when
- the data is plotted, it generates some MAP html text.
- The series will be labeled 'series 1', 'series 2' etc. unless the
- $obj->seriesnames has been set. For each series, it will create a
- polygon area, with the following structure (assuming series is named
- 'Green', and that the links member array is empty:
- <AREA
- alt="Green"
- href="#Green"
- onMouseOver="self.status='Green'; return true"
- onMouseOut="self.status=''; return true"
- shape=polygon
- coords="87, 41, 165, 250, 165, 246, 87, 37">
- So - clicking on the series will take you to #Green. If you don't
- specify #Green in the document, clicking on it will do very little. If
- you have (e.g. in the key) then it should take you there.
- =head1 new
- Use something like
- $map = new GIFgraph::WithMap(new GIFgraph::lines(400,300));
- =head1 fields
- =over
- =item map
- Once plot has been called, map contains the map text.
- print $graphWithMap->map;
- =item fuzz
- This is the up/down fuzz used to construct the ploygon. It defaults to
- 1 - so the polygon will be three pixles wide (the pixle drawn and one
- above and below it).
- =item mapname
- Set this before calling plot. This is the name of the map, as given by
- usemap="#mapname" in <img>. It is a fatal error to try to plot without
- a name.
- =item seriesnames
- Array of names for the series. If a name is absent for a series (or
- all series) then it will be named Series #. This must be set before
- the graph is plotted.
- $graphWithMap->seriesnames('name1', 'name2');
- =links
- Array of links for the series. If a link is absent for a series (or
- all series) then it will be named #SeriesName (where SeriesName is
- generated as described in L<seriwsnames>).
- =back
- =head1 Guts
- This module uses MRP::BaseClass to implement member access functions.
- In the constructor, a new object is created that is a meld of an
- MRP::BaseClass derived object, and the GIFgraph object passed in. The
- type of that object is stoored in _GIFgraph. In AUTOLOAD, first I
- check to see if the GIFgraph object's package named in _GIFgraph
- implements the function. If it does, then I return the value of that
- function - i.e. it behaves as if the object inherits from that
- package. If that fails, then I return the value of SUPER::AUTLOLOAD,
- which will presumably handle it or die gracefully. Hey presto -
- dynamic parenting.
- @ISA does not include anything to implement a GIFgraph object as a
- parent. However, I have overridden 'isa' to account for this.