-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(canvas): add canvas support for bar & heatmap
- Loading branch information
Raphaël Benitte
committed
Aug 29, 2017
1 parent
7c57546
commit 94ad4d9
Showing
16 changed files
with
862 additions
and
305 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* This file is part of the nivo project. | ||
* | ||
* Copyright 2016-present, Raphaël Benitte. | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
import React, { Component } from 'react' | ||
import { generateGroupedBars, generateStackedBars } from '../../../lib/charts/bar' | ||
import { renderAxes } from '../../../lib/canvas/axes' | ||
import { BarPropTypes } from './props' | ||
import enhance from './enhance' | ||
|
||
class BarCanvas extends Component { | ||
componentDidMount() { | ||
this.ctx = this.surface.getContext('2d') | ||
this.draw(this.props) | ||
} | ||
|
||
shouldComponentUpdate(props) { | ||
this.draw(props) | ||
return false | ||
} | ||
|
||
draw(props) { | ||
const { | ||
// data | ||
data, | ||
keys, | ||
getIndex, | ||
|
||
// dimensions | ||
width, | ||
height, | ||
outerWidth, | ||
outerHeight, | ||
margin, | ||
|
||
// layout | ||
layout, | ||
groupMode, | ||
xPadding, | ||
|
||
// axes | ||
axisTop, | ||
axisRight, | ||
axisBottom, | ||
axisLeft, | ||
|
||
// theming | ||
getColor, | ||
} = props | ||
|
||
this.surface.width = outerWidth | ||
this.surface.height = outerHeight | ||
|
||
let result | ||
if (groupMode === 'grouped') { | ||
result = generateGroupedBars(layout, data, getIndex, keys, width, height, getColor, { | ||
xPadding, | ||
}) | ||
} else if (groupMode === 'stacked') { | ||
result = generateStackedBars(layout, data, getIndex, keys, width, height, getColor, { | ||
xPadding, | ||
}) | ||
} | ||
|
||
this.ctx.clearRect(0, 0, outerWidth, outerHeight) | ||
this.ctx.translate(margin.left, margin.top) | ||
|
||
renderAxes(this.ctx, { | ||
xScale: result.xScale, | ||
yScale: result.yScale, | ||
width, | ||
height, | ||
top: axisTop, | ||
right: axisRight, | ||
bottom: axisBottom, | ||
left: axisLeft, | ||
}) | ||
|
||
result.bars.forEach(({ x, y, color, width, height }) => { | ||
this.ctx.fillStyle = color | ||
this.ctx.fillRect(x, y, width, height) | ||
}) | ||
} | ||
|
||
render() { | ||
const { outerWidth, outerHeight } = this.props | ||
|
||
return ( | ||
<canvas | ||
ref={surface => { | ||
this.surface = surface | ||
}} | ||
width={outerWidth} | ||
height={outerHeight} | ||
/> | ||
) | ||
} | ||
} | ||
|
||
BarCanvas.propTypes = BarPropTypes | ||
|
||
export default enhance(BarCanvas) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* This file is part of the nivo project. | ||
* | ||
* Copyright 2016-present, Raphaël Benitte. | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
import React from 'react' | ||
import ResponsiveWrapper from '../ResponsiveWrapper' | ||
import BarCanvas from './BarCanvas' | ||
|
||
const ResponsiveBarCanvas = props => | ||
<ResponsiveWrapper> | ||
{({ width, height }) => <BarCanvas width={width} height={height} {...props} />} | ||
</ResponsiveWrapper> | ||
|
||
export default ResponsiveBarCanvas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* This file is part of the nivo project. | ||
* | ||
* Copyright 2016-present, Raphaël Benitte. | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
import compose from 'recompose/compose' | ||
import defaultProps from 'recompose/defaultProps' | ||
import withPropsOnChange from 'recompose/withPropsOnChange' | ||
import pure from 'recompose/pure' | ||
import { withTheme, withColors, withDimensions, withMotion } from '../../../hocs' | ||
import { getInheritedColorGenerator } from '../../../lib/colors' | ||
import { getAccessorFor } from '../../../lib/propertiesConverters' | ||
import { BarDefaultProps } from './props' | ||
|
||
export default Component => | ||
compose( | ||
defaultProps(BarDefaultProps), | ||
withTheme(), | ||
withColors(), | ||
withDimensions(), | ||
withMotion(), | ||
withPropsOnChange(['indexBy'], ({ indexBy }) => ({ | ||
getIndex: getAccessorFor(indexBy), | ||
})), | ||
withPropsOnChange(['labelsTextColor'], ({ labelsTextColor }) => ({ | ||
getLabelsTextColor: getInheritedColorGenerator(labelsTextColor, 'axis.textColor'), | ||
})), | ||
withPropsOnChange(['labelsLinkColor'], ({ labelsLinkColor }) => ({ | ||
getLabelsLinkColor: getInheritedColorGenerator(labelsLinkColor, 'axis.tickColor'), | ||
})), | ||
pure | ||
)(Component) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* This file is part of the nivo project. | ||
* | ||
* Copyright 2016-present, Raphaël Benitte. | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
import PropTypes from 'prop-types' | ||
|
||
export const BarPropTypes = { | ||
// data | ||
data: PropTypes.arrayOf(PropTypes.object).isRequired, | ||
indexBy: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, | ||
getIndex: PropTypes.func.isRequired, // computed | ||
keys: PropTypes.arrayOf(PropTypes.string).isRequired, | ||
|
||
groupMode: PropTypes.oneOf(['stacked', 'grouped']).isRequired, | ||
layout: PropTypes.oneOf(['horizontal', 'vertical']).isRequired, | ||
|
||
xPadding: PropTypes.number.isRequired, | ||
|
||
// axes & grid | ||
axisTop: PropTypes.object, | ||
axisRight: PropTypes.object, | ||
axisBottom: PropTypes.object, | ||
axisLeft: PropTypes.object, | ||
enableGridX: PropTypes.bool.isRequired, | ||
enableGridY: PropTypes.bool.isRequired, | ||
|
||
// labels | ||
enableLabels: PropTypes.bool.isRequired, | ||
labelsTextColor: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, | ||
getLabelsTextColor: PropTypes.func.isRequired, // computed | ||
labelsLinkColor: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, | ||
getLabelsLinkColor: PropTypes.func.isRequired, // computed | ||
|
||
// interactions | ||
onClick: PropTypes.func, | ||
|
||
// theming | ||
getColor: PropTypes.func.isRequired, | ||
|
||
// interactivity | ||
isInteractive: PropTypes.bool, | ||
} | ||
|
||
export const BarDefaultProps = { | ||
indexBy: 'id', | ||
keys: ['value'], | ||
|
||
groupMode: 'stacked', | ||
layout: 'vertical', | ||
|
||
xPadding: 0.1, | ||
|
||
// axes & grid | ||
axisBottom: {}, | ||
axisLeft: {}, | ||
enableGridX: false, | ||
enableGridY: true, | ||
|
||
// labels | ||
enableLabels: true, | ||
labelsLinkColor: 'theme', | ||
labelsTextColor: 'theme', | ||
|
||
// interactivity | ||
isInteractive: true, | ||
} |
Oops, something went wrong.