1package Chart::Clicker::Renderer::Area;
2$Chart::Clicker::Renderer::Area::VERSION = '2.90';
3use Moose;
4
5extends 'Chart::Clicker::Renderer';
6
7# ABSTRACT: Area renderer
8
9use Graphics::Primitive::Brush;
10use Graphics::Primitive::Path;
11use Graphics::Primitive::Operation::Fill;
12use Graphics::Primitive::Operation::Stroke;
13use Graphics::Primitive::Paint::Gradient::Linear;
14use Graphics::Primitive::Paint::Solid;
15
16
17has 'brush' => (
18    is => 'rw',
19    isa => 'Graphics::Primitive::Brush',
20    default => sub { Graphics::Primitive::Brush->new }
21);
22
23
24has 'fade' => (
25    is => 'rw',
26    isa => 'Bool',
27    default => 0
28);
29
30
31has 'opacity' => (
32    is => 'rw',
33    isa => 'Num',
34    default => 0
35);
36
37override('finalize', sub {
38    my ($self) = @_;
39
40    my $height = $self->height;
41    my $width = $self->width;
42    my $clicker = $self->clicker;
43
44    my $dses = $clicker->get_datasets_for_context($self->context);
45    foreach my $ds (@{ $dses }) {
46        foreach my $series (@{ $ds->series }) {
47
48            # TODO if undef...
49            my $ctx = $clicker->get_context($ds->context);
50            my $domain = $ctx->domain_axis;
51            my $range = $ctx->range_axis;
52
53            my $lastx; # used for completing the path
54            my @vals = @{ $series->values };
55            my @keys = @{ $series->keys };
56
57            my $startx;
58
59            my $biggest;
60            for(0..($series->key_count - 1)) {
61
62                my $x = $domain->mark($width, $keys[$_]);
63                next unless defined($x);
64
65                my $ymark = $range->mark($height, $vals[$_]);
66                next unless defined($ymark);
67                my $y = $height - $ymark;
68
69                if(defined($biggest)) {
70                    $biggest = $y if $y > $biggest;
71                } else {
72                    $biggest = $y;
73                }
74
75                if($_ == 0) {
76                    $startx = $x;
77                    $self->move_to($x, $y);
78                } else {
79                    $self->line_to($x, $y);
80                }
81                $lastx = $x;
82            }
83            my $color = $self->clicker->color_allocator->next;
84
85            my $op = Graphics::Primitive::Operation::Stroke->new;
86            $op->preserve(1);
87            $op->brush($self->brush->clone);
88            $op->brush->color($color);
89
90            $self->do($op);
91
92            $self->line_to($lastx, $height);
93            $self->line_to($startx, $height);
94            $self->close_path;
95
96            my $paint;
97            if($self->opacity) {
98
99                my $clone = $color->clone;
100                $clone->alpha($self->opacity);
101                $paint = Graphics::Primitive::Paint::Solid->new(
102                    color => $clone
103                );
104            } elsif($self->fade) {
105
106                my $clone = $color->clone;
107                $clone->alpha($self->opacity);
108
109                $paint = Graphics::Primitive::Paint::Gradient::Linear->new(
110                    line => Geometry::Primitive::Line->new(
111                        start => Geometry::Primitive::Point->new(x => 0, y => 0),
112                        end => Geometry::Primitive::Point->new(x => 1, y => $biggest),
113                    ),
114                    style => 'linear'
115                );
116                $paint->add_stop(1.0, $color);
117                $paint->add_stop(0, $clone);
118            } else {
119
120                $paint = Graphics::Primitive::Paint::Solid->new(
121                    color => $color->clone
122                );
123            }
124            my $fillop = Graphics::Primitive::Operation::Fill->new(
125                paint => $paint
126            );
127
128            $self->do($fillop);
129        }
130    }
131
132    return 1;
133});
134
135__PACKAGE__->meta->make_immutable;
136
137no Moose;
138
1391;
140
141__END__
142
143=pod
144
145=head1 NAME
146
147Chart::Clicker::Renderer::Area - Area renderer
148
149=head1 VERSION
150
151version 2.90
152
153=head1 SYNOPSIS
154
155  my $ar = Chart::Clicker::Renderer::Area->new({
156      fade => 1,
157      brush => Graphics::Primitive::Brush->new({
158          width => 2
159      })
160  });
161
162=head1 DESCRIPTION
163
164Chart::Clicker::Renderer::Area renders a dataset as line-like polygons with
165their interior areas filled.
166
167=for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/area.png" width="500" height="250" alt="Area Chart" /></p>
168
169=head1 ATTRIBUTES
170
171=head2 brush
172
173Set/Get the L<brush|Graphics::Primitive::Brush> that informs the line surrounding the area renders
174individual segments.
175
176=head2 fade
177
178Set/Get the fade flag, which turns on or off a gradient in the area renderer.
179
180=head2 opacity
181
182Set the alpha value for the renderer, which makes things more or less opaque.
183
184=head1 AUTHOR
185
186Cory G Watson <gphat@cpan.org>
187
188=head1 COPYRIGHT AND LICENSE
189
190This software is copyright (c) 2016 by Cory G Watson.
191
192This is free software; you can redistribute it and/or modify it under
193the same terms as the Perl 5 programming language system itself.
194
195=cut
196