Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
285 lines (234 sloc) 10.8 KB
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>Analemma: Clojure Charts and SVG Library</title>
<style type="text/css">
body {font-family: Garamond, Bodoni, "Times New Roman"; background-color: #ffffff; padding: 5px; font-size: 1.1em; color: #333333; }
h1 { font-family: Garamond, Georgia, serif; color: #000066; }
h2 { font-family: Helvetica, Gill, sans-serif; color: #000066; }
h3, h4 { color: #444444; }
li {padding-left: 25px; padding-right: 25px; padding-top: 5px; }
.code-ref { background-color: #F8F8F8; color: #003399; font-style:italic; padding-left: 5px; padding-right: 5px; font-size: 0.9em; }
.code-sig { background-color: #DDDDDD; color: #003399; font-family: "Courier New", Courier; padding-left: 5px; }
.code-listing { background-color: #FFFFFF; color: #444444; border: #EEEEEE 1px solid; padding-bottom: 1px; padding-left: 5px; border-bottom: #DDDDDD 1px solid; border-right: #DDDDDD 1px solid; font-size: 1em }
.quote { background-color: #F8F8F8; color: #555555; font-style:italic; padding-left: 25px; padding-right: 25px; width: 500px; margin: 15px; }
code { color: #555555; }
.content { width: 675px; margin: 0px auto; }
p { text-align: justify; }
.box { background-color: #DDDDDD; color: #333333; padding-left:
15px; padding-top: 15px; padding-bottom: 15px; border: #CCCCCC 1px
solid; border-bottom: #CCCCCC 1px solid; border-right: #CCCCCC 1px
solid; font-size: 0.95em; font-family: Helvetica, Gill, sans-serif; }
.box li { padding: 2px; }
.box ul { margin-top: 5px; margin-bottom: 2px; }
.footnote { font-style: italic; color:#777777; font-size: 0.9em; padding-left: 5px;
padding-right: 25px; padding-bottom: 10px; }
strike, s { text-decoration: line-through; color: red; font-weight: bold; }
.insert { font-weight: bold; font-style: italic; color:#33a933;}
</style>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-12283660-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="content">
<embed src="images/analemma-logo.svg" width="475" height="135"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<p><i><b><a href="http://github.com/liebke/analemma">Analemma</a></b> is a <a
href="http://clojure.org">Clojure</a> library for generating
charts and <a
href="http://en.wikipedia.org/wiki/Scalable_Vector_Graphics">Scalable
Vector Graphics</a> (SVG). The code is available on <a href="http://github.com/liebke/analemma">Github</a></i></p>
<div class="footnote">* In astronomy, an <a href="http://en.wikipedia.org/wiki/Analemma">analemma</a> is the figure drawn in the sky by the different positions of the Sun recorded at the same time and location during the course of a year.</div>
<embed src="images/sin-cos-small.svg" width="600" height="300"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<h2>Architecture</h2>
<embed src="images/analemma-stack.svg" width="350" height="200"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<div class="footnote">* The above animated SVG image may not be visible in
Firefox, and has not been tested in IE.</div>
<p>Analemma was originally developed as an extended example to use
when teaching
Clojure programming, and so it's been designed to be lightweight and
have no dependencies other than Clojure.</p>
<p>Analemma is designed as a stack of three simple libraries, each building
on the one below it. At the bottom is <a href="https://github.com/liebke/analemma/blob/master/src/analemma/xml.clj">analemma.xml</a>, which provides a
lightweight DSL for generating XML from Clojure data structures; if you've used <a href="https://github.com/weavejester">James Reeves</a>'
<a href="https://github.com/weavejester/hiccup">Hiccup</a> library
for generating HTML, then the syntax will look familiar.</p>
<p>The next level up is <a href="https://github.com/liebke/analemma/blob/master/src/analemma/svg.clj">analemma.svg</a>, which provides a set of
functions for generating and transforming SVG images and animations. SVG supports an
enormous number of tags, most of which are not represented in this
library; when an unimplemented tag is required, just drop down into analemma.xml
and create the necessary SVG XML with Clojure data structures.</p>
<p>The final layer is <a href="https://github.com/liebke/analemma/blob/master/src/analemma/charts.clj">analemma.charts</a>, which provides basic charting
functionality with a syntax similar to <a
href="http://incanter.org">Incanter</a>, and a visual theme similar
to <a href="http://had.co.nz/">Hadley Wickham</a>'s <a href="http://had.co.nz/ggplot2/">ggplot2</a> library for
<a href="http://www.r-project.org">R</a>. The development of this
library has just begun, and it is missing a lot of functionality; when
additional features are required, just drop down into analemma.svg or
analemma.xml.</p>
<h2>analemma.charts examples</h2>
<h3>Plotting Analemma Data</h3>
<div class="code-listing">
<pre><code>(spit "analemma.svg"
(emit-svg
(-> (xy-plot :xmin -30 :maxx 10,
:ymin -30 :maxy 30
:height 500 :width 500)
(add-points analemma-data))))
</code></pre>
</div>
<p>The full source code and data for this example can
be found on <a
href="https://github.com/liebke/analemma/blob/master/src/examples/analemma.clj">
github</a>. The data was obtained from <a
href="http://www.wsanford.com/~wsanford/exo/sundials/analemma_calc.html">this
site</a>.</p>
<embed src="images/analemma.svg" width="600" height="600"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<h3>Plotting Sine and Cosine</h3>
<div class="code-listing">
<pre><code>(let [x (range -5 5 0.05)
y1 (map #(Math/cos %) x)
y2 (map #(Math/sin %) x)]
(spit "sin-cos-small.svg"
(emit-svg
(-> (xy-plot :width 450 :height 200
:xmin -5 :xmax 5
:ymin -1.5 :ymax 1.5)
(add-points [x y1]
:transpose-data? true
:size 1)
(add-points [x y2]
:transpose-data? true
:size 1
:fill (rgb 255 0 0))))))
</code></pre>
</div>
<p>The full source code and data for this example can
be found on <a
href="https://github.com/liebke/analemma/blob/master/src/examples/charts.clj">
github</a>.</p>
<embed src="images/sin-cos-small.svg" width="600" height="300"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<h3>Labeling Data Points</h3>
<div class="code-listing">
<pre><code>(let [x (repeatedly 25 #(rand-int 100))
y (repeatedly 25 #(rand-int 100))]
(spit "rand-plot.svg"
(emit-svg
(-> (xy-plot :width 500 :height 500
:label-points? true)
(add-points [x y] :transpose-data? true)))))
</code></pre>
</div>
<p>The full source code and data for this example can
be found on <a
href="https://github.com/liebke/analemma/blob/master/src/examples/charts.clj">
github</a>.</p>
<embed src="images/rand-plot.svg" width="600" height="600"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<h2>analemma.svg examples</h2>
<h3>Analemma Logo</h3>
<embed src="images/analemma-logo.svg" width="475" height="135"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<p>The full source code and data for this example can
be found on <a
href="https://github.com/liebke/analemma/blob/master/src/examples/analemma.clj">
github</a>.</p>
<div class="code-listing">
<pre><code>(emit
(svg
(apply group
(-> (text "Analemma")
(add-attrs :x 120 :y 60)
(style :fill #"000066"
:font-family "Garamond"
:font-size "75px"
:alignment-baseline :middle))
(for [[x y] analemma-data]
(circle (translate-value x -30 5 0 125)
(translate-value y -25 30 125 0)
2 :fill "#000066")))))
</code></pre></div>
<h3>Animated Analemma Stack</h3>
<embed src="images/analemma-stack.svg" width="350" height="200"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<div class="footnote">* The above animated SVG image may not be visible in
Firefox, and has not been tested in IE.</div>
<p>The full source code and data for this example can
be found on <a
href="https://github.com/liebke/analemma/blob/master/src/examples/charts.clj">
github</a>.</p>
<div class="code-listing">
<pre><code>(defn txt-box [txt x y fill]
(let [box-width 300
box-height 50]
(-> (svg
(group
(-> (rect 0 0 box-height box-width :rx 5 :ry 5)
(style :stroke fill :fill fill))
(-> (text txt)
(add-attrs :x (/ box-width 2)
:y (/ box-height 2)})
(style :fill "#ffffff"
:font-size "25px"
:font-family "Verdana"
:alignment-baseline :middle
:text-anchor :middle))))
(add-attrs :x x :y y))))
(defn analemma-stack [directory]
(spit (str directory "analemma-stack.svg")
(emit
(svg
(-> (group
(-> (txt-box "analemma.charts" 0 10 "#006600")
(add-attrs :visibility :hidden)
(animate :visibility :to :visible :begin 5)
(animate :y :begin 5 :dur 1 :from 0 :to 10))
(-> (txt-box "analemma.svg" 0 65 "#660000")
(add-attrs :visibility :hidden)
(animate :visibility :to :visible :begin 3)
(animate :y :begin 3 :dur 2 :from 0 :to 65))
(-> (txt-box "analemma.xml" 0 120 "#000066")
(add-attrs :visibility :hidden)
(animate :visibility :to :visible :begin 1)
(animate :y :begin 1 :dur 4 :from 0 :to 120)))
(translate 10 10))))))
</code></pre>
</div>
<h2>analemma.xml examples</h2>
The following code uses analemma.xml to produce a snippet of SVG XML.
<div class="code-listing">
<pre><code>(emit
[:svg
[:g {:x 100, :y 100}
[:rect {:x 0, :y 0, :height 50, :width 300
:style "stroke: #660000; fill: #660000;"}]
[:text {:style "fill: #660000; font-size: 25px; font-family: Verdana"
:x 150 :y 25}]]])
</code></pre>
</div>
<p>XML tags are represented as Clojure vectors. The first value in the vector represents the tag's name. If the
second value is a Clojure map, it is treated as the tag's
attributes. Any remaining values will be vectors representing child elements.</p>
<div class="footnote" align="center">&copy; 2011 David Edgar Liebke</div>
</div> <!-- content -->
</body> </html>