交换<div>位置导致 CSS3 转换效果丢失



我有一个问题,似乎是由改变两个<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

相关内容

  • 没有找到相关文章

最新更新