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"; import styles from "./BarGraph.module.css";
interface BarGraphProps { export interface BarGraphProps {
data: BarGraphData[]; data: BarGraphData[];
/** Width of the entire graph, in pixels. */ /** Width of the entire graph, in pixels. */
width: number; width: number;
@ -33,7 +33,7 @@ interface BarGraphProps {
hoverLabelSize?: number; hoverLabelSize?: number;
/** Label text for the category axis. */ /** Label text for the category axis. */
categoryAxisLabel?: string; 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; categoryAxisLabelSize?: number;
/** Controls the distance between the category axis label and the category axis. */ /** Controls the distance between the category axis label and the category axis. */
categoryAxisLabelOffset?: number; categoryAxisLabelOffset?: number;
@ -43,6 +43,10 @@ interface BarGraphProps {
valueAxisLabelSize?: number; valueAxisLabelSize?: number;
/** Controls the distance between the value axis label and the value axis. */ /** Controls the distance between the value axis label and the value axis. */
valueAxisLabelOffset?: number; 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 { interface BarGraphData {
@ -68,10 +72,9 @@ export function BarGraphHorizontal(props: BarGraphProps) {
valueAxisLabel, valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE, valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0, valueAxisLabelOffset = 0,
barPadding = 0.4,
} = props; } = props;
const barPadding = 0.4;
const categoryMax = height - margin.top - margin.bottom; const categoryMax = height - margin.top - margin.bottom;
const valueMax = width - margin.left - margin.right; const valueMax = width - margin.left - margin.right;
@ -217,9 +220,11 @@ export function BarGraphVertical(props: BarGraphProps) {
valueAxisLabel, valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE, valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0, valueAxisLabelOffset = 0,
barPadding = 0.4,
shiftBottomAxis = false,
} = props; } = 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 categoryMax = width - margin.left - margin.right;
const valueMax = height - margin.top - margin.bottom; const valueMax = height - margin.top - margin.bottom;
@ -228,7 +233,7 @@ export function BarGraphVertical(props: BarGraphProps) {
const getValue = (d: BarGraphData) => d.value; const getValue = (d: BarGraphData) => d.value;
const categoryScale = scaleBand({ const categoryScale = scaleBand({
range: [0, categoryMax], range: [gridRowExtension, categoryMax + gridRowExtension],
domain: data.map(getCategory), domain: data.map(getCategory),
padding: barPadding, padding: barPadding,
}); });
@ -242,6 +247,10 @@ export function BarGraphVertical(props: BarGraphProps) {
const categoryPoint = (d: BarGraphData) => categoryScale(getCategory(d)); const categoryPoint = (d: BarGraphData) => categoryScale(getCategory(d));
const valuePoint = (d: BarGraphData) => valueScale(getValue(d)); const valuePoint = (d: BarGraphData) => valueScale(getValue(d));
const bottomAxisLabelsOffset = shiftBottomAxis
? categoryScale.bandwidth() / 2
: 0;
return ( return (
<svg className={className} width={width} height={height}> <svg className={className} width={width} height={height}>
<Group top={margin.top} left={margin.left}> <Group top={margin.top} left={margin.left}>
@ -265,7 +274,7 @@ export function BarGraphVertical(props: BarGraphProps) {
</Group> </Group>
<GridRows <GridRows
scale={valueScale} scale={valueScale}
width={categoryMax} width={categoryMax + gridRowExtension * 2}
numTicks={5} numTicks={5}
stroke={Color.label} stroke={Color.label}
strokeWidth={4} strokeWidth={4}
@ -305,7 +314,7 @@ export function BarGraphVertical(props: BarGraphProps) {
<AxisBottom <AxisBottom
scale={categoryScale} scale={categoryScale}
top={valueMax + margin.top} top={valueMax + margin.top}
left={margin.left} left={margin.left + bottomAxisLabelsOffset}
hideAxisLine hideAxisLine
hideTicks hideTicks
tickLabelProps={() => { 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!", "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.", "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 { BarGraphHorizontal, BarGraphVertical } from "components/BarGraph";
import { BoxPlot } from "components/Boxplot"; import { BoxPlot } from "components/Boxplot";
import { Histogram } from "components/Histogram";
import { import {
mockCategoricalData, mockCategoricalData,
moreMockCategoricalData, moreMockCategoricalData,
mockBoxPlotData, mockBoxPlotData,
mockQuoteData, mockQuoteData,
mockQuoteDataLong, mockQuoteDataLong,
mockHistogramData,
} from "data/mocks"; } from "data/mocks";
import React from "react"; import React from "react";
@ -94,6 +96,22 @@ export default function Home() {
circleDiameter={180} circleDiameter={180}
/> />
</div> </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> </div>
); );
} }