Reputation: 2197
What I'm trying to do is to have on hover transition or animation (can be triggered via javascript with onmouseover
or onmouseenter
) that will also be reversible (so the opposite animation should happen on mouse leave) but
It's hard to describe without showing so please check this codepen that is pretty close to what I'm trying to achieve: http://codepen.io/anon/pen/xROOqO
There are two problems here:
transitionend
handler, so I would need to update both css and js to update transition timeIs this even possible using css transitions (perhaps keyframes animation) or should I stick to setting timers in javascript and leave out the delay from css?
Upvotes: 0
Views: 595
Reputation: 5134
Not sure if what I'm going to present is simpler, but it seems to address some of your issues, and matches my taste.
The main idea is to admit that the problem is complicated due to multiple states, and address it using a state machine. This allows for a declarative approach like this one:
const TRANSITIONS = {
'small-inside' : {
'transitionend' : 'big-inside',
'mouseover' : 'small-inside',
'mouseout' : 'small-outside',
},
'small-outside' : {
'transitionend' : 'small-outside',
'mouseover' : 'small-inside',
'mouseout' : 'small-outside',
},
'big-inside' : {
'transitionend' : 'big-inside',
'mouseover' : 'big-inside',
'mouseout' : 'big-outside',
},
'big-outside' : {
'transitionend' : 'small-outside',
'mouseover' : 'big-inside',
'mouseout' : 'big-outside',
},
}
And quite simple handling of events:
function step(e){
box.className = TRANSITIONS[box.className][e.type];
}
box.addEventListener('transitionend', step);
box.addEventListener('mouseover', step);
box.addEventListener('mouseout', step);
Another insight is that you can specify the delay using CSS transition-delay:3s
property:
div.small-inside,
div.big-inside {
width: 300px;
}
div.small-outside,
div.big-outside {
width: 150px;
}
div.big-outside {
transition-delay:3s;
}
The proof of concept is here: http://codepen.io/anon/pen/pNNMWM.
What I do not like about my solution is that it assumes that the initial state is small-outside
while actually the mouse pointer could be well located within the div when the page loads.
You've mentioned ability to trigger state transitions manually from JS. I believe this is possible as long as you keep track of two separate boolean variables: "is mouse inside?" and "does js asked to grow?". You can not mix them into a one state and expect correct "counting". As you see I already have 2*2=4
states because I'm trying to keep track of {small,big}x{inside,outside}
- one could imagine extending it to {small,big}x{inside,outside}x{js-open,js-close}
in similar manner, with some extra "events" like 'open' and 'close'.
Upvotes: 2