我有一个问题,似乎是由改变两个<divs>
在其父级中的位置引起的,基本上是重新排序它们。
两个div都有一个transition
css规则,如下所示:
-webkit-transition: all .2s ease-in-out;
-moz-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
当我调用这个来交换位置时:
function swapElements(first, second) {
$(first).insertBefore(second);
}
first
元素没有被浏览器应用的过渡效果,在与前一个/第二个元素交换后,它基本上没有动画。
这是一个问题,因为我正在听转换结束回调,然后在<div>
中做更多的工作(初始化一个画廊):
if (Modernizr.csstransitions) {
$(roomColumn).one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
if (!gallery.hasClass('slick-initialized')) {
$(gallery).slick({
lazyLoad: 'progressive',
slidesToShow: 1,
slidesToScroll: 1,
autoplay: false,
dots: false,
adaptiveHeight: false
});
}
});
}
因为浏览器没有为这个元素做过渡,事件.one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function (){});
永远不会为这个<div>
触发,所以图库没有为它初始化。
有没有人知道是什么导致了这种行为?
编辑:这是一个非常粗糙的JS小提琴。您需要展开输出窗口,以便有四列。
如您所见,单击前三个中的任何一个都会产生动画效果,单击行中最后一个<div>
(标记为LAST ROOM
)不会产生任何动画。
有趣的是,如果我把<div>
交换代码包装在setTimeout
调用中,它工作得很好,这似乎是一个定时问题,显然我不想依靠这作为一个hack的修复,虽然,它也导致div跳到不希望的地方。
出现问题是因为在交换之后,您还删除了原始类(用于小框显示)并替换为新类(用于较大的显示)。这三种情况都发生在一个阻塞调用中。无论何时添加一个元素,浏览器都需要触发一个流,但它不会在每一步之后触发一个流,因为这样做会影响性能。所以,回流发生在最后(在执行removeClass和addClass之后),因此只有一个带有新类的元素被绘制在屏幕上——没有状态改变,所以也没有过渡。
为了克服这个问题,我们需要强制UA在交换之后但在类更改之前触发回流/重绘。这可以通过两种方式完成 -一种是强制类更改语句进入不同的函数调用(使用setTimeout
的匿名函数),另一种是通过强制UA计算clientHeight
等(它们强制重新绘制,因为它们只能计算实际高度)。
Demo with setTimeout | Demo with clientHeight