Sandbox
drcmda
/
Basic-Threejs-example-with-re-use
A
index.js - nodebox - CodeSandbox
    • 1

    Explorer

      Drag a view here to display.

      Sandbox Info

        nodebox

        public
        src
        index.js
        styles.css
        .prettierrc
        package.json

        Dependencies

          three
          0.127.0

          Outline

          Show All Commands
          Ctrl+Shift+P
          Go to File
          Ctrl+P
          Find in Files
          Ctrl+Shift+F
          Toggle Full Screen
          F11
          Show Settings
          Ctrl+,
          index.js
          src
          index.js
          Cube
          render
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          65
          66
          67
          68
          69
          70
          71
          72
          73
          74
          75
          76
          77
          78
          79
          80
          81
          82
          83
          84
          85
          86
          87
          88
          89
          90
          91
          92
          93
          94
          95
          96
          97
          98
          99
          100
          101
          102
          103
          104
          105
          106
          107
          108
          109
          110
          111
          112
          113
          114
          115
          116
          117
          118
          119
          120
          121
          122
          123
          124
          125
          126
          127
          128
          129
          130
          131
          132
          133
          134
          import * as THREE from 'three'
          import './styles.css'
          class Cube extends THREE.Mesh {
            constructor() {
              super()
              this.geometry = new THREE.BoxGeometry()
              this.material = new THREE.MeshStandardMaterial({ color: new THREE.Color('orange').convertSRGBToLinear() })
              this.cubeSize = 0
              this.cubeActive = false
            }
            render() {
              this.rotation.x = this.rotation.y += 0.01
            }
            onResize(width, height, aspect) {
              this.cubeSize = width / 5 // 1/5 of the full width
              this.scale.setScalar(this.cubeSize * (this.cubeActive ? 1.5 : 1))
            }
            onPointerOver(e) {
              this.material.color.set('hotpink')
              this.material.color.convertSRGBToLinear()
            }
            onPointerOut(e) {
              this.material.color.set('orange')
              this.material.color.convertSRGBToLinear()
            }
            onClick(e) {
              this.cubeActive = !this.cubeActive
              this.scale.setScalar(this.cubeSize * (this.cubeActive ? 1.5 : 1))
            }
          }
          // state
          let width = 0
          let height = 0
          let intersects = []
          let hovered = {}
          // setup
          const scene = new THREE.Scene()
          const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
          camera.position.z = 5
          const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
          renderer.setPixelRatio(Math.min(Math.max(1, window.devicePixelRatio), 2))
          renderer.toneMapping = THREE.ACESFilmicToneMapping
          renderer.outputEncoding = THREE.sRGBEncoding
          document.getElementById('root').appendChild(renderer.domElement)
          const raycaster = new THREE.Raycaster()
          const mouse = new THREE.Vector2()
          // view
          const cube1 = new Cube()
          cube1.position.set(-1.5, 0, 0)
          const cube2 = new Cube()
          cube2.position.set(1.5, 0, 0)
          scene.add(cube1)
          scene.add(cube2)
          const ambientLight = new THREE.AmbientLight()
          const pointLight = new THREE.PointLight()
          pointLight.position.set(10, 10, 10)
          scene.add(ambientLight)
          scene.add(pointLight)
          // responsive
          function resize() {
            width = window.innerWidth
            height = window.innerHeight
            camera.aspect = width / height
            const target = new THREE.Vector3(0, 0, 0)
            const distance = camera.position.distanceTo(target)
            const fov = (camera.fov * Math.PI) / 180
            const viewportHeight = 2 * Math.tan(fov / 2) * distance
            const viewportWidth = viewportHeight * (width / height)
            camera.updateProjectionMatrix()
            renderer.setSize(width, height)
            scene.traverse((obj) => {
              if (obj.onResize) obj.onResize(viewportWidth, viewportHeight, camera.aspect)
            })
          }
          window.addEventListener('resize', resize)
          resize()
          // events
          window.addEventListener('pointermove', (e) => {
            mouse.set((e.clientX / width) * 2 - 1, -(e.clientY / height) * 2 + 1)
            raycaster.setFromCamera(mouse, camera)
            intersects = raycaster.intersectObjects(scene.children, true)
            // If a previously hovered item is not among the hits we must call onPointerOut
            Object.keys(hovered).forEach((key) => {
              const hit = intersects.find((hit) => hit.object.uuid === key)
              if (hit === undefined) {
                const hoveredItem = hovered[key]
                if (hoveredItem.object.onPointerOver) hoveredItem.object.onPointerOut(hoveredItem)
                delete hovered[key]
              }
            })
            intersects.forEach((hit) => {
              // If a hit has not been flagged as hovered we must call onPointerOver
              if (!hovered[hit.object.uuid]) {
                hovered[hit.object.uuid] = hit
                if (hit.object.onPointerOver) hit.object.onPointerOver(hit)
              }
              // Call onPointerMove
              if (hit.object.onPointerMove) hit.object.onPointerMove(hit)
            })
          })
          window.addEventListener('click', (e) => {
            intersects.forEach((hit) => {
              // Call onClick
              if (hit.object.onClick) hit.object.onClick(hit)
            })
          })
          // render-loop, called 60-times/second
          function animate(t) {
            requestAnimationFrame(animate)
            scene.traverse((obj) => {
              if (obj.render) obj.render(t)
            })
            renderer.render(scene, camera)
          }
          animate()
          Press desired key combination and then press ENTER.
          Show All Commands
          Ctrl+Shift+P
          Go to File
          Ctrl+P
          Find in Files
          Ctrl+Shift+F
          Toggle Full Screen
          F11
          Show Settings
          Ctrl+,
          Preview

              Drag a view here to display.

                  Drag a view here to display.
                  CodeSandbox - Sandbox (Web)
                  0 0
                  1
                  Prettier
                  Layout: US
                  JavaScript JSX
                  LF
                  UTF-8
                  Spaces: 2
                  Ln 13, Col 13
                  Open preview

                  🍪 Yes, we use cookies

                  This website utilizes cookies to enable essential site functionality and analytics. You may change your settings at any time or accept the default settings. You may close this banner to continue with only essential cookies.
                  Read more about this in our privacy and cookie statement.