Skip to content

Commit

Permalink
make histogram examples use a scaleBand
Browse files Browse the repository at this point in the history
  • Loading branch information
mhkeller committed Jul 6, 2022
1 parent a1e876f commit 0e10894
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 54 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
===

# 6.1.2

> not yet on npm
Makes a more helpful error message when the data passed into `calcExtents` isn't an array.

*

# 6.1.1

> 2022-06-24
Expand Down
2 changes: 1 addition & 1 deletion src/_components/AxisX.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
</script>

<g class='axis x-axis' class:snapTicks>
{#each tickVals as tick, i}
{#each tickVals as tick, i (tick)}
<g class='tick tick-{ i }' transform='translate({$xScale(tick)},{$yRange[0]})'>
{#if gridlines !== false}
<line class="gridline" y1='{$height * -1}' y2='0' x1='0' x2='0'></line>
Expand Down
70 changes: 44 additions & 26 deletions src/_components/Column.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
<!--
@component
Generates an SVG column chart.
@component
Generates an SVG column chart.
-->
<script>
import { getContext } from 'svelte';
import { getContext } from 'svelte';
const { data, xGet, yGet, yRange, xScale } = getContext('LayerCake');
$: columnWidth = d => {
const vals = $xGet(d);
return Math.max(0, (vals[1] - vals[0]));
};
$: columnHeight = d => {
return $yRange[0] - $yGet(d);
};
const { data, xGet, yGet, x, yRange, xScale, y, height, zGet, zScale, z } = getContext('LayerCake');
/** @type {String} [fill='#00e047'] - The shape's fill color. */
export let fill = '#00e047';
Expand All @@ -25,20 +16,47 @@
/** @type {Number} [strokeWidth=0] - The shape's stroke width. */
export let strokeWidth = 0;
/** @type {Boolean} [false] - Show the numbers for each column */
export let showLabels = false;
$: columnWidth = d => {
const vals = $xGet(d);
return Math.abs(vals[1] - vals[0]);
};
$: columnHeight = d => {
return $yRange[0] - $yGet(d);
};
</script>

<g class="column-group">
{#each $data as d, i}
<rect
class='group-rect'
data-id="{i}"
x="{$xScale.bandwidth ? $xGet(d) : $xGet(d)[0]}"
y="{$yGet(d)}"
width="{$xScale.bandwidth ? $xScale.bandwidth() : columnWidth(d)}"
height="{columnHeight(d)}"
{fill}
{stroke}
stroke-width="{strokeWidth}"
/>
{/each}
{#each $data as d, i}
{@const colHeight = columnHeight(d)}
{@const xGot = $xGet(d)}
{@const xPos = Array.isArray(xGot) ? xGot[0] : xGot}
{@const colWidth = $xScale.bandwidth ? $xScale.bandwidth() : columnWidth(d)}
{@const yValue = $y(d)}
<rect
class='group-rect'
data-id="{i}"
data-range="{$x(d)}"
data-count="{yValue}"
x="{xPos}"
y="{$yGet(d)}"
width="{colWidth}"
height="{colHeight}"
{fill}
{stroke}
stroke-width="{strokeWidth}"
/>
{#if showLabels && yValue}
<text x="{xPos + colWidth / 2}" y="{$height - colHeight - 5}" text-anchor="middle">{yValue}</text>
{/if}
{/each}
</g>

<style>
text {
font-size: 12px;
}
</style>
9 changes: 9 additions & 0 deletions src/_modules/calcThresholds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function calcThresholds(domain = [0, 1], n) {
const breaks = [domain[0]];
const brk = (domain[1] - domain[0]) / n;
while (breaks[breaks.length - 1] < domain[1]) {
const node = breaks[breaks.length - 1] + brk;
breaks.push(node);
}
return breaks;
}
7 changes: 7 additions & 0 deletions src/_modules/everyN.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function everyN(list, n) {
if (list.length <= n) return list;
const e = Math.round(list.length / n);
return list.filter((d, i) => {
return i % e === 0;
});
}
9 changes: 0 additions & 9 deletions src/_modules/thresholds.js

This file was deleted.

2 changes: 1 addition & 1 deletion src/lib/lib/calcExtents.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/
export default function calcExtents (data, fields) {
if (!Array.isArray(data)) {
throw new TypeError('The first argument of calcExtents() must be an array. If you got this error using the <LayerCake> component, consider passing a flat array to the `flatData` prop. More info: https://layercake.graphics/guide/#flatdata');
throw new TypeError(`The first argument of calcExtents() must be an array. You passed in a ${typeof data}. Consider passing a flat array to the \`flatData\` prop. More info: https://layercake.graphics/guide/#flatdata`);
}

if (
Expand Down
23 changes: 16 additions & 7 deletions src/routes/_examples/Histogram.svelte
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
<script>
import { LayerCake, Svg } from 'layercake';
import { histogram, extent } from 'd3-array';
import { extent, bin } from 'd3-array';
import { scaleBand } from 'd3-scale';
import Column from '../../_components/Column.svelte';
import AxisX from '../../_components/AxisX.svelte';
import AxisY from '../../_components/AxisY.svelte';
import thresholds from '../../_modules/thresholds.js';
import calcThresholds from '../../_modules/calcThresholds.js';
import everyN from '../../_modules/everyN.js'
import data from '../../_data/unemployment.js';
const xKey = ['x0', 'x1'];
const yKey = 'length';
let binCount = 40;
const domain = extent(data);
$: hist = histogram()
$: steps = calcThresholds(domain, binCount);
$: hist = bin()
.domain(domain)
.thresholds(thresholds(domain, binCount));
.thresholds(steps);
$: bins = hist(data);
$: slimSteps = everyN(steps, 5);
</script>

<style>
Expand Down Expand Up @@ -54,14 +60,17 @@
padding={{ top: 20, right: 5, bottom: 20, left: 30 }}
x={xKey}
y={yKey}
xDomain={steps}
xScale={scaleBand().paddingInner([0])}
yDomain={[0, null]}
data={bins}
data={hist(data)}
>
<Svg>
<AxisX
gridlines={false}
baseline={true}
snapTicks={true}
ticks={slimSteps}
formatTick={d => d.toFixed(2)}
/>
<AxisY
gridlines={false}
Expand Down
29 changes: 19 additions & 10 deletions src/routes/_examples_ssr/Histogram.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
<script>
import { LayerCake, ScaledSvg, Html } from 'layercake';
import { histogram, extent } from 'd3-array';
import { extent, bin } from 'd3-array';
import { scaleBand } from 'd3-scale';
import Column from '../../_components/Column.svelte';
import AxisX from '../../_components/AxisX.html.svelte';
import AxisY from '../../_components/AxisY.html.svelte';
import thresholds from '../../_modules/thresholds.js';
import calcThresholds from '../../_modules/calcThresholds.js';
import everyN from '../../_modules/everyN.js';
import data from '../../_data/unemployment.js';
let binCount = 40;
const xKey = ['x0', 'x1'];
const yKey = 'length';
const domain = extent(data);
$: hist = histogram()
$: steps = calcThresholds(domain, binCount);
$: hist = bin()
.domain(domain)
.thresholds(thresholds(domain, binCount));
.thresholds(steps);
$: bins = hist(data);
$: slimSteps = everyN(steps, 7);
</script>

<style>
Expand Down Expand Up @@ -53,17 +60,19 @@
ssr={true}
percentRange={true}
padding={{ top: 20, right: 5, bottom: 20, left: 31 }}
x={['x0', 'x1']}
y={'length'}
xDomain={domain}
x={xKey}
y={yKey}
xDomain={steps}
xScale={scaleBand().paddingInner([0])}
yDomain={[0, null]}
data={bins}
data={hist(data)}
>
<Html>
<AxisX
gridlines={false}
baseline={true}
snapTicks={true}
ticks={slimSteps}
formatTick={d => d.toFixed(2)}
/>
<AxisY
gridlines={false}
Expand Down

0 comments on commit 0e10894

Please sign in to comment.