开发者

Detecting 'transform: translate3d' support

开发者 https://www.devze.com 2023-03-09 06:31 出处:网络
Does anyone know how I would detect transform: translate3d(x,y,z) support is available? My issue is that I want to use translate3d across browsers where it is supported because it tends to use hardwa

Does anyone know how I would detect transform: translate3d(x,y,z) support is available?

My issue is that I want to use translate3d across browsers where it is supported because it tends to use hardware acceleration and hence smoother for animation, a开发者_JAVA技巧nd then fall back to translate where its not.


Check out this solution.

It is based on the fact that if a browser supports transforms, the value of

window.getComputedStyle(el).getPropertyValue('transform')

will be a string containing the transformation matrix, when a 3d transform is applied to the element el. Otherwise, it will be undefined or the string 'none', as in the case of Opera 12.02.

It works on all major browsers.

The code:

function has3d() {
    if (!window.getComputedStyle) {
        return false;
    }

    var el = document.createElement('p'), 
        has3d,
        transforms = {
            'webkitTransform':'-webkit-transform',
            'OTransform':'-o-transform',
            'msTransform':'-ms-transform',
            'MozTransform':'-moz-transform',
            'transform':'transform'
        };

    // Add it to the body to get the computed style.
    document.body.insertBefore(el, null);

    for (var t in transforms) {
        if (el.style[t] !== undefined) {
            el.style[t] = "translate3d(1px,1px,1px)";
            has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
        }
    }

    document.body.removeChild(el);

    return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
}


The original blog post announcing 3D transforms has an image flip demo, which does it with a media query, like this:

@media all and (-webkit-transform-3d) {
  /* Use the media query to determine if 3D transforms are supported */
  #flip-container {
    -webkit-perspective: 1000;
  }
  #flip-card {
    width: 100%;
    height: 100%;
    -webkit-transform-style: preserve-3d;
    -webkit-transition: -webkit-transform 1s;
  }
  #flip-container:hover #flip-card {
    -webkit-transform: rotateY(180deg);
  }
}

This blog post has a good intro to media queries. This has some more details.


You can try CCS3 @supports:

@supports (transform: translate3d) {
  div {
    transform : translate3d(20px,0,0);
  }
}

@supports not (transform: translate3d) {
  div {
    transform: translate(20px,0);
  }
}

Can I use @support


I'd suggest using Modernizr.

It does feature detection for a whole range of browser features, including 3D transforms. It also provides a method of specifying CSS rules for browsers which have various features or not, so it sounds like it will do exactly what you're looking for.

Hope that helps.


//The following is based on iScroll4's tests to determine if a browser supports CSS3 3D     transforms.
var has3d = function() {
    return ('WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix());
}


Was tinkering around with a way to check for 3d support.. used this implementation from Jeffery Way in this article. Allows for less code and more use cases ;)

/**
* Test For CSS3 property support
* use 'perspective' to test for 3d support
*/
var supports = (function() {

    'use strict';

    var div = document.createElement('div'),
        vendors = 'Khtml ms O Moz Webkit'.split(' '),
        len = vendors.length;

    return function(prop) {

        if (prop in div.style) return true;

        prop = prop.replace(/^[a-z]/, function(val) {
            return val.toUpperCase();
        });

        while(len--) {
            if (vendors[len] + prop in div.style) {
                return true;
            } 
        }

        return false;
    };
})();

if(supports('perspective')) {
    // do 3d stuff
}


This code is adjusted for testing 3D transforms support and other CSS3 features.

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

testCSSSupport('transform')

Possible return values:

false, when feature unsupported, or

{
    vendor: 'moz',
    cssStyle: '-moz-transform',
    jsStyle: 'MozTransform'
}

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 */) {
    var testDiv,
        featureCapital = feature.charAt(0).toUpperCase() + feature.substr(1),
        vendors = ['', 'webkit', 'moz', 'ms'],
        jsPrefixes = ['', 'Webkit', 'Moz', 'ms'],
        defaultTestValues = {
            transform: 'translateZ(0.5em) rotateY(10deg) scale(2)'
           // This will test for 3D transform support
           // Use translateX to test 2D transform
        },
        testFunctions = {
            transform: function (jsProperty, computed) {
                return computed[jsProperty].substr(0, 9) === 'matrix3d(';
            }
        };

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

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

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

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

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


Bootstrap uses following Code:

@media all and (transform-3d), (-webkit-transform-3d) {
    .carousel-inner > .carousel-item {
        transition: transform 0.6s ease-in-out;
        backface-visibility: hidden;
        perspective: 1000px;
    }
    .carousel-inner > .carousel-item.next,
    .carousel-inner > .carousel-item.active.right {
        left: 0;
        transform: translate3d(100%, 0, 0);
    }
    .carousel-inner > .carousel-item.prev,
    .carousel-inner > .carousel-item.active.left {
        left: 0;
        transform: translate3d(-100%, 0, 0);
    }
    .carousel-inner > .carousel-item.next.left,
    .carousel-inner > .carousel-item.prev.right,
    .carousel-inner > .carousel-item.active {
        left: 0;
        transform: translate3d(0, 0, 0);
    }
}


tl:dr - Use user agent sniffing. Here is a script for detecting CSS 3D transform support across browsers: https://github.com/zamiang/detect-css3-3D-transform

I tried most of the methods in this post, among others like Modernizer and Meny's methods but could not support browsers like Firefox while maintaining a good experience for older browsers like Safari 4&5, iOS devices and Chrome on Retina MacBook pros (they all have their quirks).

CSS3 3D transforms involve interaction between the browser and the graphics card. The browser may be able to parse the 3D declarations but may not be able to properly instruct the graphics card in how to render your page. There are many possible outcomes ranging from the page rendering with lines across it (Safari 4) to the page rendering beautifully then crashing the browser seconds later (Safari on iOS4). Any ‘feature detection’ approach would unacceptably flag these as ‘supports CSS3 3D transforms’. This is one case where ‘feature detection’ fails and user agent sniffing (and lots of testing) wins hands down.

Most feature detection assumes a 'supports' or 'does not support' binary. This is not the case with CSS3 3D Transforms - there is a 'gradient of support'.

CSS3 3D transform support can be separated into 4 levels:

  1. Reliably supports 3D transforms across most machines. For example: Safari 6
  2. Can parse and apply 3D transform declarations but ignores the 3D parts. For example: Chrome on a Retina MacBook Pro.
  3. Can parse and apply 3D transform declarations but renders in unacceptable ways. For example: Safari 4 and Safari 4/5 on Windows show lines across the page.
  4. Cannot apply 3D transform declarations in any way. For example: IE or Firefox < v10

This script will return true in scenario one and two but false for 3 and 4:

Note: new to participating in stackoverflow - please let me know if I should paste that code inline (it is a bit long)


Using jQuery:

var cssTranslate3dSupported = false;
(function()
{
    var div = $('<div style="position:absolute;">Translate3d Test</div>');
    $('body').append(div);
    div.css(
    {
        'transform' : "translate3d(20px,0,0)",
        '-moz-transform' : "translate3d(20px,0,0)",
        '-webkit-transform' : "translate3d(20px,0,0)",
        '-o-transform' : "translate3d(20px,0,0)",
        '-ms-transform' : "translate3d(20px,0,0)"
    });
    cssTranslate3dSupported = (div.offset().left == 20);
    div.empty().remove();
})();


The author of Hardware Accelerated Accordion checks like this:

var has3d = ('WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix())


just simply use:

alert($.support.cssTransform3d);

this alerts true if supported and false if not

0

精彩评论

暂无评论...
验证码 换一张
取 消