머리말
어떤 웹 사이트를 무심코 방문했을 때 그 홈페이지의 캐 러셀 효과에 깊은 매력을 느꼈습니다. 브라우저 디버깅을 통해 마침내 구현 원리를 이해하고 마침내 직접 사본을 썼습니다 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
평균 200px
2 차로 제공 될 수 있으며 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
번째 슬라이스 위치를 점유.
img
width
합계 의 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
요소는 다음 애니메이션 할 수있는 요소입니다.
이후 절대 위치 및 세트 값이 설정되고 , 이들이 한번 렌더링되도록 페이지의 상위에 위치한다.5
div
top
-100%
다음 애니메이션 효과는 달성하기가 매우 쉽습니다. 위의 루프에서 각각 div
하나만 추가 하면됩니다 transition:top linear 0.25s
.
한번 렌더링이 완료 될 때, 우리가 할 수 동적으로 각 설정 의 값 애니메이션이 트리거, 각 페이지는 천천히 위에서 아래로 슬라이딩.5
div
js
div
top
0
div
모든 애니메이션 프로세스가 완료 될 때까지 기다립니다. hook
이 사용 js
은 dom
제거되고 표시되어야합니다 item
(원본의 정적 사진 포함 dom
)는 전체 애니메이션 프로세스가 완료된이 시점에서 숨겨진 표시로 설정됩니다.
3D 효과
평면의 효과는 상대적으로 구현이 간단하고, 3D
반전 효과는 필요 에 대한 이해 의 첫 번째 속성을.css
3d
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
에서 요소의 시각적 효과가 확대됩니다.
translateZ
preserve-3d
속성이 설정된 요소 에만 적용하면 preserve-3d
모든 3d
속성이 적용될 수 있습니다.
block
3d
변형 될 dom
요소이므로 설정 preserve-3d
및 transform
변형 이 필요하며 , 부모 요소는 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
, front
및 up
부모 요소로 채워져있다 절대 위치, 폭과 높이로 설정 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
설정됩니다 .3d
perspective
perspective-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
동적으로 할당 하기 만하면됩니다.