preface
Some time ago the “spirit cage” to watch, personally feel very good (in addition to the update is slow). The characters left a deep impression on me. Such as Ran Bing, He Guang fenty, bai Yuekui and so on. Oh, and Mark. Since I like many characters, I wanted to write something to show them. Hence the 3D rotating photo album. Well, not much to say, let’s start to achieve step by step.
Page structure
<style type='text/css'>
* {
margin: 0;
padding: 0;
}
.container {
display: flex;
min-height: 100vh;
perspective: 800px;
background: #000;
touch-action: none;
}
.wrap {
position: relative;
width: 120px;
height: 180px;
margin: auto;
transform-style: preserve-3d;
pointer-events: none;
}
.wrap img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%; object-fit: cover; border-radius: 2px; } </style> <div class="container"> <div class="wrap"> <img src=".. /images/incarnation/baiyuekui.jpg" alt=""> <img src=".. /images/incarnation/heguanzhe.jpg" alt=""> <img src=".. /images/incarnation/ailika.jpg" alt=""> <img src=".. /images/incarnation/jiexika.jpg" alt=""> <img src=".. /images/incarnation/chenmin4277.jpg" alt=""> <img src=".. /images/incarnation/feixue.jpg" alt=""> <img src=".. /images/incarnation/hongkou.jpg" alt=""> <img src=".. /images/incarnation/peini.jpg" alt=""> <img src=".. /images/incarnation/suixing.jpg" alt=""> <img src=".. /images/incarnation/jingnan.jpg" alt=""> <img src=".. /images/incarnation/xiadou.jpg" alt=""> <img src=".. /images/incarnation/ranbing.jpg" alt=""> </div> </div>Copy the code
Perspective and transform-style are used to achieve the 3D effect. Use positioning to overlap all the images.
intro
/ / get the dom
const container = document.querySelector('.container');
const wrap = document.querySelector('.wrap');
const imgList = document.querySelectorAll('.wrap img');
const length = imgList.length;
// Calculate the image spacing Angle
const angle = 360 / length;
// The start animation delay is 1000/60 = 16.666667 ≈ 17, otherwise transition will not work
setTimeout(() = > {
for (let i = 0; i < length; i++) {
// Each image transition effect interval 0.1s
imgList[i].style.transition = 'transform 1s ease ' + (length - 1 - i) * 0.1 + 's';
// Offset along the z-axis by 320 pixels (set this distance as you see fit), otherwise the images will be crowded together
imgList[i].style.transform = 'rotateY(' + (angle * i) + 'deg) translateZ(320px)'; }},17);
// Wrap rotates -10 degrees along the X-axis
const rotate = { x: -10.y: 0 };
wrap.style.transform = 'rotateX(' + rotate.x + 'deg)';
Copy the code
Drag and drop to view
let isPointerDown = false;
let point = null;
let last = null;
let diff = null;
let rafId = null;
// Listen for pointerDown events
container.addEventListener('pointerdown'.function (e) {
this.setPointerCapture(e.pointerId);
isPointerDown = true;
// Stop the animation
cancelAnimationFrame(rafId);
point = { x: e.clientX, y: e.clientY };
last = { x: e.clientX, y: e.clientY };
diff = { x: 0.y: 0 };
});
// Listen for pointerMove events
container.addEventListener('pointermove'.function (e) {
if (isPointerDown) {
const current = { x: e.clientX, y: e.clientY };
// Calculate the difference with respect to the last move
diff = { x: current.x - last.x, y: current.y - last.y };
// The rotation Angle is multiplied by 0.1 to reduce the sensitivity of the rotation and prevent it from rotating too fast. You can set the appropriate value
rotate.x -= diff.y * 0.1;
rotate.y += diff.x * 0.1;
last = { x: current.x, y: current.y };
wrap.style.transform = 'rotateX(' + rotate.x + 'deg) rotateY(' + rotate.y + 'deg)'; }});// Listen for pointerup events
container.addEventListener('pointerup'.function (e) {
isPointerDown = false;
// Roll by inertia
raf();
});
// Listen for the PointerCancel event
container.addEventListener('pointercancel'.function (e) {
isPointerDown = false;
});
Copy the code
The above code is implemented using a PointerEvent PointerEvent. If you don’t know much about pointer events, check out this article. Js PointerEvent A brief introduction to pointer events.
Inertial scrolling
function raf() {
// ES6 deconstructs the assignment
let { x, y } = diff;
function step() {
/ / the friction
x *= 0.95;
y *= 0.95;
rotate.x -= y * 0.1;
rotate.y += x * 0.05;
wrap.style.transform = 'rotateX(' + rotate.x + 'deg) rotateY(' + rotate.y + 'deg)';
// < 1 stop animation
if (Math.abs(x) > 1 || Math.abs(y) > 1) {
rafId = requestAnimationFrame(step);
}
}
rafId = requestAnimationFrame(step);
}
Copy the code
Demo: jsdemo codeman. Top/HTML / 3 dphot…