From 3ea3de84b287f75c9cbcd61b9d4c9dc738734055 Mon Sep 17 00:00:00 2001 From: Franc Camps-Febrer Date: Fri, 1 Feb 2019 14:07:00 -0500 Subject: [PATCH] Automatically scroll to current Card in Narrative --- src/components/Card.jsx | 6 +++- src/components/CardStack.jsx | 68 ++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/components/Card.jsx b/src/components/Card.jsx index b8820c6..31978fb 100644 --- a/src/components/Card.jsx +++ b/src/components/Card.jsx @@ -161,10 +161,12 @@ class Card extends React.Component { render () { const { isSelected, idx } = this.props + return (
  • {this.renderMain()} {this.state.isOpen ? this.renderExtra() : null} @@ -174,4 +176,6 @@ class Card extends React.Component { } } -export default Card +// The ref to each card will be used in CardStack for programmatic scrolling +export default React.forwardRef((props, ref) => ); + diff --git a/src/components/CardStack.jsx b/src/components/CardStack.jsx index f2e908c..9f23157 100644 --- a/src/components/CardStack.jsx +++ b/src/components/CardStack.jsx @@ -6,13 +6,63 @@ import Card from './Card.jsx' import copy from '../js/data/copy.json' class CardStack extends React.Component { + + constructor() { + super() + this.refs = {} + this.refCardStack = React.createRef() + this.refCardStackContent = React.createRef() + } + + componentDidUpdate() { + const isNarrative = !!this.props.narrative + + if (isNarrative) { + this.scrollToCard() + } + } + + scrollToCard() { + const duration = 500 + const element = this.refCardStack.current + const cardScroll = this.refs[this.props.narrative.current].current.offsetTop - 20 + + let start = element.scrollTop; + let change = cardScroll - start; + let currentTime = 0; + const increment = 20; + + //t = current time + //b = start value + //c = change in value + //d = duration + Math.easeInOutQuad = function (t, b, c, d) { + t /= d / 2; + if (t < 1) return c / 2 * t * t + b; + t--; + return - c / 2 * (t * (t - 2) - 1) + b; + }; + + const animateScroll = function() { + currentTime += increment; + const val = Math.easeInOutQuad(currentTime, start, change, duration); + element.scrollTop = val; + if (currentTime < duration) setTimeout(animateScroll, increment); + }; + animateScroll(); + } + renderCards (events, selections) { // if no selections provided, select all if (!selections) { selections = events.map(e => true) } + this.refs = [] - return events.map((event, idx) => ( - { + const thisRef = React.createRef() + this.refs[idx] = thisRef + return ( - )) + />) + }) } renderSelectedCards () { @@ -38,9 +88,10 @@ class CardStack extends React.Component { renderNarrativeCards () { const { narrative } = this.props - const showing = narrative.steps.slice(narrative.current) + const showing = narrative.steps + const selections = showing - .map((_, idx) => (idx === 0)) + .map((_, idx) => (idx === narrative.current)) return this.renderCards(showing, selections) } @@ -74,7 +125,9 @@ class CardStack extends React.Component { renderNarrativeContent () { return ( -
    +
      {this.renderNarrativeCards()}
    @@ -102,6 +155,7 @@ class CardStack extends React.Component { return (