Last active
December 2, 2019 18:40
-
-
Save peacefullatom/65686b1b2a1ca2907c8058fd6b9a3baf to your computer and use it in GitHub Desktop.
Demo stand for 3D bars (vanilla version)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en" style="background: black;"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge" /> | |
<title>Neon 3D bars demo</title> | |
<style> | |
#root { | |
display: flex; | |
flex-wrap: wrap; | |
} | |
.container { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
.plane { | |
transform-style: preserve-3d; | |
animation: rotate 6s linear infinite; | |
} | |
.face { | |
background: #ffffff11; | |
border: 1px solid #ffffff22; | |
box-shadow: inset 0 0 8px 8px #ffffff22; | |
position: absolute; | |
overflow: hidden; | |
} | |
@keyframes rotate { | |
from { | |
transform: rotate3d(1, 1, 1, 0deg); | |
} | |
to { | |
transform: rotate3d(1, 1, 1, 360deg); | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div id="root"></div> | |
<script type="text/javascript"> | |
const faceFront = 0; | |
const faceBack = 1; | |
const faceRight = 2; | |
const faceLeft = 3; | |
const faceTop = 4; | |
const faceBottom = 5; | |
const faces = 6; | |
const barsCount = () => Math.floor(Math.random() * 5) + 1; | |
const objectSize = () => Math.floor(Math.random() * 250) + 100; | |
const objectDepth = () => Math.floor(Math.random() * 125) + 100; | |
const objectPerspective = () => Math.floor(Math.random() * 1000) + 250; | |
const root = document.getElementById("root"); | |
/** | |
* @param {number} order | |
* @param {number} steps | |
* @param {number} width | |
* @param {number} height | |
* @param {number} depth | |
* @return {[number, number]} | |
*/ | |
function calcSize(order, steps, width, height, depth) { | |
switch (order) { | |
case faceFront: | |
case faceBack: | |
return [width, height / steps]; | |
case faceRight: | |
case faceLeft: | |
return [depth * 2, height / steps]; | |
case faceTop: | |
case faceBottom: | |
return [width, depth * 2]; | |
} | |
} | |
function transform( | |
order, | |
nHeight, | |
nSizeY, | |
planeDepth, | |
planeWidth, | |
sizeX, | |
faceHeight | |
) { | |
switch (order) { | |
case faceFront: | |
return `translate3d(0, ${nHeight}px, ${planeDepth}px)`; | |
case faceBack: | |
return `rotateY(180deg) translate3d(0, ${nHeight}px, ${planeDepth}px)`; | |
case faceRight: | |
return `rotateY(90deg) translate3d(0, ${nHeight}px, ${sizeX / | |
-2}px)`; | |
case faceLeft: | |
return `rotateY(-90deg) translate3d(0, ${nHeight}px, ${sizeX / 2 - | |
planeWidth}px)`; | |
case faceTop: | |
return `rotateX(90deg) translate3d(0, 0, ${nSizeY - nHeight}px)`; | |
case faceBottom: | |
return `rotateX(-90deg) translate3d(0, 0, ${nHeight + | |
faceHeight - | |
nSizeY}px)`; | |
} | |
} | |
/** | |
* @param {HTMLDivElement} face | |
* @param {number} faceNumber | |
* @param {number} faceHeight | |
* @param {number} faceStep | |
* @param {number} planeWidth | |
* @param {number} planeHeight | |
* @param {number} planeDepth | |
*/ | |
function configure( | |
face, | |
faceNumber, | |
faceHeight, | |
faceStep, | |
planeWidth, | |
planeHeight, | |
planeDepth | |
) { | |
const order = faceNumber % faces; | |
const nHeight = ((faceNumber - order) / 3) * faceHeight; | |
const [sizeX, sizeY] = calcSize( | |
order, | |
faceStep, | |
planeWidth, | |
planeHeight, | |
planeDepth | |
); | |
const nSizeY = sizeY / 2; | |
face.className = "face"; | |
face.style.width = `${sizeX}px`; | |
face.style.height = `${sizeY}px`; | |
face.style.transform = transform( | |
order, | |
nHeight, | |
nSizeY, | |
planeDepth, | |
planeWidth, | |
sizeX, | |
faceHeight | |
); | |
} | |
/** | |
* @param {HTMLDivElement} container | |
* @param {number} bars | |
* @param {number} width | |
* @param {number} height | |
* @param {number} depth | |
*/ | |
function build(container, bars, width, height, depth) { | |
if (!container) { | |
return; | |
} | |
container.style.width = `${width}px`; | |
container.style.height = `${height}px`; | |
const planeWidth = width / 2; | |
const planeHeight = height / 2; | |
const planeDepth = depth / 2; | |
const faceStep = bars * 2 - 1; | |
const faceHeight = planeHeight / faceStep; | |
const plane = document.createElement("div"); | |
plane.className = "plane"; | |
plane.style.width = `${planeWidth}px`; | |
plane.style.height = `${planeHeight}px`; | |
for (var i = 0; i < bars * faces; i++) { | |
const face = document.createElement("div"); | |
configure( | |
face, | |
i, | |
faceHeight, | |
faceStep, | |
planeWidth, | |
planeHeight, | |
planeDepth | |
); | |
plane.appendChild(face); | |
} | |
container.appendChild(plane); | |
} | |
for (var i = 1; i <= 10; i++) { | |
const container = document.createElement("div"); | |
container.className = "container"; | |
container.style.perspective = `${objectPerspective()}px`; | |
build( | |
container, | |
barsCount(), | |
objectSize(), | |
objectSize(), | |
objectDepth() | |
); | |
root.appendChild(container); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment