📄 axestype.pm
字号:
#==========================================================================
# Copyright (c) 1995-1998 Martien Verbruggen
#--------------------------------------------------------------------------
#
# Name:
# GIFgraph::axestype.pm
#
# $Id: axestype.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $
#
#==========================================================================
package GIFgraph::axestype;
use strict;
use GIFgraph;
use GIFgraph::legend;
use GIFgraph::utils qw(:all);
@GIFgraph::axestype::ISA = qw( GIFgraph::legend GIFgraph );
my %Defaults = (
# Set the length for the 'short' ticks on the axes.
tick_length => 4,
# Do you want ticks to span the entire width of the graph?
long_ticks => 0,
# Number of ticks for the y axis
y_tick_number => 5,
x_tick_number => undef, # CONTRIB Scott Prahl
# Skip every nth label. if 1 will print every label on the axes,
# if 2 will print every second, etc..
x_label_skip => 1,
y_label_skip => 1,
# Do we want ticks on the x axis?
x_ticks => 1,
x_all_ticks => 0,
# Where to place the x and y labels
x_label_position => 3/4,
y_label_position => 1/2,
# vertical printing of x labels
x_labels_vertical => 0,
# Draw axes as a box? (otherwise just left and bottom)
box_axis => 1,
# Use two different axes for the first and second dataset. The first
# will be displayed using the left axis, the second using the right
# axis. You cannot use more than two datasets when this option is on.
two_axes => 0,
# Print values on the axes?
x_plot_values => 1,
y_plot_values => 1,
# Space between axis and text
axis_space => 4,
# Do you want bars to be drawn on top of each other, or side by side?
overwrite => 0,
# Draw the zero axis in the graph in case there are negative values
zero_axis => 0,
# Draw the zero axis, but do not draw the bottom axis, in case
# box-axis == 0
# This also moves the x axis labels to the zero axis
zero_axis_only => 0,
# Format of the numbers on the x and y axis
y_number_format => undef,
x_number_format => undef, # CONTRIB Scott Prahl
);
{
# PUBLIC
sub plot($) # (\@data)
{
my $self = shift;
my $data = shift;
$self->check_data($data);
$self->init_graph($self->{graph});
$self->plot_legend($self->{graph});
$self->setup_coords($data);
$self->draw_text($self->{graph});
$self->draw_axes($self->{graph}, $data);
$self->draw_ticks($self->{graph}, $data);
$self->draw_data($self->{graph}, $data);
return $self->{graph}->gif
}
sub set_x_label_font($) # (fontname)
{
my $self = shift;
$self->{xlf} = shift;
$self->set(
xlfw => $self->{xlf}->width,
xlfh => $self->{xlf}->height,
);
}
sub set_y_label_font($) # (fontname)
{
my $self = shift;
$self->{ylf} = shift;
$self->set(
ylfw => $self->{ylf}->width,
ylfh => $self->{ylf}->height,
);
}
sub set_x_axis_font($) # (fontname)
{
my $self = shift;
$self->{xaf} = shift;
$self->set(
xafw => $self->{xaf}->width,
xafh => $self->{xaf}->height,
);
}
sub set_y_axis_font($) # (fontname)
{
my $self = shift;
$self->{yaf} = shift;
$self->set(
yafw => $self->{yaf}->width,
yafh => $self->{yaf}->height,
);
}
# PRIVATE
# called on construction, by new
# use inherited defaults
sub initialise()
{
my $self = shift;
$self->SUPER::initialise();
my $key;
foreach $key (keys %Defaults)
{
$self->set( $key => $Defaults{$key} );
}
$self->set_x_label_font(GD::gdSmallFont);
$self->set_y_label_font(GD::gdSmallFont);
$self->set_x_axis_font(GD::gdTinyFont);
$self->set_y_axis_font(GD::gdTinyFont);
}
# inherit check_data from GIFgraph
sub setup_coords($)
{
my $s = shift;
my $data = shift;
# Do some sanity checks
$s->{two_axes} = 0 if ( $s->{numsets} != 2 || $s->{two_axes} < 0 );
$s->{two_axes} = 1 if ( $s->{two_axes} > 1 );
delete $s->{y_label2} unless ($s->{two_axes});
# Set some heights for text
$s->set( tfh => 0 ) unless ( $s->{title} );
$s->set( xlfh => 0 ) unless ( $s->{x_label} );
if ( ! $s->{y1_label} && $s->{y_label} )
{
$s->{y1_label} = $s->{y_label};
}
$s->set( ylfh1 => $s->{y1_label} ? 1 : 0 );
$s->set( ylfh2 => $s->{y2_label} ? 1 : 0 );
$s->set( xafh => 0, xafw => 0 ) unless ($s->{x_plot_values});
$s->set( yafh => 0, yafw => 0 ) unless ($s->{y_plot_values});
$s->{x_axis_label_height} = $s->get_x_axis_label_height($data);
my $lbl = ($s->{xlfh} ? 1 : 0) + ($s->{xafh} ? 1 : 0);
# calculate the top and bottom of the bounding box for the graph
$s->{bottom} =
$s->{gify} - $s->{b_margin} - 1 -
( $s->{xlfh} ? $s->{xlfh} : 0 ) -
( $s->{x_axis_label_height} ? $s->{x_axis_label_height} : 0) -
( $lbl ? $lbl * $s->{text_space} : 0 );
$s->{top} = $s->{t_margin} +
( $s->{tfh} ? $s->{tfh} + $s->{text_space} : 0 );
$s->{top} = $s->{yafh}/2 if ( $s->{top} == 0 );
$s->set_max_min($data);
# Create the labels for the y_axes, and calculate the max length
$s->create_y_labels();
$s->create_x_labels(); # CONTRIB Scott Prahl
# calculate the left and right of the bounding box for the graph
my $ls = $s->{yafw} * $s->{y_label_len}[1];
$s->{left} = $s->{l_margin} +
( $ls ? $ls + $s->{axis_space} : 0 ) +
( $s->{ylfh1} ? $s->{ylfh} + $s->{text_space} : 0 );
$ls = $s->{yafw} * $s->{y_label_len}[2] if $s->{two_axes};
$s->{right} = $s->{gifx} - $s->{r_margin} - 1 -
$s->{two_axes} * (
( $ls ? $ls + $s->{axis_space} : 0 ) +
( $s->{ylfh2} ? $s->{ylfh} + $s->{text_space} : 0 )
);
# CONTRIB Scott Prahl
# make sure that we can generate valid x tick marks
undef($s->{x_tick_number}) if $s->{numpoints} < 2;
undef($s->{x_tick_number}) if (
!defined $s->{x_max} ||
!defined $s->{x_min} ||
$s->{x_max} == $s->{x_min}
);
# calculate the step size for x data
# CONTRIB Changes by Scott Prahl
if (defined $s->{x_tick_number})
{
my $delta = ($s->{right}-$s->{left})/($s->{x_max}-$s->{x_min});
$s->{x_offset} =
($s->{true_x_min} - $s->{x_min}) * $delta + $s->{left};
$s->{x_step} =
($s->{true_x_max} - $s->{true_x_min}) * $delta/$s->{numpoints};
}
else
{
$s->{x_step} = ($s->{right} - $s->{left})/($s->{numpoints} + 2);
$s->{x_offset} = $s->{left};
}
# get the zero axis level
my $dum;
($dum, $s->{zeropoint}) = $s->val_to_pixel(0, 0, 1);
# Check the size
die "Vertical Gif size too small"
if ( ($s->{bottom} - $s->{top}) <= 0 );
die "Horizontal Gif size too small"
if ( ($s->{right} - $s->{left}) <= 0 );
# More sanity checks
$s->{x_label_skip} = 1 if ( $s->{x_label_skip} < 1 );
$s->{y_label_skip} = 1 if ( $s->{y_label_skip} < 1 );
$s->{y_tick_number} = 1 if ( $s->{y_tick_number} < 1 );
}
sub create_y_labels
{
my $s = shift;
$s->{y_label_len}[1] = 0;
$s->{y_label_len}[2] = 0;
my $t;
foreach $t (0 .. $s->{y_tick_number})
{
my $a;
foreach $a (1 .. ($s->{two_axes} + 1))
{
my $label =
$s->{y_min}[$a] +
$t *
($s->{y_max}[$a] - $s->{y_min}[$a])/$s->{y_tick_number};
$s->{y_values}[$a][$t] = $label;
if (defined $s->{y_number_format})
{
if (ref $s->{y_number_format} eq 'CODE')
{
$label = &{$s->{y_number_format}}($label);
}
else
{
$label = sprintf($s->{y_number_format}, $label);
}
}
my $len = length($label);
$s->{y_labels}[$a][$t] = $label;
($len > $s->{y_label_len}[$a]) and
$s->{y_label_len}[$a] = $len;
}
}
}
# CONTRIB Scott Prahl
sub create_x_labels
{
my $s = shift;
return unless defined($s->{x_tick_number});
$s->{x_label_len} = 0;
my $t;
foreach $t (0..$s->{x_tick_number})
{
my $label =
$s->{x_min} +
$t * ($s->{x_max} - $s->{x_min})/$s->{x_tick_number};
$s->{x_values}[$t] = $label;
if (defined $s->{x_number_format})
{
if (ref $s->{x_number_format} eq 'CODE')
{
$label = &{$s->{x_number_format}}($label);
}
else
{
$label = sprintf($s->{x_number_format}, $label);
}
}
my $len = length($label);
$s->{x_labels}[$t] = $label;
($len > $s->{x_label_len}) and $s->{x_label_len} = $len;
}
}
sub get_x_axis_label_height
{
my $s = shift;
my $data = shift;
return $s->{xafh} unless $s->{x_labels_vertical};
my $len = 0;
my $labels = $data->[0];
my $label;
foreach $label (@$labels)
{
my $llen = length($label);
($llen > $len) and $len = $llen;
}
return $len * $s->{xafw}
}
# inherit open_graph from GIFgraph
sub draw_text($) # GD::Image
{
my $s = shift;
my $g = shift;
# Title
if ($s->{tfh})
{
my $tx =
$s->{left} +
($s->{right} - $s->{left})/2 -
length($s->{title}) * $s->{tfw}/2;
my $ty = $s->{top} - $s->{text_space} - $s->{tfh};
$g->string($s->{tf}, $tx, $ty, $s->{title}, $s->{tci});
}
# X label
if ($s->{xlfh})
{
my $tx =
$s->{left} +
$s->{x_label_position} * ($s->{right} - $s->{left}) -
$s->{x_label_position} * length($s->{x_label}) * $s->{xlfw};
my $ty = $s->{gify} - $s->{xlfh} - $s->{b_margin};
$g->string($s->{xlf}, $tx, $ty, $s->{x_label}, $s->{lci});
}
# Y labels
if ($s->{ylfh1})
{
my $tx = $s->{l_margin};
my $ty =
$s->{bottom} -
$s->{y_label_position} * ($s->{bottom} - $s->{top}) +
$s->{y_label_position} * length($s->{y1_label}) * $s->{ylfw};
$g->stringUp($s->{ylf}, $tx, $ty, $s->{y1_label}, $s->{lci});
}
if ( $s->{two_axes} && $s->{ylfh2} )
{
my $tx = $s->{gifx} - $s->{ylfh} - $s->{r_margin};
my $ty =
$s->{bottom} -
$s->{y_label_position} * ($s->{bottom} - $s->{top}) +
$s->{y_label_position} * length($s->{y2_label}) * $s->{ylfw};
$g->stringUp($s->{ylf}, $tx, $ty, $s->{y2_label}, $s->{lci});
}
}
sub draw_axes($) # GD::Image
{
my $s = shift;
my $g = shift;
my $d = shift;
my ($l, $r, $b, $t) =
( $s->{left}, $s->{right}, $s->{bottom}, $s->{top} );
if ( $s->{box_axis} )
{
$g->rectangle($l, $t, $r, $b, $s->{fgci});
}
else
{
$g->line($l, $t, $l, $b, $s->{fgci});
$g->line($l, $b, $r, $b, $s->{fgci})
unless ($s->{zero_axis_only});
$g->line($r, $b, $r, $t, $s->{fgci})
if ($s->{two_axes});
}
if ($s->{zero_axis} or $s->{zero_axis_only})
{
my ($x, $y) = $s->val_to_pixel(0, 0, 1);
$g->line($l, $y, $r, $y, $s->{fgci});
}
}
#
# Ticks and values for y axes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -