【问题标题】:CSS3 transition abort causes ugly animationCSS3 过渡中止导致丑陋的动画
【发布时间】:2015-01-08 02:36:17
【问题描述】:

我正在使用 CSS3 步骤转换来动画精灵从一种状态到另一种状态。

当我开始一个动画时,它一次显示一帧,并具有很好的过渡效果(单击example 中的“显示/隐藏”链接)。但是,当第一个过渡仍在运行时触发第二个过渡时,帧位置会丢失,并且看起来它滚动到另一侧而不是保持逐帧动画(单击 example 中的“触发错误” )。

.tree {
    width: 26px; /* one frame */
    height: 31px; /* frame height */
    background-image: url("http://rolandschuetz.at/docs/tree-animated.png");
    background-repeat: no-repeat;
    background-position: -234px 0; /* last frame */
    transition: background-position .8s steps(10); /* this triggers the CSS3 step transition */
}
.tree-hidden {
    background-position: 26px 0; /* clear, before first frame */
}

有没有办法强制动画正常工作,即使它中止了旧动画?

PS:请不要尝试通过仅用于演示目的的触发错误按钮来“修复”。真正的问题是由快速的用户交互触发的,应该立即得到反馈。

【问题讨论】:

  • 您是否按下了“触发错误”链接?如果是这样,在哪个浏览器中?
  • 是的,但是因为它是你的动画,所以你必须解释那里有什么丑陋的地方,这样我才能找到丑陋的部分
  • 当我按下树大小时,会变小并从左到右滚动
  • 是的,它不应该滚动。这应该是一个逐帧增长的动画,就像您按下显示/隐藏链接时所看到的那样。
  • 我已经弄清楚这里发生了什么,我会画一个图表并在下面给出答案。

标签: css


【解决方案1】:

Updated code

检查这是否对您有帮助。

HTML

<div class="outer"> <!--Added this div-->
  <div class="tree"></div>        
</div>

CSS:

.outer {
    width: 26px;
    border: 1px solid grey;
}
.tree {
    width: 26px; /* one frame */
    height: 31px;

    background-image: url("http://rolandschuetz.at/docs/tree-animated.png");
    background-repeat: no-repeat;
    background-position: -234px 0; /* last frame */
    -webkit-transform: scale(1);
    margin: 0 auto;    
    /*Changed transition*/
    -webkit-transition: all .8s;
       -moz-transition: all .8s;
        -ms-transition: all .8s;
            transition: all .8s;
}
.tree-hidden {
    /* background-position: 26px 0; */ /* empty, before first frame */
    width: 0;
    -webkit-transform: scale(0);
}

【讨论】:

  • 这是个好主意,但它看起来不如逐帧动画。
【解决方案2】:

问题来了:

有 10 帧,因此您使用 10 步来制作动画。 所以基本上,CSS 为 tree-active 踩树 10 次,为 tree-not-active 踩 10 次。

如果您在第 8 帧停用树,它将按预期反转动画方向,但它会步进 10 次而不是 8 次。这使它看起来像是在滑动,但实际上它只是停在 10 个间隔位置为 8 帧。

这有意义吗?

对于这种类型的动画,您最好使用 JS 解决方案,它知道当前帧位置并正确计算所需的步骤。

我希望这会有所帮助!

【讨论】:

  • 是的,这就是问题所在。如果有纯 CSS 的解决方案,那就太酷了。
  • @RolandSchütz 不幸的是,我不这么认为。我可以用最少的 JS 做一个快速的小提琴,但我认为 JS 是去这里的方式。 CSS 不存储数据,因此它无法知道当前位置(您需要重新计算所需的步骤)。
  • 由于我正在运行大约 70 个具有不同转换持续时间的那些,因此非硬件加速版本可能会导致性能问题。
  • 如果中断动画将从最后一个过渡的终点开始,则不是最佳的错误方式更好的解决方案。所以树会突然改变它的大小,但不会有奇怪的滚动效果。
  • @RolandSchütz 那么,像这样吗? jsfiddle.net/pavkr/Lc31fjt6/19我只是给了它交替的过渡时间。
【解决方案3】:

正如 ThePav 所说,没有办法让 CSS 知道它的状态。因此,即使从上一个转换的中间开始,它也将始终使用 steps(10) 函数,并且背景位置需要更少的步骤。

解决这个问题的最简单方法(不容易,但最简单)是设置一个平行的 z-index 过渡,设置方式与背景位置相同。如果您可以给他们任何 z-index,那么 z-index 将从 0 变为 10。

.tree {
    background-position: -234px 0; 
    z-index: 0;
    transition: all .8s steps(10); // will apply both to bkg-position and z-index
}
.tree-hidden {
    background-position: 26px 0; 
    z-index: 10;
}

然后,z-index 属性用作正在进行转换的指示器,您可以在脚本中相应地设置步骤函数以更改类。

即获取z-index的值,并将其设置为transitionTimingFunction: 'steps (' + zindexval + ')'

(您也可以使用 background-position 属性来做到这一点,但要困难得多。)

代码是

function change () {
    var tree = $('.tree').eq(0);
    if (tree.hasClass('tree-hidden')) {
        var where = tree.css("zIndex");
        if (where != 10) {
            tree.css({transitionTimingFunction: 'steps(' + where + ')'})
        } else {
            tree.css({transitionTimingFunction: ''})
        }
        tree.removeClass('tree-hidden');
    } else {
        tree.css({transitionTimingFunction: ''})
        tree.addClass('tree-hidden');
    }

}

demo

【讨论】:

  • 并行 z-index 过渡是什么意思?谢谢:)
  • 添加了更多细节 :-)
  • 感谢您的所有工作。可悲的是,这在我的浏览器中不起作用。我想无论如何我都会找到一个不同的解决方案,因为代码太臃肿了。我将简单地在js中保留一个计时器。
  • 好的,别担心。祝你好运:-)
【解决方案4】:

使用 transitionend 等待删除“树隐藏”类。否则你无法通过其他方式解决。

$('.show-hide').click(function() {
    !$('.tree').hasClass('tree-hidden') &&
    $('.tree').addClass('tree-hidden').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
        $('.tree').removeClass('tree-hidden')
    });
});

更新

 $('.show-hide').click(function(evt) {
    //JUST CHECK ALREADY HAS HIDDEN CLASS
    if($('.tree').hasClass('tree-hidden'))
     //you can event prevent defaul if there is no another work
     evt.preventDefault();
     return false;
    $('.tree').addClass('tree-hidden').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
        $('.tree').removeClass('tree-hidden')
    });
});     

通过这种方式,在动画完成之前事务不会中断,无论点击更多时间。

css 事务回退

如果你需要后备,你可以使用下面的代码

function supportsTransitions() {
   var b = document.body || document.documentElement,
    s = b.style,
    p = 'transition';

    if (typeof s[p] == 'string') { return true; }

    // Tests for vendor specific prop
    var v = ['Moz', 'webkit', 'Webkit', 'Khtml', 'O', 'ms'];
    p = p.charAt(0).toUpperCase() + p.substr(1);

    for (var i=0; i<v.length; i++) {
        if (typeof s[v[i] + p] == 'string') { return true; }
    }

    return false;
}

【讨论】:

  • 这不会给用户立即反馈,并且可能会使他感到困惑。所以他点击了三下,然后出现了很多无用的动画。
  • 检查交易是否还在进行中,我已经为您更新了
猜你喜欢
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-12
  • 2023-03-18
  • 2012-06-01
相关资源
最近更新 更多