元素动画变换旋转

85

如何在jQuery的.animate()中旋转一个元素?我当前正在使用下面的代码行,它可以正确地动画化透明度,但是它支持CSS3变换吗?

$(element).animate({
   opacity: 0.25,
   MozTransform: 'rotate(-' + -amount + 'deg)',
   transform: 'rotate(' + -amount + 'deg)'
});

1
有一个jQuery插件可以动画化CSS变换。适用于Firefox,Chrome,Safari,Opera和Internet Explorer。https://github.com/puppybits/QTransform - puppybits
在同一主题的搜索中结束了,下载了插件;它可以正常工作,但是它与我制作的另一个插件中的这个指令发生了冲突:$("#"+self.id).css("transform", "scale(1)"); 我将这行代码更改为:elem.style[$.cssProps.transform] = val+'%'; 更改后的代码如下:如果 ( isNaN(val) ) elem.style[$.cssProps.transform] = val; else elem.style[$.cssProps.transform] = val+'%'; 我认为这不需要进一步解释。 - sergio0983
7个回答

97
据我所知,基本动画无法对非数字的CSS属性进行动画效果。
我认为您可以使用 step 函数和适当的 CSS3 变换来完成此操作,以符合用户浏览器的要求。对于不同浏览器,CSS3 变换需要一些技巧(例如在 IE6 中,您需要使用 Matrix 过滤器)。 编辑: 下面是一个在 WebKit 浏览器(Chrome,Safari)中有效的示例: http://jsfiddle.net/ryleyb/ERRmd/ 如果您只想支持 IE9,则可以使用 transform 而不是 -webkit-transform,而使用 -moz-transform 则支持 FireFox。
使用的技巧是对我们不关心的 CSS 属性(text-indent)进行动画处理,然后使用其值在 step 函数中执行旋转。
$('#foo').animate(
..
step: function(now,fx) {
  $(this).css('-webkit-transform','rotate('+now+'deg)'); 
}
...

这是一个痛苦的解决方案,无论是在代码维护还是速度方面。在进行“transform”时,请忘记jQuery,请查看我的解决方案。 - Dyin
如果您有一个值是在不断变化的,而不是一个固定的值如何旋转呢? - edonbajrami

80

Ryley的回答很好,但我的元素中有文字。为了使文本随其他内容一起旋转,我使用了border-spacing属性而不是text-indent。

另外,为了澄清一点,在元素的样式中,设置初始值:

#foo {
    border-spacing: 0px;
}

然后在动画块中,您的最终值为:

$('#foo').animate({  borderSpacing: -90 }, {
    step: function(now,fx) {
      $(this).css('transform','rotate('+now+'deg)');  
    },
    duration:'slow'
},'linear');
在我的情况下,它逆时针旋转了90度。 这里是实时演示

3
如果您没有在其他地方使用z-index,那么使用它也是一个不错的选择。但是,您不会想要将其设为负值。 - Sherzod
4
你可能也想添加-ms-和-o-扩展(请参见http://css3please.com/)。 - Joram van den Boezem
你怎么同时为额外的属性添加动画效果? - MadTurki
5
jQuery实际上足够聪明,可以为您添加所有的-moz-、-webkit-等前缀,因此您可以简化这段代码。非常好的回答。+1 - Octopus
现代jQuery非常棒! - atonyc
显示剩余3条评论

51
在我看来,与CSS3中的transition相比,jQuery的animate有点被过度使用了,因为它可以在任何2D或3D属性上执行动画。此外,我担心只让浏览器忘记了名为JavaScript的层可能会导致节省CPU资源 - 特别是当你希望用动画爆发时。因此,我喜欢在样式定义中使用动画,因为你用JavaScript定义功能。你注入的JavaScript越多,以后遇到的问题就越多。
你需要做的就是对你想要进行动画的元素使用addClass,在其中设置一个具有CSS transition 属性的类。你只需“激活”动画,它将实现在纯演示层上

.js

// with jQuery
$("#element").addClass("Animate");

// without jQuery library
document.getElementById("element").className += "Animate";

你可以通过jQuery 删除一个类 或者 不使用库来删除一个类

.css

#element{
    color      : white;
}

#element.Animate{
    transition        : .4s linear;
    color             : red;
    /** 
     * Not that ugly as the JavaScript approach.
     * Easy to maintain, the most portable solution.
     */
    -webkit-transform : rotate(90deg);
}

.html

<span id="element">
    Text
</span>

这是大多数使用情况下快速便捷的解决方案。
当我想要实现不同的样式(替代CSS属性)并希望通过全局0.5秒动画实时更改样式时,我也会使用这个。我向BODY添加一个新类,同时使用类似以下形式的替代CSS:.js
$("BODY").addClass("Alternative");

.css

BODY.Alternative #element{
    color      : blue;
    transition : .5s linear;
}

这样,您就可以在不加载不同CSS文件的情况下,使用动画应用不同的样式。您只需要使用JavaScript来设置一个class即可。

1
这没问题,但它仅限于支持CSS3过渡效果的浏览器(http://caniuse.com/#search=transition)。因此,没有IE8或IE9。这是一个相当大的市场份额要放弃。 - Ryley
11
你提到的12%百分比是用户数量。IE8或IE9用户不到5%。这并不是一个很大的部分需要放弃,因为我们仍然在谈论的是表现层而不是功能。大约5%的访问者将看不到你的3D动画。此外,如果浏览器(IE)不支持“过渡”(transition),那么它肯定也不会支持你的变换(transformations)。 - Dyin
这并不完全正确 - transform 在IE9上得到了支持。 但我同意,放弃IE8并不是最大的用户群。 - Ryley
2
@Dyin 这不是一个固定的12%,它取决于您的目标受众。根据Google Analytics,我公司50%的用户使用IE8。关键是要了解您的受众。话虽如此:干得好,伙计!这个答案比前两个都好多了。你真是个“精英中的钻石”。 - Ziggy
2
这也没有考虑到动态旋转值。 - Yuschick
显示剩余3条评论

19

在Ryley和atonyc的答案中,可以不必使用真正的CSS属性,例如text-indexborder-spacing,而是可以指定一个虚假的CSS属性,例如rotationmy-awesome-property。最好使用一些未来不会成为实际CSS属性的东西。

此外,有人问如何同时动画其他内容。这可以像往常一样完成,但请记住step函数会针对每个动画属性进行调用,因此您需要检查您的属性,如下所示:

$('#foo').animate(
    {
        opacity: 0.5,
        width: "100px",
        height: "100px",
        myRotationProperty: 45
    },
    {
        step: function(now, tween) {
            if (tween.prop === "myRotationProperty") {
                $(this).css('-webkit-transform','rotate('+now+'deg)');
                $(this).css('-moz-transform','rotate('+now+'deg)'); 
                // add Opera, MS etc. variants
                $(this).css('transform','rotate('+now+'deg)');  
            }
        }
    });

(注意:我找不到jQuery文档中“Tween”对象的文档;从动画文档页面中,有一个链接指向http://api.jquery.com/Types#Tween,但这个部分似乎不存在。你可以在这里的Github上找到Tween原型代码)。


我的旋转属性是什么?这是您定义的自定义内容吗?而“现在”取决于它。 - Muhammad Umer
@MuhammadUmer - 是的,myRotationProperty是一些自定义的东西,一个虚构的CSS属性。now是step回调函数的第一个参数,指定此步骤中属性值的更改。 - skagedal
那么你在 CSS 中也初始化了这个属性吗?或者你可以只将它放在动画中,这样它就会被设置为零。 - Muhammad Umer

9

只需使用CSS过渡效果:

$(element).css( { transition: "transform 0.5s",
                  transform:  "rotate(" + amount + "deg)" } );

setTimeout( function() { $(element).css( { transition: "none" } ) }, 500 );

作为示例,我将动画的持续时间设置为0.5秒。
请注意,在动画结束后(500毫秒),使用setTimeout来删除transition CSS属性。
为了可读性,我省略了供应商前缀。
当然,此解决方案需要浏览器支持过渡效果。

谢谢,对我有用。你还忘了在括号后面加上一个分号。 - Devin Carpenter
@Sorrow123444 很高兴它对你有用。我修复了缺失的分号,谢谢。 - Paolo

3
我偶然发现这篇文章,想在jQuery中使用CSS变换进行无限循环动画。这个方法对我很有效。但是我不确定它有多专业。
function progressAnim(e) {
    var ang = 0;

    setInterval(function () {
        ang += 3;
        e.css({'transition': 'all 0.01s linear',
        'transform': 'rotate(' + ang + 'deg)'});
    }, 10);
}

使用示例:

var animated = $('#elem');
progressAnim(animated)

1
//this should allow you to replica an animation effect for any css property, even //properties //that transform animation jQuery plugins do not allow

            function twistMyElem(){
                var ball = $('#form');
                document.getElementById('form').style.zIndex = 1;
                ball.animate({ zIndex : 360},{
                    step: function(now,fx){
                        ball.css("transform","rotateY(" + now + "deg)");
                    },duration:3000
                }, 'linear');
            } 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接