PlBarChart
비교되는 길이입니다. 막대는 얼마나를 길이로 나타냅니다. 축이 0에서 시작하고 그 점만은 설득당하지 않는 이유가 그것입니다.
import { PlBarChart } from 'plass-ui';
<PlBarChart series={revenue} categories={regions} />;import 'package:plass_ui/plass_ui.dart';
PlBarChart(series: revenue, categories: regions);축을 자르면 두 배 긴 막대가 두 배를 뜻하기를 그만두고, 읽는 사람은 그런 일이 있었는지 알 길이 없습니다. 각 값의 크기가 아니라 변화의 모양이 중요하다면 선 차트를 쓰세요.
Props
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| series * | readonly PlassChartSeries[] | — | 데이터 |
| categories | readonly PlassChartCategory[] | — | category 축이 말하는 것 |
| orientation | 'vertical' | 'horizontal' | 'vertical' | 막대가 나는 방향. category 이름이 낱말이면 horizontal이 맞습니다 — 가로 차트에는 이름을 위한 열이 통째로 있습니다 |
| stacked | boolean | 'full' | false | 나란히가 아니라 위로 쌓습니다. full은 모든 막대를 같은 길이로 만들어 크기가 아니라 비중에 대한 차트로 바꿉니다 |
| rounded | boolean | true | 막대의 데이터 쪽 끝만 모서리를 깎습니다. 기준선 쪽은 각진 채로 — 둥근 발은 축을 물결지게 만듭니다 |
| barSize | number | the size ladder — 24 at md | 막대가 가질 수 있는 최대 두께. 그 아래에서는 band를 나눠 채우고, 넘으면 남는 만큼이 여백이 됩니다 |
| valueLabels | 'none' | 'last' | 'extremes' | 'all' | 'none' | 막대 위에 어떤 값을 적을지. 여기서는 all이 선 차트에서와 달리 변호할 만합니다 — 숫자가 붙은 막대 여덟이면 차트이자 표입니다 |
| xAxis | PlassChartAxis | — | category 축 |
| yAxis | PlassChartAxis | — | 값 축 |
| legend | PlassChartLegend | — | 범례 |
| tooltip | PlassChartTooltip | — | 툴팁 |
| height | number | string | — | plot의 높이 |
| format | Intl.NumberFormatOptions | — | 값을 쓰는 방식 |
| label | string | 'Chart' | 그림 전체의 접근성 이름 |
| empty | ReactNode | — | 그릴 것이 없을 때 그리는 것 |
| size공통 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | 타입 스케일, plot 높이, 막대 두께 상한 |
| density공통 | 'default' | 'compact' | 'default' | category 한 칸에서 막대가 차지하는 비율. 높이는 아닙니다 |
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| series * | List<PlassChartSeries> | — | 데이터 |
| categories | List<PlassChartCategory>? | — | category 축이 말하는 것 |
| orientation | PlassOrientation | PlassOrientation.vertical | 막대가 나는 방향. category 이름이 낱말이면 horizontal이 맞습니다 — 가로 차트에는 이름을 위한 열이 통째로 있습니다 |
| stacking | PlBarStacking | PlBarStacking.grouped | series가 서로 어떻게 놓이는지. React의 boolean | 'full' 대신 이름 붙은 세 상태입니다 |
| rounded | bool | true | 막대의 데이터 쪽 끝만 모서리를 깎습니다. 기준선 쪽은 각진 채로 — 둥근 발은 축을 물결지게 만듭니다 |
| barSize | double? | the size ladder — 24 at md | 막대가 가질 수 있는 최대 두께. 그 아래에서는 band를 나눠 채우고, 넘으면 남는 만큼이 여백이 됩니다 |
| valueLabels | PlassChartValueLabels | PlassChartValueLabels.none | 막대 위에 어떤 값을 적을지. 여기서는 all이 선 차트에서와 달리 변호할 만합니다 — 숫자가 붙은 막대 여덟이면 차트이자 표입니다 |
| xAxis | PlChartAxis | PlChartAxis() | category 축 |
| yAxis | PlChartAxis | PlChartAxis() | 값 축 |
| legend | PlChartLegend | PlChartLegend() | 범례 |
| tooltip | PlChartTooltip | PlChartTooltip() | 툴팁 |
| height | double? | — | plot의 높이 |
| format | String Function(double)? | — | 값을 쓰는 방식 |
| semanticLabel | String? | 'Chart' | 그림 전체의 접근성 이름 |
| empty | Widget? | — | 그릴 것이 없을 때 그리는 것 |
| size공통 | PlassSize | PlassSize.md | 타입 스케일, plot 높이, 막대 두께 상한 |
| density공통 | PlassDensity | PlassDensity.standard | category 한 칸에서 막대가 차지하는 비율. 높이는 아닙니다 |
데이터는 모든 차트가 받는 같은 PlassChartSeries입니다. 여기서도 null은 빈 곳이고, 그런 값에는 막대를 그리지 않습니다. 이 차트에서 가장 중요한 구분입니다. 길이 0인 막대와 없는 막대는 같은 그림이고, 그중 정직한 것은 하나뿐이기 때문입니다.
라이브러리 전체에서 공유 축이 뜻하는 바는 prop 규약에 있습니다.
Examples
orientation
category 이름이 낱말이라면 horizontal이 맞습니다. 이름을 위한 열이 통째로 있고, 세로 차트에는 막대 하나의 너비밖에 없습니다.
import { PlBarChart } from 'plass-ui';
const sources = [
{
name: 'Sessions',
data: [4820, 3910, 2740, 1980, 1120]
}
];
const channels = [
'Organic search',
'Direct traffic',
'Email campaigns',
'Paid social',
'Referral links'
];
export default function BarChartOrientation() {
return (
<PlBarChart
className="w-full"
series={sources}
categories={channels}
orientation="horizontal"
valueLabels="all"
legend={false}
/>
);
}import 'package:flutter/widgets.dart';
import 'package:plass_ui/plass_ui.dart';
const List<PlassChartSeries> _sources = <PlassChartSeries>[
PlassChartSeries(
name: 'Sessions',
data: <PlassChartDatum>[
PlassChartDatum(4820),
PlassChartDatum(3910),
PlassChartDatum(2740),
PlassChartDatum(1980),
PlassChartDatum(1120),
],
),
];
const List<PlassChartCategory> _channels = <PlassChartCategory>[
PlassChartCategory.text('Organic search'),
PlassChartCategory.text('Direct traffic'),
PlassChartCategory.text('Email campaigns'),
PlassChartCategory.text('Paid social'),
PlassChartCategory.text('Referral links'),
];
class BarChartOrientation extends StatelessWidget {
const BarChartOrientation({super.key});
@override
Widget build(BuildContext context) {
return const PlBarChart(
series: _sources,
categories: _channels,
orientation: PlassOrientation.horizontal,
valueLabels: PlassChartValueLabels.all,
legend: PlChartLegend(hidden: true),
);
}
}모든 것이 함께 바뀝니다. 각 축이 어느 띠를 잡는지, 격자가 어느 방향인지, crosshair가 어느 쪽으로 가는지, 막대의 어느 끝이 둥근지.
stacked
나란한 막대는 "여기서 어느 series가 더 큰가"에 답합니다. 쌓인 막대는 "이 합계는 무엇으로 이루어졌나"에 답합니다. 서로 다른 질문이고, 차트에는 한 번에 하나만 물어야 합니다.
import { useState } from 'react';
import { PlBarChart, PlSegment, PlSegmentedButton } from 'plass-ui';
const plans = [
{ name: 'Free', data: [420, 460, 480, 510] },
{ name: 'Pro', data: [180, 220, 260, 310] },
{ name: 'Team', data: [40, 55, 72, 96] }
];
const quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
type Mode = 'grouped' | 'stacked' | 'full';
export default function BarChartStacked() {
const [mode, setMode] = useState<Mode>('stacked');
return (
<div className="flex w-full flex-col gap-4">
<PlSegmentedButton value={mode} onValueChange={(next) => setMode(next as Mode)}>
<PlSegment value="grouped">grouped</PlSegment>
<PlSegment value="stacked">stacked</PlSegment>
<PlSegment value="full">full</PlSegment>
</PlSegmentedButton>
<PlBarChart
className="w-full"
series={plans}
categories={quarters}
stacked={mode === 'grouped' ? false : mode === 'full' ? 'full' : true}
/>
</div>
);
}import 'package:flutter/widgets.dart';
import 'package:plass_ui/plass_ui.dart';
List<PlassChartDatum> _readings(List<double> values) => values.map(PlassChartDatum.new).toList();
final List<PlassChartSeries> _plans = <PlassChartSeries>[
PlassChartSeries(name: 'Free', data: _readings(<double>[420, 460, 480, 510])),
PlassChartSeries(name: 'Pro', data: _readings(<double>[180, 220, 260, 310])),
PlassChartSeries(name: 'Team', data: _readings(<double>[40, 55, 72, 96])),
];
const List<PlassChartCategory> _quarters = <PlassChartCategory>[
PlassChartCategory.text('Q1'),
PlassChartCategory.text('Q2'),
PlassChartCategory.text('Q3'),
PlassChartCategory.text('Q4'),
];
class BarChartStacked extends StatefulWidget {
const BarChartStacked({super.key});
@override
State<BarChartStacked> createState() => _BarChartStackedState();
}
class _BarChartStackedState extends State<BarChartStacked> {
PlBarStacking _stacking = PlBarStacking.stacked;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
PlSegmentedButton<PlBarStacking>(
value: _stacking,
onChanged: (PlBarStacking next) => setState(() => _stacking = next),
segments: const <PlSegment<PlBarStacking>>[
PlSegment<PlBarStacking>(value: PlBarStacking.grouped, label: Text('grouped')),
PlSegment<PlBarStacking>(value: PlBarStacking.stacked, label: Text('stacked')),
PlSegment<PlBarStacking>(value: PlBarStacking.full, label: Text('full')),
],
),
const SizedBox(height: 16),
PlBarChart(series: _plans, categories: _quarters, stacking: _stacking),
],
);
}
}'full'은 모든 막대를 같은 길이로 만들어 차트를 크기가 아니라 비중에 대한 것으로 바꿉니다. 면적 차트와 똑같고, 같은 이유로 그림이 아니라 데이터를 정규화합니다.
쌓인 두 조각 사이의 간격은 각자의 먼 쪽 끝에서 떼어 냅니다. 그래야 쌓인 전체가 여전히 옳은 길이가 되고, 이음매가 그 위에 그은 선이 아니라 비쳐 보이는 시트가 됩니다. 막대를 두른 테두리는 데이터가 아닌 잉크입니다.
음수
두 팔은 따로 누적되므로, 내려가는 series가 위의 것을 짧게 만들지 않습니다. 음수 막대는 기준선에서 아래로, 양수는 위로 자랍니다.
import { PlBarChart } from 'plass-ui';
const change = [{ name: 'Net change', data: [12, -8, 24, -3, 18, -14, 9] }];
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'];
export default function BarChartNegative() {
return (
<PlBarChart
className="w-full"
series={change}
categories={months}
valueLabels="all"
legend={false}
format={{ signDisplay: 'exceptZero' }}
/>
);
}import 'package:flutter/widgets.dart';
import 'package:plass_ui/plass_ui.dart';
const List<PlassChartSeries> _change = <PlassChartSeries>[
PlassChartSeries(
name: 'Net change',
data: <PlassChartDatum>[
PlassChartDatum(12),
PlassChartDatum(-8),
PlassChartDatum(24),
PlassChartDatum(-3),
PlassChartDatum(18),
PlassChartDatum(-14),
PlassChartDatum(9),
],
),
];
const List<PlassChartCategory> _months = <PlassChartCategory>[
PlassChartCategory.text('Jan'),
PlassChartCategory.text('Feb'),
PlassChartCategory.text('Mar'),
PlassChartCategory.text('Apr'),
PlassChartCategory.text('May'),
PlassChartCategory.text('Jun'),
PlassChartCategory.text('Jul'),
];
class BarChartNegative extends StatelessWidget {
const BarChartNegative({super.key});
@override
Widget build(BuildContext context) {
return PlBarChart(
series: _change,
categories: _months,
valueLabels: PlassChartValueLabels.all,
legend: const PlChartLegend(hidden: true),
format: (double value) => value > 0 ? '+${value.toInt()}' : '${value.toInt()}',
);
}
}기준선은 막대 위에 다시 그립니다. 모든 막대가 거기서 시작하고, 그 선이 시작점을 보여 줍니다. 아래에 두면 막대마다 첫 픽셀에 반쯤 가려집니다.
rounded
모서리는 각 막대의 데이터 쪽 끝에서만 깎입니다. 기준선 쪽은 각진 채로 둡니다. 값이 시작하는 곳이고, 둥근 발은 축을 물결지게 만듭니다.
barSize와 density
barSize는 너비가 아니라 상한입니다. 막대가 앉는 band는 plot을 category 수로 나눈 것이고, 상한 아래에서는 그 몫을 채우며, 넘으면 남는 만큼이 여백으로 남습니다. density는 막대가 애초에 band에서 차지할 수 있는 비율입니다.
Accessibility
PlLineChart에 적힌 내용이 그대로 적용됩니다. 이름과 series별 요약, 진짜 컨트롤인 범례, 그리고 React 쪽의 숨은 표.