Jquery.animate () के साथ सीएसएस रोटेशन क्रॉस ब्राउज़र


82

मैं एक क्रॉस-ब्राउज़र संगत रोटेशन (यानी 9) बनाने पर काम कर रहा हूं और मेरे पास 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 के संक्रमण का उपयोग करें?
जॉन ड्वोरक

1
@JDDvorak - सिवाय इसके कि IE9 CSS3 के बदलावों का समर्थन नहीं करता है।
स्पडली

1
मैं "इसे ठीक कर" भाग के लिए upvote हूँ (आप एक stepकॉलबैक लागू करने को समाप्त कर सकते हैं ), लेकिन "क्यों वह है" भाग बहुत स्पष्ट है।
जॉन ड्वोरक

@Spudley: हाँ, मुझे पता है: IE9 समर्थन के लिए लक्ष्य सेटइंटरवाल का उपयोग करना और कई बार DoRotate फ़ंक्शन को कॉल करना होगा।
फ्रेंच

BTW - मैंने पहले से ही अपने दूसरे प्रश्न पर मेरे जवाब में सीएसएस सैंडपेपर लाइब्रेरी की ओर इशारा किया है, जो IE में सीएसएस संक्रमणों के लिए एक पॉलीफ़िल है। आप इसे आज़माना चाह सकते हैं।
स्पडली

जवाबों:


223

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- प्लगइन में लपेट सकते हैं:

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

अद्यतन २

मैं इसके बारे में आदेश बनाने के लिए एक सा अनुकूलित 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

धन्यवाद करने के लिए Matteo जो के साथ एक समस्या का उल्लेख किया thiscomplete- में -context callback। यदि यह द्वारा तय बंधन के साथ कॉलबैक jQuery.proxyप्रत्येक नोड पर।

मैंने अपडेट 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
क्या आप इसे एक बेला में डाल सकते हैं?
फ्रेंच

4
ठीक है, बहुत अच्छा: कि क्रॉस-ब्राउज़र (IE9 +) CSS3 के रोटेशन के लिए प्लगइन है !! आप दावा कर सकते हैं कि: आपने इसे बनाया है। अच्छा काम!
फ्रेंच

1
@matteo देर से प्रतिक्रिया और आपके परीक्षण के लिए धन्यवाद के लिए क्षमा करें। मुझे इस मुद्दे को हल करने के लिए थोड़ा समय चाहिए था, लेकिन मुझे मिल गया! fiddle.jshell.net/P5J4V/43 वैसे, मैंने अपनी जाँच का उल्लेख मेरे
awer में किया है

1
@matteo कारण thisDOM ऑब्जेक्ट को संदर्भित नहीं करता है क्योंकि संदर्भ ऑब्जेक्ट पर सेट किया गया animate()था, इस मामले {deg: 0}में संदर्भ पर सेट है। आप प्रत्येक कॉलबैक फ़ंक्शन के संदर्भ को apply()/ call()या के साथ बदल सकते हैं $.proxy()(जैसा कि @yckart ने दिखाया है)। यहाँ सभी कॉलबैक को ठीक करने और 3 डी रोटेशन की अनुमति देने के लिए मेरा समाधान है: jsfiddle.net/TrevinAvery/P5J4V/44
ट्रेविन एवरी

1
यदि आप एक ही तत्व को 0बार-बार प्राप्त करना चाहते हैं, तो हर बार डिग्री शुरू करने से अपेक्षित व्यवहार नहीं होगा, इसलिए आपको वर्तमान रोटेशन मूल्य के साथ आरंभ करने की आवश्यकता है। यहाँ कैसे समझाया जाता है: stackoverflow.com/a/11840120/61818
Asbjørn Ulsberg

17

धन्यवाद याकार्ट! महान योगदान। मैंने आपके प्लग इन को थोड़ा और बढ़ा दिया। पूर्ण नियंत्रण और क्रॉस-ब्राउज़र सीएसएस के लिए 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 स्वचालित रूप से आवश्यक विक्रेता उपसर्ग जोड़ता है, इसलिए इसके लिए कोई आवश्यकता नहीं है!
जकार्ट

पार मंच के लिए +1। महान। @yart: ऑटो उपसर्ग इस मामले में मेरे लिए काम नहीं करता है।
lsmpascal

@PaxMaximinus आप किस jQuery- संस्करण का उपयोग करते हैं? blog.jquery.com/2012/08/09/jquery-1-8-released
yckart

@yart: 1.7.1 संस्करण।
lsmpascal

1
@PaxMaximinus जैसा कि आप लेख में jquery- ब्लॉग से देख सकते हैं, ऑटो-प्रीफ़िक्सिंग अभी से है jquery-1.8+!
yckart

10

यदि आप CSS3 एनिमेशन के साथ jQuery के साथ काम कर रहे हैं तो jQuery पारगमन शायद आपके जीवन को आसान बना देगा।

EDIT मार्च 2014 (क्योंकि मेरी सलाह लगातार पोस्ट अप और डाउन वोट की गई है क्योंकि मैंने इसे पोस्ट किया है)

मुझे समझाएं कि मैं शुरू में ऊपर प्लगइन की ओर क्यों इशारा कर रहा था:

DOMप्रत्येक चरण पर अद्यतन (यानी $.animate) प्रदर्शन के मामले में आदर्श नहीं है। यह काम करता है, लेकिन शुद्ध CSS3 संक्रमण या CSS3 एनिमेशन की तुलना में शायद सबसे धीमा होगा ।

यह मुख्य रूप से है क्योंकि ब्राउज़र को आगे सोचने का मौका मिलता है यदि आप इंगित करते हैं कि संक्रमण शुरू से अंत तक कैसा दिखने वाला है।

ऐसा करने के लिए, आप उदाहरण के लिए संक्रमण के प्रत्येक राज्य के लिए एक CSS क्लास बना सकते हैं और एनीमेशन स्टेट को टॉगल करने के लिए केवल jQuery का उपयोग कर सकते हैं।

यह आम तौर पर काफी साफ-सुथरा होता है क्योंकि आप इसे अपने सीएसएस के बाकी हिस्सों के साथ-साथ अपने व्यवसाय तर्क के साथ मिलाने के बजाय एनिमेशन को ट्विक कर सकते हैं:

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

यदि कोई परिवर्तन पैरामीटर गतिशील है, तो आप निश्चित रूप से इसके बजाय शैली विशेषता का उपयोग कर सकते हैं:

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

एमडीएन पर सीएसएस 3 संक्रमण पर बहुत अधिक विस्तृत जानकारी ।

फिर भी कुछ और बातें ध्यान में रखनी चाहिए और यह सब थोड़ा मुश्किल हो सकता है यदि आपके पास जटिल एनिमेशन, चेनिंग आदि हैं और jQuery ट्रांजिट सिर्फ हुड के नीचे सभी पेचीदा बिट्स करता है:

$('.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उपयोग {}या nullके लिए options

उदाहरण उपयोग:

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, फ़ायरफ़ॉक्स में करता है, लेकिन केवल फ़ायरफ़ॉक्स है।
लियाम

ठीक है इसलिए यह अब क्रोम, फ़ायरफ़ॉक्स और IE10 में काम करता है। क्या आप IE9, Liam का परीक्षण कर सकते हैं? समस्या यह थी कि परिवर्तन संपत्ति क्रोम और IE के लिए अपरिभाषित थी, इसलिए स्क्रिप्ट ने सोचा कि परिवर्तन संपत्ति अनुपलब्ध थी। इसलिए, मैं स्क्रिप्ट सभी उपसर्गों शामिल करने के लिए बदल दिया है: ms, o, webkit, mozका पता लगाने के लिए सही ढंग से सुनिश्चित करने के लिए। फ़िडेल को v12 में अद्यतन किया जाता है।
यति

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

तो आप इसे डिफ़ॉल्ट चेतक में उपयोग कर सकते हैं:

//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);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.