>  기사  >  웹 프론트엔드  >  CSS3 3D 행성 회전 및 브라우저 렌더링 원리 사용에 대한 자세한 소개

CSS3 3D 행성 회전 및 브라우저 렌더링 원리 사용에 대한 자세한 소개

高洛峰
高洛峰원래의
2017-03-19 16:44:191732검색

최근 웹 애니메이션에 빠졌는데, 학습 과정을 기록해서 여러분과 공유하겠습니다.

CSS3 3D 행성 회전 데모 페이지를 클릭하세요: 데모. (열려면 Chrome을 사용하는 것이 좋습니다.)

이 기사의 전체 코드와 더 많은 CSS3 효과를 내 Github에서 볼 수 있으니 별표를 주셨으면 좋겠습니다. CSS3 3D 행성 모션 효과 그림

무작위로 다른 스크린샷을 찍었습니다.

CSS3 3D 行星运转动画,太阳系动画

클릭하는 것이 좋습니다. CSS3 3D의 매력은 결국 보여줄 수 있는 사진이 제한되어 있기 때문입니다.

그러면 이번 CSS3 3D 행성 모션 애니메이션의 제작 과정은 자세히 설명하지 않겠습니다. 웹 애니메이션 소개와 CSS3 3D 行星运转动画,太阳系动画성능 최적화

에 초점을 맞추겠습니다. CSS3 3D에 대한 자세한 내용은 이전 블로그인 [CSS3 Advanced] Cool 3D Rotating Perspective를 검토하세요. 간단한 아이디어:

1. 이전 글에서 제작한 3D 포토월을 프로토타입으로 활용하고 수정합니다.

2. 각 구체를 만들기 위해 여러 가지 방법을 고민하다가 최종적으로 사용하게 되었습니다. 이 절충안을 통해 각 구는 그 자체로 CSS3 3D 모양이 됩니다. 그러면 제작 과정에서 Sass를 사용하여 CSS 애니메이션을 작성하는 지루한 과정을 많이 줄일 수 있습니다.

3. 데모에서는

Javascript

를 사용하여 마우스 팔로우를 작성했습니다. 이벤트를 듣고 이 이벤트를 제거하면 전체 행성 이동 애니메이션 자체가 순수 CSS로 구현됩니다.

다음은 성능 최적화의 관점에서 브라우저 렌더링 및 표시, 브라우저 다시 그리기 및 재배치, 애니메이션 성능 감지 최적화 등에 대해 이야기하는 내용입니다.

브라우저 렌더링과 디스플레이의 원리와 그것이 웹 애니메이션에 미치는 영향

자막이 좀 크네요. 이제 chrome 브라우저 커널은 Blink 커널(Chrome(버전 28 이상), Opera(버전 15 이상) 및 Yandex 브라우저에서 사용됨)이고 Firefox는 Gecko이고 IE는 Trident입니다. 브라우저 커널은 웹 페이지 해석을 담당합니다. 웹페이지를 렌더링(표시)할 때 다양한 브라우저 커널의 작동 원리는 완전히 일치하지 않습니다.

그래서 사실 아래에서 주로 다룰 내용은 크롬 브라우저에서의 렌더링 원리입니다. 크롬 커널 렌더링에 대해서는 검증 가능한 정보가 많기 때문에 다른 커널을 사용하는 브라우저에 대해서는 감히 결론을 내릴 수 없으므로 아래 설명은 기본적으로 크롬 브라우저에 대한 것입니다.

우선 몇 가지 결론을 내리고 싶습니다. API를 강제로 시작하려면 변환 API 대신

trans

for

m3d

api

를 사용하세요. GPU 가속

여기서 GPU 가속에 대해 이야기합니다. 왜 GPU가 3D 변환을 가속할 수 있나요? 이 모든 것은 브라우저의 기본 렌더링부터 시작되어야 합니다. 브라우저에서 웹 페이지를 렌더링하고 표시하는 과정은 진부하고 인터뷰에서 꼭 물어봐야 할 사항으로 대략적으로 나눌 수 있습니다. 1. HTML (HTML Parser)

2. DOM 트리 구축

3. 렌더 트리 구축

4. 렌더 트리 그리기(페인팅)

찾았습니다. 클래식 사진:

이 렌더링 프로세스는 기본 지식이므로 계속해서 더 자세히 살펴보세요.

페이지가 로드되고 구문 분석되면 브라우저에서 매우 친숙한 구조를 나타냅니다. DOM(使用CSS3 3D行星运转以及浏览器渲染原理详细介绍Document

Object

Model, Document Object 모델). 브라우저가 페이지를 렌더링할 때 개발자에게 노출되지 않는 많은 중간 표현을 사용하며, 그 중 가장 중요한 구조는 레이어입니다. 이 레이어가 이 기사의 초점입니다. Chrome에는 RenderLayer(DOM 하위 트리 담당), GraphicsLayer(RenderLayer 하위 트리 담당) 등 다양한 유형의 레이어가 있습니다. 다음으로 GraphicsLayer 레이어에 대해 논의하겠습니다.

GraphicsLayer 레이어는 텍스처로 GPU에 업로드됩니다.

여기서 질감은 매우 중요합니다.

질감이란 무엇입니까?

여기서 텍스처는 GPU 용어를 의미합니다. 이를 메인 메모리(예: RAM)에서 이미지 메모리(예: GPU의 VRAM)로 이동하는 비트맵 이미지라고 생각하세요. GPU로 이동한 후에는 이를 메쉬 형상과 일치시키고 Chrome의 텍스처를 사용하여 GPU에서 페이지 콘텐츠의 큰 부분을 가져올 수 있습니다. 3D CSS가 작동하는 방식인 매우 간단한 직사각형 그리드에 텍스처를 적용하여 다양한 위치(위치)와 변형을 쉽게 일치시킬 수 있습니다.

예제만 보면 이해하기 어렵습니다. 크롬에서는 위에서 언급한 레이어라는 개념을 볼 수 있습니다. 개발자 도구에서 다음을 선택하여 레이어 테두리 표시 옵션을 표시합니다.

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

아주 간단한 페이지에서는 아래와 같이 이 페이지를 볼 수 있습니다. 단 하나의 레이어. 파란색 그리드는 타일을 레이어 단위(레이어가 아님)로 생각할 수 있습니다. Chrome에서는 이를 대형 레이어의 일부로 GPU에 업로드할 수 있습니다.

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

요소 자체의 레이어 생성

위 페이지는 매우 간단하기 때문에 레이어가 생성되지 않지만, 예를 들어 매우 복잡한 페이지에서는 요소에 3D CSS 속성을 설정하여 변형할 수 있습니다. , 요소에 자체 레이어가 있을 때 어떻게 보이는지 확인할 수 있습니다.

이 뷰에서 레이어의 윤곽을 나타내는 주황색 테두리에 주목하세요.

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

레이어 생성은 언제 시작되나요?

위 다이어그램에서 노란색 테두리로 둘러싸인 레이어는 웹 애니메이션에 매우 중요한 GraphicsLayer입니다. 일반적으로 Chrome은 레이어의 콘텐츠를 GPU에 텍스처(페인트)로 업로드하기 전에 그립니다. )을 비트맵으로 변환합니다. 내용이 변경되지 않으면 레이어를 다시 칠할 필요가 없습니다.

이의 의미는 다시 그리는 데 소요되는 시간이 JavaScript 실행 등의 다른 작업에 사용될 수 있다는 것입니다. 그리기 시간이 너무 길면 애니메이션 실패 및 지연도 발생할 수 있습니다.

그렇다면 요소는 언제 레이어 생성을 트리거합니까? 현재로서는 다음 조건 중 하나라도 충족되면 레이어가 생성됩니다.

  • 3D 또는 원근 변환(perspective, Transform) CSS 속성

  • 가속 비디오 디코딩이 있는 39000f942b2545a5315c57fa3276f220 요소

  • 에는 3856173a0eceb679792f65a38e1fcb00 요소가 있는 3D(WebGL) 컨텍스트 또는 가속 2D 컨텍스트가 있습니다.

  • 하이브리드 플러그인(예: Flash)

  • 자신만의 불투명도에 따라 CSS 애니메이션을 수행하거나 애니메이션 변형 요소를 사용하세요

  • 가속 CSS 필터가 있는 요소

  • 요소에는 복합 레이어를 포함하는 하위 노드가 있습니다(즉, 요소에는 요소가 자체 레이어에 있는 하위 요소)

  • 요소의 하위 z-index가 있고 복합 레이어에 형제 요소가 포함되어 있습니다(즉, , 요소는 레이어 상단의 복합 렌더링에 있습니다)

레이어 다시 그리기

정적 웹 페이지의 경우 레이어를 그린 후에는 레이어가 변경되지 않습니다. 처음이지만 웹 애니메이션의 경우 페이지의 DOM 요소가 지속적으로 변경됩니다. 변환 프로세스 중에 레이어의 내용이 변경되면 레이어가 다시 그려집니다.

강력한 Chrome 개발자 도구는 애니메이션 페이지가 실행 중일 때 어떤 콘텐츠가 다시 그려졌는지 확인할 수 있는 도구를 제공합니다.

이전 버전에서는 크롬에는 페인트 사각형 표시 옵션이 있습니다. 페이지의 어떤 레이어가 다시 그려지고 빨간색 테두리로 표시되는지 확인할 수 있습니다.

그러나 새 버전의 Chrome에서는 이 옵션이 제거된 것 같습니다. 현재 옵션은 페인트 깜박임 활성화이며, 이는 웹사이트의 동적 변경 사항을 식별하는 데에도 사용되며 녹색 테두리로 표시됩니다.

위 다이어그램을 보면 페이지에 여러 개의 녹색 상자가 있어 다시 그리기가 발생했음을 나타냅니다. Chrome은 항상 전체 레이어를 다시 그리는 것은 아니며 DOM의 유효하지 않은 부분을 지능적으로 다시 그리려고 시도합니다.

논리적으로 말하면 페이지에 너무 많은 애니메이션이 발생하므로 다시 그리는 것이 매우 빈번해야 합니다. 그러나 위 그림의 내 행성 애니메이션에는 몇 개의 녹색 다시 그리기 상자만 표시됩니다. GPU 최적화, 두 번째는 전체 애니메이션 페이지에 레이어가 하나만 있는 경우 변형을 위해 변환을 사용하면 필연적으로 페이지를 다시 그려야 하지만 레이어링(GraphicsLayer) 기술, 즉 요소를 사용한다는 것입니다. 이때 생성된 레이어는 회전 등의 변형을 사용하므로 레이어를 반드시 다시 그릴 필요는 없습니다. (개인적인 의견이니 수정 부탁드립니다.)

웹 애니메이션 성능을 최적화하려면 레이어 다시 그리기를 이해하는 것이 중요합니다.

무효화 및 강제 다시 그리기의 원인은 무엇인가요? 경계 실패로 이어지는 상황이 많기 때문에 이 질문에 철저하게 답하기는 어렵습니다. 가장 일반적인 상황은 DOM을 수정하거나 CSS 스타일을 조작하여 리플로우를 발생시키는 것입니다.

다시 그리기 및 리플로우의 근본 원인을 찾는 가장 좋은 방법은 개발자 도구의 타임라인을 사용하고 페인트 플래싱 도구를 활성화한 다음 다시 그리기 직전에 DOM이 수정된 위치를 찾는 것입니다/ 리플로우.

요약

그럼 브라우저는 DOM 요소부터 최종 애니메이션까지 어떻게 표시할까요?

  • 브라우저가 HTML을 구문 분석하고 DOM을 획득하여 여러 레이어로 분할합니다(GraphicsLayer)

  • 노드에 대한 스타일 결과를 계산합니다. 각 레이어(스타일 재계산 – 스타일 재계산)

  • 각 노드에 대한 그래픽 및 위치 생성(레이아웃 – 리플로우 및 릴레이아웃)

  • 각 노드 변환 레이어 비트맵에 노드가 그려지고 채워집니다(Paint Setup 및 Paint–Redraw)

  • 레이어는 텍스처(texture)로 GPU에 업로드됩니다.

  • 여러 레이어를 페이지에 맞춰 최종 화면 이미지 생성(복합 레이어-레이어 재구성)

웹 애니메이션 비용의 큰 부분은 레이어를 다시 그리는 데 있습니다. , 레이어를 기본 복합 모델로 사용하면 렌더링 성능에 큰 영향을 미칩니다. 그리기가 필요하지 않은 경우 복합 작업의 오버헤드는 무시할 수 있으므로 렌더링 성능 문제를 디버깅할 때 첫 번째 목표는 레이어 다시 그리기를 방지하는 것입니다. 그런 다음 이는 애니메이션 성능 최적화를 위한 방향을 제공하고 요소의 다시 그리기 및 리플로우를 줄입니다.

리플로우 및 리페인트

여기서 먼저 리플로우와 리플로우라는 두 가지 개념을 구별해야 합니다.

리플로우

요소의 크기, 레이아웃, 숨기기 등의 변경으로 인해 렌더 트리의 일부(또는 전체)를 다시 작성해야 하는 경우. 이것을 리플로우(Reflow)라고 하며, 릴레이아웃(Relayout)이라고 합니다.

모든 페이지는 페이지가 처음 로드될 때 적어도 한 번은 리플로우되어야 합니다. 리플로우 동안 브라우저는 렌더링 트리의 영향을 받은 부분을 무효화하고 리플로우를 완료한 후 영향을 받은 부분을 화면에 다시 그립니다. 이 프로세스를 다시 그리기라고 합니다.

다시 칠하기

렌더링 트리의 일부 요소가 속성을 업데이트해야 하는 경우, 이러한 속성은 요소의 모양과 스타일에만 영향을 미치고 과 같은 레이아웃에는 영향을 미치지 않습니다. 배경색 . 다시 그리는 일이라고 합니다.

리플로우로 인해 반드시 다시 그리기가 발생하지만 다시 그리기로 인해 반드시 리플로우가 발생하지는 않는다는 점은 주목할 가치가 있습니다.

분명히 리플로우는 비용이 더 많이 듭니다. 간단히 말해서 리플로우는 요소를 작동하면 요소의 크기나 위치가 수정될 때 발생합니다.

리플로우가 실행되는 경우:

  • 창 크기 조정

  • 글꼴 변경)

  • 스타일시트 추가 또는 제거(스타일시트 추가 또는 제거)

  • 사용자가 입력하는 등 콘텐츠 변경 사용자가 콘텐츠를 변경하는 등

  • 입력 상자에 텍스트 입력)

  • CSS 활성화 의사 클래스 (예: :hover) (형제의 :hover(IE에서는 의사 클래스 활성화)와 같은 CSS 의사 클래스 활성화))

  • 조작 클래스 속성

  • DOM

  • 오프셋너비 및 오프셋높이 속성을 ​​계산하는 스크립트 (offsetWidth 및 offsetHeight 계산)

  • 스타일 설정 속성의 값 (스타일 속성의 속성 설정)

그래서 페이지의 경우 , 우리의 목적은 페이지의 리플로우와 다시 그리기를 최소화하는 것입니다.

// 下面这种方式将会导致回流reflow两次
var newWidth = ap.offsetWidth + 10; // Read
ap.style.width = newWidth + 'px'; // Write
var newHeight = ap.offsetHeight + 10; // Read
ap.style.height = newHeight + 'px'; // Write

// 下面这种方式更好,只会回流reflow一次
var newWidth = ap.offsetWidth + 10; // Read
var newHeight = ap.offsetHeight + 10; // Read
ap.style.width = newWidth + 'px'; // Write
ap.style.height = newHeight + 'px'; // Write


위의 네 문장은 offsetHeight 작업을 포함하기 때문에 브라우저가 두 번 리플로우하도록 강제하는 반면, 다음 네 문장은 오프셋 작업을 결합하므로 한 페이지 리플로우가 줄어듭니다.

리플로우와 다시 그리기를 줄이는 것은 실제로 렌더링 트리 작업을 줄이고(여러 DOM 및 스타일 수정을 병합), 일부 스타일 정보에 대한 요청을 줄이고, 브라우저의 최적화 전략을 최대한 활용하는 것을 의미합니다.

flushqueue

사실 브라우저 자체에는 최적화 전략이 있습니다. Javascript의 모든 문장은 DOM에서 작동합니다. 리플로우되고 다시 그려지면 브라우저가 이를 처리하지 못할 수도 있습니다. 따라서 많은 브라우저는 이러한 작업을 최적화합니다. 브라우저는 대기열을 유지하고 리플로우 및 다시 그리기를 유발하는 모든 작업을 이 대기열에 넣습니다. 대기열의 작업이 특정 수 또는 특정 시간 간격에 도달하면 대기열이 플러시되고 배치가 처리됩니다. 이렇게 하면 여러 리플로우 및 다시 그리기가 하나의 리플로우 및 다시 그리기로 전환됩니다.

그러나 때때로 다음과 같이 특정 스타일 정보를 정확하게 얻어야 하기 때문에 예외가 있습니다.


  • offset 상단, offsetLeft, offsetWidth, offsetHeight



  • scrollTop/Left / 너비/높이



  • 클라이언트 위쪽/왼쪽/너비/높이



  • 너비, 높이



  • 이 getComputeStyle()을 요청했거나 IE의 현재Style


이때, 가장 정확한 정보를 피드백하기 위해서는 브라우저가 우리에게 주어진 정보가 정확한지 확인하기 위해 즉시 reflow와 redraw를 해야 하므로 Flush Queue가 미리 실행될 수 있습니다.

display:none 및 visibility:hidden

은 모두 페이지에서 노드를 숨길 수 있습니다. 차이점은

  • display:none 숨겨진 요소가 공간을 차지하지 않는다는 것입니다. 너비, 높이 및 기타 속성 값은 "손실"됩니다.

  • visibility:hidden 숨겨진 요소 공간은 여전히 ​​존재합니다. 여전히 높이, 너비 등의 속성 값이 있습니다

성능 관점에서, 즉 리플로우 및 다시 그리기 측면에서

  • display :none은 리플로우를 트리거합니다

  • visibility:hidden은 위치 변경이 발견되지 않기 때문에 다시 그리기만 트리거합니다

최적화에서 가시성은 다음과 같습니다. 숨김으로 인해 문서에 정의된 표시 계층 구조를 변경하지 않기 때문에 숨김이 더 잘 나타납니다.

하위 요소에 미치는 영향:

  • display:none 상위 노드 요소에 display:none이 적용되면 상위 노드와 해당 하위 노드 요소가 모두 표시되지 않습니다. 표시 값이 어떻게 설정되었는지에 관계없이 하위 요소를 표시할 수 없습니다.

  • visibility:hidden visible:hidden이 상위 노드 요소에 적용되면 모든 하위 요소도 표시됩니다. 눈에 띄지 않게. 그러나 숨겨진 "실패"가 있습니다. visible:visible이 하위 요소에 적용되면 하위 요소가 다시 나타납니다.

애니메이션 성능 감지 및 최적화

성능 소모 스타일

스타일에 따라 성능 소모도 다릅니다. 예를 들어 Box- 그림자는 다른 스타일에 비해 그리기 코드를 실행하는 데 너무 오래 걸리기 때문에 렌더링 관점에서 성능 집약적입니다. 즉, 성능 집약적인 스타일을 자주 다시 그려야 하는 경우 성능 문제가 발생하게 됩니다. 둘째, 오늘은 부진한 스타일이 내일은 최적화될 수 있다는 점을 알아야 하며, 브라우저마다 차이가 있습니다.

따라서 핵심은 개발 도구를 사용하여 성능 병목 현상을 식별한 다음 브라우저의 작업 부하를 줄이는 방법을 찾는 것입니다.

다행히도 Chrome 브라우저는 위에서 언급한 것 외에도 아래의 쇼 FPS 미터를 확인하여 페이지의 FPS 정보를 표시할 수 있는 많은 강력한 기능을 제공합니다. GPU 사용량:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

will-change를 사용하여 페이지 스크롤, 애니메이션 등의 렌더링 성능을 향상시킵니다.

공식 문서에 따르면 , 이는 아직 실험적인 기능이므로 이 기능의 구문과 동작은 브라우저의 향후 버전에서 변경될 수 있습니다.

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

使用方法示例:(具体每个取值的意义,去翻翻文档)

will-change: auto
will-change: scroll-position
will-change: contents
will-change: transform        // Example of <custom-ident>
will-change: opacity          // Example of <custom-ident>
will-change: left, top        // Example of two <animateable-feature>

will-change: unset
will-change: initial
will-change: inherit

// 示例
.example{
    will-change: transform;
}

will-change 为 web 开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。 这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。

值得注意的是,用好这个属性并不是很容易:


  • 不要将 will-change 应用到太多元素上:浏览器已经尽力尝试去优化一切可以优化的东西了。有一些更强力的优化,如果与 will-change 结合在一起的话,有可能会消耗很多机器资源,如果过度使用的话,可能导致页面响应缓慢或者消耗非常多的资源。



  • 有节制地使用:通常,当元素恢复到初始状态时,浏览器会丢弃掉之前做的优化工作。但是如果直接在样式表中显式声明了 will-change 属性,则表示目标元素可能会经常变化,浏览器会将优化工作保存得比之前更久。所以最佳实践是当元素变化之前和之后通过脚本来切换 will-change 的值。



  • 不要过早应用 will-change 优化:如果你的页面在性能方面没什么问题,则不要添加 will-change 属性来榨取一丁点的速度。 will-change 的设计初衷是作为最后的优化手段,用来尝试解决现有的性能问题。它不应该被用来预防性能问题。过度使用 will-change 会导致大量的内存占用,并会导致更复杂的渲染过程,因为浏览器会试图准备可能存在的变化过程。这会导致更严重的性能问题。



  • 给它足够的工作时间:这个属性是用来让页面开发者告知浏览器哪些属性可能会变化的。然后浏览器可以选择在变化发生前提前去做一些优化工作。所以给浏览器一点时间去真正做这些优化工作是非常重要的。使用时需要尝试去找到一些方法提前一定时间获知元素可能发生的变化,然后为它加上 will-change 属性。


使用 transform3d api 代替 transform api,强制开始 GPU 加速

GPU 能够加速 Web 动画,这个上文已经反复提到了。

3D transform 会启用GPU加速,例如 translate3D, scaleZ 之类,当然我们的页面可能并没有 3D 变换,但是不代表我们不能启用 GPU 加速,在非 3D 变换的页面也使用 3D transform 来操作,算是一种 hack 加速法。我们实际上不需要z轴的变化,但是还是假模假样地声明了,去欺骗浏览器。

위 내용은 CSS3 3D 행성 회전 및 브라우저 렌더링 원리 사용에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.