2012-06-04 13 views
15

Voglio servire diversi file javascript a seconda se il browser supporta la transizione CSS3 o meno. C'è un modo migliore per rilevare il supporto di transizione rispetto al mio codice qui sotto?Rileva supporto per la transizione con JavaScript

window.onload = function() { 
    var b = document.body.style; 
    if(b.MozTransition=='' || b.WebkitTransition=='' || b.OTransition=='' || b.transition=='') { 
     alert('supported'); 
    } else { 
     alert('NOT supported') 
    } 
} 
+6

Non voglio per includere una libreria per questo. – user1087110

+0

controlla questa discussione: http://stackoverflow.com/a/13081497/104380 – vsync

risposta

3

Modernizr rileverà questo per voi. Utilizzare this link per creare un build di download personalizzato che contenga solo transizioni CSS3 2D e/o 3D.

Una volta che è eseguito, è possibile banco di prova per la classe csstransitions sul html tag (CSS), o in JavaScript, test se Modernizr.csstransitions è true.

Ulteriori documenti: http://modernizr.com/docs/#csstransitions

+12

Grazie. Ma non voglio includere una libreria per questo :) – user1087110

+0

Perché no? Non ha senso reinventare la ruota! –

+0

Il builder Modernizr consente di selezionare solo le funzionalità che si desidera rilevare, fornendo il codice più piccolo possibile. È stato ripetutamente testato e perfezionato, quindi è davvero il modo migliore per fare questo genere di cose. – Blazemonger

36

penso anche compreso Modernizr è un peso inutile. La funzione seguente dovrebbe funzionare per qualsiasi funzione.

function detectCSSFeature(featurename){ 
    var feature = false, 
    domPrefixes = 'Webkit Moz ms O'.split(' '), 
    elm = document.createElement('div'), 
    featurenameCapital = null; 

    featurename = featurename.toLowerCase(); 

    if(elm.style[featurename] !== undefined) { feature = true; } 

    if(feature === false) { 
     featurenameCapital = featurename.charAt(0).toUpperCase() + featurename.substr(1); 
     for(var i = 0; i < domPrefixes.length; i++) { 
      if(elm.style[domPrefixes[i] + featurenameCapital ] !== undefined) { 
       feature = true; 
       break; 
      } 
     } 
    } 
    return feature; 
} 

var hasCssTransitionSupport = detectCSSFeature("transition"); 

Ispirato https://developer.mozilla.org/en-US/docs/CSS/Tutorials/Using_CSS_animations/Detecting_CSS_animation_support

+4

Come IE ha segnalato elm.style [featurename] come una stringa vuota. Ho aggiunto! == undefined al primo controllo; if (elm.style [featurename]! == undefined) {feature = true; } e ora funziona. – Stoffe

1

Ecco un altro codice di test. Forse è un overkill, ma la funzione tenta di impostare la proprietà CSS su DOM oggetto e quindi leggere di nuovo da esso.

Non è mai stato testato questo codice su una grande quantità di browser esotici, ma è più sicuro del semplice controllo della disponibilità della proprietà CSS. Ah, sì, è in grado di distinguere il supporto per le trasformazioni 2D dal supporto per le trasformazioni 3D! Basta passare i valori delle proprietà CSS che vuoi testare!

Il vantaggio di questo codice è che rileva il prefisso del fornitore supportato (se presente). Possibili valori di ritorno:

false, quando la funzione non supportata, o

{ 
    vendor: 'moz', 
    cssStyle: '-moz-transition', 
    jsStyle: 'MozTransition' 
} 

quando la funzione supportata

/** 
* Test for CSS3 feature support. Single-word properties only by now. 
* This function is not generic, but it works well for transition and transform at least 
*/ 
testCSSSupport: function (feature, cssTestValue/* optional for transition and transform */) { 
    var testDiv, 
     featureCapital = feature.charAt(0).toUpperCase() + feature.substr(1), 
     vendors = ['', 'webkit', 'moz', 'ms', 'o'], 
     jsPrefixes = ['', 'Webkit', 'Moz', 'ms', 'O'], 
     defaultTestValues = { 
      transition: 'left 2s ease 1s', 
      transform: 'rotateX(-180deg) translateZ(.5em) scale(0.5)' 
      // This will test for 3D transform support 
      // Use other values if you need to test for 2D support only 
     }, 
     testFunctions = { 
      transition: function (jsProperty, computed) { 
       return computed[jsProperty + 'Delay'] === '1s' && computed[jsProperty + 'Duration'] === '2s' && computed[jsProperty + 'Property'] === 'left'; 
      }, 
      transform: function (jsProperty, computed) { 
       return computed[jsProperty].substr(0, 9) === 'matrix3d('; 
      } 
     }; 

    /* test given vendor prefix */ 
    function isStyleSupported(feature, jsPrefixedProperty) { 
     if (jsPrefixedProperty in testDiv.style) { 
      var testVal = cssTestValue || defaultTestValues[feature], 
       testFn = testFunctions[feature]; 
      if (!testVal) { 
       return false; 
      }  

      testDiv.style[jsPrefixedProperty] = testVal; 
      var computed = window.getComputedStyle(testDiv); 

      if (testFn) { 
       return testFn(jsPrefixedProperty, computed); 
      } 
      else { 
       return computed[jsPrefixedProperty] === testVal; 
      } 
     } 
     return false; 
    } 

    //Assume browser without getComputedStyle is either IE8 or something even more poor 
    if (!window.getComputedStyle) { 
     return false; 
    } 

    //Create a div for tests and remove it afterwards 
    if (!testDiv) { 
     testDiv = document.createElement('div'); 
     document.body.appendChild(testDiv); 
     setTimeout(function() { 
      document.body.removeChild(testDiv); 
      testDiv = null; 
     }, 0); 
    } 

    var cssPrefixedProperty, 
     jsPrefixedProperty; 

    for (var i = 0; i < vendors.length; i++) { 
     if (i === 0) { 
      cssPrefixedProperty = feature; //todo: this code now works for single-word features only! 
      jsPrefixedProperty = feature; //therefore box-sizing -> boxSizing won't work here 
     } 
     else { 
      cssPrefixedProperty = '-' + vendors[i] + '-' + feature; 
      jsPrefixedProperty = jsPrefixes[i] + featureCapital; 
     } 

     if (isStyleSupported(feature, jsPrefixedProperty)) { 
      return { 
       vendor: vendors[i], 
       cssStyle: cssPrefixedProperty, 
       jsStyle: jsPrefixedProperty 
      }; 
     } 
    } 

    return false; 
} 

Github: https://github.com/easy-one/CSS3test

0
if (window.TransitionEvent){ 

} 
0

Con Modernizr 3.0 (alpha), si può generare build personalizzate localmente. Questo potrebbe risolvere la preoccupazione sopra descritta di "overkill" - anche se non sono del tutto chiaro su quella preoccupazione in primo luogo (ma presumo che sia la sua dimensione). La nuova API fornisce un metodo 'build', al quale è possibile passare json contenente i test che si desidera includere nella build.

Io uso qualcosa del genere nel mio file gulp ma gulp non è necessario - un semplice script di nodo funzionerà.

gulp.task('js:modernizr', function() { 
    var modConfig = JSON.parse(fs.readFileSync('modernizr-config.json', { 
      encoding: 'utf8' 
     })); 
    modernizr.build(modConfig, function(res) { 
     fs.writeFileSync('modernizr.js', res); 
     return true; 
    }); 
}); 

E un esempio del file 'Modernizr-config.json' sarebbe

{ 
    "classPrefix": "", 
    "options": [ 
    "addTest", 
    "atRule", 
    "domPrefixes", 
    "hasEvent", 
    "html5shiv", 
    "html5printshiv", 
    "load", 
    "mq", 
    "prefixed", 
    "prefixes", 
    "prefixedCSS", 
    "setClasses", 
    "testAllProps", 
    "testProp", 
    "testStyles" 
    ], 
    "feature-detects": [ 
    "css/transforms", 
    "css/transforms3d", 
    "css/transformstylepreserve3d", 
    "css/transitions", 
    "touchevents", 
    "workers/webworkers", 
    "history" 
    ] 
} 

Il file di configurazione completo è incluso nel pacchetto Modernizr.

Con questo approccio, è possibile usufruire della suite di test Modernizr ben gestita tramite i programmi di installazione dei pacchetti e aggiungere/rimuovere facilmente i test in base alle esigenze. Meno prove, file più piccoli ovviamente.

L'opzione '' setClasses aggiungerà la relativa classe di test per il codice HTML, ma si può anche approfittare degli eventi asincroni 3.0 in questo modo:

Modernizr.on('csstransitions', function(bool) { 
    if (bool === true) // do transition stuffs 
}