three+gsap实现滚动鼠标三维包装箱子折叠效果代码
代码语言:html
所属分类:三维
代码描述:three+gsap实现滚动鼠标三维包装箱子折叠效果代码
代码标签: three gsap 滚动 鼠标 三维 包装箱 折叠
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> body { padding: 0; margin: 0; } .page { width: 100%; height: 200vh; } .container { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; } .container .ui-controls { position: absolute; top: 70%; left: 80%; transform: translateX(-100%); user-select: none; font-family: sans-serif; text-align: end; min-width: 200px; } .container button { display: inline-block; text-align: center; font-size: 20px; min-width: 25px; min-height: 25px; margin-bottom: 1em; margin-right: .2em; padding: 0; cursor: pointer; } .container .ui-controls { position: absolute; top: 70%; left: 85%; user-select: none; font-family: sans-serif; text-align: end; } .container button { font-size: 15px; width: 25px; height: 25px; margin-bottom: 1em; margin-right: .2em; cursor: pointer; } .container button.disabled { pointer-events: none; cursor: auto; opacity: .3; } </style> </head> <body translate="no" > <!-- // FULL TUTORIAL: // // https://tympanus.net/codrops/2022/12/13/how-to-code-an-on-scroll-folding-3d-cardboard-box-animation-with-three-js-and-gsap/ // --> <div class="page"> <div class="container"> <canvas id="box-canvas"></canvas> <div class="ui-controls"> <button id="zoom-in">+</button> <button id="zoom-out">-</button> <div>Scroll ⬇ To Animate</div> </div> </div> </div> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/gsap.3.10.1.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/ScrollTrigger.3.10.4.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/ScrollToPlugin3.min.js"></script> <script type="module"> import * as THREE from '//repo.bfw.wiki/bfwrepo/js/module/three/build/three.module.js'; import { OrbitControls } from '//repo.bfw.wiki/bfwrepo/js/module/three/examples/jsm/controls/OrbitControls.js'; import { mergeBufferGeometries } from '//repo.bfw.wiki/bfwrepo/js/module/three/examples/jsm/utils/BufferGeometryUtils.js'; import { GUI } from '//repo.bfw.wiki/bfwrepo/js/lil-gui.esm.js'; const container = document.querySelector('.container'); const boxCanvas = document.querySelector('#box-canvas'); let box = { params: { width: 27, widthLimits: [15, 70], length: 80, lengthLimits: [70, 120], depth: 45, depthLimits: [15, 70], thickness: .6, thicknessLimits: [.1, 1], fluteFreq: 5, fluteFreqLimits: [3, 7], flapGap: 1, copyrightSize: [15, 5] }, els: { group: new THREE.Group(), backHalf: { width: { top: new THREE.Mesh(), side: new THREE.Mesh(), bottom: new THREE.Mesh() }, length: { top: new THREE.Mesh(), side: new THREE.Mesh(), bottom: new THREE.Mesh() } }, frontHalf: { width: { top: new THREE.Mesh(), side: new THREE.Mesh(), bottom: new THREE.Mesh() }, length: { top: new THREE.Mesh(), side: new THREE.Mesh(), bottom: new THREE.Mesh() } } }, animated: { openingAngle: .02 * Math.PI, flapAngles: { backHalf: { width: { top: 0, bottom: 0 }, length: { top: 0, bottom: 0 } }, frontHalf: { width: { top: 0, bottom: 0 }, length: { top: 0, bottom: 0 } } } } }; // Globals let renderer, scene, camera, orbit, lightHolder, rayCaster, mouse, copyright; // Run the app initScene(); createControls(); window.addEventListener('resize', updateSceneSize); // run the animation automatically on start window.onbeforeunload = function () { window.scrollTo(0, 0); }; gsap.to(window, { duration: 1.5, scrollTo: window.innerHeight, ease: 'power1.inOut' }); // -------------------------------------------------- // Three.js scene function initScene() { renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true, canvas: boxCanvas }); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 10, 1000); camera.position.set(40, 90, 110); rayCaster = new THREE.Raycaster(); mouse = new THREE.Vector2(0, 0); updateSceneSize(); scene.add(box.els.group); setGeometryHierarchy(); const ambientLight = new THREE.AmbientLight(0xffffff, .5); scene.add(ambientLight); lightHolder = new THREE.Group(); const topLight = new THREE.PointLight(0xffffff, .5); topLight.position.set(-30, 300, 0); lightHolder.add(topLight); const sideLight = new THREE.PointLight(0xffffff, .7); sideLight.position.set(50, 0, 150); lightHolder.add(sideLight); scene.add(lightHolder); scene.add(box.els.group); setGeometryHierarchy(); const material = new THREE.MeshStandardMaterial({ color: new THREE.Color(0x9C8D7B), side: THREE.DoubleSide }); box.els.group.traverse(c => { if (c.isMesh) c.material = material; }); orbit = new OrbitControls(camera, boxCanvas); orbit.enableZoom = false; orbit.enablePan = false; orbit.enableDamping = true; orbit.autoRotate = true; orbit.autoRotateSpeed = .25; createCopyright(); createBoxElements(); createFoldingAnimation(); createZooming(); render(); } function render() { orbit.update(); lightHolder.quaternion.copy(camera.quaternion); renderer.render(scene, camera); requestAnimationFrame(render); } function updateSceneSize() { camera.aspect = container.clientWidth / container.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(container.clientWidth, container.clientHeight); } // End of Three.js scene // -------------------------------------------------- // -------------------------------------------------- // Box geometries function setGeometryHierarchy() { box.els.group.add(box.els.frontHalf.width.side, box.els.frontHalf.length.side, box.els.backHalf.width.side, box.els.backHalf.length.side); box.els.frontHalf.width.side.add(box.els.frontHalf.width.top, box.els.frontHalf.width.bottom); box.els.frontHalf.length.side.add(box.els.frontHalf.length.top, box.els.frontHalf.length.bottom); box.els.backHalf.width.side.add(box.els.backHalf.width.top, box.els.backHalf.width.bottom); box.els.backHalf.length.side.add(box.els.backHalf.length.top, box.els.backHalf.length.bottom); } function createBoxElements() { for (let halfIdx = 0; halfIdx < 2; halfIdx++) { for (let sideIdx = 0; sideIdx < 2; sideIdx++) { const half = halfIdx ? 'frontHalf' : 'backHalf'; const side = sideIdx ? 'width' : 'length'; const sideWidth = side === 'width' ? box.params.width : box.params.length; const flapWidth = sideWidth - 2 * box.params.flapGap; const flapHeight = .5 * box.params.width - .75 * box.params.flapGap; const sidePlaneGeometry = new THREE.PlaneGeometry( sideWidth, box.params.depth, Math.floor(5 * sideWidth), Math.floor(.2 * box.params.depth)); const flapPlaneGeometry = new THREE.PlaneGeometry( flapWidth, flapHeight, Math.floor(5 * flapWidth), Math.floor(.2 * flapHeight)); const sideGeometry = createSideGeometry( sidePlaneGeometry, [sideWidth, box.params.depth], [true, true, true, true], false); const topGeometry = createSideGeometry( flapPlaneGeometry, [flapWidth, flapHeight], [false, false, true, false], true); const bottomGeometry = createSideGeometry( flapPlaneGeometry, [flapWidth, flapHeight], [true, false, false, false], true); topGeometry.translate(0, .5 * flapHeight, 0); bottomGeometry.translate(0, -.5 * flapHeight, 0); box.els[half][side].top.geometry = topGeometry; box.els[half][side].side.geometry = sideGeometry; box.els[half][side].bottom.geometry = bottomGeometry; box.els[half][side].top.position.y = .5 * box.params.depth; box.els[half][side].bottom.position.y = -.5 * box.params.depth; } } updatePanelsTransform(); } function createSideGeometry(baseGeometry, size, folds, hasMiddleLayer) { const geometriesToMerge = []; geometriesToMerge.push(getLayerGeometry((v) => -.5 * box.params.thickness + .01 * Math.sin(box.params.fluteFreq * v))); geometriesToMerge.push(getLayerGeometry((v) => .5 .........完整代码请登录后点击上方下载按钮下载查看
网友评论0