init
This commit is contained in:
commit
f132183c1d
|
@ -0,0 +1,5 @@
|
|||
# #017 | Erosion
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/toshiya-marukubo/pen/KKyVOpw](https://codepen.io/toshiya-marukubo/pen/KKyVOpw).
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - #017 | Erosion</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
|
||||
<!-- partial -->
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js'></script><script src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,364 @@
|
|||
// sphere vertex shader source
|
||||
const vertexSphereShader = `
|
||||
uniform float uTime;
|
||||
uniform float mouse;
|
||||
varying vec2 vUv;
|
||||
float PI = 3.14159265359;
|
||||
|
||||
void main(){
|
||||
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
||||
|
||||
vUv = uv;
|
||||
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
// sphere fragment shader source
|
||||
const fragmentSphereShader = `
|
||||
uniform float uTime;
|
||||
uniform sampler2D uTexture;
|
||||
varying vec2 vUv;
|
||||
|
||||
void main () {
|
||||
vec4 color = texture2D(uTexture, vUv);
|
||||
|
||||
gl_FragColor = vec4(color);
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Mouse class
|
||||
*/
|
||||
class Mouse {
|
||||
constructor(sketch) {
|
||||
this.sketch = sketch;
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.delta = 0;
|
||||
this.mouse = new THREE.Vector3();
|
||||
this.setupEvents();
|
||||
|
||||
this.lastX = 0;
|
||||
this.lastY = 0;
|
||||
this.speed = 0;
|
||||
}
|
||||
|
||||
setupEvents() {
|
||||
window.addEventListener('scroll', this.onScroll.bind(this), false);
|
||||
window.addEventListener('mousemove', this.onMousemove.bind(this), false);
|
||||
window.addEventListener('touchmove', this.onTouchmove.bind(this), false);
|
||||
}
|
||||
|
||||
onScroll(e) {
|
||||
const docScrollTop = window.pageYOffset;
|
||||
const docHeight = document.body.scrollHeight - window.innerHeight;
|
||||
const scrollPercent = docScrollTop / docHeight;
|
||||
|
||||
this.delta = scrollPercent;
|
||||
}
|
||||
|
||||
onMousemove(e) {
|
||||
this.mouse.x = e.clientX / window.innerWidth * 2 - 1;
|
||||
this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
|
||||
this.mouse.z = 0;
|
||||
|
||||
this.speed =
|
||||
Math.sqrt((e.pageX - this.lastX) ** 2 +
|
||||
(e.pageY - this.lastY) ** 2) * 0.1;
|
||||
this.lastX = e.pageX;
|
||||
this.lastY = e.pageY;
|
||||
}
|
||||
|
||||
onTouchmove(e) {
|
||||
const touch = e.targetTouches[0];
|
||||
|
||||
this.mouse.x = touch.pageX / window.innerWidth * 2 - 1;
|
||||
this.mouse.y = -(touch.pageY / window.innerHeight) * 2 + 1;
|
||||
this.mouse.z = 0;
|
||||
|
||||
this.speed =
|
||||
Math.sqrt((touch.pageX - this.lastX) ** 2 +
|
||||
(touch.pageY - this.lastY) ** 2) * 0.5;
|
||||
this.lastX = touch.pageX;
|
||||
this.lastY = touch.pageY;
|
||||
}}
|
||||
|
||||
|
||||
/**
|
||||
* class Sketch
|
||||
*/
|
||||
class Sketch {
|
||||
constructor() {
|
||||
this.createCanvas();
|
||||
this.setupEvents();
|
||||
this.time = new THREE.Clock(true);
|
||||
this.mouse = new Mouse(this);
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
createCanvas() {
|
||||
this.renderer =
|
||||
new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
alpha: true });
|
||||
|
||||
|
||||
document.body.appendChild(this.renderer.domElement);
|
||||
}
|
||||
|
||||
setupEvents() {
|
||||
window.addEventListener('resize', this.onResize.bind(this), false);
|
||||
}
|
||||
|
||||
onResize() {
|
||||
if (this.preWidth === window.innerWidth && window.innerWidth < 480) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
if (this.animationId) {
|
||||
cancelAnimationFrame(this.animationId);
|
||||
}
|
||||
|
||||
this.preWidth = this.width = Math.ceil(window.innerWidth);
|
||||
this.height = Math.ceil(window.innerHeight);
|
||||
|
||||
this.scene = new THREE.Scene();
|
||||
|
||||
this.setupCanvas();
|
||||
this.setupCamera();
|
||||
//this.setupLight();
|
||||
this.setupShape();
|
||||
|
||||
this.draw();
|
||||
}
|
||||
|
||||
setupCanvas() {
|
||||
this.renderer.setSize(this.width, this.height);
|
||||
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||
this.renderer.setClearColor('#FFF0A6', 1.0);
|
||||
|
||||
this.renderer.domElement.style.position = 'fixed';
|
||||
this.renderer.domElement.style.top = '0';
|
||||
this.renderer.domElement.style.left = '0';
|
||||
this.renderer.domElement.style.width = '100%';
|
||||
this.renderer.domElement.style.height = '100%';
|
||||
this.renderer.domElement.style.zIndex = '-1';
|
||||
this.renderer.domElement.style.outline = 'none';
|
||||
}
|
||||
|
||||
setupCamera() {
|
||||
const fov = 120;
|
||||
const fovRadian = fov / 2 * (Math.PI / 180);
|
||||
|
||||
this.dist = this.height / 2 / Math.tan(fovRadian);
|
||||
this.camera =
|
||||
new THREE.PerspectiveCamera(
|
||||
fov,
|
||||
this.width / this.height,
|
||||
0.01,
|
||||
this.dist * 10);
|
||||
|
||||
|
||||
this.cameraV = new THREE.Vector3();
|
||||
this.cameraP = new THREE.Vector3(0, this.dist, this.dist);
|
||||
|
||||
this.camera.position.set(this.cameraP.x, this.cameraP.y, this.cameraP.z);
|
||||
this.camera.lookAt(new THREE.Vector3());
|
||||
|
||||
this.scene.add(this.camera);
|
||||
}
|
||||
|
||||
updateCamera(time) {
|
||||
this.cameraV.subVectors(this.mouse.mouse, this.cameraP).multiplyScalar(0.05);
|
||||
this.cameraP.add(this.cameraV);
|
||||
|
||||
this.camera.position.set(
|
||||
this.cameraP.x * this.dist * 0.0,
|
||||
this.cameraP.y * this.dist * 0.1,
|
||||
this.dist * 0);
|
||||
|
||||
|
||||
this.camera.lookAt(new THREE.Vector3());
|
||||
}
|
||||
|
||||
setupLight() {
|
||||
// directinal light
|
||||
this.directionalLight = new THREE.DirectionalLight(0xffffff);
|
||||
this.scene.add(this.directionalLight);
|
||||
|
||||
// point light
|
||||
this.spotLight = new THREE.SpotLight(0xffffff);
|
||||
|
||||
this.spotLightV = new THREE.Vector3();
|
||||
this.spotLightP = new THREE.Vector3(0, 0, this.dist * 0.1);
|
||||
|
||||
this.spotLight.position.set(this.spotLightP.x, this.spotLightP.y, this.spotLightP.z);
|
||||
this.spotLight.lookAt(new THREE.Vector3());
|
||||
|
||||
this.scene.add(this.spotLight);
|
||||
}
|
||||
|
||||
updateLight() {
|
||||
this.spotLightV.subVectors(this.mouse.mouse, this.spotLightP).multiplyScalar(0.05);
|
||||
this.spotLightP.add(this.spotLightV);
|
||||
|
||||
this.spotLight.position.set(
|
||||
this.spotLightP.x * this.dist,
|
||||
this.spotLightP.y * this.dist,
|
||||
this.dist);
|
||||
|
||||
|
||||
this.spotLight.lookAt(new THREE.Vector3());
|
||||
}
|
||||
|
||||
setupShape() {
|
||||
this.shape = new Shape(this, 0, 0, 0);
|
||||
}
|
||||
|
||||
draw() {
|
||||
const time = this.time.getElapsedTime();
|
||||
|
||||
this.shape.render(time);
|
||||
|
||||
this.updateCamera(time);
|
||||
//this.updateLight(time);
|
||||
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
|
||||
this.animationId = requestAnimationFrame(this.draw.bind(this));
|
||||
}}
|
||||
|
||||
|
||||
/**
|
||||
* shape class
|
||||
*/
|
||||
class Shape {
|
||||
constructor(sketch, x, y, z) {
|
||||
this.sketch = sketch;
|
||||
this.beta = 0;
|
||||
this.position = new THREE.Vector3(x, y, z);
|
||||
|
||||
this.setupSizes();
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
setupSizes() {
|
||||
this.sphereSize = null;
|
||||
|
||||
if (this.sketch.width < 768) {
|
||||
this.sphereSize = 120;
|
||||
}
|
||||
|
||||
if (this.sketch.width >= 768) {
|
||||
this.sphereSize = 192;
|
||||
}
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.createTexture();
|
||||
|
||||
// sphere
|
||||
this.sphereGeometry = new THREE.BoxGeometry(this.sphereSize, this.sphereSize, this.sphereSize, 128, 128, 128);
|
||||
this.sphereMaterial = new THREE.ShaderMaterial({
|
||||
side: THREE.DoubleSide,
|
||||
uniforms: {
|
||||
uTime: { type: 'f', value: 0 },
|
||||
mouse: { type: 'f', value: 0 },
|
||||
uTexture: { type: 't', value: this.returnTexture() } },
|
||||
|
||||
vertexShader: vertexSphereShader,
|
||||
fragmentShader: fragmentSphereShader });
|
||||
|
||||
|
||||
this.sphereMeshV = new THREE.Vector3();
|
||||
this.sphereMeshP = new THREE.Vector3(0, 0, 0);
|
||||
|
||||
this.sphereMesh = new THREE.Mesh(this.sphereGeometry, this.sphereMaterial);
|
||||
this.sphereMesh.position.set(this.sphereMeshP.x, this.sphereMeshP.y, this.sphereMeshP.z);
|
||||
this.sphereMesh.rotation.y = -Math.PI / 4;
|
||||
|
||||
this.sketch.scene.add(this.sphereMesh);
|
||||
}
|
||||
|
||||
createTexture() {
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.ctx = this.canvas.getContext('2d');
|
||||
|
||||
this.length = 256;
|
||||
|
||||
this.canvas.width = this.length;
|
||||
this.canvas.height = this.length;
|
||||
|
||||
this.bitOperation = new BitOperation(this.ctx, this.length, this.length);
|
||||
|
||||
this.texture = new THREE.CanvasTexture(this.canvas);
|
||||
}
|
||||
|
||||
returnTexture() {
|
||||
return this.texture;
|
||||
}
|
||||
|
||||
updateTexture(time) {
|
||||
this.bitOperation.render(time);
|
||||
}
|
||||
|
||||
render(time) {
|
||||
this.texture.needsUpdate = true; // important
|
||||
this.updateTexture(time);
|
||||
|
||||
this.sphereMesh.rotation.y = time * 0.3;
|
||||
|
||||
this.sphereMesh.material.uniforms.uTime.value = time;
|
||||
this.sphereMesh.material.uniforms.mouse.value = this.beta;
|
||||
}}
|
||||
|
||||
|
||||
// References
|
||||
// https://twitter.com/aemkei/status/1378106731386040322
|
||||
// Thank you so much.
|
||||
class BitOperation {
|
||||
constructor(ctx, width, height) {
|
||||
this.ctx = ctx;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.d = this.ctx.createImageData(this.width, this.height);
|
||||
}
|
||||
|
||||
drawData() {
|
||||
this.ctx.putImageData(this.d, 0, 0);
|
||||
}
|
||||
|
||||
updateData(t) {
|
||||
for (let y = 0; y < this.height; y++) {
|
||||
for (let x = 0; x < this.width; x++) {
|
||||
const i = (y * this.width + x) * 4;
|
||||
this.d.data[i + 0] = ((y | x) + t) % 256 + Math.random() * 100;
|
||||
this.d.data[i + 1] = ((y ^ x) + t) % 256 + Math.random() * 100;
|
||||
this.d.data[i + 2] = ((y & x) + t) % 256 + Math.random() * 100;
|
||||
this.d.data[i + 3] = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(t) {
|
||||
this.ctx.clearRect(0, 0, this.width, this.height);
|
||||
this.updateData(t * 100);
|
||||
this.drawData();
|
||||
}}
|
||||
|
||||
|
||||
(() => {
|
||||
window.addEventListener('load', () => {
|
||||
new Sketch();
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2022 by Toshiya Marukubo (https://codepen.io/toshiya-marukubo/pen/KKyVOpw)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,366 @@
|
|||
|
||||
|
||||
// sphere vertex shader source
|
||||
const vertexSphereShader = `
|
||||
uniform float uTime;
|
||||
uniform float mouse;
|
||||
varying vec2 vUv;
|
||||
float PI = 3.14159265359;
|
||||
|
||||
void main(){
|
||||
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
||||
|
||||
vUv = uv;
|
||||
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
// sphere fragment shader source
|
||||
const fragmentSphereShader = `
|
||||
uniform float uTime;
|
||||
uniform sampler2D uTexture;
|
||||
varying vec2 vUv;
|
||||
|
||||
void main () {
|
||||
vec4 color = texture2D(uTexture, vUv);
|
||||
|
||||
gl_FragColor = vec4(color);
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Mouse class
|
||||
*/
|
||||
class Mouse {
|
||||
constructor(sketch) {
|
||||
this.sketch = sketch;
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.delta = 0;
|
||||
this.mouse = new THREE.Vector3();
|
||||
this.setupEvents();
|
||||
|
||||
this.lastX = 0;
|
||||
this.lastY = 0;
|
||||
this.speed = 0;
|
||||
}
|
||||
|
||||
setupEvents() {
|
||||
window.addEventListener('scroll', this.onScroll.bind(this), false);
|
||||
window.addEventListener('mousemove', this.onMousemove.bind(this), false);
|
||||
window.addEventListener('touchmove', this.onTouchmove.bind(this), false);
|
||||
}
|
||||
|
||||
onScroll(e) {
|
||||
const docScrollTop = window.pageYOffset;
|
||||
const docHeight = document.body.scrollHeight - window.innerHeight;
|
||||
const scrollPercent = docScrollTop / docHeight;
|
||||
|
||||
this.delta = scrollPercent;
|
||||
}
|
||||
|
||||
onMousemove(e) {
|
||||
this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
|
||||
this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
|
||||
this.mouse.z = 0;
|
||||
|
||||
this.speed =
|
||||
Math.sqrt((e.pageX - this.lastX) **2 +
|
||||
(e.pageY - this.lastY) **2) * 0.1;
|
||||
this.lastX = e.pageX;
|
||||
this.lastY = e.pageY;
|
||||
}
|
||||
|
||||
onTouchmove(e) {
|
||||
const touch = e.targetTouches[0];
|
||||
|
||||
this.mouse.x = (touch.pageX / window.innerWidth) * 2 - 1;
|
||||
this.mouse.y = -(touch.pageY / window.innerHeight) * 2 + 1;
|
||||
this.mouse.z = 0;
|
||||
|
||||
this.speed =
|
||||
Math.sqrt((touch.pageX - this.lastX) **2 +
|
||||
(touch.pageY - this.lastY) **2) * 0.5;
|
||||
this.lastX = touch.pageX;
|
||||
this.lastY = touch.pageY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* class Sketch
|
||||
*/
|
||||
class Sketch {
|
||||
constructor() {
|
||||
this.createCanvas();
|
||||
this.setupEvents();
|
||||
this.time = new THREE.Clock(true);
|
||||
this.mouse = new Mouse(this);
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
createCanvas() {
|
||||
this.renderer =
|
||||
new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
alpha: true
|
||||
});
|
||||
|
||||
document.body.appendChild(this.renderer.domElement);
|
||||
}
|
||||
|
||||
setupEvents() {
|
||||
window.addEventListener('resize', this.onResize.bind(this), false);
|
||||
}
|
||||
|
||||
onResize() {
|
||||
if (this.preWidth === window.innerWidth && window.innerWidth < 480) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
if (this.animationId) {
|
||||
cancelAnimationFrame(this.animationId);
|
||||
}
|
||||
|
||||
this.preWidth = this.width = Math.ceil(window.innerWidth);
|
||||
this.height = Math.ceil(window.innerHeight);
|
||||
|
||||
this.scene = new THREE.Scene();
|
||||
|
||||
this.setupCanvas();
|
||||
this.setupCamera();
|
||||
//this.setupLight();
|
||||
this.setupShape();
|
||||
|
||||
this.draw();
|
||||
}
|
||||
|
||||
setupCanvas() {
|
||||
this.renderer.setSize(this.width, this.height);
|
||||
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||
this.renderer.setClearColor('#FFF0A6', 1.0);
|
||||
|
||||
this.renderer.domElement.style.position = 'fixed';
|
||||
this.renderer.domElement.style.top = '0';
|
||||
this.renderer.domElement.style.left = '0';
|
||||
this.renderer.domElement.style.width = '100%';
|
||||
this.renderer.domElement.style.height = '100%';
|
||||
this.renderer.domElement.style.zIndex = '-1';
|
||||
this.renderer.domElement.style.outline = 'none';
|
||||
}
|
||||
|
||||
setupCamera() {
|
||||
const fov = 120;
|
||||
const fovRadian = (fov / 2) * (Math.PI / 180);
|
||||
|
||||
this.dist = this.height / 2 / Math.tan(fovRadian);
|
||||
this.camera =
|
||||
new THREE.PerspectiveCamera(
|
||||
fov,
|
||||
this.width / this.height,
|
||||
0.01,
|
||||
this.dist * 10
|
||||
);
|
||||
|
||||
this.cameraV = new THREE.Vector3();
|
||||
this.cameraP = new THREE.Vector3(0, this.dist, this.dist);
|
||||
|
||||
this.camera.position.set(this.cameraP.x, this.cameraP.y, this.cameraP.z);
|
||||
this.camera.lookAt(new THREE.Vector3());
|
||||
|
||||
this.scene.add(this.camera);
|
||||
}
|
||||
|
||||
updateCamera(time) {
|
||||
this.cameraV.subVectors(this.mouse.mouse, this.cameraP).multiplyScalar(0.05);
|
||||
this.cameraP.add(this.cameraV);
|
||||
|
||||
this.camera.position.set(
|
||||
this.cameraP.x * this.dist * 0.0,
|
||||
this.cameraP.y * this.dist * 0.1,
|
||||
this.dist * 0
|
||||
);
|
||||
|
||||
this.camera.lookAt(new THREE.Vector3());
|
||||
}
|
||||
|
||||
setupLight() {
|
||||
// directinal light
|
||||
this.directionalLight = new THREE.DirectionalLight(0xffffff);
|
||||
this.scene.add(this.directionalLight);
|
||||
|
||||
// point light
|
||||
this.spotLight = new THREE.SpotLight(0xffffff);
|
||||
|
||||
this.spotLightV = new THREE.Vector3();
|
||||
this.spotLightP = new THREE.Vector3(0, 0, this.dist * 0.1);
|
||||
|
||||
this.spotLight.position.set(this.spotLightP.x, this.spotLightP.y, this.spotLightP.z);
|
||||
this.spotLight.lookAt(new THREE.Vector3());
|
||||
|
||||
this.scene.add(this.spotLight);
|
||||
}
|
||||
|
||||
updateLight() {
|
||||
this.spotLightV.subVectors(this.mouse.mouse, this.spotLightP).multiplyScalar(0.05);
|
||||
this.spotLightP.add(this.spotLightV);
|
||||
|
||||
this.spotLight.position.set(
|
||||
this.spotLightP.x * this.dist,
|
||||
this.spotLightP.y * this.dist,
|
||||
this.dist
|
||||
);
|
||||
|
||||
this.spotLight.lookAt(new THREE.Vector3());
|
||||
}
|
||||
|
||||
setupShape() {
|
||||
this.shape = new Shape(this, 0, 0, 0);
|
||||
}
|
||||
|
||||
draw() {
|
||||
const time = this.time.getElapsedTime();
|
||||
|
||||
this.shape.render(time);
|
||||
|
||||
this.updateCamera(time);
|
||||
//this.updateLight(time);
|
||||
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
|
||||
this.animationId = requestAnimationFrame(this.draw.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shape class
|
||||
*/
|
||||
class Shape {
|
||||
constructor(sketch, x, y, z) {
|
||||
this.sketch = sketch;
|
||||
this.beta = 0;
|
||||
this.position = new THREE.Vector3(x, y, z);
|
||||
|
||||
this.setupSizes();
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
setupSizes() {
|
||||
this.sphereSize = null;
|
||||
|
||||
if (this.sketch.width < 768) {
|
||||
this.sphereSize = 120;
|
||||
}
|
||||
|
||||
if (this.sketch.width >= 768) {
|
||||
this.sphereSize = 192;
|
||||
}
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.createTexture();
|
||||
|
||||
// sphere
|
||||
this.sphereGeometry = new THREE.BoxGeometry(this.sphereSize, this.sphereSize, this.sphereSize, 128, 128, 128);
|
||||
this.sphereMaterial = new THREE.ShaderMaterial({
|
||||
side: THREE.DoubleSide,
|
||||
uniforms: {
|
||||
uTime: {type: 'f', value: 0},
|
||||
mouse: {type: 'f', value: 0},
|
||||
uTexture: {type: 't', value: this.returnTexture()}
|
||||
},
|
||||
vertexShader: vertexSphereShader,
|
||||
fragmentShader: fragmentSphereShader
|
||||
});
|
||||
|
||||
this.sphereMeshV = new THREE.Vector3();
|
||||
this.sphereMeshP = new THREE.Vector3(0, 0, 0);
|
||||
|
||||
this.sphereMesh = new THREE.Mesh(this.sphereGeometry, this.sphereMaterial);
|
||||
this.sphereMesh.position.set(this.sphereMeshP.x, this.sphereMeshP.y, this.sphereMeshP.z);
|
||||
this.sphereMesh.rotation.y = -Math.PI / 4;
|
||||
|
||||
this.sketch.scene.add(this.sphereMesh);
|
||||
}
|
||||
|
||||
createTexture() {
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.ctx = this.canvas.getContext('2d');
|
||||
|
||||
this.length = 256;
|
||||
|
||||
this.canvas.width = this.length;
|
||||
this.canvas.height = this.length;
|
||||
|
||||
this.bitOperation = new BitOperation(this.ctx, this.length, this.length);
|
||||
|
||||
this.texture = new THREE.CanvasTexture(this.canvas);
|
||||
}
|
||||
|
||||
returnTexture() {
|
||||
return this.texture;
|
||||
}
|
||||
|
||||
updateTexture(time) {
|
||||
this.bitOperation.render(time);
|
||||
}
|
||||
|
||||
render(time) {
|
||||
this.texture.needsUpdate = true; // important
|
||||
this.updateTexture(time);
|
||||
|
||||
this.sphereMesh.rotation.y = time * 0.3;
|
||||
|
||||
this.sphereMesh.material.uniforms.uTime.value = time;
|
||||
this.sphereMesh.material.uniforms.mouse.value = this.beta;
|
||||
}
|
||||
}
|
||||
|
||||
// References
|
||||
// https://twitter.com/aemkei/status/1378106731386040322
|
||||
// Thank you so much.
|
||||
class BitOperation {
|
||||
constructor(ctx, width, height) {
|
||||
this.ctx = ctx;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.d = this.ctx.createImageData(this.width, this.height);
|
||||
}
|
||||
|
||||
drawData() {
|
||||
this.ctx.putImageData(this.d, 0, 0);
|
||||
}
|
||||
|
||||
updateData(t) {
|
||||
for (let y = 0; y < this.height; y++) {
|
||||
for (let x = 0; x < this.width; x++) {
|
||||
const i = (y * this.width + x) * 4;
|
||||
this.d.data[i + 0] = ((y | x) + t) % 256 + Math.random() * 100;
|
||||
this.d.data[i + 1] = ((y ^ x) + t) % 256 + Math.random() * 100;
|
||||
this.d.data[i + 2] = ((y & x) + t) % 256 + Math.random() * 100;
|
||||
this.d.data[i + 3] = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(t) {
|
||||
this.ctx.clearRect(0, 0, this.width, this.height);
|
||||
this.updateData(t * 100);
|
||||
this.drawData();
|
||||
}
|
||||
}
|
||||
|
||||
(() => {
|
||||
window.addEventListener('load', () => {
|
||||
new Sketch();
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,4 @@
|
|||
# [1] Codevember 2017 - Galaxy
|
||||
_A Pen created at CodePen.io. Original URL: [https://codepen.io/Mamboleoo/pen/MOwqOp](https://codepen.io/Mamboleoo/pen/MOwqOp).
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - [1] Codevember 2017 - Galaxy</title>
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<canvas></canvas>
|
||||
<!-- partial -->
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js'></script>
|
||||
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/OrbitControls.js'></script>
|
||||
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/perlin.js'></script><script src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,139 @@
|
|||
console.clear();
|
||||
|
||||
var ww = window.innerWidth,
|
||||
wh = window.innerHeight;
|
||||
|
||||
var renderer = new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
canvas: document.querySelector('canvas')
|
||||
});
|
||||
renderer.setSize(ww, wh);
|
||||
renderer.setClearColor(0x001a2d);
|
||||
|
||||
var scene = new THREE.Scene();
|
||||
scene.fog = new THREE.Fog(0x001a2d, 80, 140);
|
||||
|
||||
var camera = new THREE.PerspectiveCamera(45, ww/wh, 0.1, 200);
|
||||
camera.position.x = 70;
|
||||
camera.position.y = 30;
|
||||
camera.position.z = 5;
|
||||
camera.lookAt(new THREE.Vector3());
|
||||
|
||||
// var controls = new THREE.OrbitControls(camera, renderer.domElement);
|
||||
|
||||
/* LIGHTS */
|
||||
var moonLight = new THREE.PointLight(0xffffff, 2, 150);
|
||||
scene.add( moonLight );
|
||||
|
||||
var moon;
|
||||
function createMoon() {
|
||||
var geometry = new THREE.SphereGeometry(8, 32, 32);
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
color: 0x26fdd9,
|
||||
shininess:15,
|
||||
emissive: 0x2bb2e6,
|
||||
emissiveIntensity:0.8
|
||||
});
|
||||
moon = new THREE.Mesh(geometry, material);
|
||||
moon.position.x = -9;
|
||||
moon.position.z = -6.5;
|
||||
moon.position.y = 1;
|
||||
moon.rotation.y = -1;
|
||||
scene.add(moon);
|
||||
moonLight.position.copy(moon.position);
|
||||
moonLight.position.y += 4;
|
||||
var moonLight2 = new THREE.PointLight(0xffffff, 0.6, 150);
|
||||
scene.add(moonLight2);
|
||||
moonLight2.position.x += 20;
|
||||
moonLight2.position.y -= 20;
|
||||
moonLight2.position.z -= 25;
|
||||
}
|
||||
|
||||
function createTerrain () {
|
||||
var geometry = new THREE.PlaneGeometry(150,150,120,120);
|
||||
var m = new THREE.Matrix4();
|
||||
m.makeRotationX(Math.PI * -0.5);
|
||||
geometry.applyMatrix(m);
|
||||
for(var i=0;i<geometry.vertices.length;i++) {
|
||||
var vector = geometry.vertices[i];
|
||||
var ratio = noise.simplex3(vector.x*0.03, vector.z*0.03, 0);
|
||||
vector.y = ratio * 10;
|
||||
}
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
color: 0x198257,
|
||||
emissive: 0x032f50
|
||||
});
|
||||
var plane = new THREE.Mesh(geometry, material);
|
||||
scene.add( plane );
|
||||
}
|
||||
|
||||
var stars = new THREE.Group();
|
||||
scene.add(stars);
|
||||
var starsLights = new THREE.Group();
|
||||
scene.add(starsLights);
|
||||
var starsAmount = 20;
|
||||
function createStars() {
|
||||
var geometry = new THREE.SphereGeometry(0.3, 16, 16);
|
||||
var material = new THREE.MeshBasicMaterial({color: 0xffffff});
|
||||
for(var i=0;i<starsAmount;i++) {
|
||||
var star = new THREE.Mesh(geometry, material);
|
||||
star.position.x = (Math.random() - 0.5) * 150;
|
||||
star.position.z = (Math.random() - 0.5) * 150;
|
||||
var ratio = noise.simplex3(star.position.x*0.03, star.position.z*0.03, 0);
|
||||
star.position.y = ratio * 10 + 0.3;
|
||||
stars.add(star);
|
||||
var velX = (Math.random() + 0.1) * 0.1 * (Math.random()<0.5?-1:1);
|
||||
var velY = (Math.random() + 0.1) * 0.1 * (Math.random()<0.5?-1:1);
|
||||
star.vel = new THREE.Vector2(velX, velY);
|
||||
var starLight = new THREE.PointLight(0xffffff, 0.8, 3);
|
||||
starLight.position.copy(star.position);
|
||||
starLight.position.y += 0.5;
|
||||
starsLights.add(starLight);
|
||||
}
|
||||
}
|
||||
|
||||
function updateStar(star, index) {
|
||||
if (star.position.x < -75) {
|
||||
star.position.x = 75;
|
||||
}
|
||||
if (star.position.x > 75) {
|
||||
star.position.x = -75;
|
||||
}
|
||||
if (star.position.z < -75) {
|
||||
star.position.z = 75;
|
||||
}
|
||||
if (star.position.z > 75) {
|
||||
star.position.z = -75;
|
||||
}
|
||||
|
||||
star.position.x += star.vel.x;
|
||||
star.position.z += star.vel.y;
|
||||
var ratio = noise.simplex3(star.position.x*0.03, star.position.z*0.03, 0);
|
||||
star.position.y = ratio * 10 + 0.3;
|
||||
|
||||
|
||||
starsLights.children[index].position.copy(star.position);
|
||||
starsLights.children[index].position.y += 0.5;
|
||||
}
|
||||
|
||||
function render(a) {
|
||||
requestAnimationFrame(render);
|
||||
for(var i=0;i<starsAmount;i++) {
|
||||
updateStar(stars.children[i], i);
|
||||
}
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
function onResize() {
|
||||
ww = window.innerWidth;
|
||||
wh = window.innerHeight;
|
||||
camera.aspect = ww / wh;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(ww, wh);
|
||||
}
|
||||
|
||||
createMoon();
|
||||
createTerrain();
|
||||
createStars();
|
||||
requestAnimationFrame(render);
|
||||
window.addEventListener('resize', onResize);
|
|
@ -0,0 +1,4 @@
|
|||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2020 by Louis Hoebregts (https://codepen.io/Mamboleoo/pen/MOwqOp)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1 @@
|
|||
<canvas></canvas>
|
|
@ -0,0 +1,139 @@
|
|||
console.clear();
|
||||
|
||||
var ww = window.innerWidth,
|
||||
wh = window.innerHeight;
|
||||
|
||||
var renderer = new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
canvas: document.querySelector('canvas')
|
||||
});
|
||||
renderer.setSize(ww, wh);
|
||||
renderer.setClearColor(0x001a2d);
|
||||
|
||||
var scene = new THREE.Scene();
|
||||
scene.fog = new THREE.Fog(0x001a2d, 80, 140);
|
||||
|
||||
var camera = new THREE.PerspectiveCamera(45, ww/wh, 0.1, 200);
|
||||
camera.position.x = 70;
|
||||
camera.position.y = 30;
|
||||
camera.position.z = 5;
|
||||
camera.lookAt(new THREE.Vector3());
|
||||
|
||||
// var controls = new THREE.OrbitControls(camera, renderer.domElement);
|
||||
|
||||
/* LIGHTS */
|
||||
var moonLight = new THREE.PointLight(0xffffff, 2, 150);
|
||||
scene.add( moonLight );
|
||||
|
||||
var moon;
|
||||
function createMoon() {
|
||||
var geometry = new THREE.SphereGeometry(8, 32, 32);
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
color: 0x26fdd9,
|
||||
shininess:15,
|
||||
emissive: 0x2bb2e6,
|
||||
emissiveIntensity:0.8
|
||||
});
|
||||
moon = new THREE.Mesh(geometry, material);
|
||||
moon.position.x = -9;
|
||||
moon.position.z = -6.5;
|
||||
moon.position.y = 1;
|
||||
moon.rotation.y = -1;
|
||||
scene.add(moon);
|
||||
moonLight.position.copy(moon.position);
|
||||
moonLight.position.y += 4;
|
||||
var moonLight2 = new THREE.PointLight(0xffffff, 0.6, 150);
|
||||
scene.add(moonLight2);
|
||||
moonLight2.position.x += 20;
|
||||
moonLight2.position.y -= 20;
|
||||
moonLight2.position.z -= 25;
|
||||
}
|
||||
|
||||
function createTerrain () {
|
||||
var geometry = new THREE.PlaneGeometry(150,150,120,120);
|
||||
var m = new THREE.Matrix4();
|
||||
m.makeRotationX(Math.PI * -0.5);
|
||||
geometry.applyMatrix(m);
|
||||
for(var i=0;i<geometry.vertices.length;i++) {
|
||||
var vector = geometry.vertices[i];
|
||||
var ratio = noise.simplex3(vector.x*0.03, vector.z*0.03, 0);
|
||||
vector.y = ratio * 10;
|
||||
}
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
color: 0x198257,
|
||||
emissive: 0x032f50
|
||||
});
|
||||
var plane = new THREE.Mesh(geometry, material);
|
||||
scene.add( plane );
|
||||
}
|
||||
|
||||
var stars = new THREE.Group();
|
||||
scene.add(stars);
|
||||
var starsLights = new THREE.Group();
|
||||
scene.add(starsLights);
|
||||
var starsAmount = 20;
|
||||
function createStars() {
|
||||
var geometry = new THREE.SphereGeometry(0.3, 16, 16);
|
||||
var material = new THREE.MeshBasicMaterial({color: 0xffffff});
|
||||
for(var i=0;i<starsAmount;i++) {
|
||||
var star = new THREE.Mesh(geometry, material);
|
||||
star.position.x = (Math.random() - 0.5) * 150;
|
||||
star.position.z = (Math.random() - 0.5) * 150;
|
||||
var ratio = noise.simplex3(star.position.x*0.03, star.position.z*0.03, 0);
|
||||
star.position.y = ratio * 10 + 0.3;
|
||||
stars.add(star);
|
||||
var velX = (Math.random() + 0.1) * 0.1 * (Math.random()<0.5?-1:1);
|
||||
var velY = (Math.random() + 0.1) * 0.1 * (Math.random()<0.5?-1:1);
|
||||
star.vel = new THREE.Vector2(velX, velY);
|
||||
var starLight = new THREE.PointLight(0xffffff, 0.8, 3);
|
||||
starLight.position.copy(star.position);
|
||||
starLight.position.y += 0.5;
|
||||
starsLights.add(starLight);
|
||||
}
|
||||
}
|
||||
|
||||
function updateStar(star, index) {
|
||||
if (star.position.x < -75) {
|
||||
star.position.x = 75;
|
||||
}
|
||||
if (star.position.x > 75) {
|
||||
star.position.x = -75;
|
||||
}
|
||||
if (star.position.z < -75) {
|
||||
star.position.z = 75;
|
||||
}
|
||||
if (star.position.z > 75) {
|
||||
star.position.z = -75;
|
||||
}
|
||||
|
||||
star.position.x += star.vel.x;
|
||||
star.position.z += star.vel.y;
|
||||
var ratio = noise.simplex3(star.position.x*0.03, star.position.z*0.03, 0);
|
||||
star.position.y = ratio * 10 + 0.3;
|
||||
|
||||
|
||||
starsLights.children[index].position.copy(star.position);
|
||||
starsLights.children[index].position.y += 0.5;
|
||||
}
|
||||
|
||||
function render(a) {
|
||||
requestAnimationFrame(render);
|
||||
for(var i=0;i<starsAmount;i++) {
|
||||
updateStar(stars.children[i], i);
|
||||
}
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
function onResize() {
|
||||
ww = window.innerWidth;
|
||||
wh = window.innerHeight;
|
||||
camera.aspect = ww / wh;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(ww, wh);
|
||||
}
|
||||
|
||||
createMoon();
|
||||
createTerrain();
|
||||
createStars();
|
||||
requestAnimationFrame(render);
|
||||
window.addEventListener('resize', onResize);
|
|
@ -0,0 +1,4 @@
|
|||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# 1 Element CSS Spinners
|
||||
_A Pen created at CodePen.io. Original URL: [https://codepen.io/Paolo-Duzioni/pen/ZoRabJ](https://codepen.io/Paolo-Duzioni/pen/ZoRabJ).
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>1 Element CSS Spinners</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner1"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner3"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner4"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner5"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner6"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner7"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="wrapper">
|
||||
<div class="spinner spinner8"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- partial -->
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,310 @@
|
|||
@import url("https://fonts.googleapis.com/css?family=Source+Serif+Pro");
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-family: "Source Serif Pro", serif;
|
||||
font-size: 16px;
|
||||
background: dodgerblue;
|
||||
counter-reset: spinnerCount;
|
||||
}
|
||||
|
||||
.cell {
|
||||
width: 25%;
|
||||
}
|
||||
.cell .wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 10rem;
|
||||
margin: 1rem 1rem 0;
|
||||
padding-top: 2.2rem;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
.cell .wrapper::after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: 0.2rem;
|
||||
text-align: center;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
/* Increment the section counter */
|
||||
counter-increment: spinnerCount;
|
||||
/* Display the counter on pseudo-elements */
|
||||
content: counter(spinnerCount);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
.spinner.spinner1 {
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 50%;
|
||||
-webkit-animation: rotation .8s ease infinite;
|
||||
animation: rotation .8s ease infinite;
|
||||
}
|
||||
.spinner.spinner2 {
|
||||
border: 3px solid transparent;
|
||||
border-top-color: rgba(0, 0, 0, 0.5);
|
||||
border-bottom-color: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 50%;
|
||||
-webkit-animation: rotation .8s ease infinite;
|
||||
animation: rotation .8s ease infinite;
|
||||
}
|
||||
.spinner.spinner3 {
|
||||
border-top: 3px solid rgba(0, 0, 0, 0.5);
|
||||
border-right: 3px solid transparent;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: rotation .8s linear infinite;
|
||||
animation: rotation .8s linear infinite;
|
||||
}
|
||||
.spinner.spinner4 {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
-webkit-animation: flip 1.2s ease infinite;
|
||||
animation: flip 1.2s ease infinite;
|
||||
}
|
||||
.spinner.spinner5 {
|
||||
margin-top: 2rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: .5rem;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.spinner.spinner5::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -130%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
-webkit-animation: progress 4s linear infinite;
|
||||
animation: progress 4s linear infinite;
|
||||
}
|
||||
.spinner.spinner6 {
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
left: 50%;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: pulse 1s ease-in-out infinite;
|
||||
animation: pulse 1s ease-in-out infinite;
|
||||
-webkit-transform: translate(-50%, -50%) scale(0);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
}
|
||||
.spinner.spinner7 {
|
||||
position: relative;
|
||||
}
|
||||
.spinner.spinner7::before, .spinner.spinner7::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
-webkit-transform: translate(-50%, -50%) scale(0);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
}
|
||||
.spinner.spinner7::before {
|
||||
background: #fff;
|
||||
-webkit-animation: pulse2 2s ease-in-out infinite;
|
||||
animation: pulse2 2s ease-in-out infinite;
|
||||
}
|
||||
.spinner.spinner7::after {
|
||||
background: #fff;
|
||||
-webkit-animation: pulse2 2s 1s ease-in-out infinite;
|
||||
animation: pulse2 2s 1s ease-in-out infinite;
|
||||
}
|
||||
.spinner.spinner8 {
|
||||
position: relative;
|
||||
-webkit-perspective: 200px;
|
||||
perspective: 200px;
|
||||
}
|
||||
.spinner.spinner8::before {
|
||||
display: block;
|
||||
content: '';
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
-webkit-animation: 2s flipWalker ease infinite;
|
||||
animation: 2s flipWalker ease infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotation {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes flip {
|
||||
0% {
|
||||
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-180deg);
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(-180deg);
|
||||
}
|
||||
}
|
||||
@keyframes flip {
|
||||
0% {
|
||||
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(0deg);
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-180deg);
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(-180deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes progress {
|
||||
0% {
|
||||
left: -130%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
50% {
|
||||
left: 130%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
51% {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
100% {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
}
|
||||
@keyframes progress {
|
||||
0% {
|
||||
left: -130%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
50% {
|
||||
left: 130%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
51% {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
100% {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes pulse {
|
||||
0% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(0);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(1);
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(0);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(1);
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes pulse2 {
|
||||
0%, 100% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(0);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(1);
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes pulse2 {
|
||||
0%, 100% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(0);
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-50%, -50%) scale(1);
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes flipWalker {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0) rotateX(0) rotateY(0);
|
||||
transform: translate(0, 0) rotateX(0) rotateY(0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(100%, 0) rotateX(0) rotateY(180deg);
|
||||
transform: translate(100%, 0) rotateX(0) rotateY(180deg);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg);
|
||||
transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg);
|
||||
transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translate(0, 0) rotateX(0) rotateY(360deg);
|
||||
transform: translate(0, 0) rotateX(0) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes flipWalker {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0) rotateX(0) rotateY(0);
|
||||
transform: translate(0, 0) rotateX(0) rotateY(0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(100%, 0) rotateX(0) rotateY(180deg);
|
||||
transform: translate(100%, 0) rotateX(0) rotateY(180deg);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg);
|
||||
transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg);
|
||||
transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translate(0, 0) rotateX(0) rotateY(360deg);
|
||||
transform: translate(0, 0) rotateX(0) rotateY(360deg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
|
||||
<!--
|
||||
Copyright (c) 2019 by Paolo Duzioni (https://codepen.io/Paolo-Duzioni/pen/ZoRabJ)
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
-->
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
- var totSpinners = 8
|
||||
- for (var i = 1; i <= totSpinners; i++)
|
||||
.cell
|
||||
.wrapper
|
||||
div( class="spinner spinner" + i)
|
|
@ -0,0 +1,217 @@
|
|||
// TYPOGRAPHY
|
||||
@import url('https://fonts.googleapis.com/css?family=Source+Serif+Pro');
|
||||
$font-family: 'Source Serif Pro', serif;
|
||||
|
||||
// COLORS
|
||||
$white: #fff;
|
||||
$black: #000;
|
||||
$back: dodgerblue; // Change the color if you want
|
||||
|
||||
// GENERAL
|
||||
*, *::before, *::after{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-family: $font-family;
|
||||
font-size: 16px;
|
||||
background: $back;
|
||||
// Spinner count reference
|
||||
counter-reset: spinnerCount;
|
||||
}
|
||||
.cell{
|
||||
width: 25%;
|
||||
.wrapper{
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 10rem;
|
||||
margin: 1rem 1rem 0;
|
||||
padding-top: 2.2rem;
|
||||
background: rgba($white, .2);
|
||||
&::after{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: 0.2rem;
|
||||
text-align: center;
|
||||
background: rgba($white, .25);
|
||||
/* Increment the section counter */
|
||||
counter-increment: spinnerCount;
|
||||
/* Display the counter on pseudo-elements */
|
||||
content: counter(spinnerCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SPINNERS STYLES
|
||||
.spinner{
|
||||
// Common styles
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
// Individual styles
|
||||
&.spinner1{
|
||||
border: 3px solid rgba($white, .25);
|
||||
border-top-color: rgba($black, .5);
|
||||
border-radius: 50%;
|
||||
animation: rotation .8s ease infinite;
|
||||
}
|
||||
&.spinner2{
|
||||
border: 3px solid transparent;
|
||||
border-top-color: rgba($black, .5);
|
||||
border-bottom-color: rgba($black, .5);
|
||||
border-radius: 50%;
|
||||
animation: rotation .8s ease infinite;
|
||||
}
|
||||
&.spinner3{
|
||||
border-top: 3px solid rgba($black, .5);
|
||||
border-right: 3px solid transparent;
|
||||
border-radius: 50%;
|
||||
animation: rotation .8s linear infinite;
|
||||
}
|
||||
&.spinner4{
|
||||
background: rgba($black, .5);
|
||||
animation: flip 1.2s ease infinite;
|
||||
}
|
||||
&.spinner5{
|
||||
margin-top: 2rem; // just for centering the demo
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: .5rem;
|
||||
background: rgba($white, .25);
|
||||
&::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -130%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba($black, .5);
|
||||
animation: progress 4s linear infinite;
|
||||
}
|
||||
|
||||
}
|
||||
&.spinner6{
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
left: 50%;
|
||||
background: $white;
|
||||
border-radius: 50%;
|
||||
animation: pulse 1s ease-in-out infinite;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
}
|
||||
&.spinner7{
|
||||
position: relative;
|
||||
&::before, &::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
}
|
||||
&::before{
|
||||
background: $white;
|
||||
animation: pulse2 2s ease-in-out infinite;
|
||||
}
|
||||
&::after{
|
||||
background: $white;
|
||||
animation: pulse2 2s 1s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
&.spinner8{
|
||||
position: relative;
|
||||
perspective: 200px;
|
||||
&::before{
|
||||
display: block;
|
||||
content: '';
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
background: rgba($black, .5);
|
||||
animation: 2s flipWalker ease infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ANIMATIONS
|
||||
@keyframes rotation{
|
||||
from{
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to{
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flip{
|
||||
0%{
|
||||
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||
}
|
||||
50%{
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(0deg);
|
||||
}
|
||||
100%{
|
||||
transform: perspective(120px) rotateX(-180deg) rotateY(-180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes progress{
|
||||
0%{
|
||||
left: -130%;
|
||||
background: rgba($black, .5);
|
||||
}
|
||||
50%{
|
||||
left: 130%;
|
||||
background: rgba($black, .5);
|
||||
}
|
||||
51%{
|
||||
background: rgba($white, .5);
|
||||
}
|
||||
100%{
|
||||
background: rgba($white, .5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse{
|
||||
0%{
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100%{
|
||||
transform: translate(-50%, -50%) scale(1.0);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse2{
|
||||
0%, 100%{
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
50%{
|
||||
transform: translate(-50%, -50%) scale(1.0);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flipWalker{
|
||||
0%{
|
||||
transform: translate(0, 0) rotateX(0) rotateY(0);
|
||||
}
|
||||
25%{
|
||||
transform: translate(100%, 0) rotateX(0) rotateY(180deg);
|
||||
}
|
||||
50%{
|
||||
transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg);
|
||||
}
|
||||
75%{
|
||||
transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg);
|
||||
}
|
||||
100%{
|
||||
transform: translate(0, 0) rotateX(0) rotateY(360deg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# 10,000 Codepen followers!
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/chrisgannon/pen/qBPGEQy](https://codepen.io/chrisgannon/pen/qBPGEQy).
|
||||
|
||||
Heartfelt thanks to each and every person supporting my journey and hopefully learning with me along the way. Cheers!
|
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 10,000 Codepen followers!</title>
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<svg id="mainSVG" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
|
||||
<defs>
|
||||
<linearGradient id="codepenGrad" x1="0" y1="383.12" x2="556" y2="383.12" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#42c2f1"/>
|
||||
<stop offset="0.2" stop-color="#fbda4f"/>
|
||||
<stop offset="0.6" stop-color="#ab63df"/>
|
||||
<stop offset="0.8" stop-color="#5fc581"/>
|
||||
<stop offset="1" stop-color="#42c2f1"/>
|
||||
</linearGradient>
|
||||
<pattern id="gradPattern" width="556" height="62.4" x="0" y="0" patternUnits="userSpaceOnUse">
|
||||
<rect x="0" y="0" fill="url(#codepenGrad)" width="556" height="62.4" />
|
||||
</pattern>
|
||||
<clipPath id="numberMask">
|
||||
<rect class="numberMask" x="122.36" y="204.62" width="547.24" height="176.58" fill="red" />
|
||||
</clipPath>
|
||||
<clipPath id="thankYouMask">
|
||||
<rect class="thankYouMask" x="-500" y="204.62" width="615" height="176.58" fill="#29abe2"/>
|
||||
</clipPath>
|
||||
<path id="one_mid" d="M219.16,266.34h0v-62.6l15.24-.12V389.93H219.16Z" />
|
||||
<path id="one_end" d="M219.16,266.34h0v-12.9l15.24-.12-1.14,62.58h-13Z" />
|
||||
<g class="confetti">
|
||||
<rect class="paper" width="13" height="8" />
|
||||
</g>
|
||||
</defs>
|
||||
|
||||
<rect id="gradBar" x="120" y="376.31" width="556" height="10" fill="url(#gradPattern)"/>
|
||||
<path id="one_end" d="M219.16,266.34h-16.8V253.5l32-.12v89.4H219.16Z" fill="#fff" opacity="0"/>
|
||||
<g id="oneContainer">
|
||||
<path id="one" d="M219.16,266.34h-16.8V253.5l32-.12v89.4H219.16Z" fill="#fff" />
|
||||
</g>
|
||||
<g clip-path="url(#numberMask)">
|
||||
<g id="numberGroup">
|
||||
<path id="_0_1" data-name="0_1" d="M253.12,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C267.64,344.22,253.12,325.74,253.12,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16-12.72,0-20.64,12.24-20.64,32.16s8,32.28,20.76,32.28S309.76,318.06,309.76,298Z" fill="#fff" />
|
||||
<path id="comma" d="M340.6,326.58h14l-8.88,30.24h-10Z" fill="#fff" />
|
||||
<path id="_0_2" data-name="0_2" d="M366.88,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C381.4,344.22,366.88,325.74,366.88,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16C389.92,265.86,382,278.1,382,298s8,32.28,20.76,32.28S423.52,318.06,423.52,298Z" fill="#fff" />
|
||||
<path id="_0_3" data-name="0_3" d="M446.56,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C461.08,344.22,446.56,325.74,446.56,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16-12.72,0-20.64,12.24-20.64,32.16s8,32.28,20.76,32.28S503.2,318.06,503.2,298Z" fill="#fff" />
|
||||
<path id="_0_4" data-name="0_4" d="M526.24,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C540.76,344.22,526.24,325.74,526.24,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16-12.72,0-20.64,12.24-20.64,32.16s8,32.28,20.76,32.28S582.88,318.06,582.88,298Z" fill="#fff" />
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#thankYouMask)">
|
||||
<g id="thankYouGroup">
|
||||
<path d="M139.48,266.7h-23.4V253.38H178V266.7H154.72v76.08H139.48Z" fill="#fff"/>
|
||||
<path d="M241.12,300.78v42h-14.4v-38.4c0-8.76-5.52-14.4-13.68-14.4s-13.8,5.64-13.8,14.4v38.4h-14.4v-89.4h14.4v31.08c3.72-5,10.08-7.8,17.52-7.8C231.16,276.66,241.12,286.5,241.12,300.78Z" fill="#fff"/>
|
||||
<path d="M303.76,299.58v43.2H290.2v-7.2c-4.8,5.76-11.4,8.64-19.2,8.64-14.4,0-23.52-8.16-23.52-19.2,0-9.6,7.56-16,20.64-18.84l21.24-4.56v-2c0-6-4.92-10-12.12-10a15.45,15.45,0,0,0-14.88,10l-12.48-6.24c3.72-9.84,14.52-16.68,27.36-16.68C293,276.66,303.76,286.14,303.76,299.58Zm-14.4,17.16v-4.2L271,316.62c-5.4,1.2-8.52,4.32-8.52,8.28,0,4.92,4,7.92,10.2,7.92C282.28,332.82,289.36,325.86,289.36,316.74Z" fill="#fff"/>
|
||||
<path d="M368.8,300.78v42H354.4v-38.4c0-8.76-5.52-14.4-13.68-14.4s-13.8,5.64-13.8,14.4v38.4h-14.4V278.1h13.56v7.8c3.6-6,10.32-9.24,18.36-9.24C358.84,276.66,368.8,286.62,368.8,300.78Z" fill="#fff"/>
|
||||
<path d="M412.6,304.14l23.64,38.64h-16l-17-28.32-10.08,10.92v17.4h-14.4v-89.4h14.4v52.56l26.16-27.84h16.92Z" fill="#fff"/>
|
||||
<path d="M518.8,278.1,490,350.34c-2.88,7.08-7.92,18.84-24.24,18.84a23.46,23.46,0,0,1-9.48-1.68V355.38a33,33,0,0,0,7.44,1c8.28,0,10.44-4.8,12.12-8.76l2.16-5L452.56,278.1h15.72l17.4,45.72,17.4-45.72Z" fill="#fff"/>
|
||||
<path d="M519.16,310.38c0-19.56,14.88-33.72,34-33.72s34,14.16,34,33.72-15.12,33.84-34,33.84S519.16,329.94,519.16,310.38Zm52.92.12c0-11.88-8-20.52-19-20.52s-19,8.64-19,20.52,7.92,20.4,19,20.4S572.08,322.38,572.08,310.5Z" fill="#fff"/>
|
||||
<path d="M649.59,278.1v64.68H635.92v-7.44c-3.6,5.64-10.2,8.88-18.12,8.88-14.4,0-24.48-11-24.48-25.92V278.1h14.4v38.4c0,8.76,5.52,14.4,13.8,14.4s13.68-5.64,13.68-14.4V278.1Z" fill="#fff"/>
|
||||
</g>
|
||||
|
||||
</g>
|
||||
<rect id="dot" x="662.8" y="326.58" width="14.88" height="16.2" fill="#fff"/>
|
||||
<g class="container"/>
|
||||
</svg>
|
||||
<!-- partial -->
|
||||
<script src='https://unpkg.co/gsap@3/dist/gsap.min.js'></script>
|
||||
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/MorphSVGPlugin3.min.js'></script>
|
||||
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/CustomEase3.min.js'></script>
|
||||
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/CustomWiggle3.min.js'></script><script src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,244 @@
|
|||
let select = s => document.querySelector(s),
|
||||
selectAll = s => document.querySelectorAll(s),
|
||||
mainSVG = select('#mainSVG'),
|
||||
allNumbers = gsap.utils.toArray('#numberGroup path'),
|
||||
allThankYou = gsap.utils.toArray('#thankYouGroup path'),
|
||||
//colorArray = ["#EF5350", "#EC407A","#AB47BC","#7E57C2","#5C6BC0","#42A5F5","#29B6F6","#26C6DA","#26A69A","#66BB6A","#9CCC65","#D4E157","#FFEE58","#FFCA28","#FFA726","#FF7043","#8D6E63","#BDBDBD","#78909C"],
|
||||
colorArray = ["#42c2f1", "#fbda4f","#ab63df","#5fc581"],
|
||||
confetti = select('.confetti'),
|
||||
container = select('.container')
|
||||
|
||||
gsap.set('svg', {
|
||||
visibility: 'visible'
|
||||
})
|
||||
let confettiTl = gsap.timeline({paused: true});
|
||||
|
||||
function playConfetti () {
|
||||
|
||||
confettiTl.play(0);
|
||||
}
|
||||
|
||||
function createConfetti () {
|
||||
var i = 160, clone, tl, rot, duration, paperDuration;
|
||||
while(--i > -1) {
|
||||
tl = gsap.timeline();
|
||||
clone = confetti.cloneNode(true);
|
||||
container.appendChild(clone);
|
||||
rot = gsap.utils.random(0, 360);
|
||||
duration = gsap.utils.random(3, 9);
|
||||
paperDuration = (duration)/20;
|
||||
gsap.set(clone, {
|
||||
fill: gsap.utils.random(colorArray),
|
||||
rotation: rot,
|
||||
transformOrigin: '50% 50%'
|
||||
})
|
||||
|
||||
tl.fromTo(clone, {
|
||||
x: gsap.utils.random(0, 800),
|
||||
y: -50,
|
||||
rotation: rot
|
||||
}, {
|
||||
duration: duration,
|
||||
x: '+=' + gsap.utils.random(-200, 200),
|
||||
y: 650,
|
||||
rotation: '+=180',
|
||||
ease: 'linear'
|
||||
})
|
||||
.to(clone.querySelector('.paper'), {
|
||||
duration: duration/23,
|
||||
scaleY: 0.1,
|
||||
repeat: 23,
|
||||
yoyo: true
|
||||
}, 0)
|
||||
//console.log(paperDuration)
|
||||
confettiTl.add(tl, i/200).timeScale(2.3);
|
||||
}
|
||||
|
||||
gsap.set('.paper', {
|
||||
transformOrigin: '50% 50%'
|
||||
})
|
||||
}
|
||||
|
||||
let tl = gsap.timeline({repeat: -1});
|
||||
tl.add('step0', '+=2')
|
||||
.to('#one', {
|
||||
x: -105,
|
||||
ease: 'expo.inOut'
|
||||
}, 'step0')
|
||||
.to('#one', {
|
||||
rotation: 10,
|
||||
transformOrigin: '50% 150%',
|
||||
ease: 'sine.inOut'
|
||||
}, 'step0+=0')
|
||||
.to('#one', {
|
||||
rotation: 0,
|
||||
|
||||
ease: 'elastic(0.8, 0.28)'
|
||||
}, 'step0+=0.3')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: '#one_mid'
|
||||
},
|
||||
ease: 'expo.inOut'
|
||||
}, 'step0')
|
||||
.add('step1')
|
||||
.to('#one, .numberMask', {
|
||||
x: '+=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step1')
|
||||
.to('.thankYouMask', {
|
||||
x: '+=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step1')
|
||||
.from(allThankYou, {
|
||||
x: 50,
|
||||
immediateRender: false,
|
||||
stagger: {
|
||||
each: 0.05
|
||||
},
|
||||
ease: 'expo'
|
||||
}, 'step1')
|
||||
.from('#gradBar', {
|
||||
width: 0,
|
||||
ease: 'expo.inOut'
|
||||
}, 'step1')
|
||||
|
||||
.to('#one', {
|
||||
rotation: -10,
|
||||
transformOrigin: '50% 100%',
|
||||
ease: 'sine.inOut'
|
||||
}, 'step1+=0')
|
||||
.to('#one', {
|
||||
rotation: 0,
|
||||
duration: 1,
|
||||
ease: 'elastic(0.8, 0.28)'
|
||||
}, 'step1+=0.3')
|
||||
|
||||
.add('step2', '-=0')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: '#one_end'
|
||||
},
|
||||
y: '-=80',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step2')
|
||||
.to('#oneContainer', {
|
||||
scaleX: 1.4,
|
||||
scaleY: 0.6,
|
||||
duration: 0.8,
|
||||
transformOrigin: '50% 0%',
|
||||
ease: 'sine'
|
||||
}, 'step2')
|
||||
|
||||
|
||||
.add('step3')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: '#one_end'
|
||||
},
|
||||
y: '+=80',
|
||||
ease: 'expo.in'
|
||||
}, 'step3')
|
||||
.to('#oneContainer', {
|
||||
scale: 1,
|
||||
duration: 0.38,
|
||||
ease: 'expo.in'
|
||||
}, 'step3')
|
||||
|
||||
.to('#one', {
|
||||
rotation: 3,
|
||||
duration: 1,
|
||||
transformOrigin: '50% 120%',
|
||||
ease: "wiggle({type:easeOut, wiggles:8})"
|
||||
}, 'step3+=0.5')
|
||||
.from('#dot', {
|
||||
scale: 0,
|
||||
transformOrigin: '50% 50%',
|
||||
ease: 'elastic(0.4, 0.5)'
|
||||
}, 'step3+=0.46')
|
||||
.add(playConfetti, 'step3+=0.46')
|
||||
.add('step4', '+=2')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: "#one_mid"
|
||||
},
|
||||
duration: 0.2
|
||||
}, 'step4')
|
||||
.to('#one, .thankYouMask', {
|
||||
x: '-=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step4')
|
||||
.to('#dot', {
|
||||
opacity: 0,
|
||||
duration: 0.2,
|
||||
ease: 'expo'
|
||||
}, 'step4')
|
||||
.to('.numberMask', {
|
||||
x: '-=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step4')
|
||||
.from(allNumbers, {
|
||||
x: 50,
|
||||
immediateRender: false,
|
||||
stagger: {
|
||||
each: 0.05
|
||||
}
|
||||
}, 'step4')
|
||||
.from(allNumbers, {
|
||||
rotation: 50,
|
||||
transformOrigin: '50% 50%',
|
||||
immediateRender: false,
|
||||
stagger: {
|
||||
each: 0.05
|
||||
},
|
||||
ease: 'expo'
|
||||
}, 'step4')
|
||||
.to('#gradBar', {
|
||||
width: 0,
|
||||
ease: 'expo.inOut'
|
||||
}, 'step4')
|
||||
|
||||
.add('step5')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: "M219.16,266.34h-16.8V253.5l32-.12v89.4H219.16Z"
|
||||
},
|
||||
ease: 'expo.inOut',
|
||||
x: 0
|
||||
}, 'step5-=0.3')
|
||||
|
||||
.to('#one', {
|
||||
rotation: -10,
|
||||
transformOrigin: '50% 100%',
|
||||
ease: 'sine.inOut'
|
||||
}, 'step5-=0.3')
|
||||
.to('#one', {
|
||||
rotation: 0,
|
||||
duration: 1,
|
||||
ease: 'elastic(0.8, 0.28)'
|
||||
}, 'step5')
|
||||
|
||||
|
||||
createConfetti();
|
||||
|
||||
//start anim - plays once
|
||||
gsap.from('#one, #numberGroup path', {
|
||||
stagger: {
|
||||
each: 0.05
|
||||
},
|
||||
scaleY:0,
|
||||
delay: 0.6,
|
||||
duration: 0.8,
|
||||
transformOrigin: '50% 100%',
|
||||
ease: 'elastic(0.73, 0.6)'
|
||||
})
|
||||
|
||||
//loop the gradient bar
|
||||
gsap.to('#gradPattern', {
|
||||
attr:{
|
||||
x:556
|
||||
},
|
||||
duration: 2,
|
||||
repeat: -1,
|
||||
ease:'linear'
|
||||
})
|
|
@ -0,0 +1,23 @@
|
|||
body {
|
||||
background-color: #131417;
|
||||
overflow: hidden;
|
||||
text-align:center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
visibility: hidden;
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2022 by Chris Gannon (https://codepen.io/chrisgannon/pen/qBPGEQy)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<svg id="mainSVG" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
|
||||
<defs>
|
||||
<linearGradient id="codepenGrad" x1="0" y1="383.12" x2="556" y2="383.12" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#42c2f1"/>
|
||||
<stop offset="0.2" stop-color="#fbda4f"/>
|
||||
<stop offset="0.6" stop-color="#ab63df"/>
|
||||
<stop offset="0.8" stop-color="#5fc581"/>
|
||||
<stop offset="1" stop-color="#42c2f1"/>
|
||||
</linearGradient>
|
||||
<pattern id="gradPattern" width="556" height="62.4" x="0" y="0" patternUnits="userSpaceOnUse">
|
||||
<rect x="0" y="0" fill="url(#codepenGrad)" width="556" height="62.4" />
|
||||
</pattern>
|
||||
<clipPath id="numberMask">
|
||||
<rect class="numberMask" x="122.36" y="204.62" width="547.24" height="176.58" fill="red" />
|
||||
</clipPath>
|
||||
<clipPath id="thankYouMask">
|
||||
<rect class="thankYouMask" x="-500" y="204.62" width="615" height="176.58" fill="#29abe2"/>
|
||||
</clipPath>
|
||||
<path id="one_mid" d="M219.16,266.34h0v-62.6l15.24-.12V389.93H219.16Z" />
|
||||
<path id="one_end" d="M219.16,266.34h0v-12.9l15.24-.12-1.14,62.58h-13Z" />
|
||||
<g class="confetti">
|
||||
<rect class="paper" width="13" height="8" />
|
||||
</g>
|
||||
</defs>
|
||||
|
||||
<rect id="gradBar" x="120" y="376.31" width="556" height="10" fill="url(#gradPattern)"/>
|
||||
<path id="one_end" d="M219.16,266.34h-16.8V253.5l32-.12v89.4H219.16Z" fill="#fff" opacity="0"/>
|
||||
<g id="oneContainer">
|
||||
<path id="one" d="M219.16,266.34h-16.8V253.5l32-.12v89.4H219.16Z" fill="#fff" />
|
||||
</g>
|
||||
<g clip-path="url(#numberMask)">
|
||||
<g id="numberGroup">
|
||||
<path id="_0_1" data-name="0_1" d="M253.12,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C267.64,344.22,253.12,325.74,253.12,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16-12.72,0-20.64,12.24-20.64,32.16s8,32.28,20.76,32.28S309.76,318.06,309.76,298Z" fill="#fff" />
|
||||
<path id="comma" d="M340.6,326.58h14l-8.88,30.24h-10Z" fill="#fff" />
|
||||
<path id="_0_2" data-name="0_2" d="M366.88,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C381.4,344.22,366.88,325.74,366.88,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16C389.92,265.86,382,278.1,382,298s8,32.28,20.76,32.28S423.52,318.06,423.52,298Z" fill="#fff" />
|
||||
<path id="_0_3" data-name="0_3" d="M446.56,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C461.08,344.22,446.56,325.74,446.56,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16-12.72,0-20.64,12.24-20.64,32.16s8,32.28,20.76,32.28S503.2,318.06,503.2,298Z" fill="#fff" />
|
||||
<path id="_0_4" data-name="0_4" d="M526.24,298c0-27.72,14.4-46.08,35.76-46.08,21.6,0,35.88,18.48,35.88,46.08s-14.16,46.2-35.76,46.2C540.76,344.22,526.24,325.74,526.24,298Zm56.64,0c0-19.92-7.92-32.16-20.88-32.16-12.72,0-20.64,12.24-20.64,32.16s8,32.28,20.76,32.28S582.88,318.06,582.88,298Z" fill="#fff" />
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#thankYouMask)">
|
||||
<g id="thankYouGroup">
|
||||
<path d="M139.48,266.7h-23.4V253.38H178V266.7H154.72v76.08H139.48Z" fill="#fff"/>
|
||||
<path d="M241.12,300.78v42h-14.4v-38.4c0-8.76-5.52-14.4-13.68-14.4s-13.8,5.64-13.8,14.4v38.4h-14.4v-89.4h14.4v31.08c3.72-5,10.08-7.8,17.52-7.8C231.16,276.66,241.12,286.5,241.12,300.78Z" fill="#fff"/>
|
||||
<path d="M303.76,299.58v43.2H290.2v-7.2c-4.8,5.76-11.4,8.64-19.2,8.64-14.4,0-23.52-8.16-23.52-19.2,0-9.6,7.56-16,20.64-18.84l21.24-4.56v-2c0-6-4.92-10-12.12-10a15.45,15.45,0,0,0-14.88,10l-12.48-6.24c3.72-9.84,14.52-16.68,27.36-16.68C293,276.66,303.76,286.14,303.76,299.58Zm-14.4,17.16v-4.2L271,316.62c-5.4,1.2-8.52,4.32-8.52,8.28,0,4.92,4,7.92,10.2,7.92C282.28,332.82,289.36,325.86,289.36,316.74Z" fill="#fff"/>
|
||||
<path d="M368.8,300.78v42H354.4v-38.4c0-8.76-5.52-14.4-13.68-14.4s-13.8,5.64-13.8,14.4v38.4h-14.4V278.1h13.56v7.8c3.6-6,10.32-9.24,18.36-9.24C358.84,276.66,368.8,286.62,368.8,300.78Z" fill="#fff"/>
|
||||
<path d="M412.6,304.14l23.64,38.64h-16l-17-28.32-10.08,10.92v17.4h-14.4v-89.4h14.4v52.56l26.16-27.84h16.92Z" fill="#fff"/>
|
||||
<path d="M518.8,278.1,490,350.34c-2.88,7.08-7.92,18.84-24.24,18.84a23.46,23.46,0,0,1-9.48-1.68V355.38a33,33,0,0,0,7.44,1c8.28,0,10.44-4.8,12.12-8.76l2.16-5L452.56,278.1h15.72l17.4,45.72,17.4-45.72Z" fill="#fff"/>
|
||||
<path d="M519.16,310.38c0-19.56,14.88-33.72,34-33.72s34,14.16,34,33.72-15.12,33.84-34,33.84S519.16,329.94,519.16,310.38Zm52.92.12c0-11.88-8-20.52-19-20.52s-19,8.64-19,20.52,7.92,20.4,19,20.4S572.08,322.38,572.08,310.5Z" fill="#fff"/>
|
||||
<path d="M649.59,278.1v64.68H635.92v-7.44c-3.6,5.64-10.2,8.88-18.12,8.88-14.4,0-24.48-11-24.48-25.92V278.1h14.4v38.4c0,8.76,5.52,14.4,13.8,14.4s13.68-5.64,13.68-14.4V278.1Z" fill="#fff"/>
|
||||
</g>
|
||||
|
||||
</g>
|
||||
<rect id="dot" x="662.8" y="326.58" width="14.88" height="16.2" fill="#fff"/>
|
||||
<g class="container"/>
|
||||
</svg>
|
After Width: | Height: | Size: 4.7 KiB |
|
@ -0,0 +1,244 @@
|
|||
let select = s => document.querySelector(s),
|
||||
selectAll = s => document.querySelectorAll(s),
|
||||
mainSVG = select('#mainSVG'),
|
||||
allNumbers = gsap.utils.toArray('#numberGroup path'),
|
||||
allThankYou = gsap.utils.toArray('#thankYouGroup path'),
|
||||
//colorArray = ["#EF5350", "#EC407A","#AB47BC","#7E57C2","#5C6BC0","#42A5F5","#29B6F6","#26C6DA","#26A69A","#66BB6A","#9CCC65","#D4E157","#FFEE58","#FFCA28","#FFA726","#FF7043","#8D6E63","#BDBDBD","#78909C"],
|
||||
colorArray = ["#42c2f1", "#fbda4f","#ab63df","#5fc581"],
|
||||
confetti = select('.confetti'),
|
||||
container = select('.container')
|
||||
|
||||
gsap.set('svg', {
|
||||
visibility: 'visible'
|
||||
})
|
||||
let confettiTl = gsap.timeline({paused: true});
|
||||
|
||||
function playConfetti () {
|
||||
|
||||
confettiTl.play(0);
|
||||
}
|
||||
|
||||
function createConfetti () {
|
||||
var i = 160, clone, tl, rot, duration, paperDuration;
|
||||
while(--i > -1) {
|
||||
tl = gsap.timeline();
|
||||
clone = confetti.cloneNode(true);
|
||||
container.appendChild(clone);
|
||||
rot = gsap.utils.random(0, 360);
|
||||
duration = gsap.utils.random(3, 9);
|
||||
paperDuration = (duration)/20;
|
||||
gsap.set(clone, {
|
||||
fill: gsap.utils.random(colorArray),
|
||||
rotation: rot,
|
||||
transformOrigin: '50% 50%'
|
||||
})
|
||||
|
||||
tl.fromTo(clone, {
|
||||
x: gsap.utils.random(0, 800),
|
||||
y: -50,
|
||||
rotation: rot
|
||||
}, {
|
||||
duration: duration,
|
||||
x: '+=' + gsap.utils.random(-200, 200),
|
||||
y: 650,
|
||||
rotation: '+=180',
|
||||
ease: 'linear'
|
||||
})
|
||||
.to(clone.querySelector('.paper'), {
|
||||
duration: duration/23,
|
||||
scaleY: 0.1,
|
||||
repeat: 23,
|
||||
yoyo: true
|
||||
}, 0)
|
||||
//console.log(paperDuration)
|
||||
confettiTl.add(tl, i/200).timeScale(2.3);
|
||||
}
|
||||
|
||||
gsap.set('.paper', {
|
||||
transformOrigin: '50% 50%'
|
||||
})
|
||||
}
|
||||
|
||||
let tl = gsap.timeline({repeat: -1});
|
||||
tl.add('step0', '+=2')
|
||||
.to('#one', {
|
||||
x: -105,
|
||||
ease: 'expo.inOut'
|
||||
}, 'step0')
|
||||
.to('#one', {
|
||||
rotation: 10,
|
||||
transformOrigin: '50% 150%',
|
||||
ease: 'sine.inOut'
|
||||
}, 'step0+=0')
|
||||
.to('#one', {
|
||||
rotation: 0,
|
||||
|
||||
ease: 'elastic(0.8, 0.28)'
|
||||
}, 'step0+=0.3')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: '#one_mid'
|
||||
},
|
||||
ease: 'expo.inOut'
|
||||
}, 'step0')
|
||||
.add('step1')
|
||||
.to('#one, .numberMask', {
|
||||
x: '+=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step1')
|
||||
.to('.thankYouMask', {
|
||||
x: '+=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step1')
|
||||
.from(allThankYou, {
|
||||
x: 50,
|
||||
immediateRender: false,
|
||||
stagger: {
|
||||
each: 0.05
|
||||
},
|
||||
ease: 'expo'
|
||||
}, 'step1')
|
||||
.from('#gradBar', {
|
||||
width: 0,
|
||||
ease: 'expo.inOut'
|
||||
}, 'step1')
|
||||
|
||||
.to('#one', {
|
||||
rotation: -10,
|
||||
transformOrigin: '50% 100%',
|
||||
ease: 'sine.inOut'
|
||||
}, 'step1+=0')
|
||||
.to('#one', {
|
||||
rotation: 0,
|
||||
duration: 1,
|
||||
ease: 'elastic(0.8, 0.28)'
|
||||
}, 'step1+=0.3')
|
||||
|
||||
.add('step2', '-=0')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: '#one_end'
|
||||
},
|
||||
y: '-=80',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step2')
|
||||
.to('#oneContainer', {
|
||||
scaleX: 1.4,
|
||||
scaleY: 0.6,
|
||||
duration: 0.8,
|
||||
transformOrigin: '50% 0%',
|
||||
ease: 'sine'
|
||||
}, 'step2')
|
||||
|
||||
|
||||
.add('step3')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: '#one_end'
|
||||
},
|
||||
y: '+=80',
|
||||
ease: 'expo.in'
|
||||
}, 'step3')
|
||||
.to('#oneContainer', {
|
||||
scale: 1,
|
||||
duration: 0.38,
|
||||
ease: 'expo.in'
|
||||
}, 'step3')
|
||||
|
||||
.to('#one', {
|
||||
rotation: 3,
|
||||
duration: 1,
|
||||
transformOrigin: '50% 120%',
|
||||
ease: "wiggle({type:easeOut, wiggles:8})"
|
||||
}, 'step3+=0.5')
|
||||
.from('#dot', {
|
||||
scale: 0,
|
||||
transformOrigin: '50% 50%',
|
||||
ease: 'elastic(0.4, 0.5)'
|
||||
}, 'step3+=0.46')
|
||||
.add(playConfetti, 'step3+=0.46')
|
||||
.add('step4', '+=2')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: "#one_mid"
|
||||
},
|
||||
duration: 0.2
|
||||
}, 'step4')
|
||||
.to('#one, .thankYouMask', {
|
||||
x: '-=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step4')
|
||||
.to('#dot', {
|
||||
opacity: 0,
|
||||
duration: 0.2,
|
||||
ease: 'expo'
|
||||
}, 'step4')
|
||||
.to('.numberMask', {
|
||||
x: '-=548',
|
||||
ease: 'expo.inOut'
|
||||
}, 'step4')
|
||||
.from(allNumbers, {
|
||||
x: 50,
|
||||
immediateRender: false,
|
||||
stagger: {
|
||||
each: 0.05
|
||||
}
|
||||
}, 'step4')
|
||||
.from(allNumbers, {
|
||||
rotation: 50,
|
||||
transformOrigin: '50% 50%',
|
||||
immediateRender: false,
|
||||
stagger: {
|
||||
each: 0.05
|
||||
},
|
||||
ease: 'expo'
|
||||
}, 'step4')
|
||||
.to('#gradBar', {
|
||||
width: 0,
|
||||
ease: 'expo.inOut'
|
||||
}, 'step4')
|
||||
|
||||
.add('step5')
|
||||
.to('#one', {
|
||||
morphSVG: {
|
||||
shape: "M219.16,266.34h-16.8V253.5l32-.12v89.4H219.16Z"
|
||||
},
|
||||
ease: 'expo.inOut',
|
||||
x: 0
|
||||
}, 'step5-=0.3')
|
||||
|
||||
.to('#one', {
|
||||
rotation: -10,
|
||||
transformOrigin: '50% 100%',
|
||||
ease: 'sine.inOut'
|
||||
}, 'step5-=0.3')
|
||||
.to('#one', {
|
||||
rotation: 0,
|
||||
duration: 1,
|
||||
ease: 'elastic(0.8, 0.28)'
|
||||
}, 'step5')
|
||||
|
||||
|
||||
createConfetti();
|
||||
|
||||
//start anim - plays once
|
||||
gsap.from('#one, #numberGroup path', {
|
||||
stagger: {
|
||||
each: 0.05
|
||||
},
|
||||
scaleY:0,
|
||||
delay: 0.6,
|
||||
duration: 0.8,
|
||||
transformOrigin: '50% 100%',
|
||||
ease: 'elastic(0.73, 0.6)'
|
||||
})
|
||||
|
||||
//loop the gradient bar
|
||||
gsap.to('#gradPattern', {
|
||||
attr:{
|
||||
x:556
|
||||
},
|
||||
duration: 2,
|
||||
repeat: -1,
|
||||
ease:'linear'
|
||||
})
|
|
@ -0,0 +1,23 @@
|
|||
body {
|
||||
background-color: #131417;
|
||||
overflow: hidden;
|
||||
text-align:center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
visibility: hidden;
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# 10PRINT SVG
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/GeorgeDoesCode/pen/vYKyJLo](https://codepen.io/GeorgeDoesCode/pen/vYKyJLo).
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 10PRINT SVG</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
|
||||
<!-- partial -->
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/svg.js/3.0.16/svg.min.js'></script><script src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,42 @@
|
|||
// Based on https://www.youtube.com/watch?v=bEyTZ5ZZxZs thanks @shiffman!
|
||||
|
||||
const canvasWidth = 400;
|
||||
const canvasHeight = 400;
|
||||
|
||||
const canvas = SVG().addTo('body').viewbox(`0 0 ${canvasWidth} ${canvasHeight}`);
|
||||
|
||||
const space = 15;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
const lineStyle = {
|
||||
width: 2,
|
||||
color: '#FFE3EC' };
|
||||
|
||||
|
||||
(function drawLoop() {
|
||||
// play with this value to get more forward or back slashes!
|
||||
if (random(0, 1) < 0.25) {
|
||||
// backslash
|
||||
canvas.line(x, y, x + space, y + space).stroke(lineStyle);
|
||||
} else {
|
||||
// forward slash
|
||||
canvas.line(x, y + space, x + space, y).stroke(lineStyle);
|
||||
}
|
||||
|
||||
x += space;
|
||||
|
||||
if (x > canvasWidth) {
|
||||
x = 0;
|
||||
y += space;
|
||||
}
|
||||
|
||||
if (y < canvasHeight) {
|
||||
requestAnimationFrame(drawLoop);
|
||||
}
|
||||
})();
|
||||
|
||||
// random utility fn
|
||||
function random(min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
display: -webkit-box;
|
||||
display: flex;
|
||||
min-width: 240px;
|
||||
height: 100vh;
|
||||
background: #FFE3EC;
|
||||
padding: 2rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 75vmin;
|
||||
flex-shrink: 1;
|
||||
margin: auto;
|
||||
background: #FF8CBA;
|
||||
border: 6px solid #FF8CBA;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
line {
|
||||
stroke-linecap: round;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2020 by George (https://codepen.io/GeorgeDoesCode/pen/vYKyJLo)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Based on https://www.youtube.com/watch?v=bEyTZ5ZZxZs thanks @shiffman!
|
||||
|
||||
const canvasWidth = 400;
|
||||
const canvasHeight = 400;
|
||||
|
||||
const canvas = SVG().addTo('body').viewbox(`0 0 ${canvasWidth} ${canvasHeight}`);
|
||||
|
||||
const space = 15;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
const lineStyle = {
|
||||
width: 2,
|
||||
color: '#FFE3EC'
|
||||
};
|
||||
|
||||
(function drawLoop() {
|
||||
// play with this value to get more forward or back slashes!
|
||||
if(random(0, 1) < 0.25) {
|
||||
// backslash
|
||||
canvas.line(x, y, x + space, y + space).stroke(lineStyle);
|
||||
} else {
|
||||
// forward slash
|
||||
canvas.line(x, y + space, x + space, y).stroke(lineStyle);
|
||||
}
|
||||
|
||||
x += space;
|
||||
|
||||
if(x > canvasWidth) {
|
||||
x = 0;
|
||||
y += space;
|
||||
}
|
||||
|
||||
if(y < canvasHeight) {
|
||||
requestAnimationFrame(drawLoop);
|
||||
}
|
||||
})();
|
||||
|
||||
// random utility fn
|
||||
function random(min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
min-width: 240px;
|
||||
height: 100vh;
|
||||
background: #FFE3EC;
|
||||
padding: 2rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 75vmin;
|
||||
flex-shrink: 1;
|
||||
margin: auto;
|
||||
background: #FF8CBA;
|
||||
border: 6px solid #FF8CBA;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
line {
|
||||
stroke-linecap: round;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# #141 in 2021 / JavaScript Canvas
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/toshiya-marukubo/pen/VwpLWxR](https://codepen.io/toshiya-marukubo/pen/VwpLWxR).
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - #141 in 2021 / JavaScript Canvas</title>
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
|
||||
<!-- partial -->
|
||||
<script src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,82 @@
|
|||
var W, M, c, C, WW, WH,
|
||||
xNum, yNum, rad, num, angle, pos,
|
||||
animationId;
|
||||
|
||||
var getRandomNumber = function (min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min);
|
||||
};
|
||||
|
||||
var makeCanvas = function () {
|
||||
document
|
||||
.getElementsByTagName("body")[0]
|
||||
.appendChild(document.createElement("canvas"));
|
||||
};
|
||||
|
||||
var initialize = function () {
|
||||
W = window;
|
||||
M = Math;
|
||||
c = document.getElementsByTagName("canvas")[0];
|
||||
C = c.getContext("2d");
|
||||
WW = c.width = M.floor(W.innerWidth);
|
||||
WH = c.height = M.floor(W.innerHeight);
|
||||
rad = M.PI / 2;
|
||||
pos = [];
|
||||
angle = 0;
|
||||
length = 20;
|
||||
for (var y = 0; y < WH; y+=length) {
|
||||
for (var x = 0; x < WW; x+=length) {
|
||||
pos.push([x, y, getRandomNumber(0, 1)]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var f = function (t) {
|
||||
t /= 200;
|
||||
C.save();
|
||||
C.clearRect(0, 0, WW, WH);
|
||||
C.lineWidth = 5;
|
||||
for (var i = 0; i < pos.length; i++) {
|
||||
C.save();
|
||||
var cy = pos[i][1] - WH / 2;
|
||||
var cx = pos[i][0] - WW / 2;
|
||||
var dist = M.sqrt(cx * cx + cy * cy) * 0.01;
|
||||
var theta = M.atan2(cy, cx);
|
||||
var s = M.sin(M.sin(theta * M.PI / 180) + dist - t) + theta * 3 + 1;
|
||||
if (M.sin(t + s) > 0) {
|
||||
C.translate(pos[i][0] + length / 2, pos[i][1] + length / 2);
|
||||
C.strokeStyle = 'hsl(' + M.sin(t + s) * 360 + ', 80%, 60%)';
|
||||
C.rotate(t + s);
|
||||
C.translate(-pos[i][0] - length / 2, -pos[i][1] - length / 2);
|
||||
}
|
||||
if (pos[i][2] === 0) {
|
||||
C.beginPath();
|
||||
C.moveTo(pos[i][0], pos[i][1]);
|
||||
C.lineTo(pos[i][0] + length, pos[i][1] + length);
|
||||
C.stroke();
|
||||
} else {
|
||||
C.beginPath();
|
||||
C.moveTo(pos[i][0] + length, pos[i][1]);
|
||||
C.lineTo(pos[i][0], pos[i][1] + length);
|
||||
C.stroke();
|
||||
}
|
||||
C.restore();
|
||||
}
|
||||
C.restore();
|
||||
angle += 5;
|
||||
if (angle > 360) {
|
||||
angle = 0;
|
||||
}
|
||||
animationId = requestAnimationFrame(f);
|
||||
};
|
||||
|
||||
window.onload = function () {
|
||||
makeCanvas();
|
||||
initialize();
|
||||
f();
|
||||
W.onresize = function () {
|
||||
cancelAnimationFrame(animationId);
|
||||
length = 250;
|
||||
initialize();
|
||||
f();
|
||||
};
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2021 by Toshiya Marukubo (https://codepen.io/toshiya-marukubo/pen/VwpLWxR)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
var W, M, c, C, WW, WH,
|
||||
xNum, yNum, rad, num, angle, pos,
|
||||
animationId;
|
||||
|
||||
var getRandomNumber = function (min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min);
|
||||
};
|
||||
|
||||
var makeCanvas = function () {
|
||||
document
|
||||
.getElementsByTagName("body")[0]
|
||||
.appendChild(document.createElement("canvas"));
|
||||
};
|
||||
|
||||
var initialize = function () {
|
||||
W = window;
|
||||
M = Math;
|
||||
c = document.getElementsByTagName("canvas")[0];
|
||||
C = c.getContext("2d");
|
||||
WW = c.width = M.floor(W.innerWidth);
|
||||
WH = c.height = M.floor(W.innerHeight);
|
||||
rad = M.PI / 2;
|
||||
pos = [];
|
||||
angle = 0;
|
||||
length = 20;
|
||||
for (var y = 0; y < WH; y+=length) {
|
||||
for (var x = 0; x < WW; x+=length) {
|
||||
pos.push([x, y, getRandomNumber(0, 1)]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var f = function (t) {
|
||||
t /= 200;
|
||||
C.save();
|
||||
C.clearRect(0, 0, WW, WH);
|
||||
C.lineWidth = 5;
|
||||
for (var i = 0; i < pos.length; i++) {
|
||||
C.save();
|
||||
var cy = pos[i][1] - WH / 2;
|
||||
var cx = pos[i][0] - WW / 2;
|
||||
var dist = M.sqrt(cx * cx + cy * cy) * 0.01;
|
||||
var theta = M.atan2(cy, cx);
|
||||
var s = M.sin(M.sin(theta * M.PI / 180) + dist - t) + theta * 3 + 1;
|
||||
if (M.sin(t + s) > 0) {
|
||||
C.translate(pos[i][0] + length / 2, pos[i][1] + length / 2);
|
||||
C.strokeStyle = 'hsl(' + M.sin(t + s) * 360 + ', 80%, 60%)';
|
||||
C.rotate(t + s);
|
||||
C.translate(-pos[i][0] - length / 2, -pos[i][1] - length / 2);
|
||||
}
|
||||
if (pos[i][2] === 0) {
|
||||
C.beginPath();
|
||||
C.moveTo(pos[i][0], pos[i][1]);
|
||||
C.lineTo(pos[i][0] + length, pos[i][1] + length);
|
||||
C.stroke();
|
||||
} else {
|
||||
C.beginPath();
|
||||
C.moveTo(pos[i][0] + length, pos[i][1]);
|
||||
C.lineTo(pos[i][0], pos[i][1] + length);
|
||||
C.stroke();
|
||||
}
|
||||
C.restore();
|
||||
}
|
||||
C.restore();
|
||||
angle += 5;
|
||||
if (angle > 360) {
|
||||
angle = 0;
|
||||
}
|
||||
animationId = requestAnimationFrame(f);
|
||||
};
|
||||
|
||||
window.onload = function () {
|
||||
makeCanvas();
|
||||
initialize();
|
||||
f();
|
||||
W.onresize = function () {
|
||||
cancelAnimationFrame(animationId);
|
||||
length = 250;
|
||||
initialize();
|
||||
f();
|
||||
};
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# 20.
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/ycw/pen/OJRwedY](https://codepen.io/ycw/pen/OJRwedY).
|
||||
|
||||
- [camera movement](https://codepen.io/ycw/details/dypKrKq)
|
||||
- [sidewall uv](https://codepen.io/ycw/details/yLaqEWd)
|
||||
- photo by [Nik](https://unsplash.com/photos/Geu-i5VvI1A)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 20.</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
|
||||
<!-- partial -->
|
||||
<script type="module" src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,156 @@
|
|||
import * as $ from '//unpkg.com/three@0.124.0/build/three.module.js'
|
||||
import { OrbitControls } from '//unpkg.com/three@0.124.0/examples/jsm/controls/OrbitControls.js'
|
||||
import { EffectComposer } from '//unpkg.com/three@0.124.0/examples/jsm/postprocessing/EffectComposer'
|
||||
import { RenderPass } from '//unpkg.com/three@0.124.0/examples/jsm/postprocessing/RenderPass'
|
||||
import { UnrealBloomPass } from '//unpkg.com/three@0.124.0/examples/jsm/postprocessing/UnrealBloomPass'
|
||||
import { Curves } from '//unpkg.com/three@0.124.0/examples/jsm/curves/CurveExtras'
|
||||
// ---- boot
|
||||
|
||||
const renderer = new $.WebGLRenderer({});
|
||||
const scene = new $.Scene();
|
||||
const camera = new $.PerspectiveCamera(75, 2, .01, 5000);
|
||||
window.addEventListener('resize', () => {
|
||||
const { clientWidth, clientHeight } = renderer.domElement;
|
||||
renderer.setSize(clientWidth, clientHeight, false);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
camera.aspect = clientWidth / clientHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
});
|
||||
document.body.prepend(renderer.domElement);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
// ---- setup
|
||||
|
||||
scene.fog = new $.FogExp2('black', 0.05);
|
||||
scene.add(new $.HemisphereLight('cyan', 'orange', 2));
|
||||
|
||||
// ---- const
|
||||
|
||||
const mpms = (20) / 1e3;
|
||||
const steps = 2000;
|
||||
|
||||
// ---- mesh
|
||||
|
||||
const shape = new $.Shape();
|
||||
// cw
|
||||
shape.moveTo(-5, -1);
|
||||
shape.quadraticCurveTo(0, -4, 5, -1);
|
||||
shape.lineTo(6, -1);
|
||||
shape.quadraticCurveTo(0, -5, -6, -1);
|
||||
const extrudePath = new Curves.TorusKnot();
|
||||
const UVGenerator = (() => {
|
||||
let i = 0; // face id
|
||||
return {
|
||||
generateTopUV(...xs) { // for 2 "cap" faces
|
||||
return [new $.Vector2(), new $.Vector2(), new $.Vector2()];
|
||||
},
|
||||
generateSideWallUV(_geom, _vs, _a, _b, _c, _d) { // all side faces
|
||||
const segments = 5; // (shape-related; NOT eq `curveSegments`)
|
||||
if (i < segments * steps) { // ignore bottom road faces
|
||||
++i;
|
||||
return [new $.Vector2(), new $.Vector2(), new $.Vector2(), new $.Vector2()];
|
||||
}
|
||||
const n = i - segments * steps; // offseted face idx
|
||||
const total_col_segments = 7; // (shape-related)
|
||||
const col = n / steps | 0;
|
||||
const left = col / total_col_segments; // normalize
|
||||
const right = (col + 1) / total_col_segments; // normalize
|
||||
const row = n % steps;
|
||||
const bottom = row / steps; // normalize
|
||||
const top = (row + 1) / steps; // normalize
|
||||
++i;
|
||||
return [
|
||||
new $.Vector2(left, bottom), // bottom left
|
||||
new $.Vector2(right, bottom), // bottom right
|
||||
new $.Vector2(right, top), // top right
|
||||
new $.Vector2(left, top) // top left
|
||||
];
|
||||
}
|
||||
};
|
||||
})();
|
||||
const extrudeGeom = new $.ExtrudeBufferGeometry(shape, {
|
||||
bevelEnabled: false, steps, extrudePath,
|
||||
curveSegments: 5, UVGenerator
|
||||
});
|
||||
const matSideWall = f();
|
||||
const matTop = new $.MeshLambertMaterial({ color: 'black' });
|
||||
const mesh = new $.Mesh(extrudeGeom, [matTop, matSideWall]);
|
||||
scene.add(mesh);
|
||||
|
||||
// ---- composer
|
||||
|
||||
const composer = new EffectComposer(renderer);
|
||||
composer.addPass(new RenderPass(scene, camera));
|
||||
composer.addPass(new UnrealBloomPass(new $.Vector2(), 2, 0.5, 0.7));
|
||||
|
||||
// ---- anim
|
||||
|
||||
const totalLen = extrudePath.getLength();
|
||||
const { binormals } = extrudePath.computeFrenetFrames(steps);
|
||||
const $m = new $.Matrix4(); // rotation matrix
|
||||
|
||||
renderer.setAnimationLoop((t /*ms*/) => {
|
||||
const $u = ((mpms * t) % totalLen) / totalLen;
|
||||
// update cam position
|
||||
extrudePath.getPointAt($u, camera.position);
|
||||
// update cam rotation
|
||||
camera.setRotationFromMatrix($m.lookAt(
|
||||
/* eye */ camera.position,
|
||||
/* target */ extrudePath.getPointAt(Math.min(1.0, $u + 0.01)),
|
||||
/* up */ binormals[$u * steps | 0]
|
||||
));
|
||||
renderer.getDrawingBufferSize(composer.passes[1].resolution);
|
||||
composer.render();
|
||||
mesh.material[1].uniforms.t.value = t;
|
||||
});
|
||||
|
||||
// ---- sidewall material
|
||||
|
||||
function f() {
|
||||
const url = 'https://images.unsplash.com/photo-1550747528-cdb45925b3f7?ixid=MXwxMjA3fDB8MHxzZWFyY2h8Mnx8dW5pY29ybnxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=60';
|
||||
const tex = new $.TextureLoader().load(url);
|
||||
tex.wrapS = $.MirroredRepeatWrapping;
|
||||
tex.wrapT = $.RepeatWrapping;
|
||||
|
||||
const shader = $.ShaderLib.lambert;
|
||||
const uniforms = $.UniformsUtils.merge([shader.uniforms, {
|
||||
t: { value: 0 },
|
||||
stretch: { value: new $.Vector2(1, 10) },
|
||||
div: { value: new $.Vector2(32, 8) },
|
||||
}]);
|
||||
const vertexShader = `
|
||||
uniform sampler2D map;
|
||||
uniform vec2 stretch;
|
||||
` + shader.vertexShader.replace('#include <uv_vertex>', `
|
||||
#ifdef USE_UV
|
||||
vUv = ( uvTransform * vec3( uv, 1 ) ).xy * stretch;
|
||||
#endif
|
||||
`);
|
||||
const fragmentShader = `
|
||||
uniform vec2 div;
|
||||
uniform vec2 stretch;
|
||||
uniform float t;
|
||||
` + shader.fragmentShader.replace('#include <map_fragment>', `
|
||||
#ifdef USE_MAP
|
||||
{
|
||||
vec2 i = vec2(ivec2( vUv * div ));
|
||||
vec4 tA = texture2D( map, ( i ) / div );
|
||||
vec4 tB = texture2D( map, ( i + 1.0 ) / div );
|
||||
vec4 texel = 0.5 * (mix( tA, tB, vUv.x ) + mix( tA, tB, vUv.y ));
|
||||
texel.b = step( 0.5, texel.b ) + ( sin( t * 0.001 ) * 0.5 + 0.5 );
|
||||
texel.r *= 2.0;
|
||||
texel.g *= 0.5;
|
||||
vec2 uv = fract( vUv * stretch * div );
|
||||
texel *= step( 0.2, uv.x ) * step ( 0.2, uv.y );
|
||||
diffuseColor *= texel;
|
||||
}
|
||||
#endif
|
||||
`);
|
||||
const mat = new $.ShaderMaterial({
|
||||
uniforms, vertexShader, fragmentShader,
|
||||
lights: true, fog: true
|
||||
});
|
||||
mat.map = mat.uniforms.map.value = tex;
|
||||
|
||||
return mat;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
canvas {
|
||||
display:block; width:100%; height:100vh;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2021 by ycw (https://codepen.io/ycw/pen/OJRwedY)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
import * as $ from '//unpkg.com/three@0.124.0/build/three.module.js'
|
||||
import { OrbitControls } from '//unpkg.com/three@0.124.0/examples/jsm/controls/OrbitControls.js'
|
||||
import { EffectComposer } from '//unpkg.com/three@0.124.0/examples/jsm/postprocessing/EffectComposer'
|
||||
import { RenderPass } from '//unpkg.com/three@0.124.0/examples/jsm/postprocessing/RenderPass'
|
||||
import { UnrealBloomPass } from '//unpkg.com/three@0.124.0/examples/jsm/postprocessing/UnrealBloomPass'
|
||||
import { Curves } from '//unpkg.com/three@0.124.0/examples/jsm/curves/CurveExtras'
|
||||
// ---- boot
|
||||
|
||||
const renderer = new $.WebGLRenderer({});
|
||||
const scene = new $.Scene();
|
||||
const camera = new $.PerspectiveCamera(75, 2, .01, 5000);
|
||||
window.addEventListener('resize', () => {
|
||||
const { clientWidth, clientHeight } = renderer.domElement;
|
||||
renderer.setSize(clientWidth, clientHeight, false);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
camera.aspect = clientWidth / clientHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
});
|
||||
document.body.prepend(renderer.domElement);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
// ---- setup
|
||||
|
||||
scene.fog = new $.FogExp2('black', 0.05);
|
||||
scene.add(new $.HemisphereLight('cyan', 'orange', 2));
|
||||
|
||||
// ---- const
|
||||
|
||||
const mpms = (20) / 1e3;
|
||||
const steps = 2000;
|
||||
|
||||
// ---- mesh
|
||||
|
||||
const shape = new $.Shape();
|
||||
// cw
|
||||
shape.moveTo(-5, -1);
|
||||
shape.quadraticCurveTo(0, -4, 5, -1);
|
||||
shape.lineTo(6, -1);
|
||||
shape.quadraticCurveTo(0, -5, -6, -1);
|
||||
const extrudePath = new Curves.TorusKnot();
|
||||
const UVGenerator = (() => {
|
||||
let i = 0; // face id
|
||||
return {
|
||||
generateTopUV(...xs) { // for 2 "cap" faces
|
||||
return [new $.Vector2(), new $.Vector2(), new $.Vector2()];
|
||||
},
|
||||
generateSideWallUV(_geom, _vs, _a, _b, _c, _d) { // all side faces
|
||||
const segments = 5; // (shape-related; NOT eq `curveSegments`)
|
||||
if (i < segments * steps) { // ignore bottom road faces
|
||||
++i;
|
||||
return [new $.Vector2(), new $.Vector2(), new $.Vector2(), new $.Vector2()];
|
||||
}
|
||||
const n = i - segments * steps; // offseted face idx
|
||||
const total_col_segments = 7; // (shape-related)
|
||||
const col = n / steps | 0;
|
||||
const left = col / total_col_segments; // normalize
|
||||
const right = (col + 1) / total_col_segments; // normalize
|
||||
const row = n % steps;
|
||||
const bottom = row / steps; // normalize
|
||||
const top = (row + 1) / steps; // normalize
|
||||
++i;
|
||||
return [
|
||||
new $.Vector2(left, bottom), // bottom left
|
||||
new $.Vector2(right, bottom), // bottom right
|
||||
new $.Vector2(right, top), // top right
|
||||
new $.Vector2(left, top) // top left
|
||||
];
|
||||
}
|
||||
};
|
||||
})();
|
||||
const extrudeGeom = new $.ExtrudeBufferGeometry(shape, {
|
||||
bevelEnabled: false, steps, extrudePath,
|
||||
curveSegments: 5, UVGenerator
|
||||
});
|
||||
const matSideWall = f();
|
||||
const matTop = new $.MeshLambertMaterial({ color: 'black' });
|
||||
const mesh = new $.Mesh(extrudeGeom, [matTop, matSideWall]);
|
||||
scene.add(mesh);
|
||||
|
||||
// ---- composer
|
||||
|
||||
const composer = new EffectComposer(renderer);
|
||||
composer.addPass(new RenderPass(scene, camera));
|
||||
composer.addPass(new UnrealBloomPass(new $.Vector2(), 2, 0.5, 0.7));
|
||||
|
||||
// ---- anim
|
||||
|
||||
const totalLen = extrudePath.getLength();
|
||||
const { binormals } = extrudePath.computeFrenetFrames(steps);
|
||||
const $m = new $.Matrix4(); // rotation matrix
|
||||
|
||||
renderer.setAnimationLoop((t /*ms*/) => {
|
||||
const $u = ((mpms * t) % totalLen) / totalLen;
|
||||
// update cam position
|
||||
extrudePath.getPointAt($u, camera.position);
|
||||
// update cam rotation
|
||||
camera.setRotationFromMatrix($m.lookAt(
|
||||
/* eye */ camera.position,
|
||||
/* target */ extrudePath.getPointAt(Math.min(1.0, $u + 0.01)),
|
||||
/* up */ binormals[$u * steps | 0]
|
||||
));
|
||||
renderer.getDrawingBufferSize(composer.passes[1].resolution);
|
||||
composer.render();
|
||||
mesh.material[1].uniforms.t.value = t;
|
||||
});
|
||||
|
||||
// ---- sidewall material
|
||||
|
||||
function f() {
|
||||
const url = 'https://images.unsplash.com/photo-1550747528-cdb45925b3f7?ixid=MXwxMjA3fDB8MHxzZWFyY2h8Mnx8dW5pY29ybnxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=60';
|
||||
const tex = new $.TextureLoader().load(url);
|
||||
tex.wrapS = $.MirroredRepeatWrapping;
|
||||
tex.wrapT = $.RepeatWrapping;
|
||||
|
||||
const shader = $.ShaderLib.lambert;
|
||||
const uniforms = $.UniformsUtils.merge([shader.uniforms, {
|
||||
t: { value: 0 },
|
||||
stretch: { value: new $.Vector2(1, 10) },
|
||||
div: { value: new $.Vector2(32, 8) },
|
||||
}]);
|
||||
const vertexShader = `
|
||||
uniform sampler2D map;
|
||||
uniform vec2 stretch;
|
||||
` + shader.vertexShader.replace('#include <uv_vertex>', `
|
||||
#ifdef USE_UV
|
||||
vUv = ( uvTransform * vec3( uv, 1 ) ).xy * stretch;
|
||||
#endif
|
||||
`);
|
||||
const fragmentShader = `
|
||||
uniform vec2 div;
|
||||
uniform vec2 stretch;
|
||||
uniform float t;
|
||||
` + shader.fragmentShader.replace('#include <map_fragment>', `
|
||||
#ifdef USE_MAP
|
||||
{
|
||||
vec2 i = vec2(ivec2( vUv * div ));
|
||||
vec4 tA = texture2D( map, ( i ) / div );
|
||||
vec4 tB = texture2D( map, ( i + 1.0 ) / div );
|
||||
vec4 texel = 0.5 * (mix( tA, tB, vUv.x ) + mix( tA, tB, vUv.y ));
|
||||
texel.b = step( 0.5, texel.b ) + ( sin( t * 0.001 ) * 0.5 + 0.5 );
|
||||
texel.r *= 2.0;
|
||||
texel.g *= 0.5;
|
||||
vec2 uv = fract( vUv * stretch * div );
|
||||
texel *= step( 0.2, uv.x ) * step ( 0.2, uv.y );
|
||||
diffuseColor *= texel;
|
||||
}
|
||||
#endif
|
||||
`);
|
||||
const mat = new $.ShaderMaterial({
|
||||
uniforms, vertexShader, fragmentShader,
|
||||
lights: true, fog: true
|
||||
});
|
||||
mat.map = mat.uniforms.map.value = tex;
|
||||
|
||||
return mat;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
canvas {
|
||||
display:block; width:100%; height:100vh;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# 2021 to 2022
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/alvaromontoro/pen/QWqmybN](https://codepen.io/alvaromontoro/pen/QWqmybN).
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 2021 to 2022</title>
|
||||
<meta name="monetization" content="$ilp.uphold.com/2f28xFUMdj9Z" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<div class="year">
|
||||
<div class="letter letter-2">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
<div class="letter letter-0">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
<div class="letter letter-2">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
<div class="letter letter-1">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- partial -->
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,145 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Chango&display=swap');
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
perspective: 1000px;
|
||||
background: #3693;
|
||||
}
|
||||
|
||||
.year {
|
||||
--duration: 1.5s;
|
||||
--color: #147;
|
||||
--shade: #57b;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-family: Chango, Arial, sans-serif;
|
||||
font-size: 150px;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotate3d(0, 1, 0, 0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate3d(0, 1, 0, -360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes jump {
|
||||
0%, 75%, 100% {
|
||||
margin-top: 0;
|
||||
}
|
||||
50% {
|
||||
margin-top: -20px;
|
||||
}
|
||||
}
|
||||
|
||||
.letter {
|
||||
position: relative;
|
||||
animation: rotate var(--duration) linear, jump var(--duration) linear;
|
||||
atransform: rotate3d(0, 1, 0, 90deg);
|
||||
width: 120px;
|
||||
height: 110px;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.letter div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
line-height: 110px;
|
||||
color: var(--color);
|
||||
|
||||
}
|
||||
|
||||
.letter span {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
|
||||
transform: translate(-50%, -50%) rotateY(90deg);
|
||||
display: block;
|
||||
|
||||
width: 12px;
|
||||
background: var(--color);
|
||||
}
|
||||
|
||||
.letter-2 span,
|
||||
.letter-1 span{
|
||||
top: 53%;
|
||||
height: 95%;
|
||||
}
|
||||
|
||||
.letter-0 span {
|
||||
top: 54.25%;
|
||||
left: 40%;
|
||||
height: 98%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.letter div:nth-child(2) {
|
||||
transform: translate3d(0, 0, 3px);
|
||||
}
|
||||
|
||||
.letter div:nth-child(3) {
|
||||
color: var(--shade);
|
||||
transform: translate3d(0, 0, 6px);
|
||||
}
|
||||
|
||||
.letter div:nth-child(4) {
|
||||
transform: translate3d(0, 0, -3px);
|
||||
}
|
||||
|
||||
.letter div:nth-child(5) {
|
||||
color: var(--shade);
|
||||
transform: translate3d(0, 0, -6px);
|
||||
}
|
||||
|
||||
.letter-2 div::before {
|
||||
content: "2";
|
||||
}
|
||||
|
||||
.letter-0 div::before {
|
||||
content: "0";
|
||||
}
|
||||
|
||||
@keyframes changeYear {
|
||||
0%, 25% { content: "1" }
|
||||
25.5%, 100% { content: "2" }
|
||||
}
|
||||
|
||||
|
||||
@keyframes updateFilling {
|
||||
0%, 25% {
|
||||
top: 55%;
|
||||
height: 95%;
|
||||
}
|
||||
25.5%, 100% {
|
||||
top: 53%;
|
||||
height: 95%;
|
||||
}
|
||||
}
|
||||
|
||||
.letter-1 div::before {
|
||||
content: "1";
|
||||
animation: changeYear var(--duration) calc(var(--duration) * 2.4) forwards;
|
||||
}
|
||||
|
||||
.letter-1 span {
|
||||
top: 55%;
|
||||
height: 95%;
|
||||
animation: updateFilling var(--duration) calc(var(--duration) * 2.4) forwards;
|
||||
}
|
||||
|
||||
.letter:nth-child(1) { animation-delay: calc(var(--duration) * 0.6); }
|
||||
.letter:nth-child(2) { animation-delay: calc(var(--duration) * 1.2); }
|
||||
.letter:nth-child(3) { animation-delay: calc(var(--duration) * 1.8); }
|
||||
.letter:nth-child(4) { animation-delay: calc(var(--duration) * 2.4); }
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2021 by Alvaro Montoro (https://codepen.io/alvaromontoro/pen/QWqmybN)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<div class="year">
|
||||
<div class="letter letter-2">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
<div class="letter letter-0">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
<div class="letter letter-2">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
<div class="letter letter-1">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,145 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Chango&display=swap');
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
perspective: 1000px;
|
||||
background: #3693;
|
||||
}
|
||||
|
||||
.year {
|
||||
--duration: 1.5s;
|
||||
--color: #147;
|
||||
--shade: #57b;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-family: Chango, Arial, sans-serif;
|
||||
font-size: 150px;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotate3d(0, 1, 0, 0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate3d(0, 1, 0, -360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes jump {
|
||||
0%, 75%, 100% {
|
||||
margin-top: 0;
|
||||
}
|
||||
50% {
|
||||
margin-top: -20px;
|
||||
}
|
||||
}
|
||||
|
||||
.letter {
|
||||
position: relative;
|
||||
animation: rotate var(--duration) linear, jump var(--duration) linear;
|
||||
atransform: rotate3d(0, 1, 0, 90deg);
|
||||
width: 120px;
|
||||
height: 110px;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.letter div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
line-height: 110px;
|
||||
color: var(--color);
|
||||
|
||||
}
|
||||
|
||||
.letter span {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
|
||||
transform: translate(-50%, -50%) rotateY(90deg);
|
||||
display: block;
|
||||
|
||||
width: 12px;
|
||||
background: var(--color);
|
||||
}
|
||||
|
||||
.letter-2 span,
|
||||
.letter-1 span{
|
||||
top: 53%;
|
||||
height: 95%;
|
||||
}
|
||||
|
||||
.letter-0 span {
|
||||
top: 54.25%;
|
||||
left: 40%;
|
||||
height: 98%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.letter div:nth-child(2) {
|
||||
transform: translate3d(0, 0, 3px);
|
||||
}
|
||||
|
||||
.letter div:nth-child(3) {
|
||||
color: var(--shade);
|
||||
transform: translate3d(0, 0, 6px);
|
||||
}
|
||||
|
||||
.letter div:nth-child(4) {
|
||||
transform: translate3d(0, 0, -3px);
|
||||
}
|
||||
|
||||
.letter div:nth-child(5) {
|
||||
color: var(--shade);
|
||||
transform: translate3d(0, 0, -6px);
|
||||
}
|
||||
|
||||
.letter-2 div::before {
|
||||
content: "2";
|
||||
}
|
||||
|
||||
.letter-0 div::before {
|
||||
content: "0";
|
||||
}
|
||||
|
||||
@keyframes changeYear {
|
||||
0%, 25% { content: "1" }
|
||||
25.5%, 100% { content: "2" }
|
||||
}
|
||||
|
||||
|
||||
@keyframes updateFilling {
|
||||
0%, 25% {
|
||||
top: 55%;
|
||||
height: 95%;
|
||||
}
|
||||
25.5%, 100% {
|
||||
top: 53%;
|
||||
height: 95%;
|
||||
}
|
||||
}
|
||||
|
||||
.letter-1 div::before {
|
||||
content: "1";
|
||||
animation: changeYear var(--duration) calc(var(--duration) * 2.4) forwards;
|
||||
}
|
||||
|
||||
.letter-1 span {
|
||||
top: 55%;
|
||||
height: 95%;
|
||||
animation: updateFilling var(--duration) calc(var(--duration) * 2.4) forwards;
|
||||
}
|
||||
|
||||
.letter:nth-child(1) { animation-delay: calc(var(--duration) * 0.6); }
|
||||
.letter:nth-child(2) { animation-delay: calc(var(--duration) * 1.2); }
|
||||
.letter:nth-child(3) { animation-delay: calc(var(--duration) * 1.8); }
|
||||
.letter:nth-child(4) { animation-delay: calc(var(--duration) * 2.4); }
|
|
@ -0,0 +1,7 @@
|
|||
# 31. taint
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/ycw/pen/BaQdJRd](https://codepen.io/ycw/pen/BaQdJRd).
|
||||
|
||||
taint the wire gird.
|
||||
|
||||
photo by [liu yi](https://unsplash.com/photos/zTJ0e2mbrrM)
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 31. taint</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
|
||||
<!-- partial -->
|
||||
<script type="module" src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,134 @@
|
|||
import * as $ from '//cdn.skypack.dev/three@0.125.0/build/three.module.js?min'
|
||||
import { OrbitControls } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/controls/OrbitControls.js?min'
|
||||
import { EffectComposer } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/postprocessing/EffectComposer.js?min'
|
||||
import { RenderPass } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/postprocessing/RenderPass.js?min'
|
||||
import { UnrealBloomPass } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/postprocessing/UnrealBloomPass.js?min'
|
||||
|
||||
//// Boot
|
||||
|
||||
const renderer = new $.WebGLRenderer({});
|
||||
const scene = new $.Scene();
|
||||
const camera = new $.PerspectiveCamera(75, 2, 20, 12000);
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
window.addEventListener('resize', () => {
|
||||
const { clientWidth, clientHeight } = renderer.domElement;
|
||||
renderer.setSize(clientWidth, clientHeight, false);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
camera.aspect = clientWidth / clientHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
});
|
||||
document.body.prepend(renderer.domElement);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
//// Inputs
|
||||
|
||||
const size = 5000;
|
||||
const segs = 500;
|
||||
const disp = 500;
|
||||
|
||||
//// Setup
|
||||
|
||||
camera.position.set(1000, 1200, 1200);
|
||||
controls.autoRotate = true;
|
||||
controls.enableDamping = true;
|
||||
controls.maxPolarAngle = Math.PI / 2.9;
|
||||
|
||||
const light0 = new $.DirectionalLight('white', 1);
|
||||
light0.position.set(0, 1, 0);
|
||||
scene.add(light0);
|
||||
|
||||
const tex0 = new $.TextureLoader().load('https://images.unsplash.com/photo-1613799122437-c48c0e4cd5c0?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw3OXx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=60');
|
||||
|
||||
const mesh0 = new $.Mesh(
|
||||
new $.PlaneBufferGeometry(size, size, segs, segs).rotateX(-0.5 * Math.PI),
|
||||
f()
|
||||
);
|
||||
scene.add(mesh0);
|
||||
const mesh1 = new $.Mesh(
|
||||
new $.PlaneBufferGeometry(size, size, segs >> 1, segs >> 1).rotateX(-0.5 * Math.PI),
|
||||
f({ wireframe: true, color: new $.Color('#333') })
|
||||
);
|
||||
scene.add(mesh1);
|
||||
|
||||
//// Make Material
|
||||
|
||||
function f({ wireframe, color } = {}) {
|
||||
const mat = new $.ShaderMaterial({
|
||||
extensions: {
|
||||
derivatives: true, // wgl 1
|
||||
},
|
||||
lights: true,
|
||||
wireframe: Boolean(wireframe),
|
||||
uniforms: $.UniformsUtils.merge([
|
||||
$.ShaderLib.standard.uniforms, {
|
||||
time: { value: 0 },
|
||||
displacementScale: { value: disp },
|
||||
wireframe: { value: wireframe || false },
|
||||
color: { value: color || new $.Color() },
|
||||
roughness: { value: 1 },
|
||||
metalness: { value: 0 }
|
||||
}
|
||||
]),
|
||||
vertexShader: `
|
||||
varying vec3 vWorldPos;
|
||||
` + $.ShaderLib.standard.vertexShader.replace("#include <worldpos_vertex>", `
|
||||
// #if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
|
||||
vec4 worldPosition = vec4( transformed, 1.0 );
|
||||
#ifdef USE_INSTANCING
|
||||
worldPosition = instanceMatrix * worldPosition;
|
||||
#endif
|
||||
worldPosition = modelMatrix * worldPosition;
|
||||
vWorldPos = worldPosition.xyz;
|
||||
// #endif
|
||||
`).replace("#include <displacementmap_vertex>", `
|
||||
#ifdef USE_DISPLACEMENTMAP
|
||||
transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );
|
||||
// form a bowl
|
||||
float yOffset = length( position.xz ) / ${size.toFixed(1)};
|
||||
yOffset = pow(sin(yOffset * 2.0), 2.0);
|
||||
transformed.y += yOffset * ${size.toFixed(1)} / 3.0;
|
||||
#endif
|
||||
`),
|
||||
fragmentShader: `
|
||||
varying vec3 vWorldPos;
|
||||
uniform float time;
|
||||
uniform bool wireframe;
|
||||
uniform vec3 color;
|
||||
` + $.ShaderLib.standard.fragmentShader.replace(
|
||||
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );", `
|
||||
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
|
||||
float ths = ${size.toFixed(1)} * pow(sin(time * 0.00015), 2.0);
|
||||
if ( !wireframe ) {
|
||||
if ( length( vWorldPos ) > ths ) {
|
||||
discard;
|
||||
}
|
||||
} else {
|
||||
gl_FragColor = vec4( color, 1.0 );
|
||||
if ( length( vWorldPos ) < ths ) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
`)
|
||||
});
|
||||
mat.map = mat.uniforms.map.value = tex0;
|
||||
mat.displacementMap = mat.uniforms.displacementMap.value = tex0;
|
||||
return mat;
|
||||
}
|
||||
|
||||
//// Render
|
||||
|
||||
const res = new $.Vector2();
|
||||
window.addEventListener('resize', () => {
|
||||
renderer.getDrawingBufferSize(res);
|
||||
fx.setSize(res.width, res.height);
|
||||
});
|
||||
const fx = new EffectComposer(renderer);
|
||||
fx.addPass(new RenderPass(scene, camera));
|
||||
fx.addPass(new UnrealBloomPass(res, 0.5, 0.5, 0.3));
|
||||
|
||||
renderer.setAnimationLoop((t) => {
|
||||
fx.render();
|
||||
mesh0.material.uniforms.time.value = t;
|
||||
mesh1.material.uniforms.time.value = t;
|
||||
controls.update();
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
canvas {
|
||||
display:block; width:100%; height:100vh; cursor: -webkit-grab; cursor: grab;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2021 by ycw (https://codepen.io/ycw/pen/BaQdJRd)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
import * as $ from '//cdn.skypack.dev/three@0.125.0/build/three.module.js?min'
|
||||
import { OrbitControls } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/controls/OrbitControls.js?min'
|
||||
import { EffectComposer } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/postprocessing/EffectComposer.js?min'
|
||||
import { RenderPass } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/postprocessing/RenderPass.js?min'
|
||||
import { UnrealBloomPass } from '//cdn.skypack.dev/three@0.125.0/examples/jsm/postprocessing/UnrealBloomPass.js?min'
|
||||
|
||||
//// Boot
|
||||
|
||||
const renderer = new $.WebGLRenderer({});
|
||||
const scene = new $.Scene();
|
||||
const camera = new $.PerspectiveCamera(75, 2, 20, 12000);
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
window.addEventListener('resize', () => {
|
||||
const { clientWidth, clientHeight } = renderer.domElement;
|
||||
renderer.setSize(clientWidth, clientHeight, false);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
camera.aspect = clientWidth / clientHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
});
|
||||
document.body.prepend(renderer.domElement);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
//// Inputs
|
||||
|
||||
const size = 5000;
|
||||
const segs = 500;
|
||||
const disp = 500;
|
||||
|
||||
//// Setup
|
||||
|
||||
camera.position.set(1000, 1200, 1200);
|
||||
controls.autoRotate = true;
|
||||
controls.enableDamping = true;
|
||||
controls.maxPolarAngle = Math.PI / 2.9;
|
||||
|
||||
const light0 = new $.DirectionalLight('white', 1);
|
||||
light0.position.set(0, 1, 0);
|
||||
scene.add(light0);
|
||||
|
||||
const tex0 = new $.TextureLoader().load('https://images.unsplash.com/photo-1613799122437-c48c0e4cd5c0?ixid=MXwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw3OXx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=60');
|
||||
|
||||
const mesh0 = new $.Mesh(
|
||||
new $.PlaneBufferGeometry(size, size, segs, segs).rotateX(-0.5 * Math.PI),
|
||||
f()
|
||||
);
|
||||
scene.add(mesh0);
|
||||
const mesh1 = new $.Mesh(
|
||||
new $.PlaneBufferGeometry(size, size, segs >> 1, segs >> 1).rotateX(-0.5 * Math.PI),
|
||||
f({ wireframe: true, color: new $.Color('#333') })
|
||||
);
|
||||
scene.add(mesh1);
|
||||
|
||||
//// Make Material
|
||||
|
||||
function f({ wireframe, color } = {}) {
|
||||
const mat = new $.ShaderMaterial({
|
||||
extensions: {
|
||||
derivatives: true, // wgl 1
|
||||
},
|
||||
lights: true,
|
||||
wireframe: Boolean(wireframe),
|
||||
uniforms: $.UniformsUtils.merge([
|
||||
$.ShaderLib.standard.uniforms, {
|
||||
time: { value: 0 },
|
||||
displacementScale: { value: disp },
|
||||
wireframe: { value: wireframe || false },
|
||||
color: { value: color || new $.Color() },
|
||||
roughness: { value: 1 },
|
||||
metalness: { value: 0 }
|
||||
}
|
||||
]),
|
||||
vertexShader: `
|
||||
varying vec3 vWorldPos;
|
||||
` + $.ShaderLib.standard.vertexShader.replace("#include <worldpos_vertex>", `
|
||||
// #if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
|
||||
vec4 worldPosition = vec4( transformed, 1.0 );
|
||||
#ifdef USE_INSTANCING
|
||||
worldPosition = instanceMatrix * worldPosition;
|
||||
#endif
|
||||
worldPosition = modelMatrix * worldPosition;
|
||||
vWorldPos = worldPosition.xyz;
|
||||
// #endif
|
||||
`).replace("#include <displacementmap_vertex>", `
|
||||
#ifdef USE_DISPLACEMENTMAP
|
||||
transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );
|
||||
// form a bowl
|
||||
float yOffset = length( position.xz ) / ${size.toFixed(1)};
|
||||
yOffset = pow(sin(yOffset * 2.0), 2.0);
|
||||
transformed.y += yOffset * ${size.toFixed(1)} / 3.0;
|
||||
#endif
|
||||
`),
|
||||
fragmentShader: `
|
||||
varying vec3 vWorldPos;
|
||||
uniform float time;
|
||||
uniform bool wireframe;
|
||||
uniform vec3 color;
|
||||
` + $.ShaderLib.standard.fragmentShader.replace(
|
||||
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );", `
|
||||
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
|
||||
float ths = ${size.toFixed(1)} * pow(sin(time * 0.00015), 2.0);
|
||||
if ( !wireframe ) {
|
||||
if ( length( vWorldPos ) > ths ) {
|
||||
discard;
|
||||
}
|
||||
} else {
|
||||
gl_FragColor = vec4( color, 1.0 );
|
||||
if ( length( vWorldPos ) < ths ) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
`)
|
||||
});
|
||||
mat.map = mat.uniforms.map.value = tex0;
|
||||
mat.displacementMap = mat.uniforms.displacementMap.value = tex0;
|
||||
return mat;
|
||||
}
|
||||
|
||||
//// Render
|
||||
|
||||
const res = new $.Vector2();
|
||||
window.addEventListener('resize', () => {
|
||||
renderer.getDrawingBufferSize(res);
|
||||
fx.setSize(res.width, res.height);
|
||||
});
|
||||
const fx = new EffectComposer(renderer);
|
||||
fx.addPass(new RenderPass(scene, camera));
|
||||
fx.addPass(new UnrealBloomPass(res, 0.5, 0.5, 0.3));
|
||||
|
||||
renderer.setAnimationLoop((t) => {
|
||||
fx.render();
|
||||
mesh0.material.uniforms.time.value = t;
|
||||
mesh1.material.uniforms.time.value = t;
|
||||
controls.update();
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
canvas {
|
||||
display:block; width:100%; height:100vh; cursor: grab;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# 3D CSS Kinetic Type Poster
|
||||
_A Pen created at CodePen.io. Original URL: [https://codepen.io/petebarr/pen/OJPBEwy](https://codepen.io/petebarr/pen/OJPBEwy).
|
||||
|
||||
Kinetic typography poster. 3D CSS with GSAP 3.
|
||||
|
||||
Firefox doesn't seem to like -webkit-text-fill-color: transparent; in this example. Perhaps related to the transform rotation animation.
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 3D CSS Kinetic Type Poster</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<div class="wrapper">
|
||||
<div class="stage">
|
||||
<div class="poster">
|
||||
<div class="wheel">
|
||||
<h1 class="txt">Linear</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h2 class="title"> Progress</h2>
|
||||
<p class="desc">The Path Is Not Linear but Circular and Continuous</p>
|
||||
</div>
|
||||
<div class="poster__base2">
|
||||
</div>
|
||||
<div class="poster__base1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- partial -->
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/3.0.0/gsap.min.js'></script>
|
||||
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/SplitText3.min.js'></script><script src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,167 @@
|
|||
console.clear();
|
||||
|
||||
gsap.registerPlugin(SplitText);
|
||||
|
||||
select = e => document.querySelector(e);
|
||||
|
||||
let fontSize = gsap.getProperty(':root', '--fontSize');
|
||||
let txt = select('.txt');
|
||||
let wheel = select('.wheel');
|
||||
let poster = select('.poster');
|
||||
let numLines = 20;
|
||||
let radius = (fontSize/(numLines/2))/Math.sin((180/numLines)*(Math.PI/180));
|
||||
let angle = 360/numLines;
|
||||
let origin = `0% 50% -${radius*2}px`;
|
||||
let master = gsap.timeline();
|
||||
|
||||
|
||||
function cloneTxt() {
|
||||
for (i=0; i<numLines-1; i++) {
|
||||
var clone = txt.cloneNode(true);
|
||||
wheel.appendChild(clone);
|
||||
}
|
||||
}
|
||||
|
||||
function positionTxt() {
|
||||
gsap.set(wheel, {
|
||||
rotation: -90,
|
||||
rotationX: 0,
|
||||
rotationY: 0
|
||||
});
|
||||
gsap.set('.txt', {
|
||||
rotationX: function(index) {
|
||||
return angle*index;
|
||||
},
|
||||
z: radius*2,
|
||||
transformOrigin: origin
|
||||
});
|
||||
gsap.set('.char', {
|
||||
rotateX: -90,
|
||||
transformOrigin: "50% 50%"
|
||||
});
|
||||
}
|
||||
|
||||
function animateIn() {
|
||||
let tl = gsap.timeline({delay: 0});
|
||||
tl.from('.char', {
|
||||
scale: 0.01,
|
||||
y: 440,
|
||||
duration: 8,
|
||||
rotation: 90,
|
||||
ease: 'power4.inOut'
|
||||
}, 0)
|
||||
.from('.txt', {
|
||||
rotationX: -180,
|
||||
duration: 12,
|
||||
ease: 'power4'
|
||||
}, 0)
|
||||
.from('.txt', {
|
||||
x: 100,
|
||||
duration: 8,
|
||||
ease: 'power4',
|
||||
stagger: 0.2
|
||||
}, 0)
|
||||
.from(wheel, {
|
||||
rotationY: 180,
|
||||
z: -2000,
|
||||
ease: 'expo',
|
||||
duration: 12
|
||||
}, 0)
|
||||
.from('.titleChar', {
|
||||
y: 'random(-20 20)',
|
||||
opacity: 0,
|
||||
duration: 4,
|
||||
stagger: {
|
||||
each: 0.05,
|
||||
from: "center"
|
||||
},
|
||||
ease: "expo",
|
||||
}, 1)
|
||||
.from('.desc', {
|
||||
y: 30,
|
||||
opacity: 0,
|
||||
duration: 4,
|
||||
ease: "power4"
|
||||
}, 1.5)
|
||||
|
||||
return tl;
|
||||
}
|
||||
|
||||
function rotate() {
|
||||
let tl = gsap.timeline();
|
||||
tl.to(wheel, {
|
||||
rotationX: 360,
|
||||
transformOrigin: "50% 50%",
|
||||
repeat: -1,
|
||||
ease: 'none',
|
||||
duration: 12
|
||||
});
|
||||
|
||||
return tl;
|
||||
}
|
||||
|
||||
function resize() {
|
||||
let vh = window.innerHeight;
|
||||
let sh = poster.offsetHeight;
|
||||
let scaleFactor = vh/sh;
|
||||
if(scaleFactor<1) {
|
||||
gsap.set(poster, { scale: scaleFactor });
|
||||
}
|
||||
else {
|
||||
gsap.set(poster, { scale: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
let linearText = new SplitText(txt, {type:"chars", charsClass:"char", position: "relative" });
|
||||
let titleText = new SplitText('.title', {type:"chars", charsClass:"titleChar", position: "relative" });
|
||||
gsap.set(poster, { autoAlpha: 1 });
|
||||
cloneTxt();
|
||||
positionTxt();
|
||||
master.add(animateIn())
|
||||
.add(rotate(), 0);
|
||||
poster.onclick = () => {
|
||||
master.restart();
|
||||
}
|
||||
resize();
|
||||
}
|
||||
|
||||
function calcOffset(xPos, yPos) {
|
||||
let winW = window.innerWidth;
|
||||
let winH = window.innerHeight;
|
||||
let dX = 2*(xPos - winW/2)/winW;
|
||||
let dY = -2*(yPos - winH/2)/winH;
|
||||
return [dX,dY];
|
||||
}
|
||||
|
||||
function rotateTxt(xPos, yPos) {
|
||||
let nPos = calcOffset(xPos, yPos); // get cursor position from center 1-0-1
|
||||
let nX = nPos[0];
|
||||
let nY = nPos[1];
|
||||
let invertedRangeX = 1-Math.sqrt(nX*nX); // 0-1-0
|
||||
let invertedRangeY = 1-Math.sqrt(nY*nY); // 0-1-0
|
||||
gsap.to('.stage', {
|
||||
rotationX: nPos[1]*5,
|
||||
rotationY: nX*5,
|
||||
// rotation: nX*40,
|
||||
duration: 1,
|
||||
ease: 'sine'
|
||||
});
|
||||
}
|
||||
|
||||
var pointer = {
|
||||
x: window.innerWidth / 2,
|
||||
y: window.innerHeight / 2
|
||||
};
|
||||
|
||||
window.addEventListener("mousemove", function(event) {
|
||||
pointer.x = event.clientX;
|
||||
pointer.y = event.clientY;
|
||||
rotateTxt(pointer.x, pointer.y);
|
||||
});
|
||||
|
||||
window.onresize = resize;
|
||||
|
||||
window.onload = () => {
|
||||
init();
|
||||
};
|
|
@ -0,0 +1,187 @@
|
|||
@import url("https://rsms.me/inter/inter.css");
|
||||
html {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
@supports (font-variation-settings: normal) {
|
||||
html {
|
||||
font-family: 'Inter var', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
}
|
||||
:root {
|
||||
--fontSize: 120px;
|
||||
--borderW: 20px;
|
||||
}
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #C4CACE;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
body ::-moz-selection {
|
||||
background: transparent;
|
||||
}
|
||||
body ::selection {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
height: 100%;
|
||||
display: -webkit-box;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-perspective: 1400px;
|
||||
perspective: 1400px;
|
||||
}
|
||||
|
||||
.stage {
|
||||
padding: 20px;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.poster {
|
||||
position: relative;
|
||||
height: calc(var(--fontSize)*8);
|
||||
width: calc(var(--fontSize)*6);
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
background: white;
|
||||
overflow: hidden;
|
||||
-webkit-perspective: 700px;
|
||||
perspective: 700px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.3), 0 40px 50px -20px rgba(0, 0, 0, 0.3), 0 70px 60px -30px rgba(0, 0, 0, 0.1), 0 40px 70px -5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.poster__base1 {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: var(--borderW);
|
||||
left: var(--borderW);
|
||||
width: calc(100% - calc(2*var(--borderW)));
|
||||
height: calc(100% - calc(2*var(--borderW)));
|
||||
background: black;
|
||||
display: -webkit-box;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.poster__base2 {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
display: -webkit-box;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.wheel {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
top: calc(-1 * var(--fontSize)/2.5);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.txt {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
margin: 0;
|
||||
font-size: var(--fontSize);
|
||||
font-weight: 900;
|
||||
font-stretch: 50%;
|
||||
text-transform: uppercase;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
letter-spacing: -5px;
|
||||
}
|
||||
|
||||
.char {
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
/* standard gradient background */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(20%, white), color-stop(80%, black));
|
||||
background: linear-gradient(white 20%, black 80%);
|
||||
/* clip hackery */
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
padding: var(--borderW);
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-weight: 900;
|
||||
font-size: 24px;
|
||||
letter-spacing: 20px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
letter-spacing: 1px;
|
||||
color: #0090FF;
|
||||
margin-top: 24px;
|
||||
padding-right: 10px;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2020 by Pete Barr (https://codepen.io/petebarr/pen/OJPBEwy)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<div class="wrapper">
|
||||
<div class="stage">
|
||||
<div class="poster">
|
||||
<div class="wheel">
|
||||
<h1 class="txt">Linear</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h2 class="title"> Progress</h2>
|
||||
<p class="desc">The Path Is Not Linear but Circular and Continuous</p>
|
||||
</div>
|
||||
<div class="poster__base2">
|
||||
</div>
|
||||
<div class="poster__base1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
console.clear();
|
||||
|
||||
gsap.registerPlugin(SplitText);
|
||||
|
||||
select = e => document.querySelector(e);
|
||||
|
||||
let fontSize = gsap.getProperty(':root', '--fontSize');
|
||||
let txt = select('.txt');
|
||||
let wheel = select('.wheel');
|
||||
let poster = select('.poster');
|
||||
let numLines = 20;
|
||||
let radius = (fontSize/(numLines/2))/Math.sin((180/numLines)*(Math.PI/180));
|
||||
let angle = 360/numLines;
|
||||
let origin = `0% 50% -${radius*2}px`;
|
||||
let master = gsap.timeline();
|
||||
|
||||
|
||||
function cloneTxt() {
|
||||
for (i=0; i<numLines-1; i++) {
|
||||
var clone = txt.cloneNode(true);
|
||||
wheel.appendChild(clone);
|
||||
}
|
||||
}
|
||||
|
||||
function positionTxt() {
|
||||
gsap.set(wheel, {
|
||||
rotation: -90,
|
||||
rotationX: 0,
|
||||
rotationY: 0
|
||||
});
|
||||
gsap.set('.txt', {
|
||||
rotationX: function(index) {
|
||||
return angle*index;
|
||||
},
|
||||
z: radius*2,
|
||||
transformOrigin: origin
|
||||
});
|
||||
gsap.set('.char', {
|
||||
rotateX: -90,
|
||||
transformOrigin: "50% 50%"
|
||||
});
|
||||
}
|
||||
|
||||
function animateIn() {
|
||||
let tl = gsap.timeline({delay: 0});
|
||||
tl.from('.char', {
|
||||
scale: 0.01,
|
||||
y: 440,
|
||||
duration: 8,
|
||||
rotation: 90,
|
||||
ease: 'power4.inOut'
|
||||
}, 0)
|
||||
.from('.txt', {
|
||||
rotationX: -180,
|
||||
duration: 12,
|
||||
ease: 'power4'
|
||||
}, 0)
|
||||
.from('.txt', {
|
||||
x: 100,
|
||||
duration: 8,
|
||||
ease: 'power4',
|
||||
stagger: 0.2
|
||||
}, 0)
|
||||
.from(wheel, {
|
||||
rotationY: 180,
|
||||
z: -2000,
|
||||
ease: 'expo',
|
||||
duration: 12
|
||||
}, 0)
|
||||
.from('.titleChar', {
|
||||
y: 'random(-20 20)',
|
||||
opacity: 0,
|
||||
duration: 4,
|
||||
stagger: {
|
||||
each: 0.05,
|
||||
from: "center"
|
||||
},
|
||||
ease: "expo",
|
||||
}, 1)
|
||||
.from('.desc', {
|
||||
y: 30,
|
||||
opacity: 0,
|
||||
duration: 4,
|
||||
ease: "power4"
|
||||
}, 1.5)
|
||||
|
||||
return tl;
|
||||
}
|
||||
|
||||
function rotate() {
|
||||
let tl = gsap.timeline();
|
||||
tl.to(wheel, {
|
||||
rotationX: 360,
|
||||
transformOrigin: "50% 50%",
|
||||
repeat: -1,
|
||||
ease: 'none',
|
||||
duration: 12
|
||||
});
|
||||
|
||||
return tl;
|
||||
}
|
||||
|
||||
function resize() {
|
||||
let vh = window.innerHeight;
|
||||
let sh = poster.offsetHeight;
|
||||
let scaleFactor = vh/sh;
|
||||
if(scaleFactor<1) {
|
||||
gsap.set(poster, { scale: scaleFactor });
|
||||
}
|
||||
else {
|
||||
gsap.set(poster, { scale: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
let linearText = new SplitText(txt, {type:"chars", charsClass:"char", position: "relative" });
|
||||
let titleText = new SplitText('.title', {type:"chars", charsClass:"titleChar", position: "relative" });
|
||||
gsap.set(poster, { autoAlpha: 1 });
|
||||
cloneTxt();
|
||||
positionTxt();
|
||||
master.add(animateIn())
|
||||
.add(rotate(), 0);
|
||||
poster.onclick = () => {
|
||||
master.restart();
|
||||
}
|
||||
resize();
|
||||
}
|
||||
|
||||
function calcOffset(xPos, yPos) {
|
||||
let winW = window.innerWidth;
|
||||
let winH = window.innerHeight;
|
||||
let dX = 2*(xPos - winW/2)/winW;
|
||||
let dY = -2*(yPos - winH/2)/winH;
|
||||
return [dX,dY];
|
||||
}
|
||||
|
||||
function rotateTxt(xPos, yPos) {
|
||||
let nPos = calcOffset(xPos, yPos); // get cursor position from center 1-0-1
|
||||
let nX = nPos[0];
|
||||
let nY = nPos[1];
|
||||
let invertedRangeX = 1-Math.sqrt(nX*nX); // 0-1-0
|
||||
let invertedRangeY = 1-Math.sqrt(nY*nY); // 0-1-0
|
||||
gsap.to('.stage', {
|
||||
rotationX: nPos[1]*5,
|
||||
rotationY: nX*5,
|
||||
// rotation: nX*40,
|
||||
duration: 1,
|
||||
ease: 'sine'
|
||||
});
|
||||
}
|
||||
|
||||
var pointer = {
|
||||
x: window.innerWidth / 2,
|
||||
y: window.innerHeight / 2
|
||||
};
|
||||
|
||||
window.addEventListener("mousemove", function(event) {
|
||||
pointer.x = event.clientX;
|
||||
pointer.y = event.clientY;
|
||||
rotateTxt(pointer.x, pointer.y);
|
||||
});
|
||||
|
||||
window.onresize = resize;
|
||||
|
||||
window.onload = () => {
|
||||
init();
|
||||
};
|
|
@ -0,0 +1,168 @@
|
|||
@import url('https://rsms.me/inter/inter.css');
|
||||
|
||||
html {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
@supports (font-variation-settings: normal) {
|
||||
html {
|
||||
font-family: 'Inter var', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--fontSize: 120px;
|
||||
--borderW: 20px;
|
||||
}
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #C4CACE;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
::selection {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
perspective: 1400px;
|
||||
}
|
||||
|
||||
.stage {
|
||||
padding: 20px;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.poster {
|
||||
position: relative;
|
||||
height: calc(var(--fontSize)*8);
|
||||
width: calc(var(--fontSize)*6);
|
||||
transform-style: preserve-3d;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
background: white;
|
||||
overflow: hidden;
|
||||
perspective: 700px;
|
||||
cursor: pointer;
|
||||
box-shadow:
|
||||
0 20px 40px -15px rgba(0,0,0,0.3),
|
||||
0 40px 50px -20px rgba(0,0,0,0.3),
|
||||
0 70px 60px -30px rgba(0,0,0,0.1),
|
||||
0 40px 70px -5px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.poster__base1 {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: var(--borderW);
|
||||
left: var(--borderW);
|
||||
width: calc(100% - calc(2*var(--borderW)));
|
||||
height: calc(100% - calc(2*var(--borderW)));
|
||||
background: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.poster__base2 {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.wheel {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
top: calc(-1 * var(--fontSize)/2.5);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.txt {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
margin: 0;
|
||||
font-size: var(--fontSize);
|
||||
font-weight: 900;
|
||||
font-stretch: 50%;
|
||||
text-transform: uppercase;
|
||||
transform-style: preserve-3d;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
letter-spacing: -5px;
|
||||
}
|
||||
|
||||
.char {
|
||||
transform-style: preserve-3d;
|
||||
/* standard gradient background */
|
||||
background: linear-gradient(white 20%, black 80%);
|
||||
/* clip hackery */
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
padding: var(--borderW);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-weight: 900;
|
||||
font-size: 24px;
|
||||
letter-spacing: 20px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
letter-spacing: 1px;
|
||||
color: #0090FF;
|
||||
margin-top: 24px;
|
||||
padding-right: 10px;
|
||||
transform-style: preserve-3d;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# 3D CSS Plane 😎 (Tap to Toggle + Mouse Move Parallax)
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/jh3y/pen/NWdNMBJ](https://codepen.io/jh3y/pen/NWdNMBJ).
|
||||
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 3D CSS Plane 😎 (Tap to Toggle + Mouse Move Parallax)</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<input id="dark" type="checkbox"/>
|
||||
<div class="scene">
|
||||
<div class="cloud cloud--one">
|
||||
<div class="cloud__shift">
|
||||
<div class="cloud__body">
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cloud cloud--two">
|
||||
<div class="cloud__shift">
|
||||
<div class="cloud__body">
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cloud cloud--three">
|
||||
<div class="cloud__shift">
|
||||
<div class="cloud__body">
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="cuboid cuboid--cloud">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__floater">
|
||||
<div class="plane__looper">
|
||||
<div class="plane">
|
||||
<div class="plane__wheels">
|
||||
<div class="plane__axle">
|
||||
<div class="cuboid cuboid--axle">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__wheel plane__wheel--left">
|
||||
<div class="cuboid cuboid--wheel-left">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__wheel plane__wheel--right">
|
||||
<div class="cuboid cuboid--wheel-right">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__body">
|
||||
<div class="cuboid cuboid--body">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__nose">
|
||||
<div class="cuboid cuboid--nose">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__propellor">
|
||||
<div class="propellor"></div>
|
||||
</div>
|
||||
<div class="plane__screen">
|
||||
<div class="cuboid cuboid--screen">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__wings wings">
|
||||
<div class="wings__top">
|
||||
<div class="cuboid cuboid--wings-top">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wings__ghost">
|
||||
<div class="cuboid cuboid--wings-ghost">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wings__bottom">
|
||||
<div class="cuboid cuboid--wings-bottom">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wings__strobe wings__strobe--left">
|
||||
<div class="cuboid cuboid--strobe">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wings__strobe wings__strobe--right">
|
||||
<div class="cuboid cuboid--strobe">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__tail">
|
||||
<div class="cuboid cuboid--tail">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__stabilizer plane__stabilizer--horizontal">
|
||||
<div class="cuboid cuboid--horizontal-stabilizer">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__stabilizer plane__stabilizer--vertical">
|
||||
<div class="cuboid cuboid--vertical-stabilizer">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plane__beacon">
|
||||
<div class="cuboid cuboid--beacon">
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
<div class="cuboid__side"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label for="dark"></label>
|
||||
<!-- partial -->
|
||||
<script type="module" src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
import gsap from 'https://cdn.skypack.dev/gsap';
|
||||
|
||||
const BOUNDS = 50;
|
||||
document.addEventListener('pointermove', ({ x, y }) => {
|
||||
const newX = gsap.utils.mapRange(0, window.innerWidth, -BOUNDS, BOUNDS, x);
|
||||
const newY = gsap.utils.mapRange(0, window.innerHeight, BOUNDS, -BOUNDS, y);
|
||||
gsap.set(document.documentElement, {
|
||||
'--rotate-x': newY,
|
||||
'--rotate-y': newX });
|
||||
|
||||
});
|
||||
|
||||
const CHECKER = document.querySelector('[type="checkbox"]');
|
||||
|
||||
CHECKER.addEventListener('input', (e) =>
|
||||
document.documentElement.style.setProperty('--dark', CHECKER.checked ? 1 : 0));
|
|
@ -0,0 +1,777 @@
|
|||
.cuboid {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.cuboid__side:nth-of-type(1) {
|
||||
height: calc(var(--thickness) * 1vmin);
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transform: translate(0, -50%) rotateX(90deg);
|
||||
}
|
||||
.cuboid__side:nth-of-type(2) {
|
||||
height: 100%;
|
||||
width: calc(var(--thickness) * 1vmin);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translate(50%, -50%) rotateY(90deg);
|
||||
}
|
||||
.cuboid__side:nth-of-type(3) {
|
||||
width: 100%;
|
||||
height: calc(var(--thickness) * 1vmin);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
transform: translate(0%, 50%) rotateX(90deg);
|
||||
}
|
||||
.cuboid__side:nth-of-type(4) {
|
||||
height: 100%;
|
||||
width: calc(var(--thickness) * 1vmin);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%) rotateY(90deg);
|
||||
}
|
||||
.cuboid__side:nth-of-type(5) {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transform: translate3d(0, 0, calc(var(--thickness) * 0.5vmin));
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.cuboid__side:nth-of-type(6) {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transform: translate3d(0, 0, calc(var(--thickness) * -0.5vmin)) rotateY(180deg);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
*,
|
||||
*:after,
|
||||
*:before {
|
||||
box-sizing: border-box;
|
||||
transform-style: preserve-3d;
|
||||
transition: background 0.25s;
|
||||
}
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: var(--bg);
|
||||
overflow: hidden;
|
||||
}
|
||||
:root {
|
||||
--dark: 0;
|
||||
--base-size: 20;
|
||||
--plane-height: calc(var(--base-size) * 1vmin);
|
||||
--plane-width: calc(var(--plane-height) * 1.6);
|
||||
--white-one: hsl(0, 0%, calc((90 - (var(--dark) * 30)) * 1%));
|
||||
--white-two: hsl(0, 0%, calc((85 - (var(--dark) * 30)) * 1%));
|
||||
--white-three: hsl(0, 0%, calc((80 - (var(--dark) * 30)) * 1%));
|
||||
--white-four: hsl(0, 0%, calc((75 - (var(--dark) * 30)) * 1%));
|
||||
--white-five: hsl(0, 0%, calc((70 - (var(--dark) * 30)) * 1%));
|
||||
--accent-hue: 10;
|
||||
--accent-one: hsl(var(--accent-hue), 80%, calc((60 - (var(--dark) * 20)) * 1%));
|
||||
--accent-two: hsl(var(--accent-hue), 80%, calc((55 - (var(--dark) * 20)) * 1%));
|
||||
--accent-three: hsl(var(--accent-hue), 80%, calc((50 - (var(--dark) * 20)) * 1%));
|
||||
--accent-four: hsl(var(--accent-hue), 80%, calc((45 - (var(--dark) * 20)) * 1%));
|
||||
--accent-five: hsl(var(--accent-hue), 80%, calc((40 - (var(--dark) * 20)) * 1%));
|
||||
--screen: hsla(210, 80%, calc((70 - (var(--dark) * 20)) * 1%), 0.25);
|
||||
--metal-one: hsl(0, 0%, calc((60 - (var(--dark) * 20)) * 1%));
|
||||
--metal-two: hsl(0, 0%, calc((50 - (var(--dark) * 20)) * 1%));
|
||||
--metal-three: hsl(0, 0%, calc((40 - (var(--dark) * 20)) * 1%));
|
||||
--wheel-one: #1a1a1a;
|
||||
--wheel-two: #0d0d0d;
|
||||
--wheel-three: #000;
|
||||
--wheel-hub: hsl(0, 0%, calc((98 - (var(--dark) * 20)) * 1%));
|
||||
--bg: hsl(210, 80%, calc((90 - (var(--dark) * 76)) * 1%));
|
||||
--night: #082949;
|
||||
--cloud-one: hsl(0, 0%, calc((98 - (var(--dark) * 35)) * 1%));
|
||||
--cloud-two: hsl(0, 0%, calc((94 - (var(--dark) * 35)) * 1%));
|
||||
--cloud-three: hsl(0, 0%, calc((90 - (var(--dark) * 35)) * 1%));
|
||||
--cloud-four: hsl(0, 0%, calc((86 - (var(--dark) * 35)) * 1%));
|
||||
--cloud-five: hsl(0, 0%, calc((82 - (var(--dark) * 35)) * 1%));
|
||||
--cloud-six: hsl(0, 0%, calc((78 - (var(--dark) * 35)) * 1%));
|
||||
}
|
||||
.scene {
|
||||
transform: translate(-50%, -50%);
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -50%, 100vmin) rotateX(-24deg) rotateY(44deg) rotateX(calc(var(--rotate-x, 0) * 1deg)) rotateY(calc(var(--rotate-y, 0) * 1deg));
|
||||
}
|
||||
[type="checkbox"] {
|
||||
position: fixed;
|
||||
left: 100%;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
label {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
transform: translate3d(0, 0, 1000vmin);
|
||||
}
|
||||
.plane {
|
||||
height: var(--plane-height);
|
||||
width: var(--plane-width);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
-webkit-animation: roll 10s infinite ease-out alternate;
|
||||
animation: roll 10s infinite ease-out alternate;
|
||||
}
|
||||
.plane__floater {
|
||||
position: absolute;
|
||||
width: var(--plane-width);
|
||||
height: var(--plane-width);
|
||||
transform: translate(-50%, -50%);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-animation: float 2s infinite ease-in-out;
|
||||
animation: float 2s infinite ease-in-out;
|
||||
}
|
||||
.plane__looper {
|
||||
position: absolute;
|
||||
width: var(--plane-width);
|
||||
height: var(--plane-width);
|
||||
transform: translate(-50%, -50%);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform-origin: 50% 0;
|
||||
-webkit-animation: loop 10s infinite ease-in-out;
|
||||
animation: loop 10s infinite ease-in-out;
|
||||
}
|
||||
.plane * {
|
||||
position: absolute;
|
||||
}
|
||||
.plane__body {
|
||||
height: 40%;
|
||||
width: 36%;
|
||||
bottom: 20%;
|
||||
left: 10%;
|
||||
}
|
||||
.plane__wheels {
|
||||
bottom: 0;
|
||||
width: calc(var(--plane-height) * 0.2);
|
||||
left: 32%;
|
||||
transform: translate(-50%, 0);
|
||||
height: 20%;
|
||||
}
|
||||
.plane__axle {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.plane__wheel {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.plane__wings {
|
||||
height: 70%;
|
||||
width: 40%;
|
||||
bottom: 19%;
|
||||
left: 12%;
|
||||
}
|
||||
.plane__tail {
|
||||
height: 40%;
|
||||
width: 54%;
|
||||
bottom: 20%;
|
||||
left: 46%;
|
||||
}
|
||||
.plane__nose {
|
||||
height: 30%;
|
||||
width: 10%;
|
||||
bottom: 25%;
|
||||
}
|
||||
.plane__stabilizer--horizontal {
|
||||
height: 9%;
|
||||
width: 16%;
|
||||
right: 1%;
|
||||
bottom: 50%;
|
||||
}
|
||||
.plane__screen {
|
||||
bottom: 60%;
|
||||
left: 30%;
|
||||
width: 6%;
|
||||
height: 14%;
|
||||
}
|
||||
.plane__propellor {
|
||||
height: calc(var(--base-size) * 0.75vmin);
|
||||
width: calc(var(--base-size) * 0.75vmin);
|
||||
left: -1%;
|
||||
bottom: 40%;
|
||||
transform: translate(-50%, 50%) rotateY(-90deg);
|
||||
}
|
||||
.plane__propellor:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -50%, 2px);
|
||||
height: 16%;
|
||||
width: 16%;
|
||||
border-radius: 50%;
|
||||
background: var(--white-one);
|
||||
}
|
||||
.plane__stabilizer--vertical {
|
||||
height: 20%;
|
||||
width: 20%;
|
||||
right: 0;
|
||||
bottom: 60%;
|
||||
}
|
||||
.plane__beacon {
|
||||
right: 1%;
|
||||
bottom: 80%;
|
||||
height: 2%;
|
||||
width: 2%;
|
||||
}
|
||||
.plane__wheel--left {
|
||||
transform: translate3d(0, 0, calc(var(--base-size) * 0.3vmin));
|
||||
}
|
||||
.plane__wheel--right {
|
||||
transform: translate3d(0, 0, calc(var(--base-size) * -0.3vmin));
|
||||
}
|
||||
.propellor {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
-webkit-animation: spin 0.35s infinite linear;
|
||||
animation: spin 0.35s infinite linear;
|
||||
}
|
||||
.propellor:after,
|
||||
.propellor:before {
|
||||
content: '';
|
||||
height: 100%;
|
||||
width: 10%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background: linear-gradient(transparent 0 5%, var(--accent-two) 5% 15%, transparent 15% 85%, var(--accent-two) 85% 95%, transparent 95%), #000;
|
||||
transform: translate(-50%, -50%) rotate(calc(var(--r, 45) * 1deg));
|
||||
}
|
||||
.propellor:after {
|
||||
--r: -45;
|
||||
}
|
||||
.wings__ghost {
|
||||
height: 80%;
|
||||
width: 80%;
|
||||
left: 50%;
|
||||
bottom: 10%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
.wings__top {
|
||||
top: 0;
|
||||
height: 10%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
.wings__bottom {
|
||||
bottom: 0;
|
||||
height: 10%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
.wings__strobe {
|
||||
bottom: 10%;
|
||||
height: 4%;
|
||||
width: 4%;
|
||||
left: 50%;
|
||||
}
|
||||
.wings__strobe--left {
|
||||
transform: translate3d(-50%, 0, calc(var(--base-size) * 1vmin));
|
||||
}
|
||||
.wings__strobe--right {
|
||||
transform: translate3d(-50%, 0, calc(var(--base-size) * -1vmin));
|
||||
}
|
||||
.cloud {
|
||||
height: 10vmin;
|
||||
width: 15vmin;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.cloud__shift {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
-webkit-animation: pan calc(var(--speed, 5) * 1s) calc(var(--delay, 5) * -1s) infinite ease-in-out both;
|
||||
animation: pan calc(var(--speed, 5) * 1s) calc(var(--delay, 5) * -1s) infinite ease-in-out both;
|
||||
}
|
||||
.cloud__body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
-webkit-animation: scale calc(var(--speed, 5) * 1s) calc(var(--delay, 5) * -1s) infinite linear;
|
||||
animation: scale calc(var(--speed, 5) * 1s) calc(var(--delay, 5) * -1s) infinite linear;
|
||||
}
|
||||
.cloud__body > div {
|
||||
position: absolute;
|
||||
}
|
||||
.cloud__body > div:nth-of-type(1) {
|
||||
bottom: 0;
|
||||
left: 25%;
|
||||
width: 60%;
|
||||
height: 90%;
|
||||
--thickness: calc(var(--base-size) * 0.2);
|
||||
}
|
||||
.cloud__body > div:nth-of-type(2) {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 50%;
|
||||
height: 60%;
|
||||
--thickness: calc(var(--base-size) * 0.3);
|
||||
}
|
||||
.cloud__body > div:nth-of-type(3) {
|
||||
bottom: 0;
|
||||
right: 0%;
|
||||
width: 60%;
|
||||
height: 40%;
|
||||
--thickness: calc(var(--base-size) * 0.4);
|
||||
}
|
||||
.cloud--one {
|
||||
--speed: 2;
|
||||
--delay: 3;
|
||||
transform: translate(-50%, -50%) translate3d(-40vmin, 20vmin, 26vmin);
|
||||
}
|
||||
.cloud--two {
|
||||
--speed: 4;
|
||||
--delay: 1;
|
||||
transform: translate(-50%, -50%) translate3d(30vmin, -15vmin, -34vmin);
|
||||
}
|
||||
.cloud--three {
|
||||
--speed: 6;
|
||||
--delay: 2;
|
||||
transform: translate(-50%, -50%) translate3d(50vmin, 35vmin, -14vmin);
|
||||
}
|
||||
.cuboid--body {
|
||||
--thickness: calc(var(--base-size) * 0.4);
|
||||
}
|
||||
.cuboid--body div {
|
||||
background: var(--white-two);
|
||||
}
|
||||
.cuboid--body div:nth-of-type(1) {
|
||||
background: var(--white-one);
|
||||
}
|
||||
.cuboid--body div:nth-of-type(2) {
|
||||
background: var(--white-two);
|
||||
}
|
||||
.cuboid--body div:nth-of-type(3) {
|
||||
background: var(--white-three);
|
||||
}
|
||||
.cuboid--body div:nth-of-type(4) {
|
||||
background: var(--white-four);
|
||||
}
|
||||
.cuboid--body div:nth-of-type(5):after,
|
||||
.cuboid--body div:nth-of-type(6):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: calc(var(--base-size) * 0.25vmin);
|
||||
width: calc(var(--base-size) * 0.25vmin);
|
||||
background-image: url("https://assets.codepen.io/605876/avatar.png");
|
||||
background-size: cover;
|
||||
filter: saturate(0.65);
|
||||
transform: translate3d(-50%, -50%, 1px);
|
||||
}
|
||||
.cuboid--screen {
|
||||
--thickness: calc(var(--base-size) * 0.26);
|
||||
}
|
||||
.cuboid--screen div {
|
||||
background: var(--screen);
|
||||
}
|
||||
.cuboid--tail {
|
||||
--thickness: calc(var(--base-size) * 0.3);
|
||||
}
|
||||
.cuboid--tail div {
|
||||
background: var(--white-two);
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(1) {
|
||||
background: var(--white-one);
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(1):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 74%;
|
||||
width: 50%;
|
||||
background: var(--metal-three);
|
||||
top: 50%;
|
||||
right: 50%;
|
||||
transform: translate3d(-50%, -50%, 1px);
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(2) {
|
||||
background: linear-gradient(var(--white-two) 0 30%, transparent 30%);
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(3) {
|
||||
background: linear-gradient(90deg, var(--white-two) 0 20%, transparent 20%);
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(3):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: var(--white-four);
|
||||
top: 0%;
|
||||
left: 20%;
|
||||
height: 100%;
|
||||
width: 87%;
|
||||
transform-origin: 0 50%;
|
||||
transform: rotateY(-22deg);
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(5) {
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(5):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 70%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: var(--white-two);
|
||||
transform-origin: 100% 100%;
|
||||
transform: rotate(-22deg) scale(2) translate(10%, 0);
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(6) {
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cuboid--tail div:nth-of-type(6):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 70%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: var(--white-two);
|
||||
transform-origin: 0% 100%;
|
||||
transform: rotate(22deg) scale(2) translate(-10%, 0);
|
||||
}
|
||||
.cuboid--nose {
|
||||
--thickness: calc(var(--base-size) * 0.3);
|
||||
}
|
||||
.cuboid--nose div {
|
||||
background: var(--metal-three);
|
||||
}
|
||||
.cuboid--nose div:nth-of-type(1) {
|
||||
background: var(--metal-one);
|
||||
}
|
||||
.cuboid--nose div:nth-of-type(2) {
|
||||
background: var(--metal-two);
|
||||
}
|
||||
.cuboid--nose div:nth-of-type(3) {
|
||||
background: var(--metal-one);
|
||||
}
|
||||
.cuboid--wings-ghost,
|
||||
.cuboid--wings-top,
|
||||
.cuboid--wings-bottom {
|
||||
--thickness: calc(var(--base-size) * 2.2);
|
||||
}
|
||||
.cuboid--wings-ghost div,
|
||||
.cuboid--wings-top div,
|
||||
.cuboid--wings-bottom div {
|
||||
background: var(--accent-one);
|
||||
}
|
||||
.cuboid--wings-ghost div:nth-of-type(1),
|
||||
.cuboid--wings-top div:nth-of-type(1),
|
||||
.cuboid--wings-bottom div:nth-of-type(1) {
|
||||
background: var(--accent-two);
|
||||
}
|
||||
.cuboid--wings-ghost div:nth-of-type(2),
|
||||
.cuboid--wings-top div:nth-of-type(2),
|
||||
.cuboid--wings-bottom div:nth-of-type(2),
|
||||
.cuboid--wings-ghost div:nth-of-type(5),
|
||||
.cuboid--wings-top div:nth-of-type(5),
|
||||
.cuboid--wings-bottom div:nth-of-type(5) {
|
||||
background: var(--accent-three);
|
||||
}
|
||||
.cuboid--wings-ghost div:nth-of-type(4),
|
||||
.cuboid--wings-top div:nth-of-type(4),
|
||||
.cuboid--wings-bottom div:nth-of-type(4) {
|
||||
background: var(--accent-four);
|
||||
}
|
||||
.cuboid--wings-ghost div:nth-of-type(3),
|
||||
.cuboid--wings-top div:nth-of-type(3),
|
||||
.cuboid--wings-bottom div:nth-of-type(3) {
|
||||
background: var(--accent-five);
|
||||
}
|
||||
.cuboid--wings-ghost div:nth-of-type(3),
|
||||
.cuboid--wings-ghost div:nth-of-type(5),
|
||||
.cuboid--wings-ghost div:nth-of-type(6),
|
||||
.cuboid--wings-ghost div:nth-of-type(1) {
|
||||
background: transparent;
|
||||
}
|
||||
.cuboid--wings-ghost div:nth-of-type(2),
|
||||
.cuboid--wings-ghost div:nth-of-type(4) {
|
||||
background: linear-gradient(90deg, transparent 0 5%, var(--metal-one) 5% 7%, transparent 7% 33%, var(--metal-one) 33% 35%, transparent 35% 65%, var(--metal-one) 65% 67%, transparent 67% 93%, var(--metal-one) 93% 95%, transparent 95%);
|
||||
}
|
||||
.cuboid--axle {
|
||||
--thickness: calc(var(--base-size) * 0.5);
|
||||
}
|
||||
.cuboid--axle div {
|
||||
background: var(--metal-two);
|
||||
}
|
||||
.cuboid--axle div:nth-of-type(3) {
|
||||
background: var(--metal-three);
|
||||
}
|
||||
.cuboid--axle div:nth-of-type(2),
|
||||
.cuboid--axle div:nth-of-type(1) {
|
||||
background: var(--metal-one);
|
||||
}
|
||||
.cuboid--axle div:nth-of-type(6) {
|
||||
background: var(--metal-one);
|
||||
}
|
||||
.cuboid--horizontal-stabilizer {
|
||||
--thickness: calc(var(--base-size) * 0.65);
|
||||
}
|
||||
.cuboid--horizontal-stabilizer div {
|
||||
background: var(--accent-one);
|
||||
}
|
||||
.cuboid--horizontal-stabilizer div:nth-of-type(1) {
|
||||
background: var(--accent-two);
|
||||
}
|
||||
.cuboid--horizontal-stabilizer div:nth-of-type(2),
|
||||
.cuboid--horizontal-stabilizer div:nth-of-type(5) {
|
||||
background: var(--accent-three);
|
||||
}
|
||||
.cuboid--horizontal-stabilizer div:nth-of-type(3),
|
||||
.cuboid--horizontal-stabilizer div:nth-of-type(4) {
|
||||
background: var(--accent-four);
|
||||
}
|
||||
.cuboid--vertical-stabilizer {
|
||||
--thickness: calc(var(--base-size) * 0.2);
|
||||
}
|
||||
.cuboid--vertical-stabilizer div {
|
||||
background: var(--accent-one);
|
||||
}
|
||||
.cuboid--vertical-stabilizer div:nth-of-type(1) {
|
||||
background: linear-gradient(270deg, var(--accent-two) 0 30%, transparent 30%);
|
||||
}
|
||||
.cuboid--vertical-stabilizer div:nth-of-type(4) {
|
||||
background: transparent;
|
||||
}
|
||||
.cuboid--vertical-stabilizer div:nth-of-type(4):after {
|
||||
content: '';
|
||||
background: var(--accent-four);
|
||||
height: 150%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transform-origin: 50% 100%;
|
||||
transform: rotateX(-48deg);
|
||||
}
|
||||
.cuboid--vertical-stabilizer div:nth-of-type(5) {
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cuboid--vertical-stabilizer div:nth-of-type(5):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
transform-origin: 0 0;
|
||||
transform: rotate(-42deg);
|
||||
background: var(--accent-three);
|
||||
height: 150%;
|
||||
width: 160%;
|
||||
}
|
||||
.cuboid--vertical-stabilizer div:nth-of-type(6) {
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cuboid--vertical-stabilizer div:nth-of-type(6):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
transform-origin: 100% 0;
|
||||
transform: rotate(42deg);
|
||||
background: var(--accent-three);
|
||||
height: 150%;
|
||||
width: 160%;
|
||||
}
|
||||
.cuboid--wheel-left,
|
||||
.cuboid--wheel-right {
|
||||
--thickness: calc(var(--base-size) * 0.1);
|
||||
}
|
||||
.cuboid--wheel-left div,
|
||||
.cuboid--wheel-right div {
|
||||
background: var(--wheel-one);
|
||||
}
|
||||
.cuboid--wheel-left div:nth-of-type(1),
|
||||
.cuboid--wheel-right div:nth-of-type(1),
|
||||
.cuboid--wheel-left div:nth-of-type(2),
|
||||
.cuboid--wheel-right div:nth-of-type(2),
|
||||
.cuboid--wheel-left div:nth-of-type(4),
|
||||
.cuboid--wheel-right div:nth-of-type(4) {
|
||||
background: var(--wheel-two);
|
||||
}
|
||||
.cuboid--wheel-left div:nth-of-type(3),
|
||||
.cuboid--wheel-right div:nth-of-type(3) {
|
||||
background: var(--wheel-three);
|
||||
}
|
||||
.cuboid--wheel-left div:nth-of-type(5):after,
|
||||
.cuboid--wheel-right div:nth-of-type(5):after,
|
||||
.cuboid--wheel-left div:nth-of-type(6):after,
|
||||
.cuboid--wheel-right div:nth-of-type(6):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 40%;
|
||||
width: 40%;
|
||||
background: var(--wheel-hub);
|
||||
}
|
||||
.cuboid--cloud div:nth-of-type(1) {
|
||||
background: var(--cloud-one);
|
||||
}
|
||||
.cuboid--cloud div:nth-of-type(2) {
|
||||
background: var(--cloud-two);
|
||||
}
|
||||
.cuboid--cloud div:nth-of-type(3) {
|
||||
background: var(--cloud-three);
|
||||
}
|
||||
.cuboid--cloud div:nth-of-type(4) {
|
||||
background: var(--cloud-four);
|
||||
}
|
||||
.cuboid--cloud div:nth-of-type(5) {
|
||||
background: var(--cloud-five);
|
||||
}
|
||||
.cuboid--cloud div:nth-of-type(6) {
|
||||
background: var(--cloud-six);
|
||||
}
|
||||
.cuboid--beacon {
|
||||
--thickness: calc(var(--base-size) * 0.02);
|
||||
-webkit-animation: flash calc(var(--dark) * 1s) infinite;
|
||||
animation: flash calc(var(--dark) * 1s) infinite;
|
||||
}
|
||||
.cuboid--beacon div {
|
||||
background: hsla(0, 90%, 50%, var(--alpha));
|
||||
}
|
||||
.cuboid--strobe {
|
||||
--thickness: calc(var(--base-size) * 0.02);
|
||||
-webkit-animation: flash calc(var(--dark) * 0.5s) infinite;
|
||||
animation: flash calc(var(--dark) * 0.5s) infinite;
|
||||
}
|
||||
.cuboid--strobe div {
|
||||
background: hsla(0, 90%, 98%, var(--alpha));
|
||||
}
|
||||
@-webkit-keyframes flash {
|
||||
50% {
|
||||
--alpha: 1;
|
||||
}
|
||||
}
|
||||
@keyframes flash {
|
||||
50% {
|
||||
--alpha: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes float {
|
||||
50% {
|
||||
transform: translate(-50%, -40%);
|
||||
}
|
||||
}
|
||||
@keyframes float {
|
||||
50% {
|
||||
transform: translate(-50%, -40%);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes loop {
|
||||
0%, 40% {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
50%, 100% {
|
||||
transform: translate(-50%, -50%) rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes loop {
|
||||
0%, 40% {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
50%, 100% {
|
||||
transform: translate(-50%, -50%) rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes roll {
|
||||
0%, 85% {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
90%, 100% {
|
||||
transform: translate(-50%, -50%) rotateX(-360deg);
|
||||
}
|
||||
}
|
||||
@keyframes roll {
|
||||
0%, 85% {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
90%, 100% {
|
||||
transform: translate(-50%, -50%) rotateX(-360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes nightshift {
|
||||
0%, 50% {
|
||||
background: var(--bg);
|
||||
}
|
||||
75%, 100% {
|
||||
background: var(--night);
|
||||
}
|
||||
}
|
||||
@keyframes nightshift {
|
||||
0%, 50% {
|
||||
background: var(--bg);
|
||||
}
|
||||
75%, 100% {
|
||||
background: var(--night);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes scale {
|
||||
0%, 5%, 95%, 100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
10%, 90% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes scale {
|
||||
0%, 5%, 95%, 100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
10%, 90% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes pan {
|
||||
0% {
|
||||
transform: translate(-1000%, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate(1000%, 0);
|
||||
}
|
||||
}
|
||||
@keyframes pan {
|
||||
0% {
|
||||
transform: translate(-1000%, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate(1000%, 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2021 by Jhey (https://codepen.io/jh3y/pen/NWdNMBJ)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
mixin cuboid()
|
||||
.cuboid(class!=attributes.class)
|
||||
- let s = 0
|
||||
while s < 6
|
||||
.cuboid__side
|
||||
- s++
|
||||
input#dark(type="checkbox")
|
||||
.scene
|
||||
.cloud.cloud--one
|
||||
.cloud__shift
|
||||
.cloud__body
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
.cloud.cloud--two
|
||||
.cloud__shift
|
||||
.cloud__body
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
.cloud.cloud--three
|
||||
.cloud__shift
|
||||
.cloud__body
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
div
|
||||
+cuboid()(class="cuboid--cloud")
|
||||
.plane__floater
|
||||
.plane__looper
|
||||
.plane
|
||||
.plane__wheels
|
||||
.plane__axle
|
||||
+cuboid()(class="cuboid--axle")
|
||||
.plane__wheel.plane__wheel--left
|
||||
+cuboid()(class="cuboid--wheel-left")
|
||||
.plane__wheel.plane__wheel--right
|
||||
+cuboid()(class="cuboid--wheel-right")
|
||||
.plane__body
|
||||
+cuboid()(class="cuboid--body")
|
||||
.plane__nose
|
||||
+cuboid()(class="cuboid--nose")
|
||||
.plane__propellor
|
||||
.propellor
|
||||
.plane__screen
|
||||
+cuboid()(class="cuboid--screen")
|
||||
.plane__wings.wings
|
||||
.wings__top
|
||||
+cuboid()(class="cuboid--wings-top")
|
||||
.wings__ghost
|
||||
+cuboid()(class="cuboid--wings-ghost")
|
||||
.wings__bottom
|
||||
+cuboid()(class="cuboid--wings-bottom")
|
||||
.wings__strobe.wings__strobe--left
|
||||
+cuboid()(class="cuboid--strobe")
|
||||
.wings__strobe.wings__strobe--right
|
||||
+cuboid()(class="cuboid--strobe")
|
||||
.plane__tail
|
||||
+cuboid()(class="cuboid--tail")
|
||||
.plane__stabilizer.plane__stabilizer--horizontal
|
||||
+cuboid()(class="cuboid--horizontal-stabilizer")
|
||||
.plane__stabilizer.plane__stabilizer--vertical
|
||||
+cuboid()(class="cuboid--vertical-stabilizer")
|
||||
.plane__beacon
|
||||
+cuboid()(class="cuboid--beacon")
|
||||
label(for="dark")
|
|
@ -0,0 +1,17 @@
|
|||
import gsap from 'https://cdn.skypack.dev/gsap'
|
||||
|
||||
const BOUNDS = 50
|
||||
document.addEventListener('pointermove', ({ x, y }) => {
|
||||
const newX = gsap.utils.mapRange(0, window.innerWidth, -BOUNDS, BOUNDS, x)
|
||||
const newY = gsap.utils.mapRange(0, window.innerHeight, BOUNDS, -BOUNDS, y)
|
||||
gsap.set(document.documentElement, {
|
||||
'--rotate-x': newY,
|
||||
'--rotate-y': newX,
|
||||
})
|
||||
})
|
||||
|
||||
const CHECKER = document.querySelector('[type="checkbox"]')
|
||||
|
||||
CHECKER.addEventListener('input', e =>
|
||||
document.documentElement.style.setProperty('--dark', CHECKER.checked ? 1 : 0)
|
||||
)
|
|
@ -0,0 +1,668 @@
|
|||
.cuboid
|
||||
width 100%
|
||||
height 100%
|
||||
position relative
|
||||
// 1 is the top and go t, r, b, l, f, b
|
||||
|
||||
&__side:nth-of-type(1)
|
||||
height calc(var(--thickness) * 1vmin)
|
||||
width 100%
|
||||
position absolute
|
||||
top 0
|
||||
transform translate(0, -50%) rotateX(90deg)
|
||||
|
||||
&__side:nth-of-type(2)
|
||||
height 100%
|
||||
width calc(var(--thickness) * 1vmin)
|
||||
position absolute
|
||||
top 50%
|
||||
right 0
|
||||
transform translate(50%, -50%) rotateY(90deg)
|
||||
|
||||
&__side:nth-of-type(3)
|
||||
width 100%
|
||||
height calc(var(--thickness) * 1vmin)
|
||||
position absolute
|
||||
bottom 0
|
||||
transform translate(0%, 50%) rotateX(90deg)
|
||||
|
||||
&__side:nth-of-type(4)
|
||||
height 100%
|
||||
width calc(var(--thickness) * 1vmin)
|
||||
position absolute
|
||||
left 0
|
||||
top 50%
|
||||
transform translate(-50%, -50%) rotateY(90deg)
|
||||
|
||||
&__side:nth-of-type(5)
|
||||
height 100%
|
||||
width 100%
|
||||
transform translate3d(0, 0, calc(var(--thickness) * 0.5vmin))
|
||||
position absolute
|
||||
top 0
|
||||
left 0
|
||||
|
||||
&__side:nth-of-type(6)
|
||||
height 100%
|
||||
width 100%
|
||||
transform translate3d(0, 0, calc(var(--thickness) * -0.5vmin)) rotateY(180deg)
|
||||
position absolute
|
||||
top 0
|
||||
left 0
|
||||
|
||||
*
|
||||
*:after
|
||||
*:before
|
||||
box-sizing border-box
|
||||
transform-style preserve-3d
|
||||
transition background 0.25s
|
||||
|
||||
body
|
||||
min-height 100vh
|
||||
display grid
|
||||
place-items center
|
||||
background var(--bg)
|
||||
overflow hidden
|
||||
|
||||
:root
|
||||
--dark 0
|
||||
--base-size 20
|
||||
--plane-height calc(var(--base-size) * 1vmin)
|
||||
--plane-width calc(var(--plane-height) * 1.6)
|
||||
--white-one 'hsl(0, 0%, %s)' % calc((90 - (var(--dark) * 30)) * 1%)
|
||||
--white-two 'hsl(0, 0%, %s)' % calc((85 - (var(--dark) * 30)) * 1%)
|
||||
--white-three 'hsl(0, 0%, %s)' % calc((80 - (var(--dark) * 30)) * 1%)
|
||||
--white-four 'hsl(0, 0%, %s)' % calc((75 - (var(--dark) * 30)) * 1%)
|
||||
--white-five 'hsl(0, 0%, %s)' % calc((70 - (var(--dark) * 30)) * 1%)
|
||||
--accent-hue 10
|
||||
--accent-one 'hsl(%s, 80%, %s)' % (var(--accent-hue) calc((60 - (var(--dark) * 20)) * 1%))
|
||||
--accent-two 'hsl(%s, 80%, %s)' % (var(--accent-hue) calc((55 - (var(--dark) * 20)) * 1%))
|
||||
--accent-three 'hsl(%s, 80%, %s)' % (var(--accent-hue) calc((50 - (var(--dark) * 20)) * 1%))
|
||||
--accent-four 'hsl(%s, 80%, %s)' % (var(--accent-hue) calc((45 - (var(--dark) * 20)) * 1%))
|
||||
--accent-five 'hsl(%s, 80%, %s)' % (var(--accent-hue) calc((40 - (var(--dark) * 20)) * 1%))
|
||||
--screen 'hsla(210, 80%, %s, 0.25)' % calc((70 - (var(--dark) * 20)) * 1%)
|
||||
--metal-one 'hsl(0, 0%, %s)' % calc((60 - (var(--dark) * 20)) * 1%)
|
||||
--metal-two 'hsl(0, 0%, %s)' % calc((50 - (var(--dark) * 20)) * 1%)
|
||||
--metal-three 'hsl(0, 0%, %s)' % calc((40 - (var(--dark) * 20)) * 1%)
|
||||
--wheel-one hsl(0, 0%, 10%)
|
||||
--wheel-two hsl(0, 0%, 5%)
|
||||
--wheel-three hsl(0, 0%, 0%)
|
||||
--wheel-hub 'hsl(0, 0%, %s)' % calc((98 - (var(--dark) * 20)) * 1%)
|
||||
--bg 'hsl(210, 80%, %s)' % calc((90 - (var(--dark) * 76)) * 1%)
|
||||
--night hsl(210, 80%, 16%)
|
||||
--cloud-one 'hsl(0, 0%, %s)' % calc((98 - (var(--dark) * 35)) * 1%)
|
||||
--cloud-two 'hsl(0, 0%, %s)' % calc((94 - (var(--dark) * 35)) * 1%)
|
||||
--cloud-three 'hsl(0, 0%, %s)' % calc((90 - (var(--dark) * 35)) * 1%)
|
||||
--cloud-four 'hsl(0, 0%, %s)' % calc((86 - (var(--dark) * 35)) * 1%)
|
||||
--cloud-five 'hsl(0, 0%, %s)' % calc((82 - (var(--dark) * 35)) * 1%)
|
||||
--cloud-six 'hsl(0, 0%, %s)' % calc((78 - (var(--dark) * 35)) * 1%)
|
||||
|
||||
|
||||
.scene
|
||||
transform translate(-50%, -50%)
|
||||
position fixed
|
||||
top 50%
|
||||
left 50%
|
||||
transform translate3d(-50%, -50%, 100vmin) rotateX(-24deg) rotateY(44deg) rotateX(calc(var(--rotate-x, 0) * 1deg)) rotateY(calc(var(--rotate-y, 0) * 1deg))
|
||||
|
||||
[type="checkbox"]
|
||||
position fixed
|
||||
left 100%
|
||||
opacity 0
|
||||
visibility hidden
|
||||
|
||||
label
|
||||
height 100vh
|
||||
width 100vw
|
||||
position fixed
|
||||
top 0
|
||||
left 0
|
||||
right 0
|
||||
bottom 0
|
||||
transform translate3d(0, 0, 1000vmin)
|
||||
|
||||
.plane
|
||||
height var(--plane-height)
|
||||
width var(--plane-width)
|
||||
// background hsla(210, 80%, 80%, 0.5)
|
||||
position absolute
|
||||
top 50%
|
||||
left 50%
|
||||
transform translate(-50%, -50%)
|
||||
animation roll 10s infinite ease-out alternate
|
||||
|
||||
&__floater
|
||||
position absolute
|
||||
width var(--plane-width)
|
||||
height var(--plane-width)
|
||||
transform translate(-50%, -50%)
|
||||
top 50%
|
||||
left 50%
|
||||
animation float 2s infinite ease-in-out
|
||||
|
||||
&__looper
|
||||
position absolute
|
||||
width var(--plane-width)
|
||||
height var(--plane-width)
|
||||
transform translate(-50%, -50%)
|
||||
top 50%
|
||||
left 50%
|
||||
transform-origin 50% 0
|
||||
animation loop 10s infinite ease-in-out
|
||||
|
||||
*
|
||||
position absolute
|
||||
|
||||
&__body
|
||||
height 40%
|
||||
width 36%
|
||||
bottom 20%
|
||||
left 10%
|
||||
|
||||
&__wheels
|
||||
bottom 0
|
||||
width calc(var(--plane-height) * 0.2)
|
||||
left 32%
|
||||
transform translate(-50%, 0)
|
||||
height 20%
|
||||
|
||||
&__axle
|
||||
height 50%
|
||||
width 50%
|
||||
top 50%
|
||||
left 50%
|
||||
transform translate(-50%, -50%)
|
||||
|
||||
&__wheel
|
||||
height 100%
|
||||
width 100%
|
||||
top 0
|
||||
left 0
|
||||
|
||||
&__wings
|
||||
height 70%
|
||||
width 40%
|
||||
bottom 19%
|
||||
left 12%
|
||||
|
||||
&__tail
|
||||
height 40%
|
||||
width 54%
|
||||
bottom 20%
|
||||
left 46%
|
||||
|
||||
&__nose
|
||||
height 30%
|
||||
width 10%
|
||||
bottom 25%
|
||||
|
||||
&__stabilizer--horizontal
|
||||
height 9%
|
||||
width 16%
|
||||
right 1%
|
||||
bottom 50%
|
||||
|
||||
&__screen
|
||||
bottom 60%
|
||||
left 30%
|
||||
width 6%
|
||||
height 14%
|
||||
|
||||
&__propellor
|
||||
height calc(var(--base-size) * 0.75vmin)
|
||||
width calc(var(--base-size) * 0.75vmin)
|
||||
left -1%
|
||||
bottom 40%
|
||||
transform translate(-50%, 50%) rotateY(-90deg)
|
||||
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
top 50%
|
||||
left 50%
|
||||
transform translate3d(-50%, -50%, 2px)
|
||||
height 16%
|
||||
width 16%
|
||||
border-radius 50%
|
||||
background var(--white-one)
|
||||
|
||||
&__stabilizer--vertical
|
||||
height 20%
|
||||
width 20%
|
||||
right 0
|
||||
bottom 60%
|
||||
|
||||
&__beacon
|
||||
right 1%
|
||||
bottom 80%
|
||||
height 2%
|
||||
width 2%
|
||||
|
||||
&__wheel--left
|
||||
transform translate3d(0, 0, calc(var(--base-size) * 0.3vmin))
|
||||
&__wheel--right
|
||||
transform translate3d(0, 0, calc(var(--base-size) * -0.3vmin))
|
||||
|
||||
.propellor
|
||||
height 100%
|
||||
width 100%
|
||||
animation spin 0.35s infinite linear
|
||||
|
||||
&:after
|
||||
&:before
|
||||
content ''
|
||||
height 100%
|
||||
width 10%
|
||||
position absolute
|
||||
top 50%
|
||||
left 50%
|
||||
background linear-gradient(transparent 0 5%, var(--accent-two) 5% 15%, transparent 15% 85%, var(--accent-two) 85% 95%, transparent 95%), hsl(0, 0%, 0%)
|
||||
transform translate(-50%, -50%) rotate(calc(var(--r, 45) * 1deg))
|
||||
|
||||
&:after
|
||||
--r -45
|
||||
|
||||
.wings
|
||||
&__ghost
|
||||
height 80%
|
||||
width 80%
|
||||
left 50%
|
||||
bottom 10%
|
||||
transform translate(-50%, 0)
|
||||
|
||||
&__top
|
||||
top 0
|
||||
height 10%
|
||||
width 100%
|
||||
left 0
|
||||
|
||||
&__bottom
|
||||
bottom 0
|
||||
height 10%
|
||||
width 100%
|
||||
left 0
|
||||
|
||||
&__strobe
|
||||
bottom 10%
|
||||
height 4%
|
||||
width 4%
|
||||
left 50%
|
||||
|
||||
&--left
|
||||
transform translate3d(-50%, 0, calc(var(--base-size) * 1vmin))
|
||||
&--right
|
||||
transform translate3d(-50%, 0, calc(var(--base-size) * -1vmin))
|
||||
|
||||
.cloud
|
||||
height 10vmin
|
||||
width 15vmin
|
||||
position absolute
|
||||
top 50%
|
||||
left 50%
|
||||
transform translate(-50%, -50%)
|
||||
|
||||
&__shift
|
||||
height 100%
|
||||
width 100%
|
||||
animation pan calc(var(--speed, 5) * 1s) calc(var(--delay, 5) * -1s) infinite ease-in-out both
|
||||
|
||||
&__body
|
||||
height 100%
|
||||
width 100%
|
||||
animation scale calc(var(--speed, 5) * 1s) calc(var(--delay, 5) * -1s) infinite linear
|
||||
|
||||
&__body > div
|
||||
position absolute
|
||||
|
||||
&:nth-of-type(1)
|
||||
bottom 0
|
||||
left 25%
|
||||
width 60%
|
||||
height 90%
|
||||
--thickness calc(var(--base-size) * 0.2)
|
||||
|
||||
&:nth-of-type(2)
|
||||
bottom 0
|
||||
left 0
|
||||
width 50%
|
||||
height 60%
|
||||
--thickness calc(var(--base-size) * 0.3)
|
||||
|
||||
&:nth-of-type(3)
|
||||
bottom 0
|
||||
right 0%
|
||||
width 60%
|
||||
height 40%
|
||||
--thickness calc(var(--base-size) * 0.4)
|
||||
|
||||
&--one
|
||||
--speed 2
|
||||
--delay 3
|
||||
transform translate(-50%, -50%) translate3d(-40vmin, 20vmin, 26vmin)
|
||||
|
||||
&--two
|
||||
--speed 4
|
||||
--delay 1
|
||||
transform translate(-50%, -50%) translate3d(30vmin, -15vmin, -34vmin)
|
||||
|
||||
&--three
|
||||
--speed 6
|
||||
--delay 2
|
||||
transform translate(-50%, -50%) translate3d(50vmin, 35vmin, -14vmin)
|
||||
|
||||
.cuboid
|
||||
&--body
|
||||
--thickness calc(var(--base-size) * 0.4)
|
||||
div
|
||||
background var(--white-two)
|
||||
|
||||
&:nth-of-type(1)
|
||||
background var(--white-one)
|
||||
&:nth-of-type(2)
|
||||
background var(--white-two)
|
||||
&:nth-of-type(3)
|
||||
background var(--white-three)
|
||||
&:nth-of-type(4)
|
||||
background var(--white-four)
|
||||
|
||||
&:nth-of-type(5):after
|
||||
&:nth-of-type(6):after
|
||||
content ''
|
||||
position absolute
|
||||
top 50%
|
||||
left 50%
|
||||
height calc(var(--base-size) * 0.25vmin)
|
||||
width calc(var(--base-size) * 0.25vmin)
|
||||
background-image url("https://assets.codepen.io/605876/avatar.png")
|
||||
background-size cover
|
||||
filter saturate(0.65)
|
||||
transform translate3d(-50%, -50%, 1px)
|
||||
|
||||
&--screen
|
||||
--thickness calc(var(--base-size) * 0.26)
|
||||
|
||||
div
|
||||
background var(--screen)
|
||||
|
||||
&--tail
|
||||
--thickness calc(var(--base-size) * 0.3)
|
||||
|
||||
div
|
||||
background var(--white-two)
|
||||
|
||||
&:nth-of-type(1)
|
||||
background var(--white-one)
|
||||
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
height 74%
|
||||
width 50%
|
||||
background var(--metal-three)
|
||||
top 50%
|
||||
right 50%
|
||||
transform translate3d(-50%, -50%, 1px)
|
||||
|
||||
&:nth-of-type(2)
|
||||
background linear-gradient(var(--white-two) 0 30%, transparent 30%)
|
||||
|
||||
&:nth-of-type(3)
|
||||
background linear-gradient(90deg, var(--white-two) 0 20%, transparent 20%)
|
||||
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
background var(--white-four)
|
||||
top 0%
|
||||
left 20%
|
||||
height 100%
|
||||
width 87%
|
||||
transform-origin 0 50%
|
||||
transform rotateY(-22deg)
|
||||
|
||||
&:nth-of-type(5)
|
||||
background transparent
|
||||
overflow hidden
|
||||
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
bottom 70%
|
||||
height 100%
|
||||
width 100%
|
||||
background var(--white-two)
|
||||
transform-origin 100% 100%
|
||||
transform rotate(-22deg) scale(2) translate(10%, 0)
|
||||
|
||||
&:nth-of-type(6)
|
||||
background transparent
|
||||
overflow hidden
|
||||
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
bottom 70%
|
||||
height 100%
|
||||
width 100%
|
||||
background var(--white-two)
|
||||
transform-origin 0% 100%
|
||||
transform rotate(22deg) scale(2) translate(-10%, 0)
|
||||
|
||||
&--nose
|
||||
--thickness calc(var(--base-size) * 0.3)
|
||||
|
||||
div
|
||||
background var(--metal-three)
|
||||
|
||||
&:nth-of-type(1)
|
||||
background var(--metal-one)
|
||||
&:nth-of-type(2)
|
||||
background var(--metal-two)
|
||||
&:nth-of-type(3)
|
||||
background var(--metal-one)
|
||||
|
||||
&--wings-ghost
|
||||
&--wings-top
|
||||
&--wings-bottom
|
||||
--thickness calc(var(--base-size) * 2.2)
|
||||
|
||||
div
|
||||
background var(--accent-one)
|
||||
|
||||
&:nth-of-type(1)
|
||||
background var(--accent-two)
|
||||
&:nth-of-type(2)
|
||||
&:nth-of-type(5)
|
||||
background var(--accent-three)
|
||||
&:nth-of-type(4)
|
||||
background var(--accent-four)
|
||||
&:nth-of-type(3)
|
||||
background var(--accent-five)
|
||||
|
||||
&--wings-ghost
|
||||
div
|
||||
&:nth-of-type(3)
|
||||
&:nth-of-type(5)
|
||||
&:nth-of-type(6)
|
||||
&:nth-of-type(1)
|
||||
background transparent
|
||||
&:nth-of-type(2)
|
||||
&:nth-of-type(4)
|
||||
background linear-gradient(90deg, transparent 0 5%, var(--metal-one) 5% 7%, transparent 7% 33%, var(--metal-one) 33% 35%, transparent 35% 65%, var(--metal-one) 65% 67%, transparent 67% 93%, var(--metal-one) 93% 95%, transparent 95%)
|
||||
|
||||
&--axle
|
||||
--thickness calc(var(--base-size) * 0.5)
|
||||
|
||||
div
|
||||
background var(--metal-two)
|
||||
|
||||
&:nth-of-type(3)
|
||||
background var(--metal-three)
|
||||
&:nth-of-type(2)
|
||||
&:nth-of-type(1)
|
||||
background var(--metal-one)
|
||||
&:nth-of-type(6)
|
||||
background var(--metal-one)
|
||||
|
||||
&--horizontal-stabilizer
|
||||
--thickness calc(var(--base-size) * 0.65)
|
||||
|
||||
div
|
||||
background var(--accent-one)
|
||||
|
||||
&:nth-of-type(1)
|
||||
background var(--accent-two)
|
||||
&:nth-of-type(2)
|
||||
&:nth-of-type(5)
|
||||
background var(--accent-three)
|
||||
&:nth-of-type(3)
|
||||
&:nth-of-type(4)
|
||||
background var(--accent-four)
|
||||
|
||||
&--vertical-stabilizer
|
||||
--thickness calc(var(--base-size) * 0.2)
|
||||
|
||||
div
|
||||
background var(--accent-one)
|
||||
|
||||
&:nth-of-type(1)
|
||||
background linear-gradient(270deg, var(--accent-two) 0 30%, transparent 30%)
|
||||
|
||||
&:nth-of-type(4)
|
||||
background transparent
|
||||
|
||||
&:after
|
||||
content ''
|
||||
background var(--accent-four)
|
||||
height 150%
|
||||
bottom 0
|
||||
left 0
|
||||
position absolute
|
||||
width 100%
|
||||
transform-origin 50% 100%
|
||||
transform rotateX(-48deg)
|
||||
|
||||
&:nth-of-type(5)
|
||||
background transparent
|
||||
overflow hidden
|
||||
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
top 100%
|
||||
transform-origin 0 0
|
||||
transform rotate(-42deg)
|
||||
background var(--accent-three)
|
||||
height 150%
|
||||
width 160%
|
||||
|
||||
&:nth-of-type(6)
|
||||
background transparent
|
||||
overflow hidden
|
||||
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
top 100%
|
||||
right 0
|
||||
transform-origin 100% 0
|
||||
transform rotate(42deg)
|
||||
background var(--accent-three)
|
||||
height 150%
|
||||
width 160%
|
||||
|
||||
&--wheel-left
|
||||
&--wheel-right
|
||||
--thickness calc(var(--base-size) * 0.1)
|
||||
|
||||
div
|
||||
background var(--wheel-one)
|
||||
|
||||
&:nth-of-type(1)
|
||||
&:nth-of-type(2)
|
||||
&:nth-of-type(4)
|
||||
background var(--wheel-two)
|
||||
&:nth-of-type(3)
|
||||
background var(--wheel-three)
|
||||
|
||||
&:nth-of-type(5)
|
||||
&:nth-of-type(6)
|
||||
&:after
|
||||
content ''
|
||||
position absolute
|
||||
top 50%
|
||||
left 50%
|
||||
transform translate(-50%, -50%)
|
||||
height 40%
|
||||
width 40%
|
||||
background var(--wheel-hub)
|
||||
&--cloud
|
||||
div
|
||||
&:nth-of-type(1)
|
||||
background var(--cloud-one)
|
||||
&:nth-of-type(2)
|
||||
background var(--cloud-two)
|
||||
&:nth-of-type(3)
|
||||
background var(--cloud-three)
|
||||
&:nth-of-type(4)
|
||||
background var(--cloud-four)
|
||||
&:nth-of-type(5)
|
||||
background var(--cloud-five)
|
||||
&:nth-of-type(6)
|
||||
background var(--cloud-six)
|
||||
|
||||
&--beacon
|
||||
--thickness calc(var(--base-size) * 0.02)
|
||||
animation flash calc(var(--dark) * 1s) infinite
|
||||
|
||||
div
|
||||
background 'hsla(0, 90%, 50%, %s)' % var(--alpha)
|
||||
|
||||
&--strobe
|
||||
--thickness calc(var(--base-size) * 0.02)
|
||||
animation flash calc(var(--dark) * 0.5s) infinite
|
||||
|
||||
div
|
||||
background 'hsla(0, 90%, 98%, %s)' % var(--alpha)
|
||||
|
||||
@keyframes flash
|
||||
50%
|
||||
--alpha 1
|
||||
|
||||
@keyframes spin
|
||||
to
|
||||
transform rotate(360deg)
|
||||
|
||||
@keyframes float
|
||||
50%
|
||||
transform translate(-50%, -40%)
|
||||
|
||||
@keyframes loop
|
||||
0%, 40%
|
||||
transform translate(-50%, -50%)
|
||||
50%, 100%
|
||||
transform translate(-50%, -50%) rotateZ(360deg)
|
||||
|
||||
@keyframes roll
|
||||
0%, 85%
|
||||
transform translate(-50%, -50%)
|
||||
90%, 100%
|
||||
transform translate(-50%, -50%) rotateX(-360deg)
|
||||
|
||||
@keyframes nightshift
|
||||
0%, 50%
|
||||
background var(--bg)
|
||||
75%, 100%
|
||||
background var(--night)
|
||||
|
||||
@keyframes scale
|
||||
0%, 5%, 95%, 100%
|
||||
transform scale(0)
|
||||
10%, 90%
|
||||
transform scale(1)
|
||||
|
||||
@keyframes pan
|
||||
0%
|
||||
transform translate(-1000%, 0)
|
||||
100%
|
||||
transform translate(1000%, 0)
|
|
@ -0,0 +1,5 @@
|
|||
# 3D CSS Sphere
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/peterwestendorp/pen/wGECk](https://codepen.io/peterwestendorp/pen/wGECk).
|
||||
|
||||
3D ball made with just some CSS 3D transforms, border-radius and border-style. Not really useful, it just looks nice...
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 3D CSS Sphere</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<div class="scene">
|
||||
<div class="wrapper">
|
||||
<ul class="ball">
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- partial -->
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,162 @@
|
|||
@keyframes roundandround {
|
||||
to {
|
||||
transform: rotateX(360deg) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #000000;
|
||||
}
|
||||
.scene {
|
||||
width:600px;
|
||||
height:600px;
|
||||
margin:2% auto;
|
||||
perspective: 1000px;
|
||||
}
|
||||
.wrapper {
|
||||
width:100%;
|
||||
height:100%;
|
||||
transform: rotateX(45deg) rotateY(45deg);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
.ball {
|
||||
position: relative;
|
||||
width: 70%;
|
||||
height: 70%;
|
||||
margin:0 auto;
|
||||
transform-style: preserve-3d;
|
||||
animation: roundandround 7.5s 1.3s infinite linear;
|
||||
}
|
||||
.ball .ring {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border:6px;
|
||||
border-style: dashed;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
animation: show 0.75s forwards ease-in-out;
|
||||
}
|
||||
.ring:nth-child(1) {
|
||||
color:#8df435;
|
||||
transform: rotateY(4deg);
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.ring:nth-child(2) {
|
||||
color:#a8e526;
|
||||
transform: rotateY(8deg);
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
.ring:nth-child(3) {
|
||||
color:#c2d11c;
|
||||
transform: rotateY(12deg);
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
.ring:nth-child(4) {
|
||||
color:#c8cb1b;
|
||||
transform: rotateY(16deg);
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
.ring:nth-child(5) {
|
||||
color:#deb21a;
|
||||
transform: rotateY(20deg);
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
.ring:nth-child(6) {
|
||||
color:#ef9621;
|
||||
transform: rotateY(24deg);
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
.ring:nth-child(7) {
|
||||
color:#f29122;
|
||||
transform: rotateY(28deg);
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
.ring:nth-child(8) {
|
||||
color:#fb7430;
|
||||
transform: rotateY(32deg);
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
.ring:nth-child(9) {
|
||||
color:#fe5944;
|
||||
transform: rotateY(36deg);
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
.ring:nth-child(10) {
|
||||
color:#fe5548;
|
||||
transform: rotateY(40deg);
|
||||
animation-delay: 0.9s;
|
||||
}
|
||||
.ring:nth-child(11) {
|
||||
color:#f83d61;
|
||||
transform: rotateY(44deg);
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.ring:nth-child(12) {
|
||||
color:#ec2b7d;
|
||||
transform: rotateY(48deg);
|
||||
animation-delay: 1.1s;
|
||||
}
|
||||
.ring:nth-child(13) {
|
||||
color:#e82983;
|
||||
transform: rotateY(52deg);
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.ring:nth-child(14) {
|
||||
color:#d41e9f;
|
||||
transform: rotateY(56deg);
|
||||
animation-delay: 0.9s;
|
||||
}
|
||||
.ring:nth-child(15) {
|
||||
color:#bd1aba;
|
||||
transform: rotateY(60deg);
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
.ring:nth-child(16) {
|
||||
color:#b81ac0;
|
||||
transform: rotateY(64deg);
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
.ring:nth-child(17) {
|
||||
color:#9c1fd7;
|
||||
transform: rotateY(68deg);
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
.ring:nth-child(18) {
|
||||
color:#802aea;
|
||||
transform: rotateY(72deg);
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
.ring:nth-child(19) {
|
||||
color:#7a2dee;
|
||||
transform: rotateY(76deg);
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
.ring:nth-child(20) {
|
||||
color:#5f40f9;
|
||||
transform: rotateY(80deg);
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
.ring:nth-child(21) {
|
||||
color:#4657fe;
|
||||
transform: rotateY(84deg);
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
.ring:nth-child(22) {
|
||||
color:#425cfe;
|
||||
transform: rotateY(88deg);
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
.ring:nth-child(23) {
|
||||
color:#2f77fb;
|
||||
transform: rotateY(92deg);
|
||||
animation-delay: 0s;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2022 by Peter Westendorp (https://codepen.io/peterwestendorp/pen/wGECk)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<div class="scene">
|
||||
<div class="wrapper">
|
||||
<ul class="ball">
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
<li class="ring"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,162 @@
|
|||
@keyframes roundandround {
|
||||
to {
|
||||
transform: rotateX(360deg) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #000000;
|
||||
}
|
||||
.scene {
|
||||
width:600px;
|
||||
height:600px;
|
||||
margin:2% auto;
|
||||
perspective: 1000px;
|
||||
}
|
||||
.wrapper {
|
||||
width:100%;
|
||||
height:100%;
|
||||
transform: rotateX(45deg) rotateY(45deg);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
.ball {
|
||||
position: relative;
|
||||
width: 70%;
|
||||
height: 70%;
|
||||
margin:0 auto;
|
||||
transform-style: preserve-3d;
|
||||
animation: roundandround 7.5s 1.3s infinite linear;
|
||||
}
|
||||
.ball .ring {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border:6px;
|
||||
border-style: dashed;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
animation: show 0.75s forwards ease-in-out;
|
||||
}
|
||||
.ring:nth-child(1) {
|
||||
color:#8df435;
|
||||
transform: rotateY(4deg);
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.ring:nth-child(2) {
|
||||
color:#a8e526;
|
||||
transform: rotateY(8deg);
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
.ring:nth-child(3) {
|
||||
color:#c2d11c;
|
||||
transform: rotateY(12deg);
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
.ring:nth-child(4) {
|
||||
color:#c8cb1b;
|
||||
transform: rotateY(16deg);
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
.ring:nth-child(5) {
|
||||
color:#deb21a;
|
||||
transform: rotateY(20deg);
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
.ring:nth-child(6) {
|
||||
color:#ef9621;
|
||||
transform: rotateY(24deg);
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
.ring:nth-child(7) {
|
||||
color:#f29122;
|
||||
transform: rotateY(28deg);
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
.ring:nth-child(8) {
|
||||
color:#fb7430;
|
||||
transform: rotateY(32deg);
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
.ring:nth-child(9) {
|
||||
color:#fe5944;
|
||||
transform: rotateY(36deg);
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
.ring:nth-child(10) {
|
||||
color:#fe5548;
|
||||
transform: rotateY(40deg);
|
||||
animation-delay: 0.9s;
|
||||
}
|
||||
.ring:nth-child(11) {
|
||||
color:#f83d61;
|
||||
transform: rotateY(44deg);
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.ring:nth-child(12) {
|
||||
color:#ec2b7d;
|
||||
transform: rotateY(48deg);
|
||||
animation-delay: 1.1s;
|
||||
}
|
||||
.ring:nth-child(13) {
|
||||
color:#e82983;
|
||||
transform: rotateY(52deg);
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.ring:nth-child(14) {
|
||||
color:#d41e9f;
|
||||
transform: rotateY(56deg);
|
||||
animation-delay: 0.9s;
|
||||
}
|
||||
.ring:nth-child(15) {
|
||||
color:#bd1aba;
|
||||
transform: rotateY(60deg);
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
.ring:nth-child(16) {
|
||||
color:#b81ac0;
|
||||
transform: rotateY(64deg);
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
.ring:nth-child(17) {
|
||||
color:#9c1fd7;
|
||||
transform: rotateY(68deg);
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
.ring:nth-child(18) {
|
||||
color:#802aea;
|
||||
transform: rotateY(72deg);
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
.ring:nth-child(19) {
|
||||
color:#7a2dee;
|
||||
transform: rotateY(76deg);
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
.ring:nth-child(20) {
|
||||
color:#5f40f9;
|
||||
transform: rotateY(80deg);
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
.ring:nth-child(21) {
|
||||
color:#4657fe;
|
||||
transform: rotateY(84deg);
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
.ring:nth-child(22) {
|
||||
color:#425cfe;
|
||||
transform: rotateY(88deg);
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
.ring:nth-child(23) {
|
||||
color:#2f77fb;
|
||||
transform: rotateY(92deg);
|
||||
animation-delay: 0s;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# 3d d20 die with pure CSS
|
||||
_A Pen created at CodePen.io. Original URL: [https://codepen.io/vicentemundim/pen/cenIh](https://codepen.io/vicentemundim/pen/cenIh).
|
||||
|
||||
This is a 3d 20-sided die made with pure CSS. Each face is an equilateral triangle, that can be resized. You can also change de color of the die, as well as its opacity.
|
||||
|
||||
The sum of the values on opposite faces is always 21.
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>3d d20 die with pure CSS</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<div class="content">
|
||||
<div class="die">
|
||||
<figure class="face face-1"></figure>
|
||||
<figure class="face face-2"></figure>
|
||||
<figure class="face face-3"></figure>
|
||||
<figure class="face face-4"></figure>
|
||||
<figure class="face face-5"></figure>
|
||||
<figure class="face face-6"></figure>
|
||||
<figure class="face face-7"></figure>
|
||||
<figure class="face face-8"></figure>
|
||||
<figure class="face face-9"></figure>
|
||||
<figure class="face face-10"></figure>
|
||||
<figure class="face face-11"></figure>
|
||||
<figure class="face face-12"></figure>
|
||||
<figure class="face face-13"></figure>
|
||||
<figure class="face face-14"></figure>
|
||||
<figure class="face face-15"></figure>
|
||||
<figure class="face face-16"></figure>
|
||||
<figure class="face face-17"></figure>
|
||||
<figure class="face face-18"></figure>
|
||||
<figure class="face face-19"></figure>
|
||||
<figure class="face face-20"></figure>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Click to show face:</h2>
|
||||
<ul>
|
||||
<li><a href="1">1</a></li>
|
||||
<li><a href="2">2</a></li>
|
||||
<li><a href="3">3</a></li>
|
||||
<li><a href="4">4</a></li>
|
||||
<li><a href="5">5</a></li>
|
||||
<li><a href="6">6</a></li>
|
||||
<li><a href="7">7</a></li>
|
||||
<li><a href="8">8</a></li>
|
||||
<li><a href="9">9</a></li>
|
||||
<li><a href="10">10</a></li>
|
||||
<li><a href="11">11</a></li>
|
||||
<li><a href="12">12</a></li>
|
||||
<li><a href="13">13</a></li>
|
||||
<li><a href="14">14</a></li>
|
||||
<li><a href="15">15</a></li>
|
||||
<li><a href="16">16</a></li>
|
||||
<li><a href="17">17</a></li>
|
||||
<li><a href="18">18</a></li>
|
||||
<li><a href="19">19</a></li>
|
||||
<li><a href="20">20</a></li>
|
||||
</ul>
|
||||
|
||||
<a href="" class="randomize">Roll!</a>
|
||||
<!-- partial -->
|
||||
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
|
||||
<script src="./script.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,46 @@
|
|||
var $die = $('.die'),
|
||||
sides = 20,
|
||||
initialSide = 1,
|
||||
lastFace,
|
||||
timeoutId,
|
||||
transitionDuration = 500,
|
||||
animationDuration = 3000
|
||||
|
||||
$('ul > li > a').click(function () {
|
||||
reset()
|
||||
rollTo($(this).attr('href'))
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
function randomFace() {
|
||||
var face = Math.floor((Math.random() * sides)) + initialSide
|
||||
lastFace = face == lastFace ? randomFace() : face
|
||||
return face;
|
||||
}
|
||||
|
||||
function rollTo(face) {
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
$('ul > li > a').removeClass('active')
|
||||
$('[href=' + face + ']').addClass('active')
|
||||
|
||||
$die.attr('data-face', face)
|
||||
}
|
||||
|
||||
function reset() {
|
||||
$die.attr('data-face', null).removeClass('rolling')
|
||||
}
|
||||
|
||||
$('.randomize, .die').click(function () {
|
||||
$die.addClass('rolling')
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
timeoutId = setTimeout(function () {
|
||||
$die.removeClass('rolling')
|
||||
|
||||
rollTo(randomFace())
|
||||
}, animationDuration)
|
||||
|
||||
return false
|
||||
})
|
|
@ -0,0 +1,302 @@
|
|||
@-webkit-keyframes roll {
|
||||
10% {
|
||||
-webkit-transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
|
||||
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: rotateX(120deg) rotateY(240deg) rotateZ(0deg) translateX(40px) translateY(40px);
|
||||
transform: rotateX(120deg) rotateY(240deg) rotateZ(0deg) translateX(40px) translateY(40px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: rotateX(240deg) rotateY(480deg) rotateZ(0deg) translateX(-40px) translateY(-40px);
|
||||
transform: rotateX(240deg) rotateY(480deg) rotateZ(0deg) translateX(-40px) translateY(-40px);
|
||||
}
|
||||
70% {
|
||||
-webkit-transform: rotateX(360deg) rotateY(720deg) rotateZ(0deg);
|
||||
transform: rotateX(360deg) rotateY(720deg) rotateZ(0deg);
|
||||
}
|
||||
90% {
|
||||
-webkit-transform: rotateX(480deg) rotateY(960deg) rotateZ(0deg);
|
||||
transform: rotateX(480deg) rotateY(960deg) rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
@keyframes roll {
|
||||
10% {
|
||||
-webkit-transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
|
||||
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: rotateX(120deg) rotateY(240deg) rotateZ(0deg) translateX(40px) translateY(40px);
|
||||
transform: rotateX(120deg) rotateY(240deg) rotateZ(0deg) translateX(40px) translateY(40px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: rotateX(240deg) rotateY(480deg) rotateZ(0deg) translateX(-40px) translateY(-40px);
|
||||
transform: rotateX(240deg) rotateY(480deg) rotateZ(0deg) translateX(-40px) translateY(-40px);
|
||||
}
|
||||
70% {
|
||||
-webkit-transform: rotateX(360deg) rotateY(720deg) rotateZ(0deg);
|
||||
transform: rotateX(360deg) rotateY(720deg) rotateZ(0deg);
|
||||
}
|
||||
90% {
|
||||
-webkit-transform: rotateX(480deg) rotateY(960deg) rotateZ(0deg);
|
||||
transform: rotateX(480deg) rotateY(960deg) rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
body {
|
||||
background: #333;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: auto auto;
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
-webkit-perspective: 1500px;
|
||||
perspective: 1500px;
|
||||
}
|
||||
|
||||
.die {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
transition: -webkit-transform 0.5s ease-out;
|
||||
transition: transform 0.5s ease-out;
|
||||
transition: transform 0.5s ease-out, -webkit-transform 0.5s ease-out;
|
||||
cursor: pointer;
|
||||
-webkit-transform: rotateX(-53deg);
|
||||
transform: rotateX(-53deg);
|
||||
}
|
||||
.die.rolling {
|
||||
-webkit-animation: roll 3s linear;
|
||||
animation: roll 3s linear;
|
||||
}
|
||||
.die[data-face="1"] {
|
||||
-webkit-transform: rotateX(-53deg) rotateY(0deg);
|
||||
transform: rotateX(-53deg) rotateY(0deg);
|
||||
}
|
||||
.die[data-face="2"] {
|
||||
-webkit-transform: rotateX(-53deg) rotateY(72deg);
|
||||
transform: rotateX(-53deg) rotateY(72deg);
|
||||
}
|
||||
.die[data-face="3"] {
|
||||
-webkit-transform: rotateX(-53deg) rotateY(144deg);
|
||||
transform: rotateX(-53deg) rotateY(144deg);
|
||||
}
|
||||
.die[data-face="4"] {
|
||||
-webkit-transform: rotateX(-53deg) rotateY(216deg);
|
||||
transform: rotateX(-53deg) rotateY(216deg);
|
||||
}
|
||||
.die[data-face="5"] {
|
||||
-webkit-transform: rotateX(-53deg) rotateY(288deg);
|
||||
transform: rotateX(-53deg) rotateY(288deg);
|
||||
}
|
||||
.die[data-face="16"] {
|
||||
-webkit-transform: rotateX(127deg) rotateY(-72deg);
|
||||
transform: rotateX(127deg) rotateY(-72deg);
|
||||
}
|
||||
.die[data-face="17"] {
|
||||
-webkit-transform: rotateX(127deg) rotateY(-144deg);
|
||||
transform: rotateX(127deg) rotateY(-144deg);
|
||||
}
|
||||
.die[data-face="18"] {
|
||||
-webkit-transform: rotateX(127deg) rotateY(-216deg);
|
||||
transform: rotateX(127deg) rotateY(-216deg);
|
||||
}
|
||||
.die[data-face="19"] {
|
||||
-webkit-transform: rotateX(127deg) rotateY(-288deg);
|
||||
transform: rotateX(127deg) rotateY(-288deg);
|
||||
}
|
||||
.die[data-face="20"] {
|
||||
-webkit-transform: rotateX(127deg) rotateY(-360deg);
|
||||
transform: rotateX(127deg) rotateY(-360deg);
|
||||
}
|
||||
.die[data-face="6"] {
|
||||
-webkit-transform: rotateX(11deg) rotateZ(180deg) rotateY(0deg);
|
||||
transform: rotateX(11deg) rotateZ(180deg) rotateY(0deg);
|
||||
}
|
||||
.die[data-face="7"] {
|
||||
-webkit-transform: rotateX(11deg) rotateZ(180deg) rotateY(72deg);
|
||||
transform: rotateX(11deg) rotateZ(180deg) rotateY(72deg);
|
||||
}
|
||||
.die[data-face="8"] {
|
||||
-webkit-transform: rotateX(11deg) rotateZ(180deg) rotateY(144deg);
|
||||
transform: rotateX(11deg) rotateZ(180deg) rotateY(144deg);
|
||||
}
|
||||
.die[data-face="9"] {
|
||||
-webkit-transform: rotateX(11deg) rotateZ(180deg) rotateY(216deg);
|
||||
transform: rotateX(11deg) rotateZ(180deg) rotateY(216deg);
|
||||
}
|
||||
.die[data-face="10"] {
|
||||
-webkit-transform: rotateX(11deg) rotateZ(180deg) rotateY(288deg);
|
||||
transform: rotateX(11deg) rotateZ(180deg) rotateY(288deg);
|
||||
}
|
||||
.die[data-face="11"] {
|
||||
-webkit-transform: rotateX(11deg) rotateY(-252deg);
|
||||
transform: rotateX(11deg) rotateY(-252deg);
|
||||
}
|
||||
.die[data-face="12"] {
|
||||
-webkit-transform: rotateX(11deg) rotateY(-324deg);
|
||||
transform: rotateX(11deg) rotateY(-324deg);
|
||||
}
|
||||
.die[data-face="13"] {
|
||||
-webkit-transform: rotateX(11deg) rotateY(-396deg);
|
||||
transform: rotateX(11deg) rotateY(-396deg);
|
||||
}
|
||||
.die[data-face="14"] {
|
||||
-webkit-transform: rotateX(11deg) rotateY(-468deg);
|
||||
transform: rotateX(11deg) rotateY(-468deg);
|
||||
}
|
||||
.die[data-face="15"] {
|
||||
-webkit-transform: rotateX(11deg) rotateY(-540deg);
|
||||
transform: rotateX(11deg) rotateY(-540deg);
|
||||
}
|
||||
.die .face {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
margin: 0 -50px;
|
||||
border-left: 50px solid transparent;
|
||||
border-right: 50px solid transparent;
|
||||
border-bottom: 86px solid rgba(30, 180, 20, 0.75);
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
counter-increment: steps 1;
|
||||
}
|
||||
.die .face:before {
|
||||
content: counter(steps);
|
||||
position: absolute;
|
||||
top: 21.5px;
|
||||
left: -100px;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px 3px #000;
|
||||
font-size: 43px;
|
||||
text-align: center;
|
||||
line-height: 77.4px;
|
||||
width: 200px;
|
||||
height: 86px;
|
||||
}
|
||||
.die .face:nth-child(1) {
|
||||
-webkit-transform: rotateY(0deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
transform: rotateY(0deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(2) {
|
||||
-webkit-transform: rotateY(-72deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
transform: rotateY(-72deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(3) {
|
||||
-webkit-transform: rotateY(-144deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
transform: rotateY(-144deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(4) {
|
||||
-webkit-transform: rotateY(-216deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
transform: rotateY(-216deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(5) {
|
||||
-webkit-transform: rotateY(-288deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
transform: rotateY(-288deg) translateZ(33.5px) translateY(-12.9px) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(16) {
|
||||
-webkit-transform: rotateY(-108deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
transform: rotateY(-108deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(17) {
|
||||
-webkit-transform: rotateY(-36deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
transform: rotateY(-36deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(18) {
|
||||
-webkit-transform: rotateY(36deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
transform: rotateY(36deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(19) {
|
||||
-webkit-transform: rotateY(108deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
transform: rotateY(108deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(20) {
|
||||
-webkit-transform: rotateY(180deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
transform: rotateY(180deg) translateZ(33.5px) translateY(121.26px) rotateZ(180deg) rotateX(53deg);
|
||||
}
|
||||
.die .face:nth-child(6) {
|
||||
-webkit-transform: rotateY(360deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
transform: rotateY(360deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(7) {
|
||||
-webkit-transform: rotateY(288deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
transform: rotateY(288deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(8) {
|
||||
-webkit-transform: rotateY(216deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
transform: rotateY(216deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(9) {
|
||||
-webkit-transform: rotateY(144deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
transform: rotateY(144deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(10) {
|
||||
-webkit-transform: rotateY(72deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
transform: rotateY(72deg) translateZ(75px) translateY(54.18px) rotateZ(180deg) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(11) {
|
||||
-webkit-transform: rotateY(252deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
transform: rotateY(252deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(12) {
|
||||
-webkit-transform: rotateY(324deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
transform: rotateY(324deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(13) {
|
||||
-webkit-transform: rotateY(396deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
transform: rotateY(396deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(14) {
|
||||
-webkit-transform: rotateY(468deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
transform: rotateY(468deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
}
|
||||
.die .face:nth-child(15) {
|
||||
-webkit-transform: rotateY(540deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
transform: rotateY(540deg) translateZ(75px) translateY(54.18px) rotateX(-11deg);
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #fafafa;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
ul > li {
|
||||
display: inline-block;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
padding: 5px 15px;
|
||||
width: 40px;
|
||||
display: inline-block;
|
||||
border: 1px solid #dcdcdc;
|
||||
border-radius: 4px;
|
||||
background-color: #999;
|
||||
}
|
||||
a.active {
|
||||
background-color: #333;
|
||||
}
|
||||
a:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
a.randomize {
|
||||
width: auto;
|
||||
margin: 20px 10px;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
|
||||
<!--
|
||||
Copyright (c) 2019 by Vicente Mundim (https://codepen.io/vicentemundim/pen/cenIh)
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
-->
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<div class="content">
|
||||
<div class="die">
|
||||
<figure class="face face-1"></figure>
|
||||
<figure class="face face-2"></figure>
|
||||
<figure class="face face-3"></figure>
|
||||
<figure class="face face-4"></figure>
|
||||
<figure class="face face-5"></figure>
|
||||
<figure class="face face-6"></figure>
|
||||
<figure class="face face-7"></figure>
|
||||
<figure class="face face-8"></figure>
|
||||
<figure class="face face-9"></figure>
|
||||
<figure class="face face-10"></figure>
|
||||
<figure class="face face-11"></figure>
|
||||
<figure class="face face-12"></figure>
|
||||
<figure class="face face-13"></figure>
|
||||
<figure class="face face-14"></figure>
|
||||
<figure class="face face-15"></figure>
|
||||
<figure class="face face-16"></figure>
|
||||
<figure class="face face-17"></figure>
|
||||
<figure class="face face-18"></figure>
|
||||
<figure class="face face-19"></figure>
|
||||
<figure class="face face-20"></figure>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Click to show face:</h2>
|
||||
<ul>
|
||||
<li><a href="1">1</a></li>
|
||||
<li><a href="2">2</a></li>
|
||||
<li><a href="3">3</a></li>
|
||||
<li><a href="4">4</a></li>
|
||||
<li><a href="5">5</a></li>
|
||||
<li><a href="6">6</a></li>
|
||||
<li><a href="7">7</a></li>
|
||||
<li><a href="8">8</a></li>
|
||||
<li><a href="9">9</a></li>
|
||||
<li><a href="10">10</a></li>
|
||||
<li><a href="11">11</a></li>
|
||||
<li><a href="12">12</a></li>
|
||||
<li><a href="13">13</a></li>
|
||||
<li><a href="14">14</a></li>
|
||||
<li><a href="15">15</a></li>
|
||||
<li><a href="16">16</a></li>
|
||||
<li><a href="17">17</a></li>
|
||||
<li><a href="18">18</a></li>
|
||||
<li><a href="19">19</a></li>
|
||||
<li><a href="20">20</a></li>
|
||||
</ul>
|
||||
|
||||
<a href="" class="randomize">Roll!</a>
|
|
@ -0,0 +1,46 @@
|
|||
var $die = $('.die'),
|
||||
sides = 20,
|
||||
initialSide = 1,
|
||||
lastFace,
|
||||
timeoutId,
|
||||
transitionDuration = 500,
|
||||
animationDuration = 3000
|
||||
|
||||
$('ul > li > a').click(function () {
|
||||
reset()
|
||||
rollTo($(this).attr('href'))
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
function randomFace() {
|
||||
var face = Math.floor((Math.random() * sides)) + initialSide
|
||||
lastFace = face == lastFace ? randomFace() : face
|
||||
return face;
|
||||
}
|
||||
|
||||
function rollTo(face) {
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
$('ul > li > a').removeClass('active')
|
||||
$('[href=' + face + ']').addClass('active')
|
||||
|
||||
$die.attr('data-face', face)
|
||||
}
|
||||
|
||||
function reset() {
|
||||
$die.attr('data-face', null).removeClass('rolling')
|
||||
}
|
||||
|
||||
$('.randomize, .die').click(function () {
|
||||
$die.addClass('rolling')
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
timeoutId = setTimeout(function () {
|
||||
$die.removeClass('rolling')
|
||||
|
||||
rollTo(randomFace())
|
||||
}, animationDuration)
|
||||
|
||||
return false
|
||||
})
|
|
@ -0,0 +1,188 @@
|
|||
$containerWidth: 200px;
|
||||
$containerHeight: $containerWidth;
|
||||
|
||||
$faceWidth: $containerWidth*0.5;
|
||||
$faceHeight: $faceWidth*0.86;
|
||||
|
||||
$transitionDuration: 0.5s;
|
||||
$animationDuration: 3s;
|
||||
|
||||
$angle: 53deg;
|
||||
$ringAngle: -11deg;
|
||||
$sideAngle: 360deg/5;
|
||||
$opacity: 0.75;
|
||||
$color: rgba(30, 180, 20, $opacity);
|
||||
|
||||
$rotateX: -$angle;
|
||||
$translateZ: $faceWidth*0.335;
|
||||
$translateY: -$faceHeight*0.15;
|
||||
$translateRingZ: $faceWidth*0.75;
|
||||
$translateRingY: $faceHeight*0.78 + $translateY;
|
||||
$translateLowerZ: $translateZ;
|
||||
$translateLowerY: $faceHeight*0.78 + $translateRingY;
|
||||
|
||||
@keyframes roll {
|
||||
10% { transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) }
|
||||
30% { transform: rotateX(120deg) rotateY(240deg) rotateZ(0deg) translateX(40px) translateY(40px) }
|
||||
50% { transform: rotateX(240deg) rotateY(480deg) rotateZ(0deg) translateX(-40px) translateY(-40px) }
|
||||
70% { transform: rotateX(360deg) rotateY(720deg) rotateZ(0deg) }
|
||||
90% { transform: rotateX(480deg) rotateY(960deg) rotateZ(0deg) }
|
||||
}
|
||||
|
||||
body {
|
||||
background: #333;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: auto auto;
|
||||
position: relative;
|
||||
width: $containerWidth;
|
||||
height: $containerHeight;
|
||||
perspective: 1500px;
|
||||
}
|
||||
|
||||
.die {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-style: preserve-3d;
|
||||
transition: transform $transitionDuration ease-out;
|
||||
cursor: pointer;
|
||||
|
||||
transform: rotateX($rotateX);
|
||||
|
||||
&.rolling {
|
||||
animation: roll $animationDuration linear;
|
||||
}
|
||||
|
||||
@for $i from 1 through 5 {
|
||||
&[data-face="#{$i}"] {
|
||||
$angleMultiplier: $i - 1;
|
||||
transform: rotateX(-$angle) rotateY($sideAngle * $angleMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 16 through 20 {
|
||||
&[data-face="#{$i}"] {
|
||||
$angleMultiplier: $i - 15;
|
||||
transform: rotateX(-$angle + 180deg) rotateY(-$sideAngle * $angleMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 6 through 10 {
|
||||
&[data-face="#{$i}"] {
|
||||
$angleMultiplier: $i - 6;
|
||||
transform: rotateX(-$ringAngle) rotateZ(180deg) rotateY($sideAngle * $angleMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 11 through 15 {
|
||||
&[data-face="#{$i}"] {
|
||||
$angleMultiplier: $i - 8;
|
||||
transform: rotateX(-$ringAngle) rotateY(-$sideAngle * $angleMultiplier - $sideAngle/2);
|
||||
}
|
||||
}
|
||||
|
||||
.face {
|
||||
$horizontalMargin: -$faceWidth*0.5;
|
||||
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
margin: 0 $horizontalMargin;
|
||||
border-left: $faceWidth*0.5 solid transparent;
|
||||
border-right: $faceWidth*0.5 solid transparent;
|
||||
border-bottom: $faceHeight solid $color;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
transform-style: preserve-3d;
|
||||
backface-visibility: hidden;
|
||||
|
||||
counter-increment: steps 1;
|
||||
|
||||
&:before {
|
||||
content: counter(steps);
|
||||
position: absolute;
|
||||
top: $faceHeight*0.25;
|
||||
left: -$faceWidth;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px 3px #000;
|
||||
font-size: $faceHeight*0.5;
|
||||
text-align: center;
|
||||
line-height: $faceHeight*0.9;
|
||||
width: $faceWidth*2;
|
||||
height: $faceHeight;
|
||||
}
|
||||
|
||||
@for $i from 1 through 5 {
|
||||
&:nth-child(#{$i}) {
|
||||
$angleMultiplier: $i - 1;
|
||||
transform: rotateY(-$sideAngle * $angleMultiplier) translateZ($translateZ) translateY($translateY) rotateX($angle);
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 16 through 20 {
|
||||
&:nth-child(#{$i}) {
|
||||
$angleMultiplier: $i - 18;
|
||||
transform: rotateY($sideAngle * $angleMultiplier + $sideAngle/2) translateZ($translateLowerZ) translateY($translateLowerY) rotateZ(180deg) rotateX($angle);
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 6 through 10 {
|
||||
&:nth-child(#{$i}) {
|
||||
$angleMultiplier: $i - 11;
|
||||
transform: rotateY(-$sideAngle * $angleMultiplier) translateZ($translateRingZ) translateY($translateRingY) rotateZ(180deg) rotateX($ringAngle);
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 11 through 15 {
|
||||
&:nth-child(#{$i}) {
|
||||
$angleMultiplier: $i - 8;
|
||||
transform: rotateY($sideAngle * $angleMultiplier + $sideAngle/2) translateZ($translateRingZ) translateY($translateRingY) rotateX($ringAngle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #fafafa;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
> li {
|
||||
display: inline-block;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
padding: 5px 15px;
|
||||
width: 40px;
|
||||
display: inline-block;
|
||||
border: 1px solid #dcdcdc;
|
||||
border-radius: 4px;
|
||||
background-color: #999;
|
||||
|
||||
&.active {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
&.randomize {
|
||||
width: auto;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# 3D Dashboard - Spline
|
||||
|
||||
A Pen created on CodePen.io. Original URL: [https://codepen.io/ricardoolivaalonso/pen/abmqrxY](https://codepen.io/ricardoolivaalonso/pen/abmqrxY).
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CodePen - 3D Dashboard - Spline</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- partial:index.partial.html -->
|
||||
<iframe src='https://my.spline.design/dashboard-c2284376c0356ff330e8e6ae686e1ba0/' frameborder='0'></iframe>
|
||||
<!-- partial -->
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
body,
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2021 by Ricardo Oliva Alonso (https://codepen.io/ricardoolivaalonso/pen/abmqrxY)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue