Redux Animation

by Dominic Cocchiarella

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-with-addons.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://d2guulkeunn7d8.cloudfront.net/assets/redux-dev-tools-bundle-006.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.2/redux.js"></script>
<div id="container"></div>

SCSS

*, *::before, *::after {
  box-sizing: inherit;
}

html, body, 
#container, 
.container-inner {
  height: 100%;
  box-sizing: border-box;
  margin: 0;
}

.main-content {
  height: 85%;
  background-color: #43B02A;
}

.absolute-center {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}
  
.logo-wrapper {
  width: 298px;
  height: 60px;
    
  .logo-white,
  .logo-color {
    width: 100%;
    height: 100%;
    background-size: 100%;
    background-repeat: no-repeat;
    opacity: 1;
    will-change: opacity;
  }

  .logo-white {
    background-image: url(https://d2guulkeunn7d8.cloudfront.net/assets/beetstrap/brand/instacart-logo-white@2x-fb1feeeb27989918f03cae5707183b27.png);
  }

  .logo-color {
    background-image: url(https://d2guulkeunn7d8.cloudfront.net/assets/beetstrap/brand/instacart-logo-color@2x-0f6d941e7e53120ce96166e1d6f2adc4.png);
  }
}

Babel + JSX

//logging utitlity -- check the browser console for a nice log of the redux store
function logState() {
  let state = storeApp.getState().logo
  console.group('new Redux store state');
	Object.keys(state).forEach(i => {console.log(`${i}: `, state[i])})
  console.groupEnd();
}

// Redux Devtools setup
const DevTools = window.DevTools['default']
const finalCreateStore = Redux.compose(
  DevTools.instrument()
)(Redux.createStore)

// RGB color consts
const TEXT_COLOR_RED_START   = 67
const TEXT_COLOR_RED_END     = 255
const TEXT_COLOR_RED_DIFF    = TEXT_COLOR_RED_END - TEXT_COLOR_RED_START

const TEXT_COLOR_GREEN_START = 176
const TEXT_COLOR_GREEN_END   = 255
const TEXT_COLOR_GREEN_DIFF  = TEXT_COLOR_GREEN_END - TEXT_COLOR_GREEN_START

const TEXT_COLOR_BLUE_START  = 42
const TEXT_COLOR_BLUE_END    = 255
const TEXT_COLOR_BLUE_DIFF   = TEXT_COLOR_BLUE_END -TEXT_COLOR_BLUE_START

const BACKGROUND_POS_START = 50

const getBackgroundColor = function(animationProgress) {
  // 255, 255, 255 is rgb 'white'. This calculates how close to white
  // each color channel is based on the animationProgress
  let red   = TEXT_COLOR_RED_START   + Math.ceil(animationProgress * TEXT_COLOR_RED_DIFF)
  let green = TEXT_COLOR_GREEN_START + Math.ceil(animationProgress * TEXT_COLOR_GREEN_DIFF)
  let blue  = TEXT_COLOR_BLUE_START  + Math.ceil(animationProgress * TEXT_COLOR_BLUE_DIFF)

  return `rgb(${red}, ${green}, ${blue})`
}

// Redux reducer setup
const defaultLogoState = {
	animationProgress : 0,
  lightLogoOpacity  : 1,
  colorLogoOpacity  : 0,
  backgroundPos     : 0,
  backgroundColor   : 'rgb(67, 176, 42)'
}

const logoReducer = function(state = defaultLogoState, action) {
  switch (action.type){
    case 'LOGO.SET_NEXT_ANIMATION_STEP':
    	let progress = action.progress
      
      return Object.assign({}, state, {
      	animationProgress : progress,
        lightLogoOpacity  : 1 - progress,
        colorLogoOpacity  : progress,
        backgroundPos     :...