Pracuję nad utworzeniem rotacji kompatybilnej z różnymi przeglądarkami (ie9 +) i mam następujący kod w pliku 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 i HTML są naprawdę proste i tylko do celów demonstracyjnych:
.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>
Rotacja działa podczas używania, .css()
ale nie podczas używania .animate()
; dlaczego tak jest i czy istnieje sposób, aby to naprawić?
Dzięki.
jquery
css
rotation
jquery-animate
Francuz
źródło
źródło
step
wywołanie zwrotne), ale część „dlaczego tak jest” jest całkiem jasna.Odpowiedzi:
Transformacje CSS nie są jeszcze możliwe do animacji za pomocą jQuery. Możesz zrobić coś takiego:
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)' }); } }); }
Możesz przeczytać więcej o step-callback tutaj: http://api.jquery.com/animate/#step
http://jsfiddle.net/UB2XR/23/
Przy okazji: nie musisz poprzedzać transformacji css3 jQuery 1.7+
Aktualizacja
Możesz owinąć to w wtyczkę jQuery, aby trochę ułatwić sobie życie:
$.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
Aktualizacja2
I zoptymalizowany go trochę, aby kolejność
easing
,duration
icomplete
nieistotne.$.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); }); };
Aktualizacja 2.1.0
Podziękowania dla Matteo, który zauważył problem z
this
-context in the complete-callback
. Jeśli naprawiono to przez powiązanie wywołania zwrotnego zjQuery.proxy
każdym węzłem.Dodałem edycję do kodu wcześniej z Update 2 .
Aktualizacja 2.2.0
Jest to możliwa modyfikacja, jeśli chcesz wykonać coś takiego, jak przełączanie rotacji w przód iw tył. Po prostu dodałem parametr start do funkcji i zastąpiłem tę linię:
$({deg: start}).animate({deg: angle}, args);
Jeśli ktoś wie, jak uczynić to bardziej ogólnym dla wszystkich przypadków użycia, niezależnie od tego, czy chce ustawić stopień początkowy, proszę dokonać odpowiedniej edycji.
Użycie ... jest dość proste!
Zwykle masz dwa sposoby na osiągnięcie pożądanego rezultatu. Najpierw jednak spójrzmy na argumenty:
jQuery.fn.animateRotate(angle, duration, easing, complete)
Z wyjątkiem „angle”, wszystkie są opcjonalne i
jQuery.fn.animate
zastępują domyślne właściwości:duration: 400 easing: "swing" complete: function () {}
1
Ten sposób jest krótki, ale wydaje się nieco niejasny, im więcej argumentów przekazujemy.
$(node).animateRotate(90); $(node).animateRotate(90, function () {}); $(node).animateRotate(90, 1337, 'linear', function () {});
2nd
Wolę używać obiektów, jeśli jest więcej niż trzy argumenty, więc ta składnia jest moją ulubioną:
$(node).animateRotate(90, { duration: 1337, easing: 'linear', complete: function () {}, step: function () {} });
źródło
this
braku odwołania do obiektu DOM jest to, że kontekst jest ustawiony na obiekt, któryanimate()
został wywołany, w tym przypadku{deg: 0}
jest ustawiony na kontekst. Możesz to naprawić, zmieniając kontekst każdej funkcji zwrotnej za pomocąapply()
/call()
lub$.proxy()
(jak pokazał @yckart). Oto moje rozwiązanie, aby naprawić WSZYSTKIE wywołania zwrotne i zezwolić na rotację 3D: jsfiddle.net/TrevinAvery/P5J4V/440
stopni za każdym razem nie doprowadzi do oczekiwanego zachowania, więc musisz zainicjować z bieżącą wartością obrotu. Jak to zrobić, wyjaśniono tutaj: stackoverflow.com/a/11840120/61818Dzięki yckart! Wielki wkład. Rozwinąłem nieco twoją wtyczkę. Dodano startAngle dla pełnej kontroli i CSS w różnych przeglądarkach.
$.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 }); }); };
źródło
jquery-1.8+
!Tranzyt jQuery prawdopodobnie ułatwi Ci życie, jeśli masz do czynienia z animacjami CSS3 za pośrednictwem jQuery.
EDYTUJ marzec 2014 (ponieważ moja rada była stale głosowana w górę iw dół, odkąd ją opublikowałem)
Pozwól, że wyjaśnię, dlaczego początkowo sugerowałem powyżej wtyczkę:
Aktualizacja
DOM
na każdym kroku (tj.$.animate
) Nie jest idealna pod względem wydajności. Działa, ale najprawdopodobniej będzie wolniejsze niż czyste przejścia CSS3 lub animacje CSS3 .Dzieje się tak głównie dlatego, że przeglądarka ma szansę przemyśleć przyszłość, jeśli wskażesz, jak będzie wyglądać przejście od początku do końca.
Aby to zrobić, możesz na przykład utworzyć klasę CSS dla każdego stanu przejścia i używać jQuery tylko do przełączania stanu animacji.
Zwykle jest to całkiem fajne, ponieważ możesz modyfikować animacje wraz z resztą swojego CSS, zamiast mieszać je z logiką biznesową:
// 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'); });
Jeśli którykolwiek z parametrów transformacji jest dynamiczny, możesz oczywiście zamiast tego użyć atrybutu 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)' }); });
Bardziej szczegółowe informacje o przejściach CSS3 na MDN .
JEDNAK Jest kilka innych rzeczy, o których należy pamiętać, a wszystko to może być nieco skomplikowane, jeśli masz złożone animacje, łańcuchy itp., A jQuery Transit po prostu wykonuje wszystkie trudne elementy pod maską:
$('.eye').transit({ rotate: '90deg'}); // easy huh ?
źródło
Aby wykonać tę przeglądarkę, w tym IE7 +, musisz rozszerzyć wtyczkę o macierz transformacji. Ponieważ prefiks dostawcy jest wykonywany w jQuery od jquery-1.8 +, zostawię to dla
transform
właściwości.$.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); } }); };
Uwaga: parametry
options
istartAngle
są opcjonalne, jeśli potrzebujesz tylko ustawićstartAngle
użycie{}
lubnull
dlaoptions
.Przykładowe użycie:
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);
Zobacz także to jsfiddle, aby zobaczyć demo.
Aktualizacja : Możesz teraz również przekazać
extra: {}
opcje. Umożliwi to jednoczesne wykonywanie innych animacji. Na przykład:obj.animateRotate(90, {extra: {marginLeft: '100px', opacity: 0.5}});
Spowoduje to obrócenie elementu o 90 stopni i przesunięcie go w prawo o 100 pikseli i uczyni go półprzezroczystym w tym samym czasie podczas animacji.
źródło
ms
,o
,webkit
,moz
, aby zapewnić wykrywanie prawidłowo. Skrzypce również zostały zaktualizowane do wersji 12.to jest moje rozwiązanie:
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); };
możesz go użyć w domyślnym animowanym pliku 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' });
źródło
Inna odpowiedź, ponieważ jQuery.transit nie jest kompatybilny z jQuery.easing. To rozwiązanie jest dostępne jako rozszerzenie jQuery. Jest bardziej ogólny, rotacja to szczególny przypadek:
$.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)"); } });
Użycie jest tak proste, jak:
$(element).animateStep({from: 0, to: 90, step: $.fn.rotate});
źródło
Bez wtyczek i przeglądarki z 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);
źródło