ugrás a tartalomhoz

Saját tulajdonságok animálása jQuery-vel

Poetro · 2011. Már. 11. (P), 11.24

A következő budapest.js találkozón fej-fej mellett hasonlítjuk össze a népszerű JavaScript keretrendszereket. Ennek kapcsán elkezdtem kutakodni, hogyan lehet saját attribútumokat, illetve tulajdonságokat animálni, illetve CSS-ként kezelni jQuery segítségével.

A jQuery már alapértelmezetten pár egyedi tulajdonság lekérdezését teszi lehetővé. Ezek például az opacity, scrollLeft és scrollRight. Ezeket mint CSS tulajdonság teszi elérhetővé a jQuery, ugyanakkor nem (feltétlen) azok. Azaz például az opacity CSS tulajdonság Internet Explorer 9 előtt változatokban nincsen semmilyen hatással, mégis:

  1. // Be tudjuk állítani:  
  2. $(elem).css('opacity', 0.5);  
  3. // Le tudjuk kérdezni:  
  4. $(elem).css('opacity');  

És ez működik Internet Explorerben is. Hogyan? Hát úgy, hogy ezeket az egyedi tulajdonságokat a jQuery egyedileg kezeli.

Ahhoz, hogy hasonló saját „CSS” tulajdonságokat generáljunk, nem kell túl sokat tenni, csak ki kell bővíteni a jQuery cssHooks objektumát. Például:

  1. $.each(['height''width'], function (i, v) {  
  2.   var camelCase = $.camelCase('dialog-' + v);  
  3.   $.cssHooks[camelCase] = {  
  4.     get: function (elem, computed, extra) {  
  5.       return $(elem).dialog('option', v);  
  6.     },  
  7.     set: function (elem, value) {  
  8.       var dialog = $(elem),  
  9.           position = dialog.dialog('option''position');  
  10.       dialog.dialog('option', v, parseFloat(value));  
  11.       dialog.dialog('option''position', position);  
  12.     }  
  13.   };  
  14. });  

Ezzel hozzáadjuk a dialogWidth, és dialogHeight egyedi tulajdonságot a CSS kezelőhöz. Ezután a következő sorok már működni fognak:

  1. $(elem).css('dialogHeight', 300);  
  2. $(elem).css('dialog-height', 300); // ugyanaz a hatása mint az előzőnek  
  3. $(elem).css('dialogHeight');  
  4. $(elem).css('dialog-height'); // ugyanaz a hatása mint az előzőnek  

A jQuery css() függvénye a megkapott tulajdonság nevét camelCase formára alakítja; például abból, hogy dialog-height dialogHeight lesz. Ennek megfelelően kell a saját „CSS” tulajdonságunkat is definiálni, ahogy ezt meg is tettük a $.camelCase() függvény segítségével.

Ahhoz, hogy animálni is tudjuk ezeket, már csak egy kicsi lépés van hátra. A jQuery a $.fx.step objektumot használja az animáció aktuális lépésének lefuttatására. Alapértelmezetten minden tulajdonságra a $.fx.step._default() függvény fut le. Hogy saját függvényt tudjunk lefuttatni, egyszerűen hozzá kell adni a $.fx.step objektumhoz a saját kezelőnket.

  1. $.each(['height''width'], function (i, v) {  
  2.   var camelCase = $.camelCase('dialog-' + v);  
  3.   $.fx.step[camelCase] = function (fx) {  
  4.     jQuery.style( fx.elem, fx.prop, fx.now );  
  5.   };  
  6. });  

A fenti kód a $.fx.step objektumot kibővíti egy dialogHeight és egy dialogWidth tulajdonsággal, és ezek után, amikor az animate segítségével akarjuk módosítani a tulajdonságot, akkor már a $.cssHooks-ban definiált függvényeket fogja használni.

  1. $(elem).animate({  
  2.     dialogHeight: 200,  
  3.     dialogWidth: 300  
  4.   }, {  
  5.     duration: 500  
  6.   });  

Összefoglalás

Érdekesnek, és igencsak hasznosnak találtam ezen jQuery objektumok és nem igazán dokumentált függvények használatát. Érdemes lehet ezek után más gyöngyszemek után kutatni a jQuery forráskódjában.

Ezek után bármilyen egyedi tulajdonságot tudunk majd animálni, valamint CSS tulajdonságként kezelni. Sajnos a css és az animate ezen tulajdonságai csak jQuery 1.4.3 óta érhetők el, a korábbi változatokban az opacity kezelése például be volt drótozva a kódba.

 
1

És ez mire jó?

nemeseri · 2011. Már. 13. (V), 01.14
Az opacitynél a jQuery nyilván maszkolja az IE specifikus filtereket.

És mire jó, hogy saját tulajdonságot animálsz? Az animate-el eddig is tudtál bármit animálni, akár összefűzve több dolgot. Mondasz egy példát, h miért jó ez?
Mintha kimaradt volna a cikkből a mondanivaló. :P
2

CSS3, widget, HTML tulajdonság

Poetro · 2011. Már. 13. (V), 02.50
Például rengeteg CSS3 tulajdonság van, aminek nem lenne egyértelmű, hogyan animálod, mégis megoldható. Például teszem az, animálni akarod a CSS3 gradient tulajdonságát egy elemnek. Mondjuk mozgatod a gradiens pozícióit, vagy színeit és a többi. Ezen kívül például a jQuery UI widgetjei közül a slider-nek a pontját akarod animálni de függetlenül az aktuális CSS tulajdonságaitól, pusztán a beépített API-ra építve, akkor azt megteheted. Ez azért is hasznos, mert az objektum megfelelő tulajdonsága így frissül is az animáció során, nem csak úgy látszik, mintha ott lenne.
  1. jQuery(function ($) {  
  2.   $.cssHooks.sliderValue = {  
  3.     get: function (elem) {  
  4.       return $(elem).slider('option''value');  
  5.     },  
  6.     set: function (elem, value) {  
  7.       $(elem).slider('option''value', parseFloat(value));  
  8.     }  
  9.   };  
  10.   $.fx.step.sliderValue = function (fx) {  
  11.     jQuery.style( fx.elem, fx.prop, fx.now );  
  12.   };  
  13.   $('#slider').slider().animate({sliderValue: 50}, 5000);  
  14. });  
Megtekinthető.

Másik példa HTML tulajdonság animálására:
  1. <input type="number" min="0" max="100" step="2" value="0">  
  2. <input type="range" min="0" max="100" step="2" value="0">  
  3. <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>  
  4. <script type="text/javascript">  
  5.   jQuery(function ($) {  
  6.     $.cssHooks.numberValue = {  
  7.       get: function (elem) {  
  8.         return elem.value;  
  9.       },  
  10.       set: function (elem, value) {  
  11.         elem.value = Math.round(parseFloat(value) / elem.step) * elem.step;  
  12.       }  
  13.     };  
  14.     $.fx.step.numberValue = function (fx) {  
  15.       jQuery.style( fx.elem, fx.prop, fx.now );  
  16.     };  
  17.     $('input[type=number], input[type=range]').animate({numberValue: 50}, 2000);  
  18.   });  
  19. </script>  
Szintén megtekinthető.
3

Király, köszi! :)

nemeseri · 2011. Már. 13. (V), 16.01
Király, köszi! :)
4

A második példa nálam nem

bugadani · 2011. Már. 13. (V), 17.18
A második példa nálam nem működik, mindkét szövegmezőben NaN jelenik meg (Firefox 4.0 RC).
Egyébként érdekes cikk, köszönet érte!
5

Firefox

Poetro · 2011. Már. 13. (V), 18.00
Úgy tűnik a Firefox kicsit furcsán kezeli a HTML5 elemeket, ugyanis azok nem szövegmezők, hanem number illetve range mezők. Ennek megfelelően a step mező teljesen valid. Viszont a Firefox nem fér hozzá valamiért ebben az esetben a step attribútumhoz elem.step formában.
Ennek megfelelően frissítettem a kódot:
  1. jQuery(function ($) {  
  2.   $.cssHooks.numberValue = {  
  3.     get: function (elem) {  
  4.       return parseFloat(elem.value);  
  5.     },  
  6.     set: function (elem, value) {  
  7.       var step = parseFloat($(elem).attr('step'));  
  8.       elem.value = Math.round(parseFloat(value) / step) * step;  
  9.     }  
  10.   };  
  11.   $.fx.step.numberValue = function (fx) {  
  12.     jQuery.style( fx.elem, fx.prop, fx.now );  
  13.   };  
  14.   $('input[type=number], input[type=range]').animate({numberValue: 50}, 5000);  
  15. });  
Ami megtekinthető.