diff --git a/src/containers/Floating/index.js b/src/containers/Floating/index.js index ca4bc84..aeba555 100644 --- a/src/containers/Floating/index.js +++ b/src/containers/Floating/index.js @@ -1,109 +1,93 @@ import './index.styl'; import React from 'react'; -import * as THREE from "three"; -import { FontLoader } from "three/examples/jsm/loaders/FontLoader"; +import * as THREE from 'three'; +import { FontLoader } from 'three/examples/jsm/loaders/FontLoader'; import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry' import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'; import { GlitchPass } from 'three/examples/jsm/postprocessing/GlitchPass.js'; export default class Earth extends React.Component { - componentDidMount() { - this.initThree() - } - state = { backgroundColor: '#164CCA', - // ios 有 bug renderGlithPass: !(window.navigator.userAgent.toLowerCase().indexOf('mobile') > 0) } + componentDidMount() { + this.initThree() + } + initThree = () => { - var canvas, stats, camera, scene, renderer, glitchPass, composer, mouseX = 0, mouseY = 0, _this = this; - const group = new THREE.Group(), textMesh = new THREE.Mesh(), nearDist = 0.1, farDist = 10000; - init(); - animate(); - function init() { - canvas = document.getElementById('canvas'); - renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); - renderer.setPixelRatio(Math.min(2, window.devicePixelRatio)); - renderer.setSize(window.innerWidth, window.innerHeight); - renderer.setClearAlpha(0); - canvas.appendChild(renderer.domElement); + const nearDist = 0.1, farDist = 10000; + const canvas = document.getElementById('canvas'); + const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); + renderer.setPixelRatio(Math.min(2, window.devicePixelRatio)); + renderer.setSize(window.innerWidth, window.innerHeight); + renderer.setClearAlpha(0); + canvas.appendChild(renderer.domElement); - scene = new THREE.Scene(); - scene.fog = new THREE.Fog(0xeeeeee, 0, 100); - camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, nearDist, farDist); - camera.position.set(-2 * farDist, 0, 780); + const scene = new THREE.Scene(); + scene.fog = new THREE.Fog(0xeeeeee, 0, 100); + const camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, nearDist, farDist); + camera.position.set(-2 * farDist, 0, 780); - // 后期 - composer = new EffectComposer(renderer); - composer.addPass( new RenderPass(scene, camera)); - glitchPass = new GlitchPass(); - composer.addPass(glitchPass); + // 后期 + const composer = new EffectComposer(renderer); + composer.addPass( new RenderPass(scene, camera)); + const glitchPass = new GlitchPass(); + composer.addPass(glitchPass); - // 页面缩放 - window.addEventListener('resize', () => { - camera.aspect = window.innerWidth / window.innerHeight; - camera.updateProjectionMatrix(); - renderer.setSize(window.innerWidth, window.innerHeight); - composer.setSize( window.innerWidth, window.innerHeight ); - }, false); + // 页面缩放 + window.addEventListener('resize', () => { + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + renderer.setSize(window.innerWidth, window.innerHeight); + composer.setSize(window.innerWidth, window.innerHeight); + }, false); - // 双击全屏 - window.addEventListener('dblclick', () => { - const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement; - if (!fullscreenElement) { - if (canvas.requestFullscreen) { - canvas.requestFullscreen(); - } else if (canvas.webkitRequestFullscreen) { - canvas.webkitRequestFullscreen(); - } - console.log('go fullscrenn') - scene.background = new THREE.Color(_this.state.backgroundColor) - } else { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } - console.log('leave fullscrenn') - scene.background = ''; - composer.render(); + // 双击全屏 + window.addEventListener('dblclick', () => { + const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement; + if (!fullscreenElement) { + if (canvas.requestFullscreen) { + canvas.requestFullscreen(); + } else if (canvas.webkitRequestFullscreen) { + canvas.webkitRequestFullscreen(); + } + scene.background = new THREE.Color(this.state.backgroundColor) + } else { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); } - }) + scene.background = ''; + composer.render(); + } + }); - // 字体 - const loader = new FontLoader(); - loader.load('./fonts/helvetiker_regular.typeface.json', font => { - textMesh.geometry = new TextGeometry('@dragonir\nfantastic\nthree.js\nart work', { - font: font, - size: 100, - height: 40, - curveSegments: 12, - bevelEnabled: true, - bevelThickness: 30, - bevelSize: 8, - bevelOffset: 1, - bevelSegments: 12 - }); - textMesh.material = material; - textMesh.position.x = 120 * -2; - textMesh.position.z = 120 * -1; - scene.add(textMesh); + // 字体 + const textMesh = new THREE.Mesh(); + const loader = new FontLoader(); + loader.load('./fonts/helvetiker_regular.typeface.json', font => { + textMesh.geometry = new TextGeometry('@dragonir\nfantastic\nthree.js\nart work', { + font: font, + size: 100, + height: 40, + curveSegments: 12, + bevelEnabled: true, + bevelThickness: 30, + bevelSize: 8, + bevelOffset: 1, + bevelSegments: 12 }); + textMesh.material = material; + textMesh.position.x = 120 * -2; + textMesh.position.z = 120 * -1; + scene.add(textMesh); + }); - // BufferAttribute 允许更有效地将数据传递到 GPU - const octahedronGeometry = new THREE.OctahedronBufferGeometry(80); - const material = new THREE.MeshNormalMaterial(); - generateRandomMesh(octahedronGeometry, material, 100); - const torusGeometry = new THREE.TorusBufferGeometry(40, 25, 16, 40); - generateRandomMesh(torusGeometry, material, 200); - const coneGeometry = new THREE.ConeBufferGeometry(40, 80, 80); - generateRandomMesh(coneGeometry, material, 100); - scene.add(group); - } - + let mouseX = 0, mouseY = 0; const mouseFX = { windowHalfX: window.innerWidth / 2, windowHalfY: window.innerHeight / 2, @@ -111,36 +95,50 @@ export default class Earth extends React.Component { mouseX = (coordX - mouseFX.windowHalfX) * 5; mouseY = (coordY - mouseFX.windowHalfY) * 5; }, - onMouseMove: e => { mouseFX.coordinates(e.clientX, e.clientY) }, - onTouchMove: e => { mouseFX.coordinates(e.changedTouches[0].clientX, e.changedTouches[0].clientY)} + onMouseMove: e => { + mouseFX.coordinates(e.clientX, e.clientY) + }, + onTouchMove: e => { + mouseFX.coordinates(e.changedTouches[0].clientX, e.changedTouches[0].clientY) + } }; document.addEventListener('mousemove', mouseFX.onMouseMove, false); document.addEventListener('touchmove', mouseFX.onTouchMove, false); - function generateRandomMesh(geometry, material, count){ + // 创建装饰几何体 + const generateRandomMesh = (geometry, material, count) => { for (let i = 0; i < count; i++) { let mesh = new THREE.Mesh(geometry, material); let dist = farDist / 3; let distDouble = dist * 2; - let tau = 2 * Math.PI; mesh.position.x = Math.random() * distDouble - dist; mesh.position.y = Math.random() * distDouble - dist; mesh.position.z = Math.random() * distDouble - dist; - mesh.rotation.x = Math.random() * tau; - mesh.rotation.y = Math.random() * tau; - mesh.rotation.z = Math.random() * tau; - // 手动控制何时重新计算 3D 变换以获得更好的性能 + mesh.rotation.x = Math.random() * 2 * Math.PI; + mesh.rotation.y = Math.random() * 2 * Math.PI; + mesh.rotation.z = Math.random() * 2 * Math.PI; + // 手动控制何时重新计算3D变换以获得更好的性能 mesh.matrixAutoUpdate = false; mesh.updateMatrix(); group.add(mesh); } } - function animate() { + const group = new THREE.Group(); + const octahedronGeometry = new THREE.OctahedronBufferGeometry(80); + const material = new THREE.MeshNormalMaterial(); + generateRandomMesh(octahedronGeometry, material, 100); + const torusGeometry = new THREE.TorusBufferGeometry(40, 25, 16, 40); + generateRandomMesh(torusGeometry, material, 200); + const coneGeometry = new THREE.ConeBufferGeometry(40, 80, 80); + generateRandomMesh(coneGeometry, material, 100); + scene.add(group); + + // 动画 + const animate = () => { requestAnimationFrame(animate); camera.position.x += (mouseX - camera.position.x) * 0.05; camera.position.y += (mouseY * -1 - camera.position.y) * 0.05; - // 旋转世界空间中的每一个网格 camera.lookAt(scene.position); const t = Date.now() * 0.001; const rx = Math.sin(t * 0.7) * 0.5; @@ -153,9 +151,9 @@ export default class Earth extends React.Component { textMesh.rotation.y = ry; textMesh.rotation.z = rx; renderer.render(scene, camera); - _this.state.renderGlithPass && composer.render(); - stats && stats.update(); + this.state.renderGlithPass && composer.render(); } + animate(); } handleInputChange = e => { @@ -173,20 +171,20 @@ export default class Earth extends React.Component { render () { return (
-
- +
+
- -

dragonir

-

website: tricell.fun

-

juejin: @dragonir

-

cnblog: @dragonir

-

segmentFault: @dragonir

+

website: tricell.fun

+

juejin: @dragonir

+

cnblog: @dragonir

+

segmentFault: @dragonir

)