0

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'
    }
  )
  
}
cicciosgamino
  • 871
  • 3
  • 10
  • 29
  • 1
    In Firefox you're not getting optimized animation because the "layer" you're animating is too big -- twice the size of the viewport. In Firefox DevTools you can inspect the animation and see the warning that the layer size is too big (screenshot: https://imgur.com/a/RpiVNah). As for the corner looking odd, it sounds like you want the border to stay the same width while scaling the rest of the content. For that you either need to use nine-slice scaling (https://en.wikipedia.org/wiki/9-slice_scaling) or use SVG with `vector-effect: non-scaling-stroke`. – brianskold Feb 09 '23 at 23:27
  • Thanks .... but i don't care about the border to stay the same width, i'd like only get a clean edge in top left cut corner during the animation in and out, but that 45° cut corner seem animated starting from rectangle computation of the layout during the animation ... – cicciosgamino Feb 10 '23 at 09:12

1 Answers1

0

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')

}

cicciosgamino
  • 871
  • 3
  • 10
  • 29