【问题标题】:Detecting 'transform: translate3d' support检测“转换:translate3d”支持
【发布时间】:2015-12-11 16:29:35
【问题描述】:

有人知道我将如何检测transform: translate3d(x,y,z) 支持可用吗?

我的问题是我想在支持 translate3d 的浏览器中使用它,因为它倾向于使用硬件加速,因此动画更流畅,然后回退到 translate 不支持的地方。

【问题讨论】:

    标签: html css


    【解决方案1】:

    查看this solution

    这是基于这样一个事实,如果浏览器支持转换,则

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

    当对元素el 应用3d 变换时,将是一个包含变换矩阵的字符串。否则,它将是 undefined 或字符串 'none',就像 Opera 12.02 一样。

    它适用于所有主流浏览器。

    代码:

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

    【讨论】:

    • 这似乎在 IE10 中不起作用——至少对我而言。经过一番研究,我发现 IE 对 JS 转换属性使用了非标准大写。因此,msTransform 对我有用,但 MSTransform 不行。
    • 是的,我从一个月前开始使用它,并意识到 IE10 不喜欢它作为“转换”,因为样式前缀的第一个字母是小写的(所以它应该是“转换”) .这让我想知道 OTransform 是否应该改为 oTransform。
    • @JonathanTonge 不,在 Opera 中是 OTransform
    • 理论上,如果某些奇怪的浏览器不支持getComputedStyle,该函数会抛出错误。修正了你的答案。
    • 您不需要检查 OTransform 或 msTransform 以进行 3d 转换。第一个支持它们的 Opera 版本使用前缀 -webkit-,IE 10 不使用前缀 ms 作为变换属性,IE9 根本不支持 3D。 caniuse.com/#feat=transforms3d
    【解决方案2】:

    original blog post announcing 3D transforms 有一个 image flip demo,它通过媒体查询来实现,如下所示:

    @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 对媒体查询有很好的介绍。 This 有更多细节。

    【讨论】:

    • 澄清一下,只有在支持 transform3d 的情况下,您才能使用上面的媒体查询来设置元素的样式。例如,应用红色。然后你应该使用javascript来检查这个元素是否应用了属性。在我们的例子中,检查颜色是黑色还是红色。如果是红色,则支持 3d 变换。
    • 这在 OS X 上的 Chrome 38 上不起作用。是否有可以在其上运行的浏览器?
    【解决方案3】:

    你可以试试 CCS3 @supports:

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

    Can I use @support

    【讨论】:

    • @support 目前有一个非常糟糕的...支持。 ios7 不支持,只有 android 4.4 支持:caniuse.com/css-featurequeries
    • @support 是否有任何 javascript 等效项?
    • 看起来应该是@supports (transform: translate3d(0,0,0,)) {(或类似的)?需要给translate3d 提供虚拟参数。
    【解决方案4】:

    我建议使用Modernizr

    它对所有浏览器特性进行特性检测,包括 3D 变换。它还提供了一种为具有或不具有各种功能的浏览器指定 CSS 规则的方法,因此听起来它会完全满足您的需求。

    希望对您有所帮助。

    【讨论】:

    • 对不起应该提到已经尝试过,它不支持上述场景。 Modernizr.csstransforms3d 实际上检查对 perspective 的支持,尽管 -[browser-prefix]-transform: translate3d(x,y,z) 在 chrome/ff 中可用,但目前仅在 Safari 中可用。
    • @Jamie - 嗯,这么多显而易见的解决方案。 :-/ 我想知道modernizr 团队是否意识到这个问题?
    • 这不是真的 - Modernizr 检测到 Chrome 的 3d 变换很好,而 Fx 不支持它们。看看 Firefox 中的css3.bradshawenterprises.com/transforms——转换不起作用。如果您在 Chrome 中访问 modernizr.com,您会看到它在 Chrome 中检测到 3d 转换效果很好。
    • @Rich 恐怕如前所述 Modernizr 检查perspective 以确定3d 转换是否可用。不幸的是,透视是一组完全不同的功能。以下是文档“对于 Modernizr,我们测试浏览器对透视属性的支持”的部分内容。
    • 有兴趣的朋友,3dtransforms检测功能在这里:github.com/Modernizr/Modernizr/blob/master/modernizr.js#L606
    【解决方案5】:
    //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());
    }
    

    【讨论】:

    • 谢谢。如果您需要在不使用其他库的情况下测试 3d 转换支持,则此方法有效。
    • 适用于 webkit 浏览器(例如 Safari 和 Chrome)。支持 3d 转换的 Firefox 返回 false - 实际上脚本停止执行,因为函数 WebKitCSSMatrix 未定义。查看此跨浏览器解决方案:stackoverflow.com/questions/5661671/…
    【解决方案6】:

    正在修补一种检查 3d 支持的方法。在 article 中使用了 Jeffery Way 的这个实现。允许更少的代码和更多的用例;)

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

    【讨论】:

      【解决方案7】:

      此代码已针对测试 3D 变换 支持和其他 CSS3 功能进行了调整。

      此代码的优点是它检测支持的供应商前缀(如果有)。称呼它:

      testCSSSupport('transform')
      

      可能的返回值:

      false,当功能不受支持时,或

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

      当功能支持时

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

      【讨论】:

        【解决方案8】:

        Bootstrap 使用以下代码:

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

        【讨论】:

          【解决方案9】:

          tl:dr - 使用用户代理嗅探。这是一个跨浏览器检测 CSS 3D 转换支持的脚本:https://github.com/zamiang/detect-css3-3D-transform

          我尝试了这篇文章中的大部分方法,其中包括 ModernizerMeny 的方法,但无法支持 Firefox 等浏览器,同时在 Safari 4&5、iOS 设备和 Chrome 等旧版浏览器上保持良好体验Retina MacBook 专业人士(他们都有自己的怪癖)。

          CSS3 3D 转换涉及浏览器和显卡之间的交互。浏览器可能能够解析 3D 声明,但可能无法正确指示显卡如何呈现您的页面。有许多可能的结果,从带有线条的页面渲染(Safari 4)到漂亮的页面渲染然后在几秒钟后使浏览器崩溃(iOS4 上的 Safari)。任何“特征检测”方法都会不可接受地将这些标记为“支持 CSS3 3D 转换”。这是“特征检测”失败并且用户代理嗅探(和大量测试)胜出的一种情况。

          大多数特征检测都假定“支持”或“不支持”二进制文件。这不是 CSS3 3D 变换的情况 - 有一个“支持梯度”。

          CSS3 3D 变换支持可分为 4 个级别:

          1. 可靠地支持大多数机器上的 3D 变换。例如:Safari 6
          2. 可以解析和应用 3D 变换声明,但忽略 3D 部分。例如:Retina MacBook Pro 上的 Chrome。
          3. 可以解析和应用 3D 变换声明,但以不可接受的方式呈现。例如:Windows 上的 Safari 4 和 Safari 4/5 在页面上显示线条。
          4. 无法以任何方式应用 3D 变换声明。例如:IE 或 Firefox

          This script 将在场景 1 和 2 中返回 true,但在场景 3 和 4 中返回 false

          注意:刚参加 stackoverflow - 请告诉我是否应该内联粘贴该代码(它有点长)

          【讨论】:

          • 永远不要鼓励用户代理嗅探。
          【解决方案10】:

          使用 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();
          })();
          

          【讨论】:

          • 努力让它跨浏览器,但它不起作用。
          【解决方案11】:

          Hardware Accelerated Accordion 的作者这样检查:

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

          【讨论】:

          • 检查 IE10 的好方法。 [/讽刺]
          【解决方案12】:

          只需简单地使用:

          alert($.support.cssTransform3d);
          

          如果支持则提示 true,如果不支持则提示 false

          【讨论】:

          • 你确定吗?在我检查过的所有浏览器中,我没有看到the documentation$.support.cssTransform3d 中的那个是undefined
          • 这没有意义,显然不存在
          • 即使它存在,除了 jQuery 之外没有人应该依赖它。请参阅@mu 发布的文档链接太短 - “Intended for jQuery's internal use”。
          猜你喜欢
          • 2011-10-21
          • 2012-06-08
          • 2011-07-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多