Implementation effect
The development of preparation
- Design drawing: spherical projection
- Principle:
- Cut, put together into a ball
- You start stacking them, you rotate them at an Angle, and then you push them out along the Z axis, and you get close to a sphere
- In this example, cut the design drawing into 20 pieces
Method 1: Do it yourself
The code structure
├─ Audio # Background Music
│ └ ─ ─ happy. Mp3
├─ CSS # Global CSS
│ └ ─ ─ index. The CSS
├─ IMG # Pictures (Background, Spherical Projection slice -20 copies)
├─ Index.html # page
├ ─ ─ script # js
│ └ ─ ─ index. Js
├ ─ └─ start. Bat # Start http-server for cell phone testing
html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<! Viewport -->
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
<title>Css3d creation section</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<! -- Voice player -->
<audio id="audio">
<source src="./audio/happy.mp3" type="audio/mpeg">
</audio>
<! - the horn -- -- >
<div id="laba">🎺</div>
<! -- 3D container -->
<div class="container">
<! -- 3D box for pictures -->
<div id='box' class="box"></div>
</div>
<script src="./script/zepto.min.js"></script>
<script src="./script/index.js"></script>
</body>
</html>
Copy the code
css
- 1rem = 16px; Rem based on the root font size, HTML default font size: 16px;
- Each image: 129px wide by 1170px high
* {
padding: 0;
margin: 0;
}
body {
background-image: url('.. /img/bg.jpg');
}
#laba {
position: absolute;
top: 1rem;
right: 1rem;
z-index: 999;
}
.container {
margin: 0 auto;
width: 8.0625 rem; / * * / 129
perspective: 25rem; /* Set the viewing distance to 400 */
}
.container .box {
height: 100%;
transform-style: preserve-3d;
perspective-origin: 50% 50%; /* Set the observation center. * /
}
.container .box > div {
position: absolute;
width: 8.0625 rem; / * * / 129
height: 73.125 rem; / * * / 1170
}
Copy the code
js
/** * Get DOM node * by id@param {*} id
* @returns* /
function _ $(id) {
return document.getElementById(id);
}
/** * Calculate the radius *@param Length The width of each image *@param Count How many pictures *@return The length of the radius */
function calculateRadius(width, count) {
// r = width of each image /2 / TRAN (degree of each image /2); Degree of each copy = 360/ number of pictures = 360/20 = 18
// Math.PI = 180
// Why subtract 3, because when you combine a circle, there are two edges that need to merge -2, and there is still a 1px edge, so subtract -1 from this edge
// return Math.round(width / (2 * Math.tan((Math.PI * 2) / count / 2))) - 3;
return Math.round(width / (2 * Math.tan(Math.PI / count))) - 3;
}
/** * Create image and layout *@param {*} $el box
* @param {*} Len Number of images *@param {*} R Adjust the Angle */
function createDIVLayout($el, len, r) {
// Add nodes in batches
const fragment = document.createDocumentFragment();
const _img_url_prefix = './img/p{n}.png';
for (let i = 1; i <= len; i++) {
const div = document.createElement('div');
// The auxiliary tag can be removed
div.innerHTML = i;
/ / set the CSS
div.style.background = `url(${_img_url_prefix.replace(/\{n\}/g, i)}) no-repeat`;
div.style.WebkitTransform = `rotateY(The ${(360 / len) * i}deg) translateZ(${r}px)`;
// Add to fragment
fragment.appendChild(div);
}
// Add fragment batch to $el
$el.appendChild(fragment);
}
/* Define constant */
const IMG_LEN = 20;
const IMG_W = 129;
const radius = calculateRadius(IMG_W, IMG_LEN);
/* Get the relevant DOM node */
const box = _$('box');
const audio = _$('audio');
/* Create image and layout */
createDIVLayout(box, IMG_LEN, radius);
/* Zepto event */
// Control background music playback and pause
$('#laba').on('tap'.function () {
if (audio.paused) {
audio.play();
$(this).text('⏸');
} else {
audio.pause();
$(this).text('🎺'); }});// Drag the box around y
let startX = 0; // the finger starts at the X position
let endX = 0; // The X position when the finger is released
let x = 0; // The distance moved
let flag = true; // It is used to distinguish between touch triggered rotation and the phone's own rotation through the gyroscope
let touching = false;
$('#box').on('touchstart'.function (event) {
event.preventDefault();
const touch = event.targetTouches[0];
startX = touch.pageX - x;
touching = true;
});
$('#box').on('touchmove'.function (event) {
if (flag && touching) {
event.preventDefault();
const touch = event.targetTouches[0];
endX = touch.pageX;
x = endX - startX;
// How much x is moved is rotated about the y axis
box.style.transform = `rotateY(${x}deg)`; }}); $('#box').on('touchend'.function () {
touching = false;
});
// Monitor gyroscope - rotation Angle, used to change the rotation Angle of the mobile phone when it moves around the y axis
window.addEventListener('deviceorientation'.function (event) {
const gamma = event.gamma;
if (Math.abs(gamma) > 1) {
flag = false;
box.style.transform = `rotateY(${gamma * 3}deg)`; // Multiply by 3, mainly to make it faster
} else {
flag = true; }});Copy the code
Start the server
- Http-server Simply enable a server for local folders, because mobile phones cannot access local files on your PC
- Install http-server: NPM i-g http-server
- In the current code root directory, run the http-server -p 8000 command to start the service
- Enter http://10.1.251.161:8000 in the PC browser to verify that the page can be opened
Mobile Viewing
- Generate qr codes for local service addresses: The forage QR code generator can be used here
- Wechat scan code
Method 2: Use ss3D-engine
Css3d-engine is a very good css3D library, easy to get started, mainly master the following elements
- Stage: The position we place
- Plane: Used when building a Plane
- Camera: Necessary for 3D scenes, think of the Camera as our eyes
- Cube (Box): Build cubes to use
- Skybox: Used when building panoramic backgrounds
There are three elements that make up a 3D effect: scene, object and perspective. It’s much easier to understand 3D when you have these three elements:
The code structure
├─ IMG # Pictures (Background, Spherical Projection slice -20 copies)
├─ Index.html # page
├ ─ ─ script # js
│ └ ─ ─ css3d. Js
├ ─ └─ start. Bat # Start http-server for cell phone testing
html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="main" style="width:500px; height:500px;"></div>
<script type="text/javascript" src="./js/css3d.js"></script>
<script>
// Constract
const PANO_RECT = { w: 2586.h: 1170 };
const IMG_LEN = 20;
const _img_prefix = 'img/p{n}.png'
// Create a scene
const s = new C3D.Stage();
// Set the scene size and material, here is the background image
s.size(window.innerWidth, window.innerHeight).material({
image: 'img/bg.jpg'
}).update();
document.getElementById('main').appendChild(s.el);
const createPano = rect= > {
const _step = rect.w / IMG_LEN;
const _radius = Math.floor(_step / 2 / Math.tan(Math.PI / IMG_LEN)) - 1;
// Create a Sprite image
const _sp = new C3D.Sprite();
for (let i = 1; i <= IMG_LEN; i++) {
const _p = new C3D.Plane();
const _r = 360 / IMG_LEN * i;
const _a = Math.PI * 2 / IMG_LEN * i;
const img = _img_prefix.replace(/\{n\}/g, i);
_p.size(_step, rect.h).position(Math.sin(_a) * _radius, 0, -Math.cos(_a) * _radius).rotation(0, -_r, 0).material({
image: img,
repeat: 'no-repeat'.bothsides: false,
}).update();
_sp.addChild(_p);
}
return _sp
}
// Build the plane
const pano = createPano(PANO_RECT);
pano.position(0.0, -400).updateT();
// Insert panO into the scene
s.addChild(pano);
// Respond to screen resizing
function resize() {
s.size(window.innerWidth, window.innerHeight).update();
}
window.onresize = () = > resize();
resize();
// Refresh the scene
requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame ||
function (callback) {
setTimeout(callback, 1000 / 60);
};
function go() {
pano.rotate(0.0.2.0).updateT();
requestAnimationFrame(go);
}
requestAnimationFrame(go);
</script>
</body>
</html>
Copy the code