Estoy trabajando en la creación de un cross-browser compatible rotación (ie9+) y tengo el siguiente código en un 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); 
}

El CSS y HTML son muy simples y sólo para la demostración:

.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>

La rotación funciona cuando se usa .css() pero no cuando se utiliza .animate(); ¿por qué es eso, y es hay alguna manera de solucionarlo?

Gracias.

  • jQuery no tiene idea de cómo animar la rotación. Tal vez el uso de transiciones CSS3?
  • excepto que IE9 no son compatibles con CSS3 Transiciones.
  • Voy a upvote para el «fix it» parte (puede que al final de la implementación de un step de devolución de llamada), pero el «por qué es que» es bastante claro.
  • sí, ya sé: el objetivo de IE9 apoyo será a usar setInterval y llamar a la DoRotate función varias veces.
  • Por CIERTO, ya he señalado que el CSS papel de Lija de biblioteca en mi respuesta a tu otra pregunta, que es un relleno para las Transiciones de la CSS en IE. Puede que desee probar.
  • Miré el papel de Lija, pero prefiero evitar una dependencia, es por eso que estoy mirando para conseguir que este código funcione.
  • Justo lo suficiente. La razón por la que vale la pena es porque no se trataría únicamente de una dependencia para IE9, y otros navegadores sería capaz de utilizar real CSS transforma (con toda la representación beneficios que van con eso). Si usted escribe un manual de animación jQuery, usted estará castigando a los otros navegadores de IE, la falta de apoyo. Y usted tendría una dependencia de todos modos (en su propio código jQuery). Si está seguro de que preferiría no utilizarlo, que es bastante justo, pero es una buena herramienta.
  • es tu pregunta? A continuación, se marca como lo que es 😉
  • Yo estaba comiendo. Muchas gracias!!

InformationsquelleAutor frenchie | 2013-03-03

7 Comentarios

  1. 215

    CSS-Transforma no son posibles para animar con jQuery, sin embargo. Usted puede hacer algo como esto:

    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)'
                });
            }
        });
    }

    Usted puede leer más sobre el paso de devolución de llamada aquí: http://api.jquery.com/animate/#step

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

    Y, por cierto: no es necesario el prefijo css3 transforma con jQuery 1.7+

    Actualización

    Puede ajustar este en un jQuery-plugin para hacer su vida un poco más fácil:

    $.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

    Update2

    He optimizado un poco para hacer el pedido de easing, duration y complete insignificante.

    $.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);
      });
    };

    Actualización 2.1

    Gracias a matteo quien señaló que un problema con el this-contexto en el completo-callback. Si se fija por unión la devolución de llamada con jQuery.proxy en cada nodo.

    He añadido a la edición del código antes de Actualización 2.

    Actualización 2.2

    Esta es una posible modificación si quieres hacer algo como cambiar la rotación de ida y vuelta. Simplemente he añadido un parámetro de inicio a la función y se sustituye esta línea:

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

    Si alguien sabe cómo hacer esto más genérico para todos los casos de uso, si quieren o no para establecer un inicio de grado, por favor, hacer la edición correspondiente.


    El Uso…es muy simple!

    Principalmente que haya dos formas de llegar al resultado deseado. Pero en el primero, echemos un vistazo a los argumentos:

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

    A excepción de «ángulo» son todos ellos opcionales y el retroceso en el valor predeterminado jQuery.fn.animate-propiedades:

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

    1er

    Este camino es corto, pero se ve un poco confuso la más argumentos que le pasamos.

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

    Yo prefiero usar objetos, si hay más de tres argumentos, por lo que esta sintaxis es mi favorit:

    $(node).animateRotate(90, {
      duration: 1337,
      easing: 'linear',
      complete: function () {},
      step: function () {}
    });
    • (+ prefijos, ofc 😉 )
    • Se puede poner esto en un violín?
    • Estoy en el iPhone, no hay posibilidad desde jsFiddle actualizado su editor 😉 sin embargo, voy a preparar una bandeja para usted…
    • ok, es solo que estoy confundido en cuanto a cómo usarlo: $(‘#SomeDiv)…
    • Se me olvidaba algo! Actualizado mi respuesta ahora… he Aquí un ejemplo: jsbin.com/ofagog/2/edit
    • Ahora entiendo el concepto de la función de paso! Gracias!!!!
    • ok, demasiado tarde, pero si usted no entiende una respuesta just ask 😉 estamos aquí para ayudar!
    • no hay problema, creo que tu solución es impresionante; sólo se hizo una edición para incluir la duración de control. Gracias de nuevo por tu ayuda!
    • sí, buen punto 🙂 he hecho algunos cambios, tal vez se le ayuda para futuros usos.
    • Ok, muy bueno: que es EL plugin para cross-browser (IE9+) CSS3 rotación!! Se puede afirmar que: se construyen. Buen trabajo!
    • Hice este plugin de trabajar para IE7+ utilizando la transformación de la matriz, también he mejorado los parámetros. Usted realmente no desea pasar justo y exactamente esos parámetros.
    • ¿Por qué no una clase css solución?
    • Hey que hay algo mal, al menos con el «update 2» versión. Cuando la función completa se ejecuta, «this» dentro de lo que se supone será el elemento de dom, pero es algún otro objeto. ¿Alguna idea de cómo solucionar este problema?
    • jsfiddle.net/matteosistisette/P5J4V
    • ¿Cuáles son $.speed() y $.style()? No puedo encontrar ninguna documentación sobre estas dos funciones.
    • maneja los argumentos que pasa en jQuery.fn.animate, hace que el orden insignificante. (Así que usted puede pasar en duration, easing, complete o easing, duration, complete o lo que sea). jQuery.style es básicamente el mismo que el ya conocido jQuery.fn.css, sin embargo, se trabaja directamente sobre el nodo en lugar de un jQuery-objeto. (jQuery.style no es un alias para jQuery.fn.css pero se llama en ella.)
    • Lo siento por la respuesta tardía y gracias por la prueba. Yo necesitaba un poco de tiempo de trastear el tema, pero lo conseguí! fiddle.jshell.net/P5J4V/43 Por cierto, he mencionado su investigación en mi anwer 🙂
    • La razón this no se refiere a un objeto DOM es porque el contexto se establece en el objeto animate() fue llamado, en este caso {deg: 0} se establece en el contexto. Usted puede solucionar este problema, cambie el contexto de cada función de devolución de llamada con apply()/call() o $.proxy() (como @yckart ha demostrado). Aquí está mi solución para solucionar TODAS las incidencias y permitir la rotación 3d: jsfiddle.net/TrevinAvery/P5J4V/44
    • Genial! Oh, tengo que entrar al menos 15 caracteres. Que es realmente genial!
    • Gran trabajo, me gusta la forma en que maneja la promesa-las devoluciones de llamada. Sin embargo, me di cuenta de un problema de lógica. Actualmente se aplican los estilos con CSS3-sólo las propiedades, que no son compatibles con los navegadores más antiguos, para que nada se mueva alrededor. Hacer otro «tipo de cadena/objeto»de la prueba y la aplicación de los estilos, dependiendo de esta comprobación, debería solucionar el problema.
    • Si desea animar el mismo elemento de una y otra, a partir de 0 grados cada vez que no va a conducir a la esperada, por lo que necesita para inicializar con el actual valor de rotación. Cómo hacer que se explica aquí: stackoverflow.com/a/11840120/61818
    • Puede alguien explicar el $({deg: 0}).animate({deg: angle} parte de mí. No entiendo cómo iba a hacer de 0 a ángulo. Funciona incluso ángulo es negativo. 1) ¿Cómo se sabe que debe hacer deg++ o deg– 2) ¿cómo $({deg:0}) no devuelve un error, pensé $() es un selector que busque un elemento que se ajustan a los criterios, y los criterios que tiene que ser de una cierta sintaxis. Esto es como la magia para mí
    • wow esto es terrible, ¿cómo sobre la gira de vuelta a cero? Oh, instante?
    • es un ejemplo y nada de copy & paste, desconsiderado… Solo copia y código, modificar y cambiar. Si usted necesita ayuda en algún momento de crear una nueva pregunta.
    • La unión con proxy dentro del bucle es muy caro, así que es mejor usar bind fuera o llamada/aplicar.
    • Buen hallazgo. Pasando el actual a afirmar elemento como argumento para la complete de devolución de llamada, que no puede realizarse fuera del bucle. Uno podría fácilmente caer, si no es necesario. Nota, esto no es una solución completa, que lo utilizan como startingpoint para otro.
    • Para mí, este método se restablece la posición de inicio de la a a 0deg. Así que si quiero girar un elemento que tiene un valor distinto de cero ángulo de inicio no funciona. Es alguien más con el mismo problema?
    • Eso es debido a la deg: 0 parte en esas funciones. Fácilmente podría adoptar mi código y el cambio que 0 valor a cualquier otro número.

  2. 17

    Gracias yckart! Gran aporte. Yo concretarse su complemento un poco más. Añadido startAngle para el control total y cross-browser css.

    $.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
            });
        });
    };
    • jQuery añade la necesaria proveedor prefijo automáticamente, así que no hay necesidad de esto!
    • +1 para la plataforma de la cruz. Gran. @yckart : la función de prefijo de no trabajo para mí en este caso.
    • Lo jQuery-versión usas? blog.jquery.com/2012/08/09/jquery-1-8-released
    • la versión 1.7.1.
    • Como se puede ver en el artículo de jquery-blog, la auto-prefijo es sólo desde jquery-1.8+!
    • Gracias por la sugerencia !
    • Hola, ¿ esta solución funciona para IE8 así? Si no, ¿qué solución se puede utilizar para IE8, acabo de ver una de las opciones como jquery rotate plugin
    • Esta solución no funciona cuando se establece algunos datos para el elemento después de la animación. Así que usted puede continuar la animación después de algún tiempo. Así que he tomado la solución y combinado con @yckart solución para hacerla compatible con todos los navegadores.

  3. 10

    jQuery tránsito probablemente hará su vida más fácil si usted está tratando con CSS3 animaciones a través de jQuery.

    EDICIÓN de Marzo de 2014
    (porque mi consejo ha sido constantemente arriba y abajo votado desde que lo publicado)

    Permítanme explicar por qué inicialmente estaba insinuando hacia el plugin de arriba:

    La actualización de la DOM en cada paso (es decir,$.animate ) no es ideal en términos de rendimiento.
    Funciona, pero probablemente sea más lento de lo puro Transiciones CSS3 o Animaciones CSS3.

    Esto es principalmente debido a que el navegador recibe una oportunidad para pensar en el futuro si le indican lo que la transición se va a parecer a la de principio a fin.

    Para hacerlo, por ejemplo, puede crear una clase CSS para cada estado de la transición y sólo el uso de jQuery para cambiar el estado de animación.

    Este es generalmente muy cuidada como se puede ajustar usted animaciones junto con el resto de tu CSS en lugar de mezclarse con su lógica de negocio:

    //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'); });

    Si alguno de la transformación de los parámetros de la dinámica que se puede usar el atributo de estilo en su lugar:

    $('.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)'
        }); 
    });

    Un montón de información más detallada sobre Transiciones CSS3 en MDN.

    Sin EMBARGO Hay algunas otras cosas a tener en cuenta y todo esto puede ser un poco difícil si usted tiene animaciones complejas, encadenamiento etc. y jQuery Tránsito sólo hace todo el complicado bits bajo el capó:

    $('.eye').transit({ rotate: '90deg'}); //easy huh ?
    • Esto no es una respuesta…
  4. 3

    Para hacer esto con todos los navegadores incluyendo IE7+, deberá expandir el plugin con una matriz de transformación. Desde el proveedor prefijo está hecho en jQuery de jquery-1.8+ voy a dejar que se fuera para la transform propiedad.

    $.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);
    }
    });
    };

    Nota: Los parámetros options y startAngle son opcionales, si sólo necesita establecer startAngle uso {} o null para options.

    Ejemplo de uso:

    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);

    Ver también este jsfiddle para una demo.

    Actualización: ahora, también puede pasar extra: {} en las opciones. Así usted será capaz de ejecutar otras animaciones de forma simultánea. Por ejemplo:

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

    Esto hará rotar el elemento de 90 grados, y lo mueve a la derecha con 100px y hacerla semi-transparente, todo al mismo tiempo durante la animación.

    • Que el violín no funciona en Chrome, en absoluto.
    • O IE9, no en Firefox, pero sólo firefox.
    • Bueno por lo que funciona ahora en Chrome, Firefox e IE10. Puede usted probar IE9, Liam? El problema era que la transformación de la propiedad no estaba definida para Chrome y el IE, por lo tanto, la secuencia de comandos de pensamiento que la transformación de la propiedad no estaba disponible. Por lo tanto, he cambiado el script para incluir todos los prefijos: ms, o, webkit, moz para asegurar la detección correctamente. El violín se actualiza a la v12.
  5. 2

    esta es mi solución:

    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);
    };

    a continuación, se puede utilizar en el valor predeterminado animar 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' });
  6. 1

    Otra respuesta, porque jQuery.el tránsito no es compatible con jQuery.la flexibilización. Esta solución se presenta como una extensión de jQuery. Es más genérico, la rotación es un caso específico:

    $.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)");
    }
    });

    El uso es tan simple como:

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

    Sin plugin de navegador cruz con 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);

Dejar respuesta

Please enter your comment!
Please enter your name here