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