This commit is contained in:
Dym Sohin 2023-10-06 23:12:53 +02:00
commit f132183c1d
4074 changed files with 598712 additions and 0 deletions

View File

@ -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).

17
017-erosion/dist/index.html vendored Normal file
View File

@ -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>

364
017-erosion/dist/script.js vendored Normal file
View File

@ -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();
});
})();

8
017-erosion/license.txt Normal file
View File

@ -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.

View File

View File

@ -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();
});
})();

View File

@ -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).

18
1-codevember-2017galaxy/dist/index.html vendored Normal file
View File

@ -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>

139
1-codevember-2017galaxy/dist/script.js vendored Normal file
View File

@ -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);

View File

@ -0,0 +1,4 @@
body {
margin: 0;
overflow: hidden;
}

View File

@ -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.

View File

@ -0,0 +1 @@
<canvas></canvas>

View File

@ -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);

View File

@ -0,0 +1,4 @@
body {
margin: 0;
overflow: hidden;
}

View File

@ -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).

55
1-element-css-spinners/dist/index.html vendored Normal file
View File

@ -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>

310
1-element-css-spinners/dist/style.css vendored Normal file
View File

@ -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);
}
}

View File

@ -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.
-->

View File

@ -0,0 +1,5 @@
- var totSpinners = 8
- for (var i = 1; i <= totSpinners; i++)
.cell
.wrapper
div( class="spinner spinner" + i)

View File

@ -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);
}
}

View File

@ -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!

View File

@ -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>

244
10-000-codepen-followers/dist/script.js vendored Normal file
View File

@ -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'
})

23
10-000-codepen-followers/dist/style.css vendored Normal file
View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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'
})

View File

@ -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;
}

View File

@ -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).

17
10print-svg/dist/index.html vendored Normal file
View File

@ -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>

42
10print-svg/dist/script.js vendored Normal file
View File

@ -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;
}

26
10print-svg/dist/style.css vendored Normal file
View File

@ -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;
}

8
10print-svg/license.txt Normal file
View File

@ -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.

View File

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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).

View File

@ -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>

View File

@ -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();
};
};

View File

@ -0,0 +1,5 @@
* {
padding: 0;
margin: 0;
overflow: hidden;
}

View File

@ -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.

View File

@ -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();
};
};

View File

@ -0,0 +1,5 @@
* {
padding: 0;
margin: 0;
overflow: hidden;
}

8
20/README.markdown Normal file
View File

@ -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)

17
20/dist/index.html vendored Normal file
View File

@ -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>

156
20/dist/script.js vendored Normal file
View File

@ -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;
}

3
20/dist/style.css vendored Normal file
View File

@ -0,0 +1,3 @@
canvas {
display:block; width:100%; height:100vh;
}

8
20/license.txt Normal file
View File

@ -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
20/src/index.html Normal file
View File

156
20/src/script.js Normal file
View File

@ -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;
}

3
20/src/style.css Normal file
View File

@ -0,0 +1,3 @@
canvas {
display:block; width:100%; height:100vh;
}

View File

@ -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).

49
2021-to-2022/dist/index.html vendored Normal file
View File

@ -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>

145
2021-to-2022/dist/style.css vendored Normal file
View File

@ -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); }

8
2021-to-2022/license.txt Normal file
View File

@ -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.

View File

@ -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>

145
2021-to-2022/src/style.css Normal file
View File

@ -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); }

7
31-taint/README.markdown Normal file
View File

@ -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)

17
31-taint/dist/index.html vendored Normal file
View File

@ -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>

134
31-taint/dist/script.js vendored Normal file
View File

@ -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();
});

3
31-taint/dist/style.css vendored Normal file
View File

@ -0,0 +1,3 @@
canvas {
display:block; width:100%; height:100vh; cursor: -webkit-grab; cursor: grab;
}

8
31-taint/license.txt Normal file
View File

@ -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
31-taint/src/index.html Normal file
View File

134
31-taint/src/script.js Normal file
View File

@ -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();
});

3
31-taint/src/style.css Normal file
View File

@ -0,0 +1,3 @@
canvas {
display:block; width:100%; height:100vh; cursor: grab;
}

View File

@ -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.

View File

@ -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>

View File

@ -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();
};

View File

@ -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;
}

View File

@ -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.

View File

@ -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>

View File

@ -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();
};

View File

@ -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;
}

View File

@ -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).

View File

@ -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>

View File

@ -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));

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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")

View File

@ -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)
)

View File

@ -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)

View File

@ -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...

45
3d-css-sphere/dist/index.html vendored Normal file
View File

@ -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>

162
3d-css-sphere/dist/style.css vendored Normal file
View File

@ -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;
}

View File

@ -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.

View File

@ -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>

162
3d-css-sphere/src/style.css Normal file
View File

@ -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;
}

View File

@ -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.

View File

@ -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>

46
3d-d20-die-with-pure-css/dist/script.js vendored Normal file
View File

@ -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
})

302
3d-d20-die-with-pure-css/dist/style.css vendored Normal file
View File

@ -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;
}

View File

@ -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.
-->

View File

@ -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>

View File

@ -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
})

View File

@ -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;
}
}

View File

@ -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).

16
3d-dashboardspline/dist/index.html vendored Normal file
View File

@ -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>

5
3d-dashboardspline/dist/style.css vendored Normal file
View File

@ -0,0 +1,5 @@
body,
iframe {
width: 100%;
height: 100vh;
}

View File

@ -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