Optimize simple CSS / WebAnimation, eg scale()

57 Views Asked by At

I've tried different solutions to animate a sidenav bar rise from bottom right corner. This is the last solution, maybe the best one ( because i'm animating the transform scale() ) in the previous ( width / height ) but the animation still sluggish on the cut corner... with the cut line acting with strange squared forms during the animation ... so i'm looking to solve!

Here the scale() example on glitch https://glitch.com/edit/#!/heady-grey-lantern

Even on w3schools site the simple animation of Side Navigation is little shimmy and flicker https://www.w3schools.com/howto/howto_js_sidenav.asp

Here the core of animation

// css code
.sidenav {
  width: 200vw;
  height: 200vh;
  width: 200dvw;
  height: 200dvh;

  position: fixed;
  bottom: 0;
  /* left: 0; */
  right: 0;

  /* cut corner */
  --cutting: max(100vw, 100vh);
  --cutting: max(150dvw, 150dvh);
  clip-path: polygon(0 var(--cutting), var(--cutting) 0,100% 0,100% 100%,0 100%);

  /* z-index: 1; */
  background-color: #111;

  /* overflow-x: hidden; */
  will-change: transform;
  transform: scale(0);
  transform-origin: bottom right;
 }


// Js code
const sidenav = document.getElementById("mySidenav")

const duration = 500
const openSidenav = [
  { transform: 'scaleX(0) scaleY(0)' },
  { transform: 'scaleX(1) scaleY(1)' }
]

const closeSidenav = [
  { transform: 'scaleX(1) scaleY(1)' },
  { transform: 'scaleX(0) scaleY(0)' }
]

const openNav = () => {

  console.log('@NAV >> Open')
  // document.getElementById("mySidenav").style.width = '175vw'
  // document.getElementById("mySidenav").style.height = '175vh'

  sidenav.animate(
    openSidenav, {
      duration,
      iterations: 1,
      easing: 'ease-in',
      fill: 'forwards'
    }
  )

}

const closeNav = () => {

  console.log('@NAV >> Close')
  // document.getElementById("mySidenav").style.width = '0'
  // document.getElementById("mySidenav").style.height = '0'

  sidenav.animate(
    closeSidenav, {
      duration,
      iterations: 1,
      easing: 'ease-in',
      fill: 'forwards'
    }
  )
  
}
1

There are 1 best solutions below

0
On

Last, better one!

  /* css */
  #sidenav {
      width: 100vw;
      height: 100vh;
      width: 100dvw;
      height: 100dvh;

      position: fixed;

      /* cut corner */
      --cutting: max(100vw, 100vh);
      clip-path: polygon(0 var(--cutting), var(--cutting) 0,100% 0,100% 100%,0 100%);
      /* set transition as in WebAnimation API */
      transition: all 0.5s;

      will-change: transform;
      transform: scale(0);
      transform-origin: bottom right;

      z-index: 11;
      background-color: var(--surface1);

      display: grid;
      justify-items: center;
      align-items: center;

      /* justify-items: end;
      align-items: end; */

    }

    #sidenav[active] {
      --cutting: 0;
      transition: all 0.5s;
    }

    /* --------------- Mobile Nav -------------- */
    nav {
      /* TODO fallback inline-size: 75vw;
      block-size: 75vh; */
      inline-size: 75dvw;
      block-size: 75dvh;

      display: block;
      flex-direction: column;

      background-color: crimson;
    }

// javascript animations
const openSidenav = [
 { transform: 'scale(0)' },
 { transform: 'scale(0.25)' },
 { transform: 'scale(0.5)' },
 { transform: 'scale(0.75)' },
 { transform: 'scale(1)' }
]

const closeSidenav = [
 { transform: 'scale(1)' },
 { transform: 'scale(0.75)' },
 { transform: 'scale(0.5)' },
 { transform: 'scale(0.25)' },
 { transform: 'scale(0)' }
]

const slideIn = [
 { transform: 'translateX(100%)' },
 { transform: 'translateX(0)', opacity: 1 }
]

const slideOut = [
 { transform: 'translateX(0)' },
 { transform: 'translateX(100%)', opacity: 0 }
]

// duration animation
const openSidenavDuration = 500
const closeSidenavDuration = 300
// duration animation per a tag
const slideInDuration = 200
const slideOutDuration = 100

// javascript
openNav (e) {
const sidenav =
  this.renderRoot.getElementById('sidenav')

this.sidenavIsOpen = true

const openAnimation = sidenav.animate(
  openSidenav, {
    duration: openSidenavDuration,
    iterations: 1,
    easing: 'ease-in',
    fill: 'forwards'
  }
)

openAnimation.addEventListener('finish', (e) => {
  // console.log('@EVENT >> ', e.type)

  sidenav.setAttribute('active', '')
  // sidenav.style.setProperty('--cutting', 0)
})

}

closeNav (e) {
const sidenav =
  this.renderRoot.getElementById('sidenav')

this.sidenavIsOpen = false

sidenav.animate(
  closeSidenav, {
    duration: closeSidenavDuration,
    iterations: 1,
    easing: 'ease-in',
    fill: 'forwards',
    delay: slideOutDuration * 3
  }
)

sidenav.removeAttribute('active')

}