jquery.animate ()를 사용한 CSS 회전 크로스 브라우저


81

브라우저 간 호환 회전 (ie9 +)을 만드는 중이며 jsfiddle에 다음 코드가 있습니다.

$(document).ready(function () { 
    DoRotate(30);
    AnimateRotate(30);
});

function DoRotate(d) {

    $("#MyDiv1").css({
          '-moz-transform':'rotate('+d+'deg)',
          '-webkit-transform':'rotate('+d+'deg)',
          '-o-transform':'rotate('+d+'deg)',
          '-ms-transform':'rotate('+d+'deg)',
          'transform': 'rotate('+d+'deg)'
     });  
}

function AnimateRotate(d) {

        $("#MyDiv2").animate({
          '-moz-transform':'rotate('+d+'deg)',
          '-webkit-transform':'rotate('+d+'deg)',
          '-o-transform':'rotate('+d+'deg)',
          '-ms-transform':'rotate('+d+'deg)',
          'transform':'rotate('+d+'deg)'
     }, 1000); 
}

CSS와 HTML은 정말 간단하고 데모 용입니다.

.SomeDiv{
    width:50px;
    height:50px;       
    margin:50px 50px;
    background-color: red;}

<div id="MyDiv1" class="SomeDiv">test</div>
<div id="MyDiv2" class="SomeDiv">test</div>

회전은 사용할 때 작동 .css()하지만 사용할 때는 작동 하지 않습니다 .animate(). 그 이유는 무엇이며 고칠 수있는 방법이 있습니까?

감사.


jQuery는 회전 애니메이션 방법을 모릅니다. 아마도 CSS3 전환을 사용합니까?
John Dvorak 2013 년

1
@JanDvorak-IE9가 CSS3 전환을 지원하지 않는 것을 제외하고.
Spudley 2013 년

1
"고정"부분에 대해 찬성표를 던지지 만 ( step콜백 을 구현하게 될 수도 있음 ) "왜 그럴까요"부분은 매우 명확합니다.
John Dvorak 2013 년

@Spudley : 예, 알아요 : IE9 지원의 목표는 setInterval을 사용하고 DoRotate 함수를 여러 번 호출하는 것입니다.
frenchie 2013 년

BTW-IE의 CSS Transitions에 대한 polyfill 인 다른 질문에 대한 답변에서 CSS Sandpaper 라이브러리를 이미 지적했습니다. 시도해 볼 수 있습니다.
Spudley 2013 년

답변:


222

CSS 변환은 아직 jQuery로 애니메이션 할 수 없습니다. 다음과 같이 할 수 있습니다.

function AnimateRotate(angle) {
    // caching the object for performance reasons
    var $elem = $('#MyDiv2');

    // we use a pseudo object for the animation
    // (starts from `0` to `angle`), you can name it as you want
    $({deg: 0}).animate({deg: angle}, {
        duration: 2000,
        step: function(now) {
            // in the step-callback (that is fired each step of the animation),
            // you can use the `now` paramter which contains the current
            // animation-position (`0` up to `angle`)
            $elem.css({
                transform: 'rotate(' + now + 'deg)'
            });
        }
    });
}

단계 콜백에 대한 자세한 내용은 http://api.jquery.com/animate/#step에서 확인할 수 있습니다.

http://jsfiddle.net/UB2XR/23/

그리고 btw : jQuery 1.7+를 사용하여 css3 변환을 접두사로 지정할 필요가 없습니다.

최신 정보

이것을 jQuery-plugin으로 감싸서 삶을 좀 더 쉽게 만들 수 있습니다.

$.fn.animateRotate = function(angle, duration, easing, complete) {
  return this.each(function() {
    var $elem = $(this);

    $({deg: 0}).animate({deg: angle}, {
      duration: duration,
      easing: easing,
      step: function(now) {
        $elem.css({
           transform: 'rotate(' + now + 'deg)'
         });
      },
      complete: complete || $.noop
    });
  });
};

$('#MyDiv2').animateRotate(90);

http://jsbin.com/ofagog/2/edit

업데이트 2

나는 순서를 easing, duration그리고 complete중요하지 않게 만들기 위해 약간 최적화했습니다 .

$.fn.animateRotate = function(angle, duration, easing, complete) {
  var args = $.speed(duration, easing, complete);
  var step = args.step;
  return this.each(function(i, e) {
    args.complete = $.proxy(args.complete, e);
    args.step = function(now) {
      $.style(e, 'transform', 'rotate(' + now + 'deg)');
      if (step) return step.apply(e, arguments);
    };

    $({deg: 0}).animate({deg: angle}, args);
  });
};

2.1 업데이트

전체 에서 -context 관련 문제를 지적한 matteo 에게 감사드립니다 . 콜백 을 각 노드에 바인딩 하여 수정 한 경우 .thiscallbackjQuery.proxy

업데이트 2 에서 이전에 코드에 에디션을 추가했습니다 .

2.2 업데이트

이것은 회전을 앞뒤로 토글하는 것과 같은 작업을 수행하려는 경우 가능한 수정입니다. 함수에 시작 매개 변수를 추가하고 다음 줄을 바꿨습니다.

$({deg: start}).animate({deg: angle}, args);

시작 정도를 설정하든 원하지 않든 모든 사용 사례에 대해 이것을 더 일반적으로 만드는 방법을 아는 사람이 있으면 적절하게 편집하십시오.


사용법 은 아주 간단합니다!

주로 원하는 결과에 도달하는 두 가지 방법이 있습니다. 하지만 먼저 인수를 살펴 보겠습니다.

jQuery.fn.animateRotate(angle, duration, easing, complete)

"각도"를 제외하고 모두 선택 사항이며 기본 jQuery.fn.animate속성 으로 대체됩니다 .

duration: 400
easing: "swing"
complete: function () {}

1 위

이 방법은 짧은 방법이지만 더 많은 인수를 전달할수록 약간 불분명 해 보입니다.

$(node).animateRotate(90);
$(node).animateRotate(90, function () {});
$(node).animateRotate(90, 1337, 'linear', function () {});

2 차

세 개 이상의 인수가있는 경우 객체를 사용하는 것을 선호하므로이 구문이 가장 좋습니다.

$(node).animateRotate(90, {
  duration: 1337,
  easing: 'linear',
  complete: function () {},
  step: function () {}
});

4
이것을 바이올린에 넣을 수 있습니까?
frenchie 2013 년

4
좋아, 아주 멋지다 : 브라우저 간 (IE9 +) CSS3 회전을위한 플러그인입니다 !! 당신은 그것을 주장 할 수 있습니다. 잘 하셨어요!
frenchie 2013 년

1
@matteo 답변이 늦어서 죄송합니다. 테스트 해 주셔서 감사합니다. 문제를 해결하는 데 약간의 시간이 필요했지만 해냈습니다! fiddle.jshell.net/P5J4V/43 그건 그렇고, 나는 내 답변에서 당신의 조사를 언급했습니다 :)
yckart

1
@matteo thisDOM 객체를 참조하지 않는 이유 는 컨텍스트가 객체 animate()로 설정되어 있기 때문 입니다.이 경우 {deg: 0}컨텍스트로 설정됩니다. apply()/ call()또는 $.proxy()(@yckart에 표시된대로)를 사용 하여 각 콜백 함수의 컨텍스트를 변경하여이 문제를 해결할 수 있습니다 . 다음은 모든 콜백을 수정하고 3D 회전을 허용하는 솔루션입니다. jsfiddle.net/TrevinAvery/P5J4V/44
Trevin Avery

1
동일한 요소를 반복해서 애니메이션하려면 0매번 각도 에서 시작해 도 예상되는 동작이 발생하지 않으므로 현재 회전 값으로 초기화해야합니다. 여기에서 설명되는 작업을 수행하는 방법 : stackoverflow.com/a/11840120/61818
Asbjørn Ulsberg

17

감사합니다 yckart! 큰 공헌. 플러그인을 좀 더 구체화했습니다. 모든 권한 및 브라우저 간 CSS를 위해 startAngle을 추가했습니다.

$.fn.animateRotate = function(startAngle, endAngle, duration, easing, complete){
    return this.each(function(){
        var elem = $(this);

        $({deg: startAngle}).animate({deg: endAngle}, {
            duration: duration,
            easing: easing,
            step: function(now){
                elem.css({
                  '-moz-transform':'rotate('+now+'deg)',
                  '-webkit-transform':'rotate('+now+'deg)',
                  '-o-transform':'rotate('+now+'deg)',
                  '-ms-transform':'rotate('+now+'deg)',
                  'transform':'rotate('+now+'deg)'
                });
            },
            complete: complete || $.noop
        });
    });
};

5
jQuery는 필요한 공급 업체 접두사를 자동으로 추가하므로 필요하지 않습니다!
yckart 2013-07-23

크로스 플랫폼의 경우 +1. 큰. @yckart :이 경우 자동 접두사가 작동하지 않습니다.
lsmpascal

@PaxMaximinus 어떤 jQuery 버전을 사용하십니까? blog.jquery.com/2012/08/09/jquery-1-8 출시
yckart 2013-08-27

@yckart : 1.7.1 버전.
lsmpascal

1
@PaxMaximinus jquery-blog의 기사에서 볼 수 있듯이 자동 접두사는 jquery-1.8+!
yckart

10

jQuery를 통해 CSS3 애니메이션을 다루는 경우 jQuery 전송 은 아마도 삶을 더 쉽게 만들어 줄 것입니다.

2014 년 3 월 수정 (내 조언이 게시 된 이후 지속적으로 투표를 받았기 때문에)

내가 처음에 위의 플러그인을 암시하는 이유를 설명하겠습니다.

DOM각 단계 (예 :)에서 를 업데이트하는 $.animate것은 성능 측면에서 이상적이지 않습니다. 작동하지만 순수한 CSS3 전환 이나 CSS3 애니메이션 보다 느릴 것 입니다.

이는 주로 브라우저가 처음부터 끝까지 전환이 어떻게 보일지 표시하면 미리 생각할 기회를 갖기 때문입니다.

예를 들어 전환의 각 상태에 대해 CSS 클래스를 만들고 jQuery 만 사용하여 애니메이션 상태를 전환 할 수 있습니다.

이것은 일반적으로 비즈니스 로직과 혼합하는 대신 나머지 CSS와 함께 애니메이션을 조정할 수 있으므로 매우 깔끔합니다.

// initial state
.eye {
   -webkit-transform: rotate(45deg);
   -moz-transform: rotate(45deg);
   transform: rotate(45deg);
   // etc.

   // transition settings
   -webkit-transition: -webkit-transform 1s linear 0.2s;
   -moz-transition: -moz-transform 1s linear 0.2s;
   transition: transform 1s linear 0.2s;
   // etc.
}

// open state    
.eye.open {

   transform: rotate(90deg);
}

// Javascript
$('.eye').on('click', function () { $(this).addClass('open'); });

변환 매개 변수가 동적이면 당연히 style 속성을 대신 사용할 수 있습니다.

$('.eye').on('click', function () { 
    $(this).css({ 
        -webkit-transition: '-webkit-transform 1s ease-in',
        -moz-transition: '-moz-transform 1s ease-in',
        // ...

        // note that jQuery will vendor prefix the transform property automatically
        transform: 'rotate(' + (Math.random()*45+45).toFixed(3) + 'deg)'
    }); 
});

MDN의 CSS3 전환에 대한 자세한 정보 .

그러나 명심해야 할 몇 가지 다른 사항이 있으며 복잡한 애니메이션, 체인 등이 있고 jQuery Transit 이 모든 까다로운 작업을 내부적으로 수행 하는 경우이 모든 것이 약간 까다로울 수 있습니다 .

$('.eye').transit({ rotate: '90deg'}); // easy huh ?

3

IE7 +를 포함하여이 크로스 브라우저를 수행하려면 변환 매트릭스로 플러그인을 확장해야합니다. 공급 업체 접두사는 jquery-1.8 +의 jQuery에서 수행되므로 transform속성에 대해서는 생략하겠습니다 .

$.fn.animateRotate = function(endAngle, options, startAngle)
{
    return this.each(function()
    {
        var elem = $(this), rad, costheta, sintheta, matrixValues, noTransform = !('transform' in this.style || 'webkitTransform' in this.style || 'msTransform' in this.style || 'mozTransform' in this.style || 'oTransform' in this.style),
            anims = {}, animsEnd = {};
        if(typeof options !== 'object')
        {
            options = {};
        }
        else if(typeof options.extra === 'object')
        {
            anims = options.extra;
            animsEnd = options.extra;
        }
        anims.deg = startAngle;
        animsEnd.deg = endAngle;
        options.step = function(now, fx)
        {
            if(fx.prop === 'deg')
            {
                if(noTransform)
                {
                    rad = now * (Math.PI * 2 / 360);
                    costheta = Math.cos(rad);
                    sintheta = Math.sin(rad);
                    matrixValues = 'M11=' + costheta + ', M12=-'+ sintheta +', M21='+ sintheta +', M22='+ costheta;
                    $('body').append('Test ' + matrixValues + '<br />');
                    elem.css({
                        'filter': 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\'auto expand\','+matrixValues+')',
                        '-ms-filter': 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\'auto expand\','+matrixValues+')'
                    });
                }
                else
                {
                    elem.css({
                        //webkitTransform: 'rotate('+now+'deg)',
                        //mozTransform: 'rotate('+now+'deg)',
                        //msTransform: 'rotate('+now+'deg)',
                        //oTransform: 'rotate('+now+'deg)',
                        transform: 'rotate('+now+'deg)'
                    });
                }
            }
        };
        if(startAngle)
        {
            $(anims).animate(animsEnd, options);
        }
        else
        {
            elem.animate(animsEnd, options);
        }
    });
};

참고 : 또는에 대한 사용 만 설정해야하는 경우 options및 매개 변수 startAngle는 선택 사항 입니다 .startAngle{}nulloptions

사용 예 :

var obj = $(document.createElement('div'));
obj.on("click", function(){
    obj.stop().animateRotate(180, {
        duration: 250,
        complete: function()
        {
            obj.animateRotate(0, {
                duration: 250
            });
        }
    });
});
obj.text('Click me!');
obj.css({cursor: 'pointer', position: 'absolute'});
$('body').append(obj);

데모 는이 jsfiddle 을 참조하십시오 .

업데이트 : 이제 extra: {}옵션을 전달할 수도 있습니다. 이렇게하면 다른 애니메이션을 동시에 실행할 수 있습니다. 예를 들면 :

obj.animateRotate(90, {extra: {marginLeft: '100px', opacity: 0.5}});

이렇게하면 요소가 90도 회전하고 100px로 오른쪽으로 이동하고 애니메이션 중에 동시에 반투명하게됩니다.


또는 IE9는 Firefox에서 작동하지만 firefox에서만 가능합니다.
Liam

이제 Chrome, Firefox 및 IE10에서 작동합니다. IE9, Liam을 테스트 할 수 있습니까? 문제는 Chrome 및 IE에 대해 transform 속성이 정의되지 않았기 때문에 스크립트에서 transform 속성을 사용할 수 없다고 생각했습니다. 따라서, 나는 모든 접두사를 포함 할 수있는 스크립트를 변경 : ms, o, webkit, moz정확하게 탐지를 보장 할 수 있습니다. 바이올린도 v12로 업데이트됩니다.
Yeti 2014

2

이것은 내 해결책입니다.

var matrixRegex = /(?:matrix\(|\s*,\s*)([-+]?[0-9]*\.?[0-9]+(?:[e][-+]?[0-9]+)?)/gi;

var getMatches = function(string, regex) {
    regex || (regex = matrixRegex);
    var matches = [];
    var match;
    while (match = regex.exec(string)) {
        matches.push(match[1]);
    }
    return matches;
};

$.cssHooks['rotation'] = {
    get: function(elem) {
        var $elem = $(elem);
        var matrix = getMatches($elem.css('transform'));
        if (matrix.length != 6) {
            return 0;
        }
        return Math.atan2(parseFloat(matrix[1]), parseFloat(matrix[0])) * (180/Math.PI);
    }, 
    set: function(elem, val){
        var $elem = $(elem);
        var deg = parseFloat(val);
        if (!isNaN(deg)) {
            $elem.css({ transform: 'rotate(' + deg + 'deg)' });
        }
    }
};
$.cssNumber.rotation = true;
$.fx.step.rotation = function(fx) {
    $.cssHooks.rotation.set(fx.elem, fx.now + fx.unit);
};

그런 다음 기본 애니메이션 fkt에서 사용할 수 있습니다.

//rotate to 90 deg cw
$('selector').animate({ rotation: 90 });

//rotate to -90 deg ccw
$('selector').animate({ rotation: -90 });

//rotate 90 deg cw from current rotation
$('selector').animate({ rotation: '+=90' });

//rotate 90 deg ccw from current rotation
$('selector').animate({ rotation: '-=90' });

1

또 다른 대답은 jQuery.transit가 jQuery.easing과 호환되지 않기 때문입니다. 이 솔루션은 jQuery 확장으로 제공됩니다. 더 일반적이며 회전은 특정 경우입니다.

$.fn.extend({
    animateStep: function(options) {
        return this.each(function() {
            var elementOptions = $.extend({}, options, {step: options.step.bind($(this))});
            $({x: options.from}).animate({x: options.to}, elementOptions);
        });
    },
    rotate: function(value) {
        return this.css("transform", "rotate(" + value + "deg)");
    }
});

사용법은 다음과 같이 간단합니다.

$(element).animateStep({from: 0, to: 90, step: $.fn.rotate});

0

setInterval을 사용하는 플러그인 크로스 브라우저가없는 경우 :

                        function rotatePic() {
                            jQuery({deg: 0}).animate(
                               {deg: 360},  
                               {duration: 3000, easing : 'linear', 
                                 step: function(now, fx){
                                   jQuery("#id").css({
                                      '-moz-transform':'rotate('+now+'deg)',
                                      '-webkit-transform':'rotate('+now+'deg)',
                                      '-o-transform':'rotate('+now+'deg)',
                                      '-ms-transform':'rotate('+now+'deg)',
                                      'transform':'rotate('+now+'deg)'
                                  });
                              }
                            });
                        }

                        var sec = 3;
                        rotatePic();
                        var timerInterval = setInterval(function() {
                            rotatePic();
                            sec+=3;
                            if (sec > 30) {
                                clearInterval(timerInterval);
                            }
                        }, 3000);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.