Dogstudio / highway

Highway - A Modern Javascript Transitions Manager
https://highway.js.org/
MIT License
1.43k stars 92 forks source link

from.remove() when the user does not wait for the transition to be completed (with overlap) #92

Closed Totokoutonio closed 4 years ago

Totokoutonio commented 4 years ago

Hello!

I'm using Highway to make overlap transition. Everything works fine but the old page isn't remove if the user click on a link before the end of the transition.

I didn't use gasp (or any other transition library), I use keyframes from my CSS and run from.remove() with a setTimeout. Maybe that's where the problem's coming from?

//main.js
import Highway from './highway.module.js';
import Overlap from './CustomTransition.js';
(() => {
  const H = new Highway.Core({
    transitions: {
      default: Overlap
    }
  });
})();
//CustomTransition.js
import Highway from './highway.module.js';
 class Overlap extends Highway.Transition {
  in({ from, to, trigger, done }) {      
      from.style.position = 'absolute';
      to.style.animation = "overlapTest 1s";            
      let timeremove = setTimeout(() => from.remove(), 1200)      
      done();
  }
  out({ from, done }) {
    done();    
  }
}
export default Overlap;
/*style.css*/
@keyframes overlapTest {
    from{ transform: translateX(100vw); }
    to{transform: translateX(0); }    
}

I have make a demo with a transition of 1s => https://eloquent-heisenberg-124835.netlify.app/

I have also make a repo : https://github.com/Totokoutonio/Highway_Overlap

Thx for helping!

Anthodpnt commented 4 years ago

Hey @Totokoutonio

Highway doesn't manage the cancellation of the click event on the links during a transition. That's something we may add in the future. However, you can access all the links used by Highway with H.links and you also have access to the H.attach and H.detach methods.

I believe this is enough to cancel the click event or call the e.preventDefault method on each one of them during the transition before enabling it again when the transition is done. We'll see what we can do as soon as possible to add a fix in the library for this use case but in the meantime you have enough elements to create your own solution with the events available in the Highway.

Keep us in touch when you'll have found a clean solution. That may contribute to the improvement of the library and that may help other members of the community :).

Best regards, Anthodpnt

ThaoD5 commented 4 years ago

Hey @Totokoutonio , just to add another option that I use myself to avoid clicking on another element when navigation already started. Here's what I do :

This should prevent clicking on elements while a navigation is running.

Totokoutonio commented 4 years ago

Hey @Anthodpnt and @ThaoD5 thanks for your fast answer!

I have use the option with the pointer-events: none in my CustomTransition file. And it's look fine. I set a timer to match the duration of the transition (1s in the demo) and I remove the class in this timer.

//CustomTransition.js
import Highway from './highway.module.js';

class Overlap extends Highway.Transition {
  in({ from, to, done }) {      
      let el = document.querySelector('body');
      el.classList.add('transitions-active');      
      to.style.animation = "overlapTest 1s";            
      function remover(){
          from.remove();
          el.classList.remove('transitions-active');
      }
      let timeremove = setTimeout( remover, 1000)      
      done();
  }
  out({ from, done }) {
    done();
  }
}

export default Overlap;

But do you think using a timer is a good approach?

Thanks for your prompt help and for Highway!

ThaoD5 commented 4 years ago

For a cleaner approach, I would advise to use an event like 'transitionend on the element that has your transition animation, that way you're not playing with settimeout, but this is a very personal approach. :)

Glad that solution worked for you !

Totokoutonio commented 4 years ago

@ThaoD5 I have use animationend and it works well!

//CustomTransition.js
import Highway from './highway.module.js';

class Overlap extends Highway.Transition {
  in({ from, to, done }) {      
      let el = document.querySelector('body');
      el.classList.add('transitions-active');      
      to.style.animation = "overlapTest 1s";
      to.addEventListener('animationend', () => {
        from.remove();
        el.classList.remove('transitions-active');
      });
      done();
  }
  out({ from, done }) {
    done();
  }
}

export default Overlap;
/*style.css*/
@keyframes overlapTest {
    from{ transform: translateX(100vw); }    
    to{ transform: translateX(0); }    
}

body.transitions-active{
    pointer-events: none;
}

Thanks a lot, I close this issue.