Dave Jarvis' Repositories

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

Rewrote how to create pie slices.

Author Dave Jarvis <email>
Date 2014-08-02 18:22:59 GMT-0700
Commit aaaf9b325964745f1411e9b6a4fc38819657b39e
Parent 5de8f6a
xml/chart.xsl
<xsl:variable name="base_colour" select="'46A5E5'" />
+ <xsl:variable name="stroke_colour" select="'white'" />
+ <xsl:variable name="width" select="200" />
+ <xsl:variable name="height" select="$width" />
<!-- Convert XML data into a pie chart. -->
<xsl:template match="dataset" mode="piechart">
- <xsl:variable name="width">100</xsl:variable>
- <xsl:variable name="height" select="$width" />
<!-- Number of pie pieces. -->
<xsl:variable name="pieces" select="count(data)" />
<!-- Calculate the total value for all pieces (for percentages). -->
<xsl:variable name="total" select="sum(//value)" />
- <!-- http://jbkflex.wordpress.com/2011/07/28/creating-a-svg-pie-chart-html5/ -->
- <!-- http://www.codestore.net/store.nsf/unid/epsd-5dtt4l -->
<div class="chart">
<div class="graph">
<svg:svg width="30%" height="30%" viewBox="0 0 {$width} {$height}" version="1.1">
- <svg:g stroke-width="0" fill="#000" stroke="#000">
- <xsl:for-each select="data">
- <xsl:variable name="piece" select="position()" />
-
- <!-- Calculate pie piece fill colour. -->
- <xsl:variable name="fill">
+ <xsl:for-each select="data">
+ <xsl:apply-templates select="value" mode="piechart">
+ <xsl:with-param name="colour">
<xsl:call-template name="fill">
- <xsl:with-param name="piece" select="$piece" />
+ <xsl:with-param name="piece" select="position()" />
<xsl:with-param name="pieces" select="$pieces" />
<xsl:with-param name="colour" select="$base_colour" />
</xsl:call-template>
- </xsl:variable>
-
- <xsl:for-each select="value">
- <!-- Pie piece item number. -->
- <xsl:variable name="item" select="position()" />
-
- <xsl:variable name="title" select="concat(../name,' (',format-number(. div $total, '0.00%'),')')" />
-
- <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>
- <!-- Whole pie. -->
- <xsl:when test="$piece = 1">360</xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="360 * (1 - sum(//data[position() &lt;= $piece -1]/value[position() = $item]) div $total)" />
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="c">
- <xsl:call-template name="sin">
- <xsl:with-param name="degrees" select="$deg" />
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="s">
- <xsl:call-template name="sin">
- <xsl:with-param name="degrees" select="-$deg - 90" />
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:variable name="deg2" select="360 * (1 - sum(//data[position() &lt;= $piece]/value[position() = $item]) div $total)" />
- <xsl:variable name="c2">
- <xsl:call-template name="sin">
- <xsl:with-param name="degrees" select="$deg2" />
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="s2">
- <xsl:call-template name="sin">
- <xsl:with-param name="degrees" 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>
-
- <!-- Fill the pie piece. -->
- <svg:path fill="{$fill}" title="{$title}" stroke="white" stroke-width="0.5" 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>
+ </xsl:with-param>
+ <xsl:with-param name="total" select="$total" />
+ <xsl:with-param name="runningTotal" select="sum(preceding-sibling::data/value)" />
+ <xsl:with-param name="radius" select="$width * 0.5" />
+ </xsl:apply-templates>
+ </xsl:for-each>
</svg:svg>
</div>
+ <!-- SVG 1.1 has no text flow abilities: legend is plain HTML. -->
<div class="legend">
<xsl:for-each select="//name">
- <xsl:variable name="fill">
+ <xsl:variable name="colour">
<xsl:call-template name="fill">
<xsl:with-param name="piece" select="position()" />
<div class="piece">
- <div class="bullet" style="background-color:{$fill}" />
+ <div class="bullet" style="background-color:{$colour}" />
<xsl:value-of select="$percent" />
</div>
-
</xsl:for-each>
</div>
</div>
+ </xsl:template>
+
+ <!-- http://www.svgopen.org/2003/papers/CreatingSVGPieChartsThroughWebService/ -->
+ <!-- http://jbkflex.wordpress.com/2011/07/28/creating-a-svg-pie-chart-html5/ -->
+ <!-- http://www.codestore.net/store.nsf/unid/epsd-5dtt4l -->
+ <xsl:template match="value" mode="piechart">
+ <xsl:param name="colour" />
+ <xsl:param name="total" />
+ <xsl:param name="runningTotal" />
+ <xsl:param name="radius" />
+
+ <xsl:variable name="title" select="concat(../name,' (',format-number(. div $total, '0.00%'),')')" />
+ <xsl:variable name="r" select="$radius" />
+
+ <!-- Set the start and ending angles. -->
+ <xsl:variable name="sa" select="360.0 * ($runningTotal div $total)" />
+ <xsl:variable name="ea" select="360.0 * (($runningTotal + .) div $total)" />
+
+ <xsl:variable name="x1">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="degrees" select="-$sa" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="y1">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="degrees" select="(-$sa - 90)" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="x2">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="degrees" select="-$ea" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="y2">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="degrees" select="(-$ea - 90)" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="sweep">
+ <xsl:choose>
+ <xsl:when test="($ea - $sa &gt; 180)">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <svg:path
+ fill="{$colour}"
+ title="{$title}"
+ stroke="{$stroke_colour}"
+ transform="translate({$radius},{$radius})"
+ d="{concat('M 0 0 L ', $x1 * $r, ' ', $y1 * $r, ' A ', $r, ' ', $r, ' 0 ', $sweep, ' 0 ', $x2 * $r, ' ', $y2 * $r, ' Z' )}" />
</xsl:template>
xml/math.xsl
</xsl:template>
- <!-- sin(x) = x(1 - (x^2/2*3)(1 - (x^2/4*5)(1 - (x^2/6*7)))) -->
- <xsl:template name="sin">
+ <!--
+ | Calculates sin(x), given x in degrees (not radians):
+ | x(1 - (x^2/2*3)(1 - (x^2/4*5)(1 - (x^2/6*7))))
+ +-->
+ <xsl:template name="sine">
<xsl:param name="degrees" />
<xsl:param name="radians" select="$degrees * $PI div 180" />
<xsl:param name="iter" select="31" />
<xsl:param name="result" select="1" />
<xsl:variable name="term" select="($radians * $radians) div (($iter - 1) * $iter)" />
<xsl:choose>
<xsl:when test="$iter &gt; 2">
- <xsl:call-template name="sin">
+ <xsl:call-template name="sine">
<xsl:with-param name="radians" select="$radians" />
<xsl:with-param name="iter" select="$iter - 2" />
</xsl:template>
- <!-- Returns the larger of the two values (a, b). -->
+ <!-- Returns the larger of two values (a, b). -->
<xsl:template name="max">
<xsl:param name="a" select="0" />
Delta 75 lines added, 70 lines removed, 5-line increase