Vuejs 2.5 sink page animation

by jpeter06

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="main">
  <p-menu></p-menu>
  <trans1> 
    <component v-bind:is="page"></component>
  </trans1>
</div>


<template id="pMenu">
  <div class="menu" v-bind:class="{ active: isActive }">
    <div id="cabecera">TITULO</div>
    <ul>
      <li  v-bind:class="[page==item ?'focused':'']" v-for="item  in items" v-on:click="click(item)">
      {{item}}
      </li>
    </ul>
  </div>
</template>

<!-- PAGES -->
<template id="page2">
  <div class="page" >
   Page2
   <innertext2>sd</innertext2>
   <innertext/>
   <innertext2/>
  </div>
</template>
 
<template id="page1">
  <div class="page">
   Page1
   <innertext2> </innertext2>
   <innertext> </innertext>
   <innertext2> </innertext2>
   <innertext> </innertext>
  </div>
</template>
 
<template id="page3">
  <div class="page"  style="background:#fea">
  Page3
  <innertext/>
  </div>
</template>

<template id="page4">
  <div class="page" style="background:#eee">
  Page4
  <innertext/>
  </div>
</template>



<template id="innertext">
  <div style="text-align: justify;line-height: 1.3;">
  Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr,  sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero 
  </div>
</template>
<template id="innertext2">
  <div style="text-align: justify;">
  Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum...

CSS

html, body ,#main
{
    height: 100%;
    width: 100%;
    margin: 0px;
    padding: 0px;
    overflow: hidden;
    background:#fff;
    font-family:Arial;
    color:#888;
}

#main{
  display:flex; flex-direction:column;
  --animation-speed: 1.2s;
  --scale: 0.92;
}
#cabecera{  flex-grow:0;height:40px;text-align:center; 
            color:#777; font-size:30px; ;margin-top:16px;}
           
.pageContExt{flex-grow:1;position:relative;overflow: hidden;
          border: 10px solid transparent;display:flex;}

/*PAGECONT CSS SHADOW & ANIMATION*/
.pageCont{flex-grow:1;position:relative;overflow: hidden; }
.pageCont.active{border: 1px inset rgba(250,250,250,0.6); }
/*shadow with animation*/
.pageShadow {
  box-shadow: 0 0px 15px rgba(0,0,0,0.3) inset;
  opacity: 0;
  position: absolute;
  top: 0;  left: 0;  width: 100%;  height: 100%;
  content:"";  pointer-events: none;
}
.pageShadow.active {  animation: show-hole calc(var(--animation-speed) );}
@keyframes show-hole{
  0%  {opacity:0 ;animation-timing-function: ease-out;  }
  33%  { opacity: 1;animation-timing-function: ease-out;  }
  70%  { opacity: 1;animation-timing-function: ease-in;  }
 100% { opacity: 0.2; animation-timing-function: ease-in; }
}

/*** PAGES ANIMATIONS ***/
.pageL-enter-active {  animation: bounce-li var(--animation-speed);}
.pageL-leave-active {  animation: bounce-lo var(--animation-speed);}
.pageR-enter-active {  animation: bounce-ri var(--animation-speed);}
.pageR-leave-active {  animation: bounce-ro var(--animation-speed);}


@keyframes bounce-li{
  0%  {transform:   translate(0%,calc( 100% + 40px)) scale(var(--scale),var(--scale));animation-timing-function: ease-out;  }
  25%  {transform:   translate(0%,calc( 100% + 40px)) scale(var(--scale),var(--scale));animation-timing-function: ease-out;  }
  75%  {transform:   translate(0%,0%) scale(var(--scale),var(--scale));animation-timing-function: ease-in;  }
 100% {transform:    translate(0%,0%); animation-timing-function: ease-in; }
}
@keyframes...

JavaScript

///////// trans1 ////
var trans1 = Vue.extend({
  template: `    <div class="pageContExt">
                  <div class="pageCont" v-bind:class="{ active: isActive }">
                    <transition :name="transitionName" 
                    v-on:before-enter="beforeEnter"
                    v-on:after-enter="afterEnter" appear>
                      <slot></slot>
                    </transition>
                  </div> 
                  <div class="pageShadow" ref="pageShadow" v-bind:class="{ active: isActive }">
                  </div>
                </div>`,
  props: ['page'],
  data:function(){
  	return {
    		isActive:false,
    		transitionName:'pageL',
        el:null
    }
  },
  methods:{ 
    beforeEnter: function (el) { console.log(el);
      this.el=el;
      if(this.$refs["pageShadow"]){
        var self=this; 
        this.$refs["pageShadow"].classList.remove("active");
       setTimeout(function(){  self.$refs["pageShadow"].classList.add("active");  },88);
      }
      this.isActive=true;
    },
    afterEnter: function (el) {
      if(this.el==el){	this.isActive=false; this.el=null }
    }
  }
})
Vue.component('trans1', trans1);

///////// pMenu ////
var pMenu = Vue.extend({
  template: '#pMenu',
  data:function(){
  	return {
    		page:'page1',
        isActive:false,
        timeoutId:null,
    		items:['page1','page2','page3','page4']
        }
  },
  methods:{
  	click:function(item){
      var isR=this.items.indexOf(item)>this.items.indexOf(this.page);
    	this.page=item;
      vv.transitionName=isR?'pageL':'pageR';
      vv.page=item;
    },
 		isFocused:function(item){
    	return item==this.page?'focused':''
    }   
  },
  watch: {
    page: function(newValue) {}
  }
})
Vue.component('p-menu', pMenu);


/////////// PAGE 2 ///////////////
Vue.component('page1', {  template: '#page1'});  
/////////// PAGE 2 ///////////////
Vue.component('page2', {  template: '#page2'});  
/////////// PAGE 3...