Skip to content

Commit

Permalink
feat(bar): add annotations/borderRadius to canvas flavor
Browse files Browse the repository at this point in the history
  • Loading branch information
wyze committed Jun 28, 2021
1 parent 602c1c3 commit 3143823
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 37 deletions.
15 changes: 5 additions & 10 deletions packages/bar/src/BarAnnotations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,11 @@ export const BarAnnotations = <RawDatum,>({ bars, annotations }: BarAnnotationsP
x: bar.x + bar.width / 2,
y: bar.y + bar.height / 2,
}),
getDimensions: bar => {
const width = bar.width
const height = bar.height

return {
width,
height,
size: Math.max(width, height),
}
},
getDimensions: ({ height, width }) => ({
width,
height,
size: Math.max(width, height),
}),
})

return (
Expand Down
53 changes: 46 additions & 7 deletions packages/bar/src/BarCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import {
} from 'react'
import { canvasDefaultProps } from './props'
import { generateGroupedBars, generateStackedBars, getLegendData } from './compute'
import {
renderAnnotationsToCanvas,
useAnnotations,
useComputedAnnotations,
} from '@nivo/annotations'
import { renderAxesToCanvas, renderGridLinesToCanvas } from '@nivo/axes'
import { renderLegendToCanvas } from '@nivo/legends'
import { useInheritedColor, useOrdinalColorScale } from '@nivo/colors'
Expand Down Expand Up @@ -80,23 +85,19 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
gridXValues,
gridYValues,

// barComponent = canvasDefaultProps.barComponent,

enableLabel = canvasDefaultProps.enableLabel,
label = canvasDefaultProps.label,
labelSkipWidth = canvasDefaultProps.labelSkipWidth,
labelSkipHeight = canvasDefaultProps.labelSkipHeight,
labelTextColor = canvasDefaultProps.labelTextColor,

// markers,

colorBy = canvasDefaultProps.colorBy,
colors = canvasDefaultProps.colors,
// borderRadius = canvasDefaultProps.borderRadius,
borderRadius = canvasDefaultProps.borderRadius,
borderWidth = canvasDefaultProps.borderWidth,
borderColor = canvasDefaultProps.borderColor,

// annotations = canvasDefaultProps.annotations,
annotations = canvasDefaultProps.annotations,

legendLabel,
tooltipLabel = canvasDefaultProps.tooltipLabel,
Expand Down Expand Up @@ -183,6 +184,23 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
[enableLabel, labelSkipHeight, labelSkipWidth]
)

// Using any because return type isn't correct
const boundAnnotations: any = useComputedAnnotations({
annotations: useAnnotations({
data: result.bars,
annotations,
getPosition: node => ({
x: node.x,
y: node.y,
}),
getDimensions: ({ width, height }) => ({
width,
height,
size: Math.max(width, height),
}),
}),
})

useEffect(() => {
const ctx = canvasEl.current?.getContext('2d')

Expand Down Expand Up @@ -270,7 +288,24 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
}

ctx.beginPath()
ctx.rect(x, y, width, height)

if (borderRadius > 0) {
const radius = Math.min(borderRadius, height)

ctx.moveTo(x + radius, y)
ctx.lineTo(x + width - radius, y)
ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
ctx.lineTo(x + width, y + height - radius)
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height)
ctx.lineTo(x + radius, y + height)
ctx.quadraticCurveTo(x, y + height, x, y + height - radius)
ctx.lineTo(x, y + radius)
ctx.quadraticCurveTo(x, y, x + radius, y)
ctx.closePath()
} else {
ctx.rect(x, y, width, height)
}

ctx.fill()

if (borderWidth > 0) {
Expand All @@ -285,13 +320,17 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
}
})

renderAnnotationsToCanvas(ctx, { annotations: boundAnnotations, theme })

ctx.save()
}, [
axisBottom,
axisLeft,
axisRight,
axisTop,
borderRadius,
borderWidth,
boundAnnotations,
enableGridX,
enableGridY,
getBorderColor,
Expand Down
32 changes: 12 additions & 20 deletions packages/bar/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,9 @@ export type BarCommonProps<RawDatum> = {
innerPadding: number
padding: number

barComponent: React.FC<BarItemProps<RawDatum>>

valueScale: ScaleSpec
indexScale: ScaleBandSpec

// axisBottom?: AxisProps
// axisLeft?: AxisProps
// axisRight?: AxisProps
// axisTop?: AxisProps

enableGridX: boolean
gridXValues?: GridValues<string | number>
enableGridY: boolean
Expand Down Expand Up @@ -214,7 +207,6 @@ export type BarCommonProps<RawDatum> = {

annotations: AnnotationMatcher<ComputedBarDatum<RawDatum>>[]
legends: BarLegendProps[]
markers?: CartesianMarkerProps[]

renderWrapper?: boolean
}
Expand All @@ -231,6 +223,10 @@ export type BarSvgProps<RawDatum extends BarDatum> = Partial<BarCommonProps<RawD
axisRight: AxisProps
axisTop: AxisProps

barComponent: React.FC<BarItemProps<RawDatum>>

markers: CartesianMarkerProps[]

initialHiddenIds: string[]
layers: BarLayer<RawDatum>[]
role: string
Expand All @@ -239,21 +235,17 @@ export type BarSvgProps<RawDatum extends BarDatum> = Partial<BarCommonProps<RawD
export type BarCanvasProps<RawDatum extends BarDatum> = Partial<BarCommonProps<RawDatum>> &
DataProps<RawDatum> &
BarHandlers<RawDatum, HTMLCanvasElement> &
Dimensions & {
axisBottom?: CanvasAxisProp<any>
axisLeft?: CanvasAxisProp<any>
axisRight?: CanvasAxisProp<any>
axisTop?: CanvasAxisProp<any>
Dimensions &
Partial<{
axisBottom: CanvasAxisProp<any>
axisLeft: CanvasAxisProp<any>
axisRight: CanvasAxisProp<any>
axisTop: CanvasAxisProp<any>

pixelRatio?: number
}
pixelRatio: number
}>

export type BarAnnotationsProps<RawDatum> = {
annotations: AnnotationMatcher<ComputedBarDatum<RawDatum>>[]
bars: ComputedBarDatum<RawDatum>[]
}

export type TooltipHandlers = {
hideTooltip: () => void
showTooltip: (content: JSX.Element, event: React.MouseEvent<SVGRectElement>) => void
}
19 changes: 19 additions & 0 deletions packages/bar/stories/bar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,22 @@ stories.add('custom legend labels', () => (
stories.add('with formatted value', () => (
<Bar {...commonProps} valueFormat={value => `${value}`.split('').join('.')} />
))

stories.add('with annotations', () => (
<Bar
{...commonProps}
annotations={[
{
type: 'circle',
match: { key: 'fries.AE' },
noteX: 25,
noteY: 25,
offset: 3,
noteTextOffset: -3,
noteWidth: 5,
note: 'an annotation',
size: 40,
},
]}
/>
))
20 changes: 20 additions & 0 deletions packages/bar/stories/barCanvas.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ stories.add('custom tooltip', () => (
/>
))

stories.add('with annotations', () => (
<BarCanvas
{...commonProps}
borderRadius={10}
annotations={[
{
type: 'circle',
match: { key: 'fries.AE' },
noteX: 25,
noteY: 25,
offset: 3,
noteTextOffset: -3,
noteWidth: 5,
note: 'an annotation',
size: 40,
},
]}
/>
))

stories.add('Get canvas - download the chart', () => {
const ref = useRef(undefined)

Expand Down

0 comments on commit 3143823

Please sign in to comment.