div#app
  app
script#App(type='x/template')
  div#App.App
    .canv
      .small(ref="small")
      .big(ref="big")
      .shadow(ref="shadow")
View Compiled
#App
  .big,
  .small
    position absolute
    bottom 10%
    left 50%
    width 100px
    height 100px
    margin-left -50px
    margin-top -50px
    background #9c27b0
    cursor pointer
    color white
    text-align center
    line-height 100px
    font-weight bold
    border-radius 6px
    transform-origin center bottom
    will-change transform
    backface-visibility hidden
    perspective 1000px
    transform translateZ(0.0001px)
    zoom 1
  .small
      background #5af158
      width 50px
      height 50px
      margin-left -25px
      margin-top -25px
  .shadow
    position absolute
    background-color #dedede
    width 140px
    height 10px
    border-radius 80%
    left 50%
    bottom calc(10% - 5px)
    margin-left -70px
    z-index -1
    opacity 1
    
View Compiled
const {
  styler,
  easing,
  keyframes,
  parallel,
  multicast
} = window.popmotion
const {
  createExpoIn,
  mirrored,
  reversed
} = easing
const customEaseIn = createExpoIn(1)
const customEaseInOut = mirrored(customEaseIn)
Vue.component('app', {
  data: () => ({
    duration: 1500,
    bigStyler: void 0,
    smallStyler: void 0,
    shadowStyler: void 0,
    boxesRotation: multicast(),
  }),
  template: '#App',
  mounted() {
    this.bigStyler = styler(this.$refs.big)
    this.smallStyler = styler(this.$refs.small)
    this.shadowStyler = styler(this.$refs.shadow)
    this.boxesRotation.subscribe(v => this.bigStyler.set({ rotate: v[0][1].rot }))
    this.boxesRotation.subscribe(v => this.smallStyler.set({ rotate: -v[0][1].rot }))
    this.handleJump()
  },
  methods: {
    jump() {
      const
        move = keyframes({
          values: [{
              scaleX: 1.5,
              scaleY: 0.4,
              y: 0
            },
            {
              scaleX: 1,
              scaleY: 1,
              y: 0
            },
            {
              scaleX: 1,
              scaleY: 1,
              y: -200
            },
            {
              scaleX: 1,
              scaleY: 1,
              y: 0
            },
            {
              scaleX: 1.5,
              scaleY: 0.4,
              y: 0
            },
          ],
          duration: this.duration,
          times: [0, 0.15, 0.5, 0.85, 1],
          easings: [d3.easeCircleIn, d3.easeCircleOut, d3.easeCircleIn, d3.easeCircleOut],
          loop: Infinity,
        }),
        rotate = keyframes({
          values: [{
              rot: 0
            },
            {
              rot: 0
            },
            {
              rot: -360
            },
            {
              rot: -360
            },
          ],
          duration: this.duration,
          times: [0, 0.15, 0.85, 1],
          easings: [easing.linear, customEaseInOut, easing.linear],
          loop: Infinity,
        })
      return parallel(move, rotate)
    },
    jumpsmall() {
      const
        move = keyframes({
          values: [{
              scaleX: 1.6,
              scaleY: 0.4,
              y: -40
            },
            {
              scaleX: 1,
              scaleY: 1,
              y: -100
            },
            {
              scaleX: 1,
              scaleY: 1,
              y: -400
            },
            {
              scaleX: 1,
              scaleY: 1,
              y: -100
            },
            {
              scaleX: 1.6,
              scaleY: 0.4,
              y: -40
            },
          ],
          duration: this.duration,
          times: [0, 0.15, 0.5, 0.85, 1],
          easings: [d3.easeCircleIn, d3.easeCircleOut, d3.easeCircleIn, d3.easeCircleOut],
          loop: Infinity,
        })
        // rotate = keyframes({
        //  values: [{
        //      rot: 0
        //    },
        //    {
        //      rot: 0
        //    },
        //    {
        //      rot: 360
        //    },
        //    {
        //      rot: 360
        //    },
        //  ],
        //  duration: this.duration,
        //  times: [0, 0.15, 0.85, 1],
        //  easings: [easing.linear, customEaseInOut, easing.linear],
        //  loop: Infinity,
        // })
      return parallel(move)
    },
    animshadow() {
      const
        scale = keyframes({
          values: [{
              scale: 1
            },
            {
              scale: 1
            },
            {
              scale: 0.5
            },
            {
              scale: 1
            },
            {
              scale: 1
            },
          ],
          duration: this.duration,
          times: [0, 0.15, 0.5, 0.85, 1],
          easings: [easing.circIn, easing.circOut, easing.circIn, easing.circOut],
          loop: Infinity,
        })
      return scale
    },
    multijump() {
      return parallel(this.jump(), this.jumpsmall(), this.animshadow())
    },
    addOrigin(v) {
      // console.log(v)
      v[3] = {
        origin: v[0][0].scaleX === 1 ? 'center center' : 'center bottom'
      }
      return v
    },
    handleJump() {
      this.multijump().pipe(this.addOrigin).start({
        update: v => {
          this.boxesRotation.update(v)
          this.bigStyler.set({
            y: v[0][0].y,
            scaleX: v[0][0].scaleX,
            scaleY: v[0][0].scaleY,
            // rotate: v[0][1].rot,
            transformOrigin: v[3].origin,
          })
          this.smallStyler.set({
            y: v[1][0].y,
            scaleX: v[1][0].scaleX,
            scaleY: v[1][0].scaleY,
            // rotate: v[1][1].rot,
            transformOrigin: v[3].origin,
          })
          // this.shadowStyler.set({
          //   scaleX: v[2].scaleX,
          // })
          this.shadowStyler.set(v[2])
        },
        // complete: () => console.log('complete triggered'),
      })
    },
  },
})

new Vue({
  el: '#app',
  data: {},
  components: [
    app,
  ],
})
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js
  2. https://unpkg.com/popmotion/dist/popmotion.global.min.js
  3. https://d3js.org/d3-ease.v1.min.js