Skip to content

Commit

Permalink
new(demo/xychart): add AreaStack, add stackOffset variable for stacks
Browse files Browse the repository at this point in the history
  • Loading branch information
williaster committed Jan 26, 2021
1 parent 59ded3f commit 96284ef
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 34 deletions.
47 changes: 44 additions & 3 deletions packages/visx-demo/src/sandboxes/visx-xychart/Example.tsx
Expand Up @@ -45,6 +45,7 @@ export default function Example({ height }: XYChartProps) {
editAnnotationLabelPosition,
numTicks,
renderAreaSeries,
renderAreaStack,
renderBarGroup,
renderBarSeries,
renderBarStack,
Expand All @@ -63,6 +64,7 @@ export default function Example({ height }: XYChartProps) {
showVerticalCrosshair,
snapTooltipToDatumX,
snapTooltipToDatumY,
stackOffset,
theme,
xAxisOrientation,
yAxisOrientation,
Expand All @@ -87,7 +89,7 @@ export default function Example({ height }: XYChartProps) {
numTicks={numTicks}
/>
{renderBarStack && (
<AnimatedBarStack>
<AnimatedBarStack offset={stackOffset}>
<AnimatedBarSeries
dataKey="New York"
data={data}
Expand Down Expand Up @@ -143,7 +145,7 @@ export default function Example({ height }: XYChartProps) {
/>
)}
{renderAreaSeries && (
<AnimatedAreaStack curve={curve} order="ascending">
<>
<AnimatedAreaSeries
dataKey="Austin"
data={data}
Expand All @@ -168,6 +170,37 @@ export default function Example({ height }: XYChartProps) {
fillOpacity={0.4}
curve={curve}
/>
</>
)}
{renderAreaStack && (
<AnimatedAreaStack
curve={curve}
offset={stackOffset}
renderLine={stackOffset !== 'wiggle'}
>
<AnimatedAreaSeries
dataKey="Austin"
data={data}
xAccessor={accessors.x.Austin}
yAccessor={accessors.y.Austin}
fillOpacity={0.4}
/>

<AnimatedAreaSeries
dataKey="New York"
data={data}
xAccessor={accessors.x['New York']}
yAccessor={accessors.y['New York']}
fillOpacity={0.4}
/>

<AnimatedAreaSeries
dataKey="San Francisco"
data={data}
xAccessor={accessors.x['San Francisco']}
yAccessor={accessors.y['San Francisco']}
fillOpacity={0.4}
/>
</AnimatedAreaStack>
)}
{renderLineSeries && (
Expand Down Expand Up @@ -215,10 +248,18 @@ export default function Example({ height }: XYChartProps) {
/>
<AnimatedAxis
key={`temp-axis-${animationTrajectory}-${renderHorizontally}`}
label="Temperature (°F)"
label={
stackOffset == null
? 'Temperature (°F)'
: stackOffset === 'expand'
? 'Fraction of total temperature'
: ''
}
orientation={renderHorizontally ? xAxisOrientation : yAxisOrientation}
numTicks={numTicks}
animationTrajectory={animationTrajectory}
// values don't make sense in stream graph
tickFormat={stackOffset === 'wiggle' ? () => '' : undefined}
/>
{annotationDataKey && annotationDatum && (
<AnimatedAnnotation
Expand Down
139 changes: 108 additions & 31 deletions packages/visx-demo/src/sandboxes/visx-xychart/ExampleControls.tsx
Expand Up @@ -65,6 +65,7 @@ type ProvidedProps = {
setAnnotationDataKey: (key: DataKey | null) => void;
setAnnotationLabelPosition: (position: { dx: number; dy: number }) => void;
renderAreaSeries: boolean;
renderAreaStack: boolean;
renderBarGroup: boolean;
renderBarSeries: boolean;
renderBarStack: boolean;
Expand All @@ -80,6 +81,7 @@ type ProvidedProps = {
showVerticalCrosshair: boolean;
snapTooltipToDatumX: boolean;
snapTooltipToDatumY: boolean;
stackOffset?: 'wiggle' | 'expand' | 'diverging' | 'silhouette';
theme: XYChartTheme;
xAxisOrientation: 'top' | 'bottom';
yAxisOrientation: 'left' | 'right';
Expand Down Expand Up @@ -108,11 +110,12 @@ export default function ExampleControls({ children }: ControlsProps) {
const [snapTooltipToDatumY, setSnapTooltipToDatumY] = useState(true);
const [sharedTooltip, setSharedTooltip] = useState(true);
const [renderBarStackOrGroup, setRenderBarStackOrGroup] = useState<
'bar' | 'stack' | 'group' | 'none'
'bar' | 'barstack' | 'bargroup' | 'none'
>('none');
const [renderLineOrAreaSeries, setRenderLineOrAreaSeries] = useState<'line' | 'area' | 'none'>(
'area',
);
const [renderAreaLineOrStack, setRenderAreaLineOrStack] = useState<
'line' | 'area' | 'areastack' | 'none'
>('areastack');
const [stackOffset, setStackOffset] = useState<ProvidedProps['stackOffset']>();
const [renderGlyphSeries, setRenderGlyphSeries] = useState(false);
const [editAnnotationLabelPosition, setEditAnnotationLabelPosition] = useState(false);
const [annotationLabelPosition, setAnnotationLabelPosition] = useState({ dx: -40, dy: -20 });
Expand Down Expand Up @@ -185,7 +188,9 @@ export default function ExampleControls({ children }: ControlsProps) {
[renderHorizontally],
);

const canRenderLineOrArea = renderBarStackOrGroup === 'bar' || renderBarStackOrGroup === 'none';
// cannot snap to a stack position
const canSnapTooltipToDatum =
renderBarStackOrGroup !== 'barstack' && renderAreaLineOrStack !== 'areastack';

return (
<>
Expand All @@ -211,14 +216,15 @@ export default function ExampleControls({ children }: ControlsProps) {
: data,
editAnnotationLabelPosition,
numTicks,
renderBarGroup: renderBarStackOrGroup === 'group',
renderBarGroup: renderBarStackOrGroup === 'bargroup',
renderBarSeries: renderBarStackOrGroup === 'bar',
renderBarStack: renderBarStackOrGroup === 'stack',
renderBarStack: renderBarStackOrGroup === 'barstack',
renderGlyphSeries,
renderGlyph,
renderHorizontally,
renderAreaSeries: canRenderLineOrArea && renderLineOrAreaSeries === 'area',
renderLineSeries: canRenderLineOrArea && renderLineOrAreaSeries === 'line',
renderAreaSeries: renderAreaLineOrStack === 'area',
renderAreaStack: renderAreaLineOrStack === 'areastack',
renderLineSeries: renderAreaLineOrStack === 'line',
setAnnotationDataIndex,
setAnnotationDataKey,
setAnnotationLabelPosition,
Expand All @@ -228,14 +234,15 @@ export default function ExampleControls({ children }: ControlsProps) {
showHorizontalCrosshair,
showTooltip,
showVerticalCrosshair,
snapTooltipToDatumX: renderBarStackOrGroup !== 'stack' && snapTooltipToDatumX,
snapTooltipToDatumY: renderBarStackOrGroup !== 'stack' && snapTooltipToDatumY,
snapTooltipToDatumX: canSnapTooltipToDatum && snapTooltipToDatumX,
snapTooltipToDatumY: canSnapTooltipToDatum && snapTooltipToDatumY,
stackOffset,
theme,
xAxisOrientation,
yAxisOrientation,
})}
{/** This style is used for annotated elements via colorAccessor. */}
<svg>
<svg className="pattern-lines">
<PatternLines
id={selectedDatumPatternId}
width={6}
Expand Down Expand Up @@ -332,27 +339,45 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="radio"
disabled={!canRenderLineOrArea}
onChange={() => setRenderLineOrAreaSeries('line')}
checked={canRenderLineOrArea && renderLineOrAreaSeries === 'line'}
onChange={() => {
if (renderBarStackOrGroup === 'barstack' || renderBarStackOrGroup === 'bargroup') {
setRenderBarStackOrGroup('none');
}
setRenderAreaLineOrStack('line');
}}
checked={renderAreaLineOrStack === 'line'}
/>
line
</label>
<label>
<input
type="radio"
disabled={!canRenderLineOrArea}
onChange={() => setRenderLineOrAreaSeries('area')}
checked={canRenderLineOrArea && renderLineOrAreaSeries === 'area'}
onChange={() => {
if (renderBarStackOrGroup === 'barstack' || renderBarStackOrGroup === 'bargroup') {
setRenderBarStackOrGroup('none');
}
setRenderAreaLineOrStack('area');
}}
checked={renderAreaLineOrStack === 'area'}
/>
area
</label>
<label>
<input
type="radio"
disabled={!canRenderLineOrArea}
onChange={() => setRenderLineOrAreaSeries('none')}
checked={renderLineOrAreaSeries === 'none' || !canRenderLineOrArea}
onChange={() => {
setRenderBarStackOrGroup('none');
setRenderAreaLineOrStack('areastack');
}}
checked={renderAreaLineOrStack === 'areastack'}
/>
area stack
</label>
<label>
<input
type="radio"
onChange={() => setRenderAreaLineOrStack('none')}
checked={renderAreaLineOrStack === 'none'}
/>
none
</label>
Expand All @@ -361,7 +386,7 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="radio"
disabled={!canRenderLineOrArea || renderLineOrAreaSeries === 'none'}
disabled={renderAreaLineOrStack === 'none'}
onChange={() => setCurveType('linear')}
checked={curveType === 'linear'}
/>
Expand All @@ -370,7 +395,7 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="radio"
disabled={!canRenderLineOrArea || renderLineOrAreaSeries === 'none'}
disabled={renderAreaLineOrStack === 'none'}
onChange={() => setCurveType('cardinal')}
checked={curveType === 'cardinal'}
/>
Expand All @@ -379,7 +404,7 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="radio"
disabled={!canRenderLineOrArea || renderLineOrAreaSeries === 'none'}
disabled={renderAreaLineOrStack === 'none'}
onChange={() => setCurveType('step')}
checked={curveType === 'step'}
/>
Expand Down Expand Up @@ -440,24 +465,35 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="radio"
onChange={() => setRenderBarStackOrGroup('bar')}
onChange={() => {
if (renderAreaLineOrStack === 'areastack') {
setRenderAreaLineOrStack('none');
}
setRenderBarStackOrGroup('bar');
}}
checked={renderBarStackOrGroup === 'bar'}
/>
bar
</label>
<label>
<input
type="radio"
onChange={() => setRenderBarStackOrGroup('stack')}
checked={renderBarStackOrGroup === 'stack'}
onChange={() => {
setRenderAreaLineOrStack('none');
setRenderBarStackOrGroup('barstack');
}}
checked={renderBarStackOrGroup === 'barstack'}
/>
bar stack
</label>
<label>
<input
type="radio"
onChange={() => setRenderBarStackOrGroup('group')}
checked={renderBarStackOrGroup === 'group'}
onChange={() => {
setRenderAreaLineOrStack('none');
setRenderBarStackOrGroup('bargroup');
}}
checked={renderBarStackOrGroup === 'bargroup'}
/>
bar group
</label>
Expand All @@ -470,6 +506,42 @@ export default function ExampleControls({ children }: ControlsProps) {
none
</label>
</div>
<div>
<strong>stack series offset</strong>
<label>
<input
type="radio"
disabled={
renderAreaLineOrStack !== 'areastack' && renderBarStackOrGroup !== 'barstack'
}
onChange={() => setStackOffset(undefined)}
checked={stackOffset == null}
/>
auto (zero-baseline)
</label>
<label>
<input
type="radio"
disabled={
renderAreaLineOrStack !== 'areastack' && renderBarStackOrGroup !== 'barstack'
}
onChange={() => setStackOffset('expand')}
checked={stackOffset === 'expand'}
/>
expand (values sum to 1)
</label>
<label>
<input
type="radio"
disabled={
renderAreaLineOrStack !== 'areastack' && renderBarStackOrGroup !== 'barstack'
}
onChange={() => setStackOffset('wiggle')}
checked={stackOffset === 'wiggle'}
/>
wiggle (stream graph)
</label>
</div>

<br />
{/** tooltip */}
Expand All @@ -486,7 +558,7 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="checkbox"
disabled={!showTooltip || renderBarStackOrGroup === 'stack'}
disabled={!showTooltip || !canSnapTooltipToDatum}
onChange={() => setSnapTooltipToDatumX(!snapTooltipToDatumX)}
checked={showTooltip && snapTooltipToDatumX}
/>
Expand All @@ -495,7 +567,7 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="checkbox"
disabled={!showTooltip || renderBarStackOrGroup === 'stack'}
disabled={!showTooltip || !canSnapTooltipToDatum}
onChange={() => setSnapTooltipToDatumY(!snapTooltipToDatumY)}
checked={showTooltip && snapTooltipToDatumY}
/>
Expand Down Expand Up @@ -720,6 +792,11 @@ export default function ExampleControls({ children }: ControlsProps) {
input[type='radio'] {
height: 10px;
}
.pattern-lines {
position: absolute;
pointer-events: none;
opacity: 0;
}
`}</style>
</>
);
Expand Down

0 comments on commit 96284ef

Please sign in to comment.