WEBLEB
होम
संपादक
लॉग इन करें
Pro
हिंदी
English
Français
Español
Português
Deutsch
Italiano
हिंदी
फोटो फाड़
899
Andev.web
संपादक में खोलें
अपना कोड प्रकाशित करें
क्या आपको एक वेबसाइट चाहिए?
अनुशंसित
30 November 2024
क्रिएटिव फोटोग्राफी शोकेस स्लाइडर | स्वाइपर स्लाइडर
13 November 2024
छवियों के लिए 3D CSS फोटो फ्रेम प्रभाव
8 September 2024
फोटो संपादक यूआई
HTML
Copy
Andev Web
CSS
Copy
html, body { width: 100%; min-height: 100%; margin: 0; background: #17181D; padding: 0; position: relative; overflow: hidden; } body { position: relative; -ms-scroll-chaining: none; overscroll-behavior: contain; } body.zoomed, body.loading { overflow: hidden; } .page { z-index: 3; position: relative; margin: 0; } .page.under { z-index: 1; position: absolute; top: 0; left: 0; } canvas { position: fixed; top: 0; left: 0; z-index: 2; cursor: -webkit-grab; cursor: grab; } .info { position: fixed; top: 0; left: 0; display: flex; justify-content: center; align-items: center; z-index: 200; pointer-events: none; right: 0; bottom: 0; } .info svg { opacity: 0; width: clamp(50px, 5vw, 120px); height: clamp(50px, 5vw, 120px); transform: translateX(150%); }
JS
Copy
console.clear(); import * as THREE from 'https://cdn.skypack.dev/three@0.125.0'; import gsap from "https://cdn.skypack.dev/gsap@3.5.1"; const BackgroundGradient = (colorA, colorB) => { var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry(2, 2, 1, 1), new THREE.ShaderMaterial({ uniforms: { uColorA: { value: new THREE.Color(colorA) }, uColorB: { value: new THREE.Color(colorB) } }, vertexShader: ` varying vec2 vUv; void main(){ vUv = uv; float depth = -1.; //or maybe 1. you can experiment gl_Position = vec4(position.xy, depth, 1.); } `, fragmentShader: ` varying vec2 vUv; uniform vec3 uColorA; uniform vec3 uColorB; void main(){ gl_FragColor = vec4( mix( uColorA, uColorB, vec3(vUv.y)), 1. ); } ` })); mesh.material.depthWrite = false; mesh.renderOrder = -99999; return mesh; }; class Stage { constructor(domCanvasElement, topColor, bottomColor) { this.canvas = domCanvasElement; this.scene = new THREE.Scene(); this.sizes = { width: 0, height: 0 }; /** * Background Gradient */ this.background = BackgroundGradient(bottomColor, topColor); this.scene.add(this.background); /** * Camera */ this.camera = new THREE.PerspectiveCamera(30, this.sizes.width / this.sizes.height, 0.1, 100); this.camera.position.set(0, 0, 6); this.scene.add(this.camera); /** * Camera Group */ this.cameraGroup = new THREE.Group(); this.scene.add(this.cameraGroup); /** * Renderer */ const renderer = new THREE.WebGLRenderer({ canvas: this.canvas, antialias: window.devicePixelRatio === 1 ? true : false }); renderer.physicallyCorrectLights = true; renderer.outputEncoding = THREE.sRGBEncoding; renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1; this.renderer = renderer; window.addEventListener('resize', () => {this.onResize();}); this.onResize(); } onResize() { // Update sizes this.sizes.width = window.innerWidth; this.sizes.height = window.innerHeight; if (this.sizes.width < 800) this.camera.position.z = 10;else this.camera.position.z = 6; // Update camera this.camera.aspect = this.sizes.width / this.sizes.height; this.camera.updateProjectionMatrix(); // Update renderer this.renderer.setSize(this.sizes.width, this.sizes.height); this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); } add(item) { this.scene.add(item); } cameraAdd(item) { this.cameraGroup.add(item); } render(elapsedTime) { this.cameraGroup.position.copy(this.camera.position); this.cameraGroup.rotation.copy(this.camera.rotation); this.renderer.render(this.scene, this.camera); }} class Loader { constructor(color = 'black', shadow = "white", size = 1) { this.mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry(2, 2, 1, 1), new THREE.ShaderMaterial({ uniforms: { uColor: { value: new THREE.Color(color) }, uColorShadow: { value: new THREE.Color(shadow) }, uProgress: { value: 0 }, uAlpha: { value: 1 }, uNoiseSize: { value: size } }, vertexShader: ` void main(){ gl_Position = vec4(position.xy, 0.5, 1.); } `, fragmentShader: ` uniform vec3 uColor; uniform float uAlpha; void main () { gl_FragColor = vec4(uColor, uAlpha); } `, transparent: true, depthTest: false })); } get progress() { return this.mesh.material.uniforms.uProgress.value; } set progress(newValue) { this.mesh.material.uniforms.uProgress.value = newValue; } get alpha() { return this.mesh.material.uniforms.uAlpha.value; } set alpha(newValue) { this.mesh.material.uniforms.uAlpha.value = newValue; } get noiseSize() { return this.mesh.material.uniforms.uNoiseSize.value; } set noiseSize(newValue) { this.mesh.material.uniforms.uNoiseSize.value = newValue; }} const ripVertexShader = ` uniform float uTearAmount; uniform float uTearWidth; uniform float uTearXAngle; uniform float uTearYAngle; uniform float uTearZAngle; uniform float uTearXOffset; uniform float uXDirection; uniform float uRipSide; uniform float uRipSeed; varying vec2 vUv; varying float vAmount; mat4 rotationX( in float angle ) { return mat4( 1.0, 0, 0, 0, 0, cos(angle), -sin(angle), 0, 0, sin(angle), cos(angle), 0, 0, 0, 0, 1); } mat4 rotationY( in float angle ) { return mat4( cos(angle), 0, sin(angle), 0, 0, 1.0, 0, 0, -sin(angle), 0, cos(angle), 0, 0, 0, 0, 1); } mat4 rotationZ( in float angle ) { return mat4( cos(angle), -sin(angle), 0, 0, sin(angle), cos(angle), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); } void main(){ float ripAmount = 0.0; float yAmount = max(0.0, (uTearAmount - (1.0 - uv.y))); float zRotate = uTearZAngle * yAmount; float xRotate = uTearXAngle * yAmount; float yRotate = uTearYAngle * yAmount; vec3 rotation = vec3(xRotate* yAmount, yRotate* yAmount, zRotate* yAmount); float halfHeight = float(HEIGHT) * 0.5; float halfWidth = (float(WIDTH) - uTearWidth * 0.5) * 0.5; vec4 vertex = vec4(position.x + (halfWidth * uXDirection) - halfWidth, position.y + halfHeight, position.z, 1.0); vertex = vertex * rotationY(rotation.y ) * rotationX(rotation.x ) * rotationZ(rotation.z ); vertex.x += uTearXOffset * yAmount + ripAmount + halfWidth ; vertex.y -= halfHeight; vec4 modelPosition = modelMatrix * vertex; vec4 viewPosition = viewMatrix * modelPosition; vec4 projectedPosition = projectionMatrix * viewPosition; gl_Position = projectedPosition; vUv = uv; vAmount = yAmount; } `; const ripFragmentShader = ` uniform sampler2D uMap; uniform sampler2D uRip; uniform sampler2D uBorder; uniform vec3 uShadeColor; uniform float uUvOffset; uniform float uRipSide; uniform float uTearXAngle; uniform float uShadeAmount; uniform float uTearWidth; uniform float uWhiteThreshold; uniform float uTearOffset; varying vec2 vUv; varying float vAmount; void main () { bool rightSide = uRipSide == 1.0; float ripAmount = -1.0; float width = float(WIDTH); float widthOverlap = (uTearWidth * 0.5) + width; bool frontSheet = uTearXAngle > 0.0; float xScale = widthOverlap / float(FULL_WIDTH); vec2 uvOffset = vec2(vUv.x * xScale + uUvOffset, vUv.y); vec4 textureColor = texture2D(uMap, uvOffset); vec4 borderColor = texture2D(uBorder, uvOffset); if(borderColor.r > 0.0) textureColor = vec4(vec3(0.95), 1.0); float ripRange = uTearWidth / widthOverlap; float ripStart = rightSide ? 0.0 : 1.0 - ripRange; float alpha = 1.0; float ripX = (vUv.x - ripStart) / ripRange; float ripY = vUv.y * 0.5 + (0.5 * uTearOffset); vec4 ripCut = texture2D(uRip, vec2(ripX, ripY)); vec4 ripColor = texture2D(uRip, vec2(ripX * 0.9, ripY - 0.02)); float whiteness = dot(vec4(1.0), ripCut) / 4.0; if (!rightSide && whiteness <= uWhiteThreshold) { whiteness = dot(vec4(1.0), ripColor) / 4.0; if(whiteness >= uWhiteThreshold) textureColor = ripColor; else alpha = 0.0; } if (rightSide && whiteness >= uWhiteThreshold) alpha = 0.0; gl_FragColor = mix(vec4(textureColor.rgb, alpha), vec4(uShadeColor, alpha), vAmount * uShadeAmount); } `; class Photo { constructor(textures, destoryCallback) { this.destroyCallback = destoryCallback; this.photoTexture = textures.photo; this.borderTexture = textures.border; this.ripTexture = textures.rip; this.interactive = false; this.group = new THREE.Group(); this.group.rotation.z = (Math.random() * 2 - 1) * Math.PI; this.group.position.y = 10; setTimeout(() => { this.interactive = true; }, 400); const introAnimation = gsap.timeline({ delay: 0.3, defaults: { duration: 0.8, ease: 'power3.out' } }); introAnimation.to(this.group.rotation, { z: 0 }, 0); introAnimation.to(this.group.position, { y: 0 }, 0); const width = 3; const tearWidth = 0.4; this.sheetSettings = { widthSegments: 30, heightSegments: 50, tearOffset: Math.random(), width: width, height: 2, tearAmount: 0, tearWidth: tearWidth, ripWhiteThreshold: 0.7, left: { uvOffset: 0, ripSide: 0, tearXAngle: -0.01, tearYAngle: -0.1, tearZAngle: 0.05, tearXOffset: 0, direction: -1, shadeColor: new THREE.Color('white'), shadeAmount: 0.2 }, right: { uvOffset: (width - tearWidth) / width * 0.5, ripSide: 1, tearXAngle: 0.2, tearYAngle: 0.1, tearZAngle: -0.1, tearXOffset: 0, direction: 1, shadeColor: new THREE.Color('black'), shadeAmount: 0.4 } }; this.sides = [ { id: 'left', mesh: null, material: null }, { id: 'right', mesh: null, material: null }]; this.sheetPlane = new THREE.PlaneBufferGeometry(this.sheetSettings.width / 2 + this.sheetSettings.tearWidth / 2, this.sheetSettings.height, this.sheetSettings.widthSegments, this.sheetSettings.heightSegments); this.sides.forEach((side) => { side.material = this.getRipMaterial(side.id); side.mesh = new THREE.Mesh(this.sheetPlane, side.material); if (this.sheetSettings[side.id].tearXAngle > 0) { side.mesh.position.z += 0.0001; } this.group.add(side.mesh); }); } getRipMaterial(side) { const material = new THREE.ShaderMaterial({ defines: { HEIGHT: this.sheetSettings.height, WIDTH: this.sheetSettings.width / 2, FULL_WIDTH: this.sheetSettings.width, HEIGHT_SEGMENTS: this.sheetSettings.heightSegments, WIDTH_SEGMENTS: this.sheetSettings.widthSegments }, uniforms: { uMap: { value: this.photoTexture }, uRip: { value: this.ripTexture }, uBorder: { value: this.borderTexture }, uRipSide: { value: this.sheetSettings[side].ripSide }, uTearWidth: { value: this.sheetSettings.tearWidth }, uWhiteThreshold: { value: this.sheetSettings.ripWhiteThreshold }, uTearAmount: { value: this.sheetSettings.tearAmount }, uTearOffset: { value: this.sheetSettings.tearOffset }, uUvOffset: { value: this.sheetSettings[side].uvOffset }, uTearXAngle: { value: this.sheetSettings[side].tearXAngle }, uTearYAngle: { value: this.sheetSettings[side].tearYAngle }, uTearZAngle: { value: this.sheetSettings[side].tearZAngle }, uTearXOffset: { value: this.sheetSettings[side].tearXOffset }, uXDirection: { value: this.sheetSettings[side].direction }, uShadeColor: { value: this.sheetSettings[side].shadeColor }, uShadeAmount: { value: this.sheetSettings[side].shadeAmount } }, transparent: true, vertexShader: ripVertexShader, fragmentShader: ripFragmentShader }); return material; } shouldCompleteRip() { return this.sheetSettings.tearAmount >= 1.5; } updateUniforms() { if (this.interactive && this.shouldCompleteRip()) { this.remove(); } else { if (this.sheetSettings.tearAmount === 0) this.sheetSettings.tearOffset = Math.random(); this.sides.forEach((side) => { const uniforms = side.mesh.material.uniforms; uniforms.uTearAmount.value = this.sheetSettings.tearAmount; uniforms.uTearOffset.value = this.sheetSettings.tearOffset; uniforms.uUvOffset.value = this.sheetSettings[side.id].uvOffset; uniforms.uTearXAngle.value = this.sheetSettings[side.id].tearXAngle; uniforms.uTearYAngle.value = this.sheetSettings[side.id].tearYAngle; uniforms.uTearZAngle.value = this.sheetSettings[side.id].tearZAngle; uniforms.uTearXOffset.value = this.sheetSettings[side.id].tearXOffset; uniforms.uXDirection.value = this.sheetSettings[side.id].direction; uniforms.uShadeColor.value = this.sheetSettings[side.id].shadeColor; uniforms.uShadeAmount.value = this.sheetSettings[side.id].shadeAmount; uniforms.uWhiteThreshold.value = this.sheetSettings.ripWhiteThreshold; }); } } completeRip() { if (this.sheetSettings.tearAmount >= 1.15) this.remove();else this.reset(); } reset() { gsap.to(this.sheetSettings, { tearAmount: 0, onUpdate: () => this.updateUniforms() }); } remove() { this.interactive = false; this.destroyCallback(); const removeAnimation = gsap.timeline({ defaults: { duration: 1, ease: 'power2.in' }, onComplete: () => this.destroyMe() }); removeAnimation.to(this.sheetSettings, { tearAmount: 1.5 + Math.random() * 1.5, ease: 'power2.out', onUpdate: () => this.updateUniforms() }); removeAnimation.to(this.group.position, { z: 1 }, 0); this.sides.forEach((side) => { removeAnimation.to(side.mesh.position, { y: -3 + Math.random() * -3, x: (2 + Math.random() * 3) * (this.sheetSettings[side.id].ripSide - 0.5) }, 0); removeAnimation.to(side.mesh.rotation, { z: (-2 + Math.random() * -3) * (this.sheetSettings[side.id].ripSide - 0.5) }, 0); }); } destroyMe() { this.sheetPlane.dispose(); this.sides.forEach((side) => { side.material.dispose(); this.group.remove(side.mesh); }); }} let interacted = false; /** * Stage */ const canvas = document.querySelector('canvas.webgl'); const stage = new Stage(canvas, '#F1EBE4', '#D5C3AE'); /** * Loaders */ const loaderScreen = new Loader('black'); stage.add(loaderScreen.mesh); const loadingManager = new THREE.LoadingManager( () => { const tl = gsap.timeline(); tl.to(loaderScreen, { progress: 1, alpha: 0, duration: .5, ease: 'power4.inOut' }, 0); init(); }); const textureLoader = new THREE.TextureLoader(loadingManager); /** * Lights */ let envLight = new THREE.AmbientLight({ color: 'white', intensity: 6 }); stage.add(envLight); let pointLight = new THREE.PointLight({ color: 'white', intensity: 20 }); pointLight.position.z = -1; stage.add(pointLight); /** * Materials */ const images = [ { texture: textureLoader.load('https://images.unsplash.com/photo-1544027993-37dbfe43562a?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), colors: [[192, 208, 220], [217, 190, 174]] }, { texture: textureLoader.load('https://images.unsplash.com/photo-1521839745427-1f25030b3a46?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), colors: [[168, 163, 150], [218, 180, 141]] }]; let currentImage = -1; const textureRip = textureLoader.load('https://assets.codepen.io/557388/rip.jpg'); const textureBorder = textureLoader.load('https://assets.codepen.io/557388/border.png'); /** * Paper */ const photos = []; const mouseStart = new THREE.Vector2(); let mouseDown = false; const extraImages = [ { file: 'https://images.unsplash.com/photo-1554384032-56ff486b6cd4?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', colors: [[208, 229, 224], [209, 209, 220]] }, { file: 'https://images.unsplash.com/photo-1520261456177-6ec5aac5dbd2?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', colors: [[191, 192, 184], [217, 200, 170]] }, { file: 'https://assets.codepen.io/557388/photo-6.jpg', colors: [[217, 226, 233], [216, 220, 203]] }, { file: 'https://assets.codepen.io/557388/photo-7.jpg', colors: [[206, 221, 226], [219, 213, 222]] }, { file: 'https://assets.codepen.io/557388/photo-5.jpg', colors: [[199, 199, 210], [218, 203, 195]] }]; const postInitTextureLoader = new THREE.TextureLoader(); const getMousePos = (x, y) => { return { x: x / stage.sizes.width * 2 - 1, y: -(y / stage.sizes.height) * 2 + 1 }; }; const down = (x, y) => { if (photos.length && photos[0].interactive) { interacted = true; hideHand(); let pos = getMousePos(x, y); mouseStart.x = pos.x; mouseStart.y = pos.y; mouseDown = true; } }; const move = (x, y) => { if (mouseDown && photos.length && photos[0].interactive) { let pos = getMousePos(x, y); let distanceY = mouseStart.y - pos.y; photos[0].sheetSettings.tearAmount = Math.max(2 * distanceY, 0); photos[0].updateUniforms(); } }; const up = () => { if (mouseDown && photos.length && photos[0].interactive) { mouseDown = false; photos[0].completeRip(); } }; const loadExtraPhoto = () => { const nextImage = extraImages.shift(); images.push({ texture: postInitTextureLoader.load(nextImage.file), colors: nextImage.colors }); }; const addNewPhoto = () => { currentImage++; if (currentImage >= images.length) currentImage = 0; if (images.length - currentImage < 2 && extraImages.length) loadExtraPhoto(); mouseDown = false; const nextImage = images[currentImage]; let photo = new Photo( { photo: nextImage.texture, rip: textureRip, border: textureBorder }, () => addNewPhoto()); photos.unshift(photo); stage.add(photo.group); gsap.to(stage.background.material.uniforms.uColorB.value, { r: nextImage.colors[0][0] / 255, g: nextImage.colors[0][1] / 255, b: nextImage.colors[0][2] / 255, ease: 'power4.inOut', duration: 1 }); gsap.to(stage.background.material.uniforms.uColorA.value, { r: nextImage.colors[1][0] / 255, g: nextImage.colors[1][1] / 255, b: nextImage.colors[1][2] / 255, ease: 'power4.inOut', duration: 1 }); }; const init = () => { addNewPhoto(); window.addEventListener('mousedown', event => down(event.clientX, event.clientY)); window.addEventListener('touchstart', event => down(event.touches[0].clientX, event.touches[0].clientY)); window.addEventListener('mousemove', event => move(event.clientX, event.clientY)); window.addEventListener('touchmove', event => move(event.touches[0].clientX, event.touches[0].clientY)); window.addEventListener('mouseup', up); window.addEventListener('touchend', up); }; /** * Tick */ const clock = new THREE.Clock(); const tick = () => { const elapsedTime = clock.getElapsedTime(); stage.render(elapsedTime); window.requestAnimationFrame(tick); }; tick(); const hand = document.getElementById('hand'); const downDuration = 2; const upDuration = 0.7; const hintAnimation = gsap.timeline({ repeat: -1, defaults: { duration: downDuration, ease: 'power4.inOut' } }); hintAnimation.fromTo(hand, { y: '-100%' }, { y: '100%' }); hintAnimation.to(hand, { y: '-100%', duration: upDuration, motionPath: [{ rotate: '-10' }, { rotate: '0' }] }, downDuration); hintAnimation.to(hand, { rotate: '-25', scale: 1.1, duration: upDuration * 0.5, ease: 'power4.in' }, downDuration); hintAnimation.to(hand, { rotate: '0', scale: 1, duration: upDuration * 0.5, ease: 'power4.out' }, downDuration + upDuration * 0.5); hintAnimation.pause(); const showHand = () => { if (!interacted) { hintAnimation.play(); gsap.to(hand, { opacity: 1 }); } }; const hideHand = () => { gsap.to(hand, { opacity: 0, onComplete: () => hintAnimation.pause() }); }; setTimeout(() => showHand(), 5000);