Added BAR CHARTS!

This commit is contained in:
Joshua Seigler 2016-07-05 01:49:18 -04:00
parent 603666e167
commit c5f6c0476e
5 changed files with 116 additions and 23 deletions

View file

@ -3,7 +3,11 @@
PHP project to generate clean-looking SVG price charts
![Dash 24h price in BTC from Poloniex](http://cryptohistory.org/charts/dark/dash-btc/30d/svg?lineColor=1C74BC)
7d of Dash price in Bitcoin from Poloniex.com
30 days of Dash price in Bitcoin from Poloniex.com
Ethereum 7-day price in BTC from Poloniex ![Ethereum 7d price in BTC from Poloniex](http://cryptohistory.org/charts/sparkline/eth-btc/7d/svg)
More examples at [cryptohistory.org](http://cryptohistory.org/).
## Requirements
@ -66,6 +70,7 @@ In your HTML:
## Available Options
### LineChart
| Option | Default |
| --- | --- |
| width | 800 |
@ -77,6 +82,21 @@ In your HTML:
| fontSize | 15 |
| yAxisEnabled | true |
| xAxisEnabled | false |
| yAxisZero | false |
| filled | false |
### BarChart
| Option | Default |
| --- | --- |
| width | 600 |
| height | 300 |
| barColor | '#000' |
| markerColor | '#000' |
| labelColor | '#000' |
| fontSize | 15 |
| yAxisEnabled | true |
| xAxisEnabled | false |
| yAxisZero | true |
## Credits

View file

@ -1,11 +1,11 @@
<?php
require_once 'vendor/autoload.php';
function randomData($count = 96) {
function randomData($count = 96, $offsetMax = 100) {
$randomData = [];
$offset = 100 * (rand()/getRandMax())**2;
$scale = max(0.1 * $offset, 100 * rand() / getRandMax());
$volatility = 0.25 * (rand()/getRandMax())**3 + 0.25;
$offset = $offsetMax * (rand()/getRandMax())**2;
$scale = max(0.25 * $offset, 100 * rand() / getRandMax());
$volatility = 0.5 * (rand()/getRandMax())**3 + 0.25;
for ($n = 0, $current = $offset + 0.5 * $scale; $n < $count; $n++) {
$current -= $offset;
$current *= 1 + $volatility * (rand()/getRandMax() - 0.5);
@ -39,9 +39,9 @@ function randomData($count = 96) {
</figure>
</section>
<section>
<h2>Chart in <code>svg</code> tag, zero axis shown</h2>
<h2>Chart in <code>svg</code> tag, zero axis shown, filled</h2>
<figure>
<?php
<?php
$chart = new NeatCharts\LineChart(randomData(), [
'width'=>800,
'height'=>250,
@ -49,7 +49,8 @@ $chart = new NeatCharts\LineChart(randomData(), [
'labelColor'=>'#222',
'smoothed'=>false,
'fontSize'=>14,
'yAxisZero'=>true
'yAxisZero'=>true,
'filled'=>true
]);
echo $chart->render();
?>
@ -59,10 +60,10 @@ echo $chart->render();
<section>
<h2>Smoothed chart in <code>svg</code> tag</h2>
<figure>
<?php
<?php
$chart = new NeatCharts\LineChart(randomData(12), [
'width'=>300,
'height'=>300,
'width'=>400,
'height'=>300, // null works as a height too, it picks a height that makes the plot look good
'lineColor'=>'#080',
'labelColor'=>'#222',
'smoothed'=>true,
@ -88,6 +89,18 @@ $chart = new NeatCharts\LineChart(randomData(48), [
'xAxisEnabled'=>false
]);
echo $chart->render();
?>
<figcaption>Random generated data, loaded right in the page</figcaption>
</figure>
</section>
<section>
<h2>Bar chart in <code>svg</code> tag</h2>
<figure>
<?php
$chart = new NeatCharts\BarChart(randomData(10, 0), [
'barColor'=>'#409'
]);
echo $chart->render();
?>
<figcaption>Random generated data, loaded right in the page</figcaption>
</figure>

View file

@ -0,0 +1,59 @@
<?php
namespace NeatCharts {
class BarChart extends NeatChart {
public function setOptions($options) {
$this->options = [ // BarChart defaults
'width' => 600,
'height' => 300,
'barColor' => '#000',
'markerColor' => '#000',
'labelColor' => '#000',
'fontSize' => 15,
'yAxisEnabled'=>true,
'xAxisEnabled'=>false,
'yAxisZero'=>true
];
parent::setOptions($options);
}
public function setData($chartData) {
$this->setWindow($chartData, $this->options); // sets min, max, range, etc
// we assume $chartData is sorted by key and keys and values are all numeric
$count = count($chartData);
$deltaX = $this->xRange / $count;
$this->xMin -= $deltaX / 2;
$this->xMax += $deltaX / 2;
$this->xRange += $deltaX;
$gridLabelXML = $this->buildGridLabelXML();
// this also sets $this->width and $this->height
$barRadius = min($this->width / $count / 2.5, $this->width / $count / 2 - 1);
$chartPoints = '';
foreach($chartData as $x => $y) {
$barX = $this->transformX($x);
$barY = $this->transformY($y);
$barY0 = $this->transformY(0);
$chartPoints .= ' M'.($barX - $barRadius).','.$barY0.' '.($barX + $barRadius).','.$barY0.' '.($barX + $barRadius).','.$barY.' '.($barX - $barRadius).','.$barY.' Z';
}
$this->output = '<svg viewBox="-'.( $this->padding['left'] ).' -'.( $this->padding['top'] ).' '.( $this->options['width'] ).' '.( $this->options['height'] ).'" width="'.( $this->options['width'] ).'" height="'.( $this->options['height'] ).'" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g class="neatchart">'.
$gridLabelXML.'
<g
class="chart__bars"
fill="'.( $this->options['barColor'] ).'"
fill-opacity="0.5"
stroke="'.( $this->options['barColor'] ).'"
stroke-width="2"
stroke-linecap="round"
>
<path d="'.( $chartPoints ).'" />
</g>
</g>
</svg>';
}
}
}

View file

@ -12,7 +12,8 @@ namespace NeatCharts {
'fontSize' => 15,
'yAxisEnabled'=>true,
'xAxisEnabled'=>false,
'yAxisZero'=>false
'yAxisZero'=>false,
'filled'=>false
];
parent::setOptions($options);
}
@ -128,7 +129,7 @@ namespace NeatCharts {
stroke="url(#neatchart-fadeFromNothing-'.( $chartID ).')"
marker-end="url(#neatchart-markerCircle-'.( $chartID ).')"
>
<path d="'.( $chartPoints ).'" />'.($this->options['yAxisZero'] ? '
<path d="'.( $chartPoints ).'" />'.($this->options['filled'] ? '
<path
stroke="none"
fill="url(#neatchart-fadeFromNothing-'.( $chartID ).')"

View file

@ -91,20 +91,20 @@ namespace NeatCharts {
$labelInterval = ceil($labelInterval * $labelModulation) / $labelModulation;
$labelPrecision = $this->getPrecision($labelInterval);
$this->padding['left'] = $this->options['fontSize'] * 0.6 * (
1 + max(1, ceil(log($this->yMax, 10))) + $this->getPrecision($labelInterval)
) + 10;
$this->padding['left'] = $this->options['fontSize'] * 0.65 * (
2.5 + max(1, ceil(log($this->yMax, 10))) + $this->getPrecision($labelInterval)
);
$this->width = $this->options['width'] - $this->padding['left'] - $this->padding['right'];
// Top and bottom grid lines
$gridLines =
'M10,0 '.$this->width.',0 '.
' M10,'.$this->height.','.$this->width.','.$this->height;
'M0,0 '.$this->width.',0 '.
' M0,'.$this->height.','.$this->width.','.$this->height;
// Top and bottom grid labels
$gridText =
'<text text-anchor="end" x="'.(0.4 * $this->options['fontSize']).'" y="'.($this->options['fontSize'] * 0.4).'">'.($this->labelFormat($this->yMax, $labelPrecision + 1)).'</text>' .
'<text text-anchor="end" x="'.(0.4 * $this->options['fontSize']).'" y="'.($this->options['fontSize'] * 0.4 + $this->height).'">'.($this->labelFormat($this->yMin, $labelPrecision + 1)).'</text>';
'<text text-anchor="end" x="'.(-0.4 * $this->options['fontSize']).'" y="'.($this->options['fontSize'] * 0.4).'">'.($this->labelFormat($this->yMax, $labelPrecision + 1)).'</text>' .
'<text text-anchor="end" x="'.(-0.4 * $this->options['fontSize']).'" y="'.($this->options['fontSize'] * 0.4 + $this->height).'">'.($this->labelFormat($this->yMin, $labelPrecision + 1)).'</text>';
// Main labels and grid lines
for (
@ -117,8 +117,8 @@ namespace NeatCharts {
$labelHeight < $this->height - 1.5 * $this->options['fontSize'] &&
$labelHeight > $this->options['fontSize'] * 1.5
) {
$gridText .= '<text text-anchor="end" x="-'.(0.25 * $this->options['fontSize']).'" y="'.($labelHeight + $this->options['fontSize'] * 0.4).'">'.$this->labelFormat($labelY, $labelPrecision).'</text>';
$gridLines .= ' M0,'.$labelHeight.' '.$this->width.','.$labelHeight;
$gridText .= '<text text-anchor="end" x="-'.($this->options['fontSize']).'" y="'.($labelHeight + $this->options['fontSize'] * 0.4).'">'.$this->labelFormat($labelY, $labelPrecision).'</text>';
$gridLines .= ' M-'.($this->options['fontSize'] * 0.65).','.$labelHeight.' '.$this->width.','.$labelHeight;
} else if ( // label is too close
$labelHeight < $this->height - $this->options['fontSize'] * 0.75 &&
$labelHeight > $this->options['fontSize'] * 0.75
@ -133,9 +133,9 @@ namespace NeatCharts {
<g class="chart__gridLines"
fill="none"
stroke="'.( $this->options['labelColor'] ).'"
stroke-opacity="0.4"
stroke-width="1"
vector-effect="non-scaling-stroke"
stroke-dasharray="2, 2"
shape-rendering="crispEdges">
<path class="chart__gridLinePaths" d="'.( $gridLines ).'" />
</g>