그림 조각의 회전식 효과

머리말

어떤 웹 사이트를 무심코 방문했을 때 그 홈페이지의 캐 러셀 효과에 깊은 매력을 느꼈습니다. 브라우저 디버깅을 통해 마침내 구현 원리를 이해하고 마침내 직접 사본을 썼습니다 Demo. 최종 효과는 다음과 같습니다. 소스 코드가 끝에 있습니다)

평면 효과 :

여기에 사진 설명 삽입

3D 효과 :

여기에 사진 설명 삽입

이 캐 러셀은 그림을 여러 조각으로 자른 다음, 자른 조각을 애니메이션 효과로 차례로 재생하고 마지막으로 새 그림으로 연결합니다.

프론트 엔드 기술 스택을 리콜하는 과정에서 이미지를 직접 자르고 여러 조각으로 나눌 수있는 기술은없는 것 같습니다. 일반적으로 적용하는 이미지 자르기 효과 canvas는 생성을 시뮬레이션하는 데만 사용 됩니다.

내 자신의 디버깅을 통해이 회전식 그림은 canvas동일한 자르기 효과를 얻기 위해 더 간단한 방법을 사용하는 것으로 나타났습니다 .

다음으로, 더 얕은 것에서 더 깊은 것까지 단계적으로 진행하여 구현 원칙을 드러내십시오.

평면 효과

평면 효과부터 시작해 보겠습니다. 먼저 일반적인 html회전식 다이어그램을 작성합니다. 구조는 다음과 같습니다.

 <div class="main" id="el">
       <div class="item">
         <img src="./img/1.jpg" />
       </div>
       <div class="item">
         <img src="./img/2.jpg" />
       </div>
       <div class="item">
         <img src="./img/3.jpg" />
       </div>
 </div>

el세 개의 회전 목마 그림이 들어있는 외부 컨테이너입니다.

애니메이션 효과를 만들고 싶다면 한 단계를 따라야합니다.

  • 애니메이션 할 dom요소 생성 또는 가져 오기
  • dom애니메이션 효과를 추가 받는 요소

이제 다음 그림과 같이 평면 효과의 애니메이션 속도를 줄이고 특성을주의 깊게 관찰하십시오.

여기에 사진 설명 삽입

html이 그림 조각은 원본 코드 에서 찾을 수 없습니다. 즉, 애니메이션 할 요소를 우리가 생성하고 렌더링을 위해 페이지 문서에 추가해야합니다.

설정 그림을 여러 5부분 으로 자르면 다음과 같이 슬라이스 이미지 구조를 생성합니다.

   <div class="main" id="el">
         <div class="item">
           <img src="./img/1.jpg" />
         </div>
         <div class="item">
           <img src="./img/2.jpg" />
         </div>
         <div class="item">
           <img src="./img/3.jpg" />
         </div>
         <!--做动画的dom元素-->
         <div class="hook">
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
         </div>
   </div>

하여 일본어 페이지 js주기라는 클래스 생성 hook의를 html片段측위 모드로서, absolute.

hook다섯 가지가 있습니다 div각각 보여 2.jpg해당 사진 컷 문제가 지금 직면하는 방법이 있도록하는 것입니다 5하나가 div이 그림 그것의 일부를 확장 할 수 있었습니까?

hook외부 용기를 설정 하면 1000px하위 요소 5의 총 너비가 div평균 200px2 차로 제공 될 수 있으며 2 차 컷만 div표시 되도록 할 수 있습니다 img.

  <div style="position:absolute;width:200px;left:200px;overflow:hidden">
     <img src="./img/2.jpg" style="position:absolute;width:500%;left:-200px"/>
  </div>

외층의 총 폭 이후 1000px에, 컷 5부를 각각 div나타내는 200px(실제의 부호화 200를 통해 js계산 된), 그리고 우측으로 이동 200px번째 슬라이스 위치를 점유.

imgwidth합계 left할당이 요점이며 특정 값도 총 너비와 슬라이스 수로 계산됩니다.

width로 설정 500%하면 그림의 너비가 1000px가장 바깥 쪽 컨테이너와 같고 왼쪽으로 이동합니다 200px. 부모가 div설정되어 overflow:hidden있으므로 효과를 상상하면 효과가 나옵니다.

위에서 언급 한 이러한 프로세스 는 다음과 유사한 js문자열 연결되고 계산 되어야합니다 html字符串.

  for(i=0;i<n;i++){ //循环i次,n(总共将图片切成n份),unit_width对应每一个切块的宽度
           html += `
               <div 
               style="position:absolute;
               width:${unit_width}px;
               top:-100%;
               left:${ i * unit_width};
               overflow:hidden">
                   <img src="${src}" 
                       style="position:absolute;
                       width:${n*100}%;
                       left:${-i * unit_width}px"/>
              </div>
     `     
  }

5애프터 div바느질이 완료,에 넣어 <div class="hook"></div>자신과 페이지 문서 렌더링에 추가합니다. 마지막으로 생성 된 dom요소는 다음 애니메이션 할 수있는 요소입니다.

이후 절대 위치 및 세트 값이 설정되고 , 이들이 한번 렌더링되도록 페이지의 상위에 위치한다.5divtop-100%

다음 애니메이션 효과는 달성하기가 매우 쉽습니다. 위의 루프에서 각각 div하나만 추가 하면됩니다 transition:top linear 0.25s.

한번 렌더링이 완료 될 때, 우리가 할 수 동적으로 각 설정 애니메이션이 트리거, 각 페이지는 천천히 위에서 아래로 슬라이딩.5divjsdivtop0div

모든 애니메이션 프로세스가 완료 될 때까지 기다립니다. hook이 사용 jsdom제거되고 표시되어야합니다 item(원본의 정적 사진 포함 dom)는 전체 애니메이션 프로세스가 완료된이 시점에서 숨겨진 표시로 설정됩니다.

3D 효과

평면의 효과는 상대적으로 구현이 간단하고, 3D반전 효과는 필요 에 대한 이해 첫 번째 속성을.css3d

3D 부동산 검토

rotateX: X회전축을 중심으로 Lenovo 单杠运动.
rotateY: Y회전축을 중심으로 Lenovo 钢管舞.
rotateZ: Z회전축을 중심으로 Lenovo 老式钟表盘.

위의 세 가지 속성은 일반적으로 많이 접촉하므로 반복하지 않겠습니다. 다음은 3d속성에 중점을 둡니다 .

    .container{
       perspective: 1200px;
       perspective-origin: right center;
      .wrapper {
        transform-style: preserve-3d;
        transform:translateZ(-100px);
      }
    }

외부 컨테이너 container에는 자식이 포함 되어 있습니다 wrapper. 자식은 3d애니메이션 할 특정 요소이므로 속성을 설정해야합니다 transform-style: preserve-3d.

설정된 경우에만 preserve-3d요소가 그 3d효과를 표시 할 수 있습니다 .

translateZ그리고 translateX, translateY이 두 속성은 동일하지 않습니다. translateX평면에서 이동하려고 translateY하며 수직 평면에서 이동합니다.

translateZ그것은이입니다 3d구성하지 않습니다 attribute.It, 아래, 왼쪽, 비행기 오른쪽 변위하지만, 또는 방향의 수직 중 평면에 변위를합니다.

translateZ(-100px)요소가 화면 내부로 이동했음을 의미합니다 100px. 근거리, 거대, 먼, 작은 규칙 에 따라 요소 의 최종 시각 효과가 전체적으로 100px감소 합니다. 양수일 경우 화면으로 이동합니다. 화면 외부 100px에서 요소의 시각적 효과가 확대됩니다.

translateZpreserve-3d속성이 설정된 요소 에만 적용하면 preserve-3d모든 3d속성이 적용될 수 있습니다.

block3d변형 dom요소이므로 설정 preserve-3dtransform변형 이 필요하며 , 부모 요소는 container무대와 동일하며 block무대 공연의 배우로 볼 수있다.

perspective관객과 무대 사이의 거리를 나타내는 것으로 perspective, 값이 작을수록 관객이 무대에 가까워지고 무대 위의 장면이 더 선명하게 보일 것이라고 생각할 수있다.

실제 장면에 해당 perspective에 해당하는 dom의 요소 사이의 거리 사용자의 눈의 더 큰 거리, 멀리 떨어진 wrapper작고 적은 내부를 취소합니다. 반대로, perspective더 큰, wrapper더 큰 모양을하고 내부 세부 사항이 더 명확 해집니다.

perspective-origin무대 위에서 공연을보기 위해 사용자가 강당의 왼쪽, 중간, 오른쪽에 앉아 있는지, 시야의 영향이 다른 것으로 이해할 수있다.

이제 주제로 돌아가서 3d뒤집기 효과의 회전식 다이어그램을 계속 연구 합니다. 다음 그림과 같이 애니메이션 시간을 줄임으로써 세부 사항을 관찰합니다.

여기에 사진 설명 삽입

위의 그림을보고 애니메이션 할 요소는 현재 페이지에서 사용할 수 없으며 js동적으로 생성 해야한다는 것을 금방 깨달았습니다 .

애니메이션 요소는 두 개의 모션 효과를 포함하는 큐브입니다. 하나는 왼쪽으로 이동하고 다른 하나는 앞으로 뒤집는 것입니다. 왼쪽으로 이동하는 것은 쉽게 할 수 있으며 절대 위치 동적 변경 left으로 설정합니다 . RotateX(-90deg)Arrived 를 설정 하면됩니다 ( X축을 따라 90각도 뒤집는 것과 동일 ).

큐브의 애니메이션 효과는 달성하기 어렵지 않으며 이러한 큐브를 생성하는 방법에 어려움이 있습니다.

큐브 그리기

현재 장면에서 큐브는 위, 앞, 왼쪽 및 오른쪽의 네 개의 면만 그리면됩니다. 위는 다음 사진이 캐 러셀로 저장되고 앞면은 현재 표시된 사진, 왼쪽과 오른쪽은 검은 색. 배경은 그림을 더욱 입체적으로 만들기 위해 채워 html지며 구조는 다음과 같습니다.


   <div class="wrapper">
            <div class="left"></div>
            <div class="right"></div>
            <div class="front"><img src="1.jpg"></div>
            <div class="up"><img src="2.jpg"></div>
   </div>

left, right, frontup부모 요소로 채워져있다 절대 위치, 폭과 높이로 설정 left하고 top설정 0.

front바로 정면에있는 얼굴이고, 원래는 평면에 표시되어 있으며 어떤 처리도 할 필요가 없습니다.

left중심점을 왼쪽 상단 모서리에 배치하려면 y축을 따라 렌더링 90각도가 측면을 형성합니다.

.left {
  transform-origin: 0% 0%;
  transform: rotateY(90deg);
  background-color: #333;
}

right전체 너비를 오른쪽으로 이동 한 다음 y 축을 따라 회전 90하여 오른쪽을 형성해야합니다.

html += `
    ... //js中dom字符串拼接
   <div class="right" style="transform: translateX(${unit_width}px) rotateY(90deg);">
      ...
   </div>
   ...
`

up표면은 먼저 왼쪽 하단 모서리에 중심점을 설정하고 X축을 중심으로 회전 90한 다음 전체 높이 위로 이동하여 상단을 형성합니다.

.up{
    transform-origin: 0% 100%;
}
html += `
    ... //js中dom字符串拼接
   <div class="up" style="transform: rotateX(90deg) translateZ(${container_height}px);">
     ...
   </div>
   ...
`

이 네면 dom구조는 js내부에 스 플라이 싱되어 wrapper해당 부모에 배치됩니다 div. 위에서 언급했듯이 속성 wrapper은 내부 preserve-3d설정되어야 wrapper하며 요소는 실제로 애니메이션되는 요소입니다 dom.

wrapper요소가 캡슐화 된 후에는 무대 요소로 발생합니다 container, 그리고 속성 container설정됩니다 .3dperspectiveperspective-origin

하나 container는 큐브 슬라이스에 해당하고 잘라낸 모든 큐브에 의해 형성된 html문자열을 페이지 문서에 넣고 렌더링하는 방식으로 애니메이션 dom요소가 생성됩니다.

플립 애니메이션 추가

애니메이션 dom수행하는 요소가 페이지에 생성되어 렌더링되었습니다. 이전 분석에 따르면 각 큐브 ( wrapper해당 div)에 rotateX(-90deg)속성 추가 하면 큐브가 뒤집힐 수 있습니다. 결과는 다음과 같습니다.

여기에 사진 설명 삽입
wrapper또한 rotateX(-90deg)속성은 실제로 앞으로 뒤집혀 있지만 최종 위치는지면에 가깝지 않습니다.

사고의 원인은 wrapper단순한 평면이 아닌 입방체 이기 때문에 4 개의 평면도 포함되어 있었기 때문에 이제 입방체가 회전 할 때 중심점의 위치가 매우 중요합니다.

wrapper의 높이는 100%부모 전체 가득 차 있습니다. 테스트를 통해 큐브의 속성 변환은 실제로 앞면 ( front얼굴)을 기준으로하는 것으로 나타났습니다. 큐브 의 중심점 은 얼굴 높이의 front중간에 위치 front합니다. 경우]. 얼굴의 높이 인 600px다음 경우 300px드로잉 X축이 축 방향의 전체 큐브를 회전한다.는 IF front표면의 높이가 800px, 그 큐브 것이다 400px회전 에 따라 축.

이제 위의 경우로 돌아 가면 front얼굴의 높이가 100%부모 요소 채우도록 설정되고 큐브는 가운데에 축을 그리고 앞으로 뒤집기 90때문에 아래에 빈 공간이 생깁니다. 우리는 큐브를 놓을 수 없습니다. 공중에서 회전 및 정지, 지상에 다시 놓을 방법을 찾으려면.

앞서 말씀 드린 front대로 입방체는 표면을 기준면으로 사용합니다 .도를 뒤집 90으면 front표면이 바닥으로 오게됩니다. 그러면 입방체가 front바닥을 향하고 있기 때문에 아래로 내려 가야 합니다. translateZ(contrainer_height/2)정육면체를 아래로 이동시키기 위해 설정하기 만하면되고 높이의 절반이 바닥에 부착됩니다.

이 설정은 뒤집힌 큐브가 바닥에 부착되도록 보장 할 수 있지만 그 안의 그림은 변형됩니다.

정육면체가 rotateX(-90deg)앞으로 뒤집 히도록 설정 되어 있으면 실제로 앞으로 이동합니다. 거의 크고 작음의 규칙에 따라 그림의 시각적 효과가 확대됩니다.이 문제를 해결하려면 먼저 큐브 translateZ(-contrainer_height/2)사용하여 절반을 밀어 내부 높이의 높이를 설정 한 다음 큐브를 앞으로 뒤집어 이미지 스트레칭 문제를 해결하면 코드는 다음과 같습니다.


while ((el = eles.shift())) {
    //el对应着每个立方体的dom
    //立方体先沿Z轴往后推一半高度,再朝前做翻转,翻转完后向下移动一半高度贴底 
    el.style.transform = `translateZ(${  
      -this.container_height / 2
    }px) rotateX(-90deg) translateZ(${this.container_height / 2}px)`;
    ...
  }

뒤집기 효과가 끝나면 입방체가 우리를 향하고 뒤집히는 것을 알 수 있습니다. 검은 색 배경으로 입방체의 오른쪽을 볼 수 없으므로 right매우 비차 원적으로 보입니다.

아까 속성을 소개했는데, perspective-origin:right center마치 강당 오른쪽에 앉아있는 관객과 같고, 무대는 강당만큼 넓고, 객석을 향한 무대에는 철제 케이지가 있습니다. 청중의 시야는 철제 케이지 앞쪽에서만 볼 수 있습니다. 케이지를 무대 왼쪽으로 밀면 청중 오른쪽에 앉은 고객은 철제 케이지의 전면 만 볼 수 없습니다. ,하지만 철창 오른쪽도 볼 수 있습니다.

같은 방식으로 큐브를 뒤집었을 때 입체적으로 보이게하려면 애니메이션 도중 오른쪽의 검은 색 배경을 표시 할 수 있습니다.이를 위해 큐브를 왼쪽으로 이동해야합니다. , perspective-origin속성의 지원 을 더한 큐브는 뒤집힌 입체적인 효과가 나옵니다.

큐브를 왼쪽으로 이동하려면 큐브의 dom요소를 가져와 left동적으로 할당 하기 만하면됩니다.

소스 코드

완전한 코드

추천

출처blog.csdn.net/brokenkay/article/details/115034048