add histogram

This commit is contained in:
e26chiu 2022-09-28 18:34:37 -04:00
parent 9526f1b0f5
commit a45a7de79b
4 changed files with 55 additions and 8 deletions

View File

@ -11,7 +11,7 @@ import { Color } from "utils/Color";
import styles from "./BarGraph.module.css";
interface BarGraphProps {
export interface BarGraphProps {
data: BarGraphData[];
/** Width of the entire graph, in pixels. */
width: number;
@ -33,7 +33,7 @@ interface BarGraphProps {
hoverLabelSize?: number;
/** Label text for the category axis. */
categoryAxisLabel?: string;
/** Font size of the label for the cateogry axis, in pixels. */
/** Font size of the label for the category axis, in pixels. */
categoryAxisLabelSize?: number;
/** Controls the distance between the category axis label and the category axis. */
categoryAxisLabelOffset?: number;
@ -43,6 +43,10 @@ interface BarGraphProps {
valueAxisLabelSize?: number;
/** Controls the distance between the value axis label and the value axis. */
valueAxisLabelOffset?: number;
/** Controls the space between each bar. */
barPadding?: number;
/** Shift bottom axis labels to the right and extends grid lines to center bars in the graph if true */
shiftBottomAxis?: boolean;
}
interface BarGraphData {
@ -68,10 +72,9 @@ export function BarGraphHorizontal(props: BarGraphProps) {
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
barPadding = 0.4,
} = props;
const barPadding = 0.4;
const categoryMax = height - margin.top - margin.bottom;
const valueMax = width - margin.left - margin.right;
@ -217,9 +220,11 @@ export function BarGraphVertical(props: BarGraphProps) {
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
barPadding = 0.4,
shiftBottomAxis = false,
} = props;
const barPadding = 0.4;
const gridRowExtension = shiftBottomAxis ? margin.left / 4 : 0; // extend the grid lines to center the bars in the graph
const categoryMax = width - margin.left - margin.right;
const valueMax = height - margin.top - margin.bottom;
@ -228,7 +233,7 @@ export function BarGraphVertical(props: BarGraphProps) {
const getValue = (d: BarGraphData) => d.value;
const categoryScale = scaleBand({
range: [0, categoryMax],
range: [gridRowExtension, categoryMax + gridRowExtension],
domain: data.map(getCategory),
padding: barPadding,
});
@ -242,6 +247,10 @@ export function BarGraphVertical(props: BarGraphProps) {
const categoryPoint = (d: BarGraphData) => categoryScale(getCategory(d));
const valuePoint = (d: BarGraphData) => valueScale(getValue(d));
const bottomAxisLabelsOffset = shiftBottomAxis
? categoryScale.bandwidth() / 2
: 0;
return (
<svg className={className} width={width} height={height}>
<Group top={margin.top} left={margin.left}>
@ -265,7 +274,7 @@ export function BarGraphVertical(props: BarGraphProps) {
</Group>
<GridRows
scale={valueScale}
width={categoryMax}
width={categoryMax + gridRowExtension * 2}
numTicks={5}
stroke={Color.label}
strokeWidth={4}
@ -305,7 +314,7 @@ export function BarGraphVertical(props: BarGraphProps) {
<AxisBottom
scale={categoryScale}
top={valueMax + margin.top}
left={margin.left}
left={margin.left + bottomAxisLabelsOffset}
hideAxisLine
hideTicks
tickLabelProps={() => {

7
components/Histogram.tsx Normal file
View File

@ -0,0 +1,7 @@
import React from "react";
import { BarGraphVertical, BarGraphProps } from "./BarGraph";
export function Histogram(props: BarGraphProps) {
return <BarGraphVertical {...props} barPadding={0} shiftBottomAxis={true} />;
}

View File

@ -106,3 +106,16 @@ export const mockQuoteDataLong = [
"Hello, world!",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla in enim neque. Sed sit amet convallis tellus. Integer condimentum a felis id gravida. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nullam metus libero, sagittis in consectetur in, scelerisque sed sapien. Nullam ut feugiat sapien. Praesent dictum ac ipsum ac lacinia.",
];
export const mockHistogramData = [
{ category: "10", value: 88 },
{ category: "20", value: 16 },
{ category: "30", value: 22 },
{ category: "40", value: 20 },
{ category: "50", value: 45 },
{ category: "60", value: 17 },
{ category: "70", value: 35 },
{ category: "80", value: 27 },
{ category: "90", value: 54 },
{ category: "100", value: 50 },
];

View File

@ -1,11 +1,13 @@
import { BarGraphHorizontal, BarGraphVertical } from "components/BarGraph";
import { BoxPlot } from "components/Boxplot";
import { Histogram } from "components/Histogram";
import {
mockCategoricalData,
moreMockCategoricalData,
mockBoxPlotData,
mockQuoteData,
mockQuoteDataLong,
mockHistogramData,
} from "data/mocks";
import React from "react";
@ -94,6 +96,22 @@ export default function Home() {
circleDiameter={180}
/>
</div>
<h2>
<code>{"<Histogram />"}</code>
</h2>
<Histogram
className={styles.barGraphDemo}
data={mockHistogramData}
width={800}
height={500}
margin={{
top: 20,
bottom: 80,
left: 50,
right: 60,
}}
/>
</div>
);
}