你可以让它以你期望的自然方式工作 - 使用显示 - 但你必须限制浏览器才能让它工作,使用 Javascript 或其他人建议的一个花哨的技巧,一个标签内有另一个标签。我不关心内部标签,因为它使 CSS 和尺寸进一步复杂化,所以这里是 Javascript 解决方案:
https://jsfiddle.net/b9chris/hweyecu4/17/
从一个盒子开始,如:
<div id="box" class="hidden">Lorem</div>
一个隐藏的盒子。
div.hidden {
display: none;
}
#box {
transition: opacity 1s;
}
我们将使用在相关 q/a 中找到的技巧,检查 offsetHeight 以立即限制浏览器:
https://stackoverflow.com/a/16575811/176877
首先,将上述技巧形式化的库:
$.fn.noTrnsn = function () {
return this.each(function (i, tag) {
tag.style.transition = 'none';
});
};
$.fn.resumeTrnsn = function () {
return this.each(function (i, tag) {
tag.offsetHeight;
tag.style.transition = null;
});
};
接下来,我们将使用它来显示一个框,并将其淡入:
$('#button').on('click', function() {
var tag = $('#box');
if (tag.hasClass('hidden'))
tag.noTrnsn().removeClass('hidden')
.css({ opacity: 0 })
.resumeTrnsn().css({ opacity: 1 });
else
tag.css({ opacity: 0 });
});
这会使盒子淡入淡出。所以,.noTrnsn()
关闭转换,然后我们删除类,它从hidden
翻转到它的默认值,. 然后我们将不透明度设置为 0 以准备淡入。现在我们已经设置好舞台,我们重新打开过渡,使用. 最后,通过将不透明度设置为 1 来开始过渡。display
none
block
.resumeTrnsn()
如果没有库,对显示的更改和对不透明度的更改都会给我们带来不希望的结果。如果我们简单地删除库调用,我们根本不会得到任何转换。
请注意,上面没有在淡出动画结束时再次将 display 设置为 none。不过我们可以变得更漂亮。让我们用一个从 0 开始淡入并在高度上增长的东西来做。
想要!
https://jsfiddle.net/b9chris/hweyecu4/22/
#box {
transition: height 1s, opacity 1s;
}
我们现在正在转换高度和不透明度。请注意,我们没有设置高度,这意味着它是默认值,auto
. 按照惯例,这不能转换 - 从自动移动到像素值(如 0)将使您没有转换。我们将使用库和另一种库方法来解决这个问题:
$.fn.wait = function (time, fn) {
if (time)
this.delay(time);
if (!fn)
return this;
var _this = this;
return this.queue(function (n) {
fn.call(_this);
n();
});
};
这是一种方便的方法,可以让我们参与 jQuery 现有的 fx/animation 队列,而不需要任何现在在 jQuery 3.x 中排除的动画框架。我不打算解释 jQuery 是如何工作的,但我只想说,jQuery 提供的.queue()
管道.stop()
可以帮助我们防止动画相互踩踏。
让我们为滑下效果制作动画。
$('#button').on('click', function() {
var tag = $('#box');
if (tag.hasClass('hidden')) {
// Open it
// Measure it
tag.stop().noTrnsn().removeClass('hidden').css({
opacity: 0, height: 'auto'
});
var h = tag.height();
tag.css({ height: 0 }).resumeTrnsn()
// Animate it
.css({ opacity: 1, height: h })
.wait(1000, function() {
tag.css({ height: 'auto' });
});
} else {
// Close it
// Measure it
var h = tag.noTrnsn().height();
tag.stop().css({ height: h })
.resumeTrnsn()
// Animate it
.css({ opacity: 0, height: 0 })
.wait(1000, function() {
tag.addClass('hidden');
});
}
});
这段代码首先检查#box
它是否是隐藏的,检查它的类。但是它使用wait()
库调用完成了更多工作,通过hidden
在滑出/淡出动画的末尾添加类,如果它实际上是隐藏的,您希望找到它 - 这是上面更简单的示例无法做到的。这恰好也启用了一遍又一遍地显示/隐藏元素,这是前面示例中的一个错误,因为隐藏的类从未恢复。
您还可以看到在调用 CSS 和类更改之后.noTrnsn()
通常会为动画设置舞台,包括进行测量,例如在调用之前测量最终高度#box
而不向用户显示的最终高度.resumeTrnsn()
,并从完整设置中对其进行动画处理阶段到其目标 CSS 值。
旧答案
https://jsfiddle.net/b9chris/hweyecu4/1/
你可以让它在点击时转换:
function toggleTransition() {
var el = $("div.box1");
if (el.length) {
el[0].className = "box";
el.stop().css({maxWidth: 10000}).animate({maxWidth: 10001}, 2000, function() {
el[0].className = "box hidden";
});
} else {
el = $("div.box");
el[0].className = "box";
el.stop().css({maxWidth: 10001}).animate({maxWidth: 10000}, 50, function() {
el[0].className = "box box1";
});
}
return el;
}
someTag.click(toggleTransition);
CSS是你猜的:
.hidden {
display: none;
}
.box {
width: 100px;
height: 100px;
background-color: blue;
color: yellow;
font-size: 18px;
left: 20px;
top: 20px;
position: absolute;
-webkit-transform-origin: 0 50%;
transform-origin: 0 50%;
-webkit-transform: scale(.2);
transform: scale(.2);
-webkit-transition: transform 2s;
transition: transform 2s;
}
.box1{
-webkit-transform: scale(1);
transform: scale(1);
}
关键是限制显示属性。通过移除隐藏的类,然后等待 50 毫秒,然后通过添加的类开始转换,我们让它出现,然后像我们想要的那样展开,而不是它只是在没有任何动画的情况下闪烁到屏幕上。类似的情况发生在另一个方面,除了我们等到动画结束后再应用隐藏。
注意:我在.animate(maxWidth)
这里滥用以避免setTimeout
竞争条件。setTimeout
当您或其他人在不知情的情况下拾取代码时,会很快引入隐藏的错误。.animate()
很容易被杀死.stop()
。我只是用它在标准 fx 队列上放置 50 毫秒或 2000 毫秒的延迟,在此基础上构建的其他编码器很容易找到/解决。