Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/delibero.git

Simplified pie chart code.

AuthorDave Jarvis <email>
Date2014-07-30 11:30:26 GMT-0700
Commitdf2594f17ff7c0e18d97faca3457e607b36b1067
Parent12bc3d3
xml/chart.xsl
<!-- Globals -->
+ <xsl:variable name="PI">3.14159265358979323846</xsl:variable>
<xsl:variable name="fontAdjustment">1.2</xsl:variable>
<xsl:variable name="fontWidthEstimate">1.8</xsl:variable>
- <xsl:variable name="spacing">5</xsl:variable>
<xsl:variable name="epsilon">0.0001</xsl:variable>
<xsl:variable name="tickWidth">2.5</xsl:variable>
<!-- Convert XML data into a Pie Chart. -->
- <xsl:template match="dataset" mode="chart">
+ <xsl:template match="dataset" mode="piechart">
<xsl:variable name="width">100</xsl:variable>
- <xsl:variable name="height">100</xsl:variable>
+ <xsl:variable name="height" select="$width - $PI" />
- <svg:svg width="50%" height="50%" viewBox="0 0 {$width+30} {$height+30}" version="1.1">
+ <svg:svg width="30%" height="30%" viewBox="0 0 {$width} {$height}" version="1.1">
<svg:g stroke-width="0" font-family="sans-serif" fill="#000" stroke="#000">
- <xsl:variable name="depth">0</xsl:variable>
- <xsl:variable name="maxLegend">
- <xsl:call-template name="maxLegend" />
- </xsl:variable>
-
- <xsl:variable name="legendWidth">
- <xsl:choose>
- <xsl:when test="$maxLegend &gt; 0">
- <xsl:value-of select="$maxLegend * $fontAdjustment div $fontWidthEstimate + 2*$spacing" />
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$spacing" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
-
- <xsl:variable name="cols" select="count(data)" />
- <xsl:variable name="rows" select="count(data)" />
+ <!-- Number of pie pieces -->
+ <xsl:variable name="pieces" select="count(data)" />
+ <!-- Calculate the total value for all pieces -->
+ <xsl:variable name="total" select="sum(//value)" />
<xsl:for-each select="data">
- <xsl:variable name="col" select="position()" />
+ <xsl:variable name="piece" select="position()" />
<!-- Calculate Fill Color -->
<xsl:variable name="fill">
- <xsl:variable name="range9">
- <xsl:choose>
- <xsl:when test="$cols &gt; 9">9</xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$cols" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="hue" select="((($col -1) mod $range9) div $range9 div 3.0 + (($col -1) mod 3) div 3.0) * 0.85" />
- <xsl:variable name="saturation" select="1.0 - (floor(($col -1) div $range9 * 0.5) mod 2) * 0.5 " />
- <xsl:variable name="brightness" select="0.8 - floor(($col -1+$range9) div $range9 * 0.5) div (($cols+$range9) div $range9 * 0.5) * 0.4" />
- <xsl:variable name="b" select="floor($brightness * 255 + 0.5)" />
- <xsl:variable name="h" select="floor(($hue - floor($hue)) * 6.0)" />
- <xsl:variable name="f" select="$h - floor($h)" />
- <xsl:variable name="p" select="floor($brightness * (1.0 - $saturation) * 255 + 0.5)" />
- <xsl:variable name="q" select="floor($brightness * (1.0 - $saturation * $f) * 255 + 0.5)" />
- <xsl:variable name="t" select="floor($brightness * (1.0 - ($saturation * (1.0 - $f))) * 255 + 0.5)" />
- <xsl:choose>
- <xsl:when test="$h = 0">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$t" />,<xsl:value-of select="$p" />)</xsl:when>
- <xsl:when test="$h = 1">rgb(<xsl:value-of select="$q" />,<xsl:value-of select="$b" />,<xsl:value-of select="$p" />)</xsl:when>
- <xsl:when test="$h = 2">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$b" />,<xsl:value-of select="$t" />)</xsl:when>
- <xsl:when test="$h = 3">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$q" />,<xsl:value-of select="$b" />)</xsl:when>
- <xsl:when test="$h = 4">rgb(<xsl:value-of select="$t" />,<xsl:value-of select="$p" />,<xsl:value-of select="$b" />)</xsl:when>
- <xsl:when test="$h = 5">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$p" />,<xsl:value-of select="$q" />)</xsl:when>
- </xsl:choose>
+ <xsl:call-template name="fill">
+ <xsl:with-param name="piece" select="$piece" />
+ <xsl:with-param name="pieces" select="$pieces" />
+ </xsl:call-template>
</xsl:variable>
<xsl:for-each select="value">
<xsl:variable name="row" select="position()" />
- <xsl:variable name="total" select="sum(//value[position() = $row])" />
<xsl:variable name="title"><xsl:value-of select="../name" /></xsl:variable>
<xsl:variable name="percent" select="concat($title,' (',format-number(. div $total, '0.00%'),')')" />
- <xsl:variable name="x" select="($width - $legendWidth) * (position()-1) + $spacing" />
- <xsl:variable name="y" select="$fontAdjustment+2*$spacing" />
- <xsl:variable name="rx" select="$width* 0.5" />
- <xsl:variable name="ry" select="($height -$spacing - $depth) * 0.5" />
+ <xsl:variable name="x" select="0" />
+ <xsl:variable name="y" select="0" />
+ <xsl:variable name="rx" select="$width * 0.5" />
+ <xsl:variable name="ry" select="$height * 0.5" />
+
+ <xsl:variable name="deg">
+ <xsl:choose>
+ <xsl:when test="$piece = 1">360</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="360 * (1-sum(//data[position() &lt;=$piece -1]/value[position() = $row]) div $total)" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="c">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="deg" select="$deg" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="s">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="deg" select="-$deg - 90" />
+ </xsl:call-template>
+ </xsl:variable>
- <xsl:choose>
- <xsl:when test="$cols = 1">
- <svg:path fill="{$fill}" title="{$percent}" stroke="none" d="{concat('M',$x,' ',$y+$ry,'a',$rx,' ',$ry,' 0 0 1 ',2*$rx,' 0l0 ',$depth,'a',$rx,' ',$ry,' 0 0 1 ',-2*$rx,' 0l0 ',$depth,'z')}" />
- </xsl:when>
- <xsl:otherwise>
- <xsl:variable name="deg">
- <xsl:choose>
- <xsl:when test="$col = 1">360</xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="360 * (1-sum(//data[position() &lt;=$col -1]/value[position() = $row]) div $total)" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="c">
- <xsl:call-template name="sine">
- <xsl:with-param name="deg" select="$deg" />
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="s">
- <xsl:call-template name="sine">
- <xsl:with-param name="deg" select="-$deg - 90" />
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="deg2" select="360 * (1-sum(//data[position() &lt;=$col]/value[position() = $row]) div $total)" />
- <xsl:variable name="c2">
- <xsl:call-template name="sine">
- <xsl:with-param name="deg" select="$deg2" />
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="s2">
- <xsl:call-template name="sine">
- <xsl:with-param name="deg" select="-$deg2 - 90" />
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="opt">
- <xsl:choose>
- <xsl:when test="$deg - $deg2 &lt; 180">0</xsl:when>
- <xsl:otherwise>1</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <svg:path fill="{$fill}" title="{$percent}" stroke="none" d="{concat('M',$x+$rx,' ',$y+$ry,'L',$x+$rx+$rx*$c2,' ',$y+$ry+$ry*$s2,'A',$rx,' ',$ry,' 0 ',$opt,' 1 ',$x+$rx + $rx * $c,' ',$y+$ry +$ry*$s,'z')}" />
- <xsl:if test="$depth &gt; 0 and $deg2 &lt; 270 and $deg &gt; 90">
- <xsl:variable name="c3">
- <xsl:choose>
- <xsl:when test="$deg2 &lt; 90">1</xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$c2" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="c4">
- <xsl:choose>
- <xsl:when test="$deg &gt; 270">-1</xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$c" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="s3">
- <xsl:choose>
- <xsl:when test="$deg2 &lt; 90">0</xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$s2" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="s4">
- <xsl:choose>
- <xsl:when test="$deg &gt; 270">0</xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$s" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <svg:path fill="{$fill}" stroke="none" d="{concat('M',$x+$rx+$rx*$c3,' ',$y+$ry+$ry*$s3,'A',$rx,' ',$ry,' 0 ',$opt,' 1 ',$x+$rx+$rx*$c4,' ',$y+$ry+$ry*$s4,'l0 ',$depth,'A',$rx,' ',$ry,' 0 ',$opt,' 0 ',$x+$rx+$rx*$c3,' ',$y+$ry+$ry*$s3 +$depth,'z')}" />
- </xsl:if>
- </xsl:otherwise>
- </xsl:choose>
- <xsl:if test="$depth &gt; 0">
- <svg:path fill="black" opacity="0.25" stroke="none" d="{concat('M',$x,' ',$y+$ry,'a',$rx,' ',$ry,' 0 0 0 ',2*$rx,' 0l0 ',$depth,'a',$rx,' ',$ry,' 0 0 1 ',-2*$rx,' 0z')}" />
- </xsl:if>
- </xsl:for-each>
+ <xsl:variable name="deg2" select="360 * (1-sum(//data[position() &lt;=$piece]/value[position() = $row]) div $total)" />
+ <xsl:variable name="c2">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="deg" select="$deg2" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="s2">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="deg" select="-$deg2 - 90" />
+ </xsl:call-template>
+ </xsl:variable>
- <xsl:variable name="yleg" select="((position() -1) ) * $fontAdjustment + 2*$spacing" />
- <svg:g>
- <xsl:for-each select="//dataset/@*">
- <xsl:attribute name="{name()}">
- <xsl:value-of select="'hello'" />
- </xsl:attribute>
- </xsl:for-each>
- <xsl:if test="$maxLegend &gt; 0">
- <svg:text x="{$width -$legendWidth + 2*$spacing}" y="{$yleg}">
- <xsl:for-each select="//data[$col]/@*">
- <xsl:choose>
- <xsl:when test="name() = 'name'"></xsl:when>
- <xsl:when test="name() = 'color'"></xsl:when>
- <xsl:otherwise>
- <xsl:attribute name="{name()}">
- <xsl:value-of select="'hello'" />
- </xsl:attribute>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:for-each>
- <xsl:value-of select="@name" />
- </svg:text>
- <!--
- <svg:rect x="{$width -$legendWidth + $spacing}" y="{$yleg}" width="{$legendSize}" height="{$legendSize}" fill="{$fill}" stroke-width="0" />
- -->
- </xsl:if>
- </svg:g>
+ <xsl:variable name="opt">
+ <xsl:choose>
+ <xsl:when test="$deg - $deg2 &lt; 180">0</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- Fill the piece. -->
+ <svg:path fill="{$fill}" title="{$percent}" stroke="none" d="{concat('M',$x+$rx,' ',$y+$ry,'L',$x+$rx+$rx*$c2,' ',$y+$ry+$ry*$s2,'A',$rx,' ',$ry,' 0 ',$opt,' 1 ',$x+$rx + $rx * $c,' ',$y+$ry +$ry*$s,'z')}" />
+ </xsl:for-each>
</xsl:for-each>
</svg:g>
</svg:svg>
</xsl:template>
-
<xsl:template name="root">
<xsl:template name="sine">
- <!-- deg or rad -->
<xsl:param name="deg" />
- <xsl:param name="rad">
- <xsl:value-of select="$deg div 180 * 3.14159265358979323846" />
+ <xsl:param name="radians">
+ <xsl:value-of select="$deg div 180 * $PI" />
</xsl:param>
- <xsl:param name="ans">
- <xsl:value-of select="$rad" />
+ <xsl:param name="answer">
+ <xsl:value-of select="$radians" />
</xsl:param>
<xsl:param name="loc">1</xsl:param>
<xsl:param name="fract">
- <xsl:value-of select="$rad" />
+ <xsl:value-of select="$radians" />
</xsl:param>
- <xsl:variable name="fract2" select="-1 * $fract * $rad * $rad div ($loc *2 * ($loc * 2 + 1))" />
+ <xsl:variable name="fract2" select="-1 * $fract * $radians * $radians div ($loc *2 * ($loc * 2 + 1))" />
<xsl:choose>
<!-- Exit when at end of precision -->
<xsl:when test="$fract2 &lt; $epsilon and $fract2 &gt; -$epsilon">
- <xsl:value-of select="$ans" />
+ <xsl:value-of select="$answer" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="sine">
- <xsl:with-param name="rad" select="$rad" />
- <xsl:with-param name="ans" select="$ans + $fract2" />
+ <xsl:with-param name="radians" select="$radians" />
+ <xsl:with-param name="answer" select="$answer + $fract2" />
<xsl:with-param name="loc" select="$loc+1" />
<xsl:with-param name="fract" select="$fract2" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
-
- <xsl:template name="maxLegend">
- <xsl:param name="loc">1</xsl:param>
- <xsl:param name="min">0</xsl:param>
- <xsl:variable name="current" select="string-length(//data[$loc]/@name)" />
- <xsl:variable name="max">
+
+ <xsl:template name="fill">
+ <xsl:param name="piece" />
+ <xsl:param name="pieces" />
+
+ <xsl:variable name="range9">
<xsl:choose>
- <xsl:when test="$min &lt; $current">
- <xsl:value-of select="$current" />
- </xsl:when>
+ <xsl:when test="$pieces &gt; 9">9</xsl:when>
<xsl:otherwise>
- <xsl:value-of select="$min" />
+ <xsl:value-of select="$pieces" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
+ <xsl:variable name="hue" select="((($piece -1) mod $range9) div $range9 div 3.0 + (($piece -1) mod 3) div 3.0) * 0.85" />
+ <xsl:variable name="saturation" select="1.0 - (floor(($piece -1) div $range9 * 0.5) mod 2) * 0.5 " />
+ <xsl:variable name="brightness" select="0.8 - floor(($piece -1+$range9) div $range9 * 0.5) div (($pieces+$range9) div $range9 * 0.5) * 0.4" />
+ <xsl:variable name="b" select="floor($brightness * 255 + 0.5)" />
+ <xsl:variable name="h" select="floor(($hue - floor($hue)) * 6.0)" />
+ <xsl:variable name="f" select="$h - floor($h)" />
+ <xsl:variable name="p" select="floor($brightness * (1.0 - $saturation) * 255 + 0.5)" />
+ <xsl:variable name="q" select="floor($brightness * (1.0 - $saturation * $f) * 255 + 0.5)" />
+ <xsl:variable name="t" select="floor($brightness * (1.0 - ($saturation * (1.0 - $f))) * 255 + 0.5)" />
<xsl:choose>
- <xsl:when test="$loc = count(//data)">
- <xsl:value-of select="$max" />
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="maxLegend">
- <xsl:with-param name="min" select="$max" />
- <xsl:with-param name="loc" select="$loc + 1" />
- </xsl:call-template>
- </xsl:otherwise>
+ <xsl:when test="$h = 0">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$t" />,<xsl:value-of select="$p" />)</xsl:when>
+ <xsl:when test="$h = 1">rgb(<xsl:value-of select="$q" />,<xsl:value-of select="$b" />,<xsl:value-of select="$p" />)</xsl:when>
+ <xsl:when test="$h = 2">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$b" />,<xsl:value-of select="$t" />)</xsl:when>
+ <xsl:when test="$h = 3">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$q" />,<xsl:value-of select="$b" />)</xsl:when>
+ <xsl:when test="$h = 4">rgb(<xsl:value-of select="$t" />,<xsl:value-of select="$p" />,<xsl:value-of select="$b" />)</xsl:when>
+ <xsl:when test="$h = 5">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$p" />,<xsl:value-of select="$q" />)</xsl:when>
</xsl:choose>
</xsl:template>
-
</xsl:stylesheet>
xml/common.xsl
</xsl:template>
-<xsl:template match="chart">
- <div class="chart">
- <xsl:apply-templates mode="chart" />
+<xsl:template match="expenses">
+ <div class="expenses">
+ <xsl:apply-templates mode="piechart" />
</div>
</xsl:template>
-<xsl:template match="title" mode="chart">
+<xsl:template match="title" mode="piechart">
<div class="title"><xsl:apply-templates /></div>
</xsl:template>
xml/resources.css
}
-.chart > .title {
+.expenses > .title {
margin-top: 0.5em;
+ margin-bottom: 0.5em;
font-size: 1.2em;
border-bottom: none;
xml/resources.xml
</summary>
<resources>
- <chart>
+ <expenses>
<title>Federal Expenses</title>
<dataset>
</data>
</dataset>
- </chart>
+ </expenses>
</resources>
Delta97 lines added, 200 lines removed, 103-line decrease