Skip to content

Commit

Permalink
Scroller
Browse files Browse the repository at this point in the history
  • Loading branch information
rodion committed Jan 1, 2019
1 parent 61d2d69 commit 3cbb43c
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 12 deletions.
11 changes: 5 additions & 6 deletions example/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export default class App extends React.Component {
barsNumber,
barsWithLabels,
bars: getMockBars(barsNumber, barsWithLabels),
showScroll: true,
showScroller: true,
selectCenterBarOnScroll: true
}
}
Expand All @@ -95,11 +95,10 @@ export default class App extends React.Component {
barSpace,
centerBarIndex,
selectCenterBarOnScroll,
showScroll,
showScroller,
barsWithLabels,
barsNumber
} = this.state
console.log(bars)
return (
<Page>
<Wrapper>
Expand All @@ -110,7 +109,7 @@ export default class App extends React.Component {
centerBarIndex={centerBarIndex}
onBarSelect={(centerBarIndex) => this.setState({ centerBarIndex })}
selectCenterBarOnScroll={selectCenterBarOnScroll}
showScroll={showScroll}
showScroller={showScroller}
/>
</Wrapper>
<Panel>
Expand All @@ -132,8 +131,8 @@ export default class App extends React.Component {
<BoolParam>
<Param>show scroll: </Param>
<Switch
checked={showScroll}
onChange={() => this.setState({ showScroll: !showScroll })}
checked={showScroller}
onChange={() => this.setState({ showScroller: !showScroller })}
/>
</BoolParam>
</PanelRow>
Expand Down
37 changes: 33 additions & 4 deletions src/components/bar-chart/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@ export default class BarChart extends React.Component {
}
render() {
const { theme, showScroller, barWidth, barSpace, bars, centerBarIndex, onBarSelect } = this.props
const { width, offset, oldOffset, height } = this.state
const { width, offset, oldOffset, height, scrolling, totalWidth } = this.state

const barTotalWidth = barWidth + barSpace
const totalWidth = bars.length * barTotalWidth

const getStartIndex = () => {
const startIndex = Math.floor((totalWidth - width - oldOffset - (offset > oldOffset ? offset - oldOffset : 0)) / barTotalWidth)
Expand Down Expand Up @@ -104,7 +103,16 @@ export default class BarChart extends React.Component {
/>
))
}

const scrollerProps = {
totalWidth,
width,
offset,
oldOffset,
scrolling,
onDragStart: () => this.setState({ scrolling: true, oldOffset: this.state.offset }),
onDrag: this.onScroll,
onDragEnd: () => this.setState({ scrolling: false })
}
return (
<React.Fragment>
<DataContainer {...dataConainerProps}>
Expand All @@ -114,7 +122,7 @@ export default class BarChart extends React.Component {
{bars.length > 0 && <Line/>}
<Labels/>
</DataContainer>
{showScroller && <Scroller/>}
{showScroller && <Scroller {...scrollerProps} />}
</React.Fragment>
)
}
Expand Down Expand Up @@ -185,4 +193,25 @@ export default class BarChart extends React.Component {
totalWidth
}
}

onScroll = (movementX) => {
const { width, offset, totalWidth } = this.state
const { barWidth, barSpace, bars, selectCenterBarOnScroll, centerBarIndex, onBarSelect } = this.props
const additionalOffset = (totalWidth / width) * movementX
const getOffset = () => {
const newOffset = offset - additionalOffset
if (newOffset < 0) return 0
if (newOffset + width > totalWidth) return totalWidth - width
return newOffset
}
const newOffset = getOffset(0)
this.setState({ offset: newOffset, oldOffset: newOffset })
if (selectCenterBarOnScroll) {
const center = totalWidth - newOffset - width / 2
const newCenterBarIndex = bars.findIndex((_, index) => (index * (barWidth + barSpace)) >= center) - 1
if (centerBarIndex !== newCenterBarIndex) {
onBarSelect(newCenterBarIndex)
}
}
}
}
80 changes: 79 additions & 1 deletion src/components/bar-chart/scroller.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react'
import styled from 'styled-components'
import { animationStyle } from './styles';

const Container = styled.div`
position: relative;
Expand All @@ -8,4 +10,80 @@ const Container = styled.div`
align-items: center;
`

export default Container
const Line = styled.div`
position: absolute;
width: 100%;
height: 6px;
background-color: ${props => props.theme.scrollerBackgroundColor};
`

const Position = styled.div`
cursor: pointer;
position: absolute;
height: 6px;
background-color: ${props => props.theme.mainColor};
border-radius: 3px;
&:hover {
height: 8px;
border-radius: 4px;
}
${animationStyle}
`

export default class Scroller extends React.Component {
render() {
const { totalWidth, offset, oldOffset, width } = this.props
const getMargin = offset => ((totalWidth - (offset + width)) /totalWidth) * 100
const periodMargin = getMargin(oldOffset)
if (periodMargin < 0) return null

const periodWidth = (width * 100) / totalWidth
const animationOffset = getMargin(offset) - periodMargin
const positionStyle = { width: `${periodWidth}%`, marginLeft: `${periodMargin}%` }

return (
<Container>
<Line/>
<Position
offset={(animationOffset * width) / 100}
style={positionStyle}
onTouchStart={e => e.preventDefault()}
onDragStart={e => e.preventDefault()}
onMouseDown={this.onMouseDown}
/>
</Container>
)
}

shouldComponentUpdate(nextProps) {
return nextProps !== this.props
}

componentDidMount() {
document.addEventListener('mouseup', this.onMouseUp)
document.addEventListener('mousemove', this.onMouseMove)
}

componentWillUnmount() {
document.removeEventListener('mouseup', this.onMouseUp)
document.removeEventListener('mousemove', this.onMouseMove)
}

onMouseDown = () => {
this.props.onDragStart()
}

onMouseMove = (e) => {
const { scrolling, onDrag } = this.props
if (scrolling && e.movementX) {
onDrag(e.movementX)
}
}

onMouseUp = () => {
const { scrolling, onDragEnd } = this.props
if (scrolling) {
onDragEnd()
}
}
}
2 changes: 1 addition & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const DEFAULT_THEME = {
mainColor: 'white',
scrollerBakgroundColor: 'rgba(255, 255, 255, 0.15)',
scrollerBackgroundColor: 'rgba(255, 255, 255, 0.15)',
labelFontSize: 12
}

0 comments on commit 3cbb43c

Please sign in to comment.