2012-06-04 16 views
15

Quiero servir diferentes archivos javascript dependiendo de si el navegador admite la transición CSS3 o no. ¿Hay una forma mejor de detectar el soporte de transición que mi código a continuación?Detectar compatibilidad para la transición 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

no quiero para incluir una biblioteca para esto. – user1087110

+0

revise este hilo: http://stackoverflow.com/a/13081497/104380 – vsync

Respuesta

3

Modernizr detectará esto por usted. Use this link para crear una compilación de descarga personalizada que solo contenga transiciones CSS3 2D y/o 3D.

Una vez que se ejecuta, puede cualquiera de las pruebas para la clase csstransitions en la etiqueta html (CSS), o en JavaScript, prueba si Modernizr.csstransitions es true.

Más documentos: http://modernizr.com/docs/#csstransitions

+12

Gracias. Pero no quiero incluir una biblioteca para esto :) – user1087110

+0

¿Por qué no? ¡No tiene sentido reinventar la rueda! –

+0

El constructor Modernizr le permite seleccionar solo las características que desea detectar, proporcionándole el código más pequeño posible. Ha sido probado y refinado repetidamente, por lo que realmente es la mejor manera de hacer este tipo de cosas. – Blazemonger

36

también pienso incluyendo Modernizr es una exageración. La siguiente función debería funcionar para cualquier característica.

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

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

+4

, ya que IE informó elm.style [nombre de función] como una cadena vacía. ¡Agregué! == indefinido en el primer cheque; if (elm.style [featurename]! == undefined) {feature = true; } y ahora funciona. – Stoffe

1

Aquí hay otro código de prueba. Tal vez sea una exageración, pero la función intenta establecer la propiedad de CSS en el objeto DOM y luego volver a leer desde allí.

Nunca probé este código en una gran cantidad de navegadores exóticos, pero es más seguro que solo verificar la disponibilidad de la propiedad de CSS. ¡Ah, sí, puede distinguir el soporte de transformación 2D del soporte de transformación 3D! ¡Solo pase los valores de las propiedades CSS que quiera probar!

La ventaja de este código es que detecta el prefijo del proveedor admitido (si lo hay). Los posibles valores:

false, cuando la función no compatible, o

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

cuando característica compatible

/** 
* 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 (alfa), que puede generar compilaciones personalizadas localmente Esto puede resolver la preocupación de "exageración" antes mencionada, aunque no estoy del todo claro con respecto a esa preocupación en primer lugar (pero supongo que es el tamaño). La nueva API proporciona un método de 'compilación', al que puede pasar json que contiene las pruebas que le gustaría incluir en la compilación.

Utilizo algo como esto en mi archivo tragamonedas, pero no se necesita un trago: un simple script de nodo funcionará.

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

Y un ejemplo del fichero 'Modernizr-config.json' habría

{ 
    "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" 
    ] 
} 

El archivo de configuración completo se incluye en el paquete Modernizr.

Con este enfoque, puede aprovechar el paquete de pruebas Modernizr bien mantenido a través de instaladores de paquetes y agregar/eliminar pruebas fácilmente según sea necesario. Menos pruebas, archivo más pequeño, obviamente.

La opción '' setClasses añadirá la clase de prueba en relación con su html pero también se puede tomar ventaja de los eventos asincrónicos 3.0, así:

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