可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have written a small amount of code to try and replicate jQuery's .fadeIn()
and .fadeOut()
functions using CSS transitions to look better on touch devices.
Ideally I'd like to avoid using a library so that I can write exactly what I want, and as a learning exercise.
fadeOut
works well.
The idea for fadeIn
is to use CSS3 transitions to adjust the opacity of an element, after which the element will be set to display:block;
(using is-hidden
class) to ensure it's not still clickable or covering something beneath it.
fadeIn
is not working though. I think it is due to adding the is-animating
class at the same time as removing the is-hiding
class. The transitionEnd event never fires because a transition does not occur:
function fadeIn (elem, fn) {
var $elem = $(elem);
$elem.addClass('is-animating');
$elem.removeClass('is-hidden');
$elem.removeClass('is-hiding');
$elem.on(transitionEndEvent, function () {
$elem.removeClass('is-animating');
if (typeof fn === 'function') {
fn();
}
});
};
And the CSS
.is-animating {
@include transition(all 2000ms);
}
.is-hiding {
// Will transition
@include opacity(0);
}
.is-hidden {
// Won't transition
display: none;
}
Here's the code: CodePen link
Update: I have found what I'd describe as a hack, but that works very well: CSS3 replacement for jQuery.fadeIn and fadeOut
Working code after this fix: Fixed
A solution without setTimeout
would be very valuable though.
回答1:
i don't know what you really wanna achieve but if your using css3 your using a modern browser. in that case pure css & javascript is a better solution.
it's all about how you write the css transition.
here is the js code
var div=document.getElementsByTagName('div')[0],
btn=document.getElementsByTagName('button')[0];
div.addEventListener('click',function(){
this.classList.add('hide');
},false);
div.addEventListener('webkitTransitionEnd',function(e){
console.log(e.propertyName);
},false);
btn.addEventListener('click',function(e){
div.classList.toggle('hide');
},false);
css code
div{
width:200px;height:200px;
opacity:1;
overflow:hidden;
line-height:200px;
text-align:center;
background-color:green;
-webkit-transition:opacity 700ms ease 300ms,height 300ms ease ;
}
div.hide{
height:0px;
opacity:0;
-webkit-transition:opacity 700ms ease,height 300ms ease 700ms;
/*add the various -moz -ms .. prefixes for more support*/
}
and the html
some text
<div>click here</div>
some text
<button>toggle</button>
here is an example.
http://jsfiddle.net/qQM5F/1/
回答2:
Alternative solution using Keyframes
js
var div=document.getElementsByTagName('div')[0],
btn=document.getElementsByTagName('button')[0];
div.addEventListener('webkitAnimationEnd',function(e){
div.style.display=div.classList.contains('hide')?'none':'';
},false);
btn.addEventListener('click',function(e){
div.style.display='';
div.classList.toggle('hide');
},false);
css3
div{
background-color:green;
-webkit-animation:x 700ms ease 0ms 1 normal running;/*normal*/
opacity:1;
}
div.hide{
-webkit-animation:x 700ms ease 0ms 1 reverse running;/*reverse*/
opacity:0;
}
@-webkit-keyframes x{
0%{opacity:0;}
100%{opacity:1;}
}
example
http://jsfiddle.net/qQM5F/8/
here is a prototype
Object.defineProperty(HTMLElement.prototype,'toggleOpacity',{value:function(){
function check(e){
this.style.display=this.classList.contains('hide')?'none':'';
this.removeEventListener('webkitAnimationEnd',check,false);// clean up
}
this.addEventListener('webkitAnimationEnd',check,false);
this.style.display='';
this.classList.toggle('hide');
},writable:false,enumerable:false});
css
.fade{
-webkit-animation:x 700ms ease 0 1 normal;
opacity:1;
}
.fade.hide{
-webkit-animation:x 700ms ease 0 1 reverse;
opacity:0;
}
@-webkit-keyframes x{
0%{opacity:0}
100%{opacity:1}
}
usage
the element you need to fade needs a class fade
then toggle it with
element.toggleOpacity();
example
http://jsfiddle.net/qQM5F/9/
回答3:
You may want to consider a couple of plugins that might take care of what you want:
jQuery.transition.js retrofits the existing jQuery animation methods to use CSS transitions in browsers that support them.
Transit adds a transition
function you can use to define your own transitions. It uses jQuery's effect queue, so you can queue up the changed display
value to run after opacity
has finished transitioning.
回答4:
I have managed to fix this by doing something that feels unnatural and hacky:
function fadeIn (elem, fn) {
var $elem = $(elem);
$elem.addClass('is-animating');
$elem.removeClass('is-hidden');
// Smelly, setTimeout fix
setTimeout(function () {
$elem.removeClass('is-hiding');
}, 0);
$elem.on(transitionEndEvent, function () {
$elem.removeClass('is-animating');
if (typeof fn === 'function') {
fn();
}
});
};
Adding the setTimeout
function to the class that contains the transition-able property fixes the issue.
Working code here: Codepen fixed code