2011-01-13 7 views
4

CSS3 전환으로 애니메이션을 적용 할 수있는 속성 목록이 브라우저간에 일관성이 없으며 새 브라우저 버전으로 변경 될 수 있습니다. 예를 들어 -moz-transform은 FF3.6에서 -moz-transition을 사용하여 애니메이션화 할 수 없지만 FF4에서는 사용합니다.CSS3 전환으로 속성을 애니메이션화 할 수 있는지 여부를 감지 하시겠습니까?

그래서 특정 속성에 애니메이션이 가능한지 JavaScript에서 감지하는 방법이 있습니까? 신뢰할 수 없으므로 사용자 에이전트 스니핑을 사용하고 싶지 않습니다.

미리 감사드립니다.

+2

@Mourner 당신이 나의 대답을 받아들이지 않고 요르단을 받아 들일 수 있다면 그것은 단지 이런 종류의 물건을 인터넷 검색을하는 사람들에게만 해당 될 것입니다. – Duopixel

답변

3

편집 : 애니메이션 가능한 속성을 감지하는 좋은 기술은 Jordan's answer을 참조하십시오.

속성이 애니메이션 가능한지 여부를 쉽게 감지 할 수있는 방법이 없습니다. 그러나 속성은 대부분 일치합니다 (유일한 문제는 FF4 전환 + 텍스트 그림자 + ​​변형).

http://www.w3.org/TR/css3-transitions/#the-transition-property-property-#properties-from-css-

파이어 폭스 3.6 CSS 전환을 지원하지 않습니다, 당신은 모더 나이저 등의 JS 라이브러리와이를 감지 할 수 있습니다

http://www.modernizr.com/

+0

감사! 나는 애니메이트 가능한 변환없이 트랜지션 지원이있는 FF의 안정 버전이 있다고 확신했지만, 이것은 FF4 베타 중 일부 였고 이제 모든 것이 정상인 것처럼 보입니다. – Mourner

+0

다른 프로젝트에서이 문제에 대해 생각해 봤는데 실제로 가능합니다. 아래를 참조하십시오. :) –

7

예, 방법이있다. 데모는 다음과 같습니다. 일부 매우 중요한 경고이 관련되어 있으므로 계속 읽으십시오.

다음 코드는 브라우저가 두 값 사이를 움직일 수 있는지 테스트합니다.

코드

jsFiddle demo. 이를 위해

필수 인수를 사용하는 방법

/* 
@param property The property to test. 
@param from  A valid starting value for the animation. 
@param to  A valid ending value for the animation. 
@param [element] The element to test with. (Required for testing 
       properties with prerequisites, e.g. "top" requires 
       non-static position.) 
*/ 
function isAnimationSupported(property, from, to, element) { 
    var doc = document.documentElement, 
     style = doc.appendChild(document.createElement("style")), 
     rule = [ 
       'capTest{', 
        '0%{', property, ':', from, '}', 
        '100%{', property, ':', to, '}', 
       '}' 
       ].join(''), 
     propCamel = property.toCamelCase(), 
     prefixes = 'moz ms o webkit '.split(' '), // Unprefixed last, see comments. 
     prefixCount = prefixes.length, 
     canAnimate = false; 

    element = doc.appendChild((element) 
      ? element.cloneNode(false) 
      : document.createElement('div')); 

    // Detect invalid start value. (Webkit tries to use default.) 
    element.style[propCamel] = to; 

    // Iterate through supported prefixes. 
    for (var i = 0; i < prefixCount; i++) { 

     // Variations on current prefix. 
     var prefix = prefixes[i], 
      hPrefix = (prefix) ? '-' + prefix + '-' : '', 
      uPrefix = (prefix) ? prefix.toUpperCase() + '_' : ''; 

     // Test for support. 
     if (CSSRule[uPrefix + 'KEYFRAMES_RULE']) { 

      // Rule supported; add keyframe rule to test stylesheet. 
      style.sheet.insertRule('@'+ hPrefix + 'keyframes ' + rule, 0); 

      // Apply animation. 
      var animationProp = (hPrefix + 'animation').toCamelCase(); 
      element.style[animationProp] = 'capTest 1s 0s both'; 

      // Get initial computed style. 
      var before = getComputedStyle(element)[propCamel]; 

      // Skip to last frame of animation. 
      // BUG: Firefox doesn't support reverse or update node style while 
      // attached. 
      doc.removeChild(element); 
      element.style[animationProp] = 'capTest 1s -1s alternate both'; 
      doc.appendChild(element); 
      // BUG: Webkit doesn't update style when animation skipped ahead. 
      element.style[animationProp] = 'capTest 1s 0 reverse both'; 

      // Get final computed style. 
      var after = getComputedStyle(element)[propCamel]; 

      // If before and after are different, property and values are animable. 
      canAnimate = before !== after; 
      break; 
     } 
    } 

    // Clean up the test elements. 
    doc.removeChild(element); 
    doc.removeChild(style); 

    return canAnimate; 
} 

// Cribbed from Lea Verou's prefixfree. 
String.prototype.toCamelCase = function() { 
    return this.replace(/-([a-z])/g, function($0, $1) { return $1.toUpperCase(); }) 
       .replace('-',''); 
}; 

는 애니메이션 할 수있는 속성과 시작과 수행해야 할 마무리 값입니다. 선택적으로 다른 초기 스타일이 설정된 요소를 전달할 수 있습니다 (예 : position: absolute. 이 함수는 요소를 복제하므로 문서에서 노드를 전달할 수 있으며 변경되지 않습니다. 요소를 전달하지 않으면 UA가 적용하는 기본 스타일을 사용하여 div에서 애니메이션이 테스트됩니다. 그것은 from 값과 to 값으로 설정된 최종 프레임에 설정된 초기 프레임과,

키 프레임 애니메이션 규칙 더미 스타일에 추가 원리

. 이 애니메이션은 요소에 적용됩니다. 그런 다음 애니메이션 속성의 계산 된 스타일을 검사하여 최종 프레임에서 시작할 때와 비교하여 애니메이션이 초기 프레임에서 시작될 때 다른 스타일인지 확인합니다.

전환 효과와 키 프레임 애니메이션의 애니메이션 가능한 속성이 동일하고 브라우저가 속성이 애니메이션을 지원하는 경우에만 브라우저에서 키 프레임 값을 적용하기 때문입니다.

주의 사항은 (이들 중 일부는 불쾌하고, 사용하기 전에 읽어!) 브라우저가 애니메이션을 처리하는 방법에 여러 가지 불일치가 있습니다

.이 두 가지는 가능한 미래의 방법으로 해결했습니다. 그러나 그 중 일부는 다루기가 어렵습니다.

정적 요소에서 Firefox는 tweens 위치 값 (예 : left)을 사용하지만 다른 요소 (예 : Webkit 및 Opera)는 그렇지 않습니다. 실제로는 요소는으로 이동하지 않지만 해당 속성의 값은 업데이트됩니다. 따라서 정적으로 배치되지 않은 요소를 전달하지 않고 위치 값에 애니메이션을 적용하려고하면 브라우저간에 서로 다른 결과를 얻게됩니다.

CSS 전환을 지원하는 주요 브라우저의 최신 버전은 CSS 키 프레임도 지원하지만 일부 이전 버전은 CSS 키 프레임을 지원하지만 후자는 지원하지 않습니다. (예 : Opera 11.)

마지막으로, 내가 더 우아하게 이것을 수행하면 prefixfree을 사용하여 올바른 접두사를 직접 결정할 수 있습니다. 현재 접두어 배열에 대해 테스트합니다. 접두어가 붙지 않는 버전부터 시작합니다.

+1

+1 아주 멋지다! 테스트 div가 절대적으로 위치하지 않기 때문에 '오른쪽 상단 왼쪽 하단'에 거짓을 표시합니다. 이 문제를 어떻게 처리해야할지 모르겠다. 아마 테스트 div를 재정의하기 위해 요소를 전달할 수 있을까? – Duopixel

+0

좋은 지적! 선택적 요소 매개 변수를 추가하는 것이 좋습니다. 내 광대역이 죽었을 때 실제로 바이올린을 업데이트 한 것으로 나타났습니다. 내가 온라인으로 돌아 왔을 때 설명을 업데이트 할 것이다! :) –

+1

쿨! 또 다른 좋은 테스트는 실패 할 것으로 예상되는 인라인 요소에 CSS 변환을 애니메이션으로 적용하는 것입니다. – Duopixel

관련 문제