Detect support for transition with JavaScript

一个人想着一个人 提交于 2019-12-20 09:59:26

问题


I want to serve different javascript files depending on if browser supports CSS3 transition or not. Is there a better way to detect transition support than my code below?

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

回答1:


Modernizr will detect this for you. Use this link to create a custom download build that only contains CSS3 2D and/or 3D transitions.

Once it's run, you can either test for the csstransitions class on the html tag (CSS), or in JavaScript, test if Modernizr.csstransitions is true.

More docs: http://modernizr.com/docs/#csstransitions




回答2:


I also think including Modernizr is an overkill. The function below should work for any feature.

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

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




回答3:


Here is another testing code. Maybe it is an overkill, but the function tries to set the CSS property to DOM object and then read back from it.

Never tested this code on large amount of exotic browsers, but it is safer than just checking for the CSS property availability. Ah, yes, it can distinguish 2D transform support from 3D transform support! Just pass CSS property values you want to test!

The plus of this code is that it detects the vendor prefix supported (if any). Possible return values:

false, when feature unsupported, or

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

when feature supported

/**
 * 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




回答4:


if (window.TransitionEvent){

}



回答5:


With Modernizr 3.0 (alpha), you can generate custom builds locally. This may resolve the aforementioned "overkill" concern - although i'm not entirely clear on that concern in the first place (but i'm assuming it's size). The new api provides a 'build' method, to which you can pass json containing the tests that you would like to include in the build.

I use something like this in my gulp file but gulp is not needed - a simple node script will do.

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

And an example of the 'modernizr-config.json' file would be

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

The full config file is included in the Modernizr package.

With this approach, you can take advantage of the well maintained Modernizr test suite via package installers and easily add/remove tests as needed. Less tests, smaller file obviously.

The 'setClasses' option will add the related test class to your html but you can also take advantage of the 3.0 async events like so:

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


来源:https://stackoverflow.com/questions/10888211/detect-support-for-transition-with-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!