[Catalyst-commits] r8683 - in trunk/examples/CatalystAdvent/root: 2008/pen static/images static/images/2008 static/images/2008/sparklines

gphat at dev.catalyst.perl.org gphat at dev.catalyst.perl.org
Tue Dec 2 01:00:54 GMT 2008


Author: gphat
Date: 2008-12-02 01:00:54 +0000 (Tue, 02 Dec 2008)
New Revision: 8683

Added:
   trunk/examples/CatalystAdvent/root/2008/pen/3.pod
   trunk/examples/CatalystAdvent/root/static/images/2008/
   trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/
   trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/all-spark.png
   trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/bigchart.png
   trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/curr-spark.png
   trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/range-spark.png
   trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/simple-spark.png
Log:
Day 3 (sparklines) and images for same.

Added: trunk/examples/CatalystAdvent/root/2008/pen/3.pod
===================================================================
--- trunk/examples/CatalystAdvent/root/2008/pen/3.pod	                        (rev 0)
+++ trunk/examples/CatalystAdvent/root/2008/pen/3.pod	2008-12-02 01:00:54 UTC (rev 8683)
@@ -0,0 +1,426 @@
+=head1 Making sparklines with Chart::Clicker
+
+=begin pod::xhtml
+
+<style>
+ table td,
+ table th {
+     border: 1px solid gray;
+     padding: 3px;
+ }
+ table thead {
+     background-color: gray; color: white; padding: 3px
+ }
+ blockquote {
+     font-weight: bold;
+ }
+ pre {
+     border: 1px solid gray;
+     background-color: #d9d9d9;
+     font-size: 1.2em;
+     padding: 3px;
+ }
+</style>
+
+<p>
+Today we will use Chart::Clicker and Catalyst::View::Graphics::Primitive to
+create a Catalyst web application for serving sparklines.
+</p>
+
+<h2>Sparklines?</h2>
+
+<p>
+Sparklines are "information graphics".  The <a href="http://en.wikipedia.org/wiki/Sparkline">term</a>
+was proposed by <a href="http://en.wikipedia.org/wiki/Edward_Tufte">Edward Tufte</a>, the author
+of many books on data visualization.
+</p>
+
+<h2>Preparation</h2>
+
+<p>
+First, you'll need to install L<Chart::Clicker|http://search.cpan.org/perldoc?Chart::Clicker>.
+Clicker is a great-looking L<charting package|http://www.onemogin.com/clicker/>
+that uses L<Graphics::Primitive|http://search.cpan.org/perldoc?Graphics::Primitive>.
+</p>
+
+<p>
+You'll also need the L<Catalyst view|http://search.cpan.org/perldoc?Catalyst::View::Graphics::Primitive>.
+</p>
+
+<p>
+Adding a Graphics::Primitive view to your application is a breeze:
+
+<pre>
+script/yourapp_create.pl view GP Graphics::Primitive
+</pre>
+
+<p>
+This creates a <tt>GP </tt> view.  You'll need to decide on a suitable way to forward
+to the appropriate view in your application.  Since this view expects to find
+a Graphics::Primitive object in the <tt>graphics_primitive</tt> key of the
+stash, you might forward to the <tt>GP </tt> view when that key is set.
+
+<h2>The Problem</h2>
+
+<p>
+It is fairly common in documents to throw a tidbit of info at the reader. I
+recently wrote a report on the effects of an ad campaign on our site and
+included the following sentence:
+</p>
+<blockquote>
+Our throughput is currently 4.4Mb/s.
+</blockquote>
+<p>
+When presenting such a measurement to a reader, such as the amount of bandwidth
+being consumed by your site, it is often desirable to give the number
+some context. If we wanted to conduct more information to the reader, such as
+the last 24 measurements we might resort to a table.
+</p>
+<table>
+ <thead>
+  <tr>
+   <th>Time</th>
+   <th>Mb/s</th>
+  </tr>
+ </thead>
+ <tbody>
+  <tr>
+   <td>2008-11-26 16:00</td><td>5.8</td>
+  </tr>
+  <tr>
+   <td>2008-11-26 17:00</td><td>5.0</td>
+  </tr>
+  <tr>
+   <td>2008-11-26 18:00</td><td>4.9</td>
+  </tr>
+  <tr>
+   <td>2008-11-26 19:00</td><td>4.8</td>
+  </tr>
+  <tr>
+   <td>2008-11-26 20:00</td><td>4.5</td>
+  </tr>
+  <tr>
+   <td>2008-11-26 21:00</td><td>4.25</td>
+  </tr>
+  <tr>
+   <td>2008-11-26 22:00</td><td>3.5</td>
+  </tr>
+  <tr>
+   <td>2008-11-26 23:00</td><td>2.9</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 00:00</td><td>2.5</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 01:00</td><td>1.8</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 02:00</td><td>0.9</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 03:00</td><td>0.8</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 04:00</td><td>0.7</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 05:00</td><td>1.1</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 06:00</td><td>1.7</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 07:00</td><td>2.5</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 08:00</td><td>3.0</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 09:00</td><td>4.5</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 10:00</td><td>5.0</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 11:00</td><td>4.9</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 12:00</td><td>4.7</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 13:00</td><td>4.8</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 14:00</td><td>4.2</td>
+  </tr>
+  <tr>
+   <td>2008-11-27 15:00</td><td>4.4</td>
+  </tr>
+ </tbody>
+</table>
+<p>
+Now the reader can contextualize the information.  Is the throughput high or low?  Was
+it sustained?  Many questions are answered here.
+</p>
+<p>
+While accurately portraying the information, this might be a bit "wordy" for our needs.
+Humans are visual creatures and large blocks of text like this don't mean much to our
+eyes.  Your next option would be to generate a chart that presents this information.
+We won't cover how to do this with Catalyst at the moment.  We'll just look
+at the result for now.
+<p>
+<img src="/static/images/2008/sparklines/bigchart.png" alt="A Big Chart">
+<p>
+This is a wonderful idea!  The data is now presented in a really meaningful way.  The
+problem is that the chart is a very large image for such a small amount of information.
+Our snippet about throughput was really just supposed to convey that the throughput of
+4.4Mb/s was normal.
+</p>
+<h2>The Solution</h2>
+<p>
+Enter the sparkline!
+</p>
+<p>We'll begin with a standard Catalyst contoller and action:</p>
+
+=end pod::xhtml
+
+ package MyApp::Pretty;
+
+ use strict;
+ use warnings;
+ use base 'Catalyst::Controller';
+
+ sub spark : Local {
+    my ($self, $c) = @_;
+
+ }
+
+ 1;
+
+=begin pod::xhtml
+
+<p>
+Now we'll add the <tt>use</tt> statements to get Clicker imported:
+</p>
+
+=end pod::xhtml
+
+ use Chart::Clicker;
+ use Chart::Clicker::Context;
+ use Chart::Clicker::Data::DataSet;
+ use Chart::Clicker::Data::Marker;
+ use Chart::Clicker::Data::Series;
+ use Chart::Clicker::Renderer::Point;
+ use Geometry::Primitive::Rectangle;
+ use Graphics::Color::RGB;
+
+=begin pod::xhtml
+
+<p>
+With that out of the way, we can add the following to our <tt>spark</tt>
+action.
+</p>
+
+=end pod::xhtml
+
+ my $cc = Chart::Clicker->new(width => 75, height => 18);
+
+ my @hours = qw(
+     1 2 3 4 5 6 7 8 9 10 11 12
+     13 14 15 16 17 18 19 20 21 22 23 24
+ );
+ my @bw = qw(
+     5.8 5.0 4.9 4.8 4.5 4.25 3.5 2.9 2.5 1.8 .9 .8
+     .7 1.1 1.7 2.5 3.0 4.5 5.0 4.9 4.7 4.8 4.2 4.4
+ );
+
+ my $series = Chart::Clicker::Data::Series->new(
+     keys    => \@hours,
+     values  => \@bw,
+ );
+
+ my $ds = Chart::Clicker::Data::DataSet->new(series => [ $series ]);
+
+ $cc->add_to_datasets($ds);
+
+=end pod::xhtml
+
+=begin pod::xhtml
+
+<p>
+That gets our chart created and the data in it.  You'll want to substitute
+this static static for something dynamic.  Since I've no idea where your data
+is then I will leave it to you.
+</p>
+
+=end pod::xhtml
+
+ my $grey = Graphics::Color::RGB->new(
+     red => .36, green => .36, blue => .36, alpha => 1
+ );
+
+ $cc->color_allocator->colors([ $grey ]);
+
+=begin pod::xhtml
+
+<p>
+This gets our line's color set to grey.
+</p>
+
+=end pod::xhtml
+
+ $cc->plot->grid->visible(0);
+ $cc->legend->visible(0);
+ $cc->padding(2);
+ $cc->border->width(0);
+
+=begin pod::xhtml
+
+<p>That hides all the decorations around the chart itself.</p>
+
+=end pod::xhtml
+
+ my $defctx = $cc->get_context('default');
+ $defctx->range_axis->hidden(1);
+ $defctx->range_axis->fudge_amount(.2);
+ $defctx->domain_axis->hidden(1);
+ $defctx->domain_axis->fudge_amount(.1);
+ $defctx->renderer->brush->width(1);
+
+=begin pod::xhtml
+
+<p>
+Finally, we hide the axes and provide a little "fudge" to make things look
+nice.
+</p>
+
+<p>
+Now we can put the Clicker object into the stash so that Graphics::Primitive
+will render it for us.
+</p>
+
+=end pod::xhtml
+
+ $c->stash->{graphics_primitive_driver_args} = { format => 'png' };
+ $c->stash->{graphics_primitive_content_type} = 'image/png';
+ $c->stash->{graphics_primitive} = $cc;
+
+=begin pod::xhtml
+
+<p>
+The sparkline provides a small but dense view into the data being discussed.  In
+lieu of the methods already discussed, one could place the following:
+</p>
+<blockquote>
+Throughput is <img src="/static/images/2008/sparklines/simple-spark.png"> 4.4Mb/s.
+</blockquote>
+
+<p>
+You'll get this sparkline when you visit the action we made above!
+</p>
+
+<p>
+This is an effective way of providing a wealth of context to the reader without bogging
+them down sorting out a chart.  But we can do much better!
+</p>
+
+<blockquote>
+Throughput is <img src="/static/images/2008/sparklines/curr-spark.png"> <span style="color: #ff0000">4.4Mb/s</span>.
+</blockquote>
+
+=end pod::xhtml
+
+ my $series2 = Chart::Clicker::Data::Series->new(
+     keys => [ 24 ],
+     values => [ 4.4 ]
+ );
+
+ my $currds = Chart::Clicker::Data::DataSet->new(series => [ $series2 ]);
+ $cc->add_to_datasets($currds);
+
+ my $currctx = Chart::Clicker::Context->new(
+   name => 'current',
+   renderer => Chart::Clicker::Renderer::Point->new(
+       shape => Geometry::Primitive::Rectangle->new(
+           width => 3,
+           height => 3
+       )
+   ),
+   range_axis => $defctx->range_axis,
+   domain_axis => $defctx->domain_axis
+ );
+ $cc->add_to_contexts($currctx);
+ $currds->context('current');
+
+=begin pod::xhtml
+
+<p>
+Here we've added a new series to the chart.  We then set the series to use a
+Point renderer.  With this we highlight the "current" point on the chart.
+</p>
+
+<p>
+Unfortunately, this has flaws as well.  The graph gives us enough context to know that
+4.4Mb/s is on the high end, but the scale is ambiguous.  We can improve this even further:
+</p>
+<blockquote>
+Throughput is <img src="/static/images/2008/sparklines/all-spark.png"> <span style="color: #ff0000">4.4Mb/s</span> (<span style="color: #3399ff">High 5.8, Low 0.7</span>).
+</blockquote>
+
+=end pod::xhtml
+
+ my $series3 = Chart::Clicker::Data::Series->new(
+    keys => [ 1, 13 ],
+    values => [ 5.8, .7 ]
+ );
+
+ my $noteds = Chart::Clicker::Data::DataSet->new(series => [ $series3 ]);
+ $cc->add_to_datasets($noteds);
+
+ my $notectx = Chart::Clicker::Context->new(
+   name => 'notable',
+   renderer => Chart::Clicker::Renderer::Point->new(
+       shape => Geometry::Primitive::Rectangle->new(
+           width => 3,
+           height => 3
+       )
+   ),
+   range_axis => $defctx->range_axis,
+   domain_axis => $defctx->domain_axis
+ );
+ $cc->add_to_contexts($notectx);
+ $noteds->context('notable');
+
+=begin pod::xhtml
+
+<p>
+You could go a step further and highlight the "normal" range of values:
+</p>
+<blockquote>
+Throughput is <img src="/static/images/2008/sparklines/range-spark.png"> <span style="color: #ff0000">4.4Mb/s</span> (<span style="color: #3399ff">High 5.8, Low 0.7</span>).
+</blockquote>
+
+=end pod::xhtml
+
+ my $mark = Chart::Clicker::Data::Marker->new(value => 2, value2 => 4);
+ $mark->brush->color(
+     Graphics::Color::RGB->new(red => 0, green => 0, blue => 0, alpha => .15)
+ );
+ $mark->inside_color(
+     Graphics::Color::RGB->new(red => 0, green => 0, blue => 0, alpha => .15)
+ );
+ $defctx->add_marker($mark);
+
+=begin pod::xhtml
+
+<h2>Conclusion</h2>
+
+<p>
+Sparklines are an effective way of providing a lot of information in a small
+space.  I hope that this introduction will allow you to spice up your
+application with information-rich snippets.  Exploring Chart::Clicker's
+documentation or reading L<more on sparklines|http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR>
+may give you other ideas.
+</p>
+
+<p style="font-style: italic">-- Cory 'gphat' Watson</p>
\ No newline at end of file

Added: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/all-spark.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/all-spark.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/bigchart.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/bigchart.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/curr-spark.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/curr-spark.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/range-spark.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/range-spark.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/simple-spark.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/CatalystAdvent/root/static/images/2008/sparklines/simple-spark.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream




More information about the Catalyst-commits mailing list