feat: 新增Cell container,首页样式优化.
This commit is contained in:
parent
e7c3815445
commit
c144181f3d
|
|
@ -5,6 +5,7 @@ import City from './containers/City/index';
|
|||
import Earth from './containers/Earth/index';
|
||||
import Demo from './containers/Demo/index';
|
||||
import Lunar from './containers/Lunar/index';
|
||||
import Cell from './containers/Cell/index';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
|
@ -16,6 +17,7 @@ function App() {
|
|||
<Route element={ <Earth /> } path="/earth" />
|
||||
<Route element={ <Demo /> } path="/demo" />
|
||||
<Route element={ <Lunar /> } path="/lunar" />
|
||||
<Route element={ <Cell /> } path="/cell" />
|
||||
</Routes>
|
||||
</Router>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
.cell_loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background: #03c03c;
|
||||
background: -webkit-linear-gradient(to right, #64e06b, #03c03c);
|
||||
background: linear-gradient(to right, #64e06b, #03c03c);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
font-size: 64px;
|
||||
color: #FFFFFF;
|
||||
text-shadow: 0 1px 0 hsl(174,5%,80%),
|
||||
0 2px 0 hsl(174,5%,75%),
|
||||
0 3px 0 hsl(174,5%,70%),
|
||||
0 4px 0 hsl(174,5%,66%),
|
||||
0 5px 0 hsl(174,5%,64%),
|
||||
0 6px 0 hsl(174,5%,62%),
|
||||
0 7px 0 hsl(174,5%,61%),
|
||||
0 8px 0 hsl(174,5%,60%),
|
||||
0 0 5px rgba(0,0,0,.05),
|
||||
0 1px 3px rgba(0,0,0,.2),
|
||||
0 3px 5px rgba(0,0,0,.2),
|
||||
0 5px 10px rgba(0,0,0,.2),
|
||||
0 10px 10px rgba(0,0,0,.2),
|
||||
0 20px 20px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
.toggle_button {
|
||||
position: fixed;
|
||||
width: 160px;
|
||||
height: 48px;
|
||||
top: 100px;
|
||||
left: 50%;
|
||||
margin-left: -80px;
|
||||
cursor: pointer;
|
||||
background: rgba(255, 255, 255, .3);
|
||||
border: 1px groove rgba(255, 255, 255, .5);
|
||||
backdrop-filter: 2px;
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, .8);
|
||||
text-shadow: 0 0 1px rgba(0, 0, 0, .2);
|
||||
border-radius: 24px;
|
||||
box-shadow: 1px 1px 10px rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import * as THREE from "three";
|
||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
|
||||
import plantCellModel from './models/plant_cell.glb';
|
||||
import AnimalCellModel from './models/animal_cell.glb';
|
||||
import './index.css';
|
||||
|
||||
export default class Cell extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
state = {
|
||||
// 页面模型加载进度,0:未加载,100:加载完成
|
||||
loadingProcess: 0,
|
||||
showAnimal: false
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.initThree()
|
||||
}
|
||||
|
||||
initThree = () => {
|
||||
var container, controls, stats;
|
||||
var camera, scene, renderer, light, earthMeshes = [];
|
||||
var _this = this;
|
||||
init();
|
||||
animate();
|
||||
function init() {
|
||||
container = document.getElementById('container');
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.shadowMap.enabled = true;
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(0x03c03c);
|
||||
_this.scene = scene;
|
||||
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||
camera.position.set(0, 16, 18);
|
||||
camera.lookAt(new THREE.Vector3(0, 0, 0));
|
||||
|
||||
const cubeGeometry = new THREE.BoxGeometry(0.001, 0.001, 0.001);
|
||||
const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xdc161a });
|
||||
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
|
||||
cube.position.set(0, 0, 0,);
|
||||
light = new THREE.DirectionalLight(0x03c03c, 1);
|
||||
light.intensity = 1.2;
|
||||
light.position.set(-5, 10, 3);
|
||||
light.castShadow = true;
|
||||
light.target = cube;
|
||||
light.shadow.mapSize.width = 512 * 12;
|
||||
light.shadow.mapSize.height = 512 * 12;
|
||||
light.shadow.camera.top = 10;
|
||||
light.shadow.camera.bottom = - 5;
|
||||
light.shadow.camera.left = - 5;
|
||||
light.shadow.camera.right = 10;
|
||||
scene.add(light);
|
||||
|
||||
var ambientLight = new THREE.AmbientLight(0xffffff);
|
||||
ambientLight.intensity = 1.2;
|
||||
scene.add(ambientLight);
|
||||
|
||||
// 模型加载进度管理
|
||||
const manager = new THREE.LoadingManager();
|
||||
manager.onStart = (url, loaded, total) => {};
|
||||
manager.onLoad = () => {};
|
||||
manager.onProgress = async(url, loaded, total) => {
|
||||
if (Math.floor(loaded / total * 100) === 100) {
|
||||
_this.loadingProcessTimeout && clearTimeout(_this.loadingProcessTimeout);
|
||||
_this.loadingProcessTimeout = setTimeout(() => {
|
||||
_this.setState({ loadingProcess: Math.floor(loaded / total * 100) });
|
||||
}, 800);
|
||||
} else {
|
||||
_this.setState({ loadingProcess: Math.floor(loaded / total * 100) });
|
||||
}
|
||||
};
|
||||
|
||||
var loader = new GLTFLoader(manager);
|
||||
// 植物细胞
|
||||
loader.load(plantCellModel, function (mesh) {
|
||||
mesh.scene.traverse(function (child) {
|
||||
if (child.isMesh) {
|
||||
earthMeshes.push(child)
|
||||
child.castShadow = true;
|
||||
child.receiveShadow = true;
|
||||
child.material.metalness = 1;
|
||||
child.material.roughness = 0;
|
||||
}
|
||||
});
|
||||
mesh.scene.position.set(0, 0, 0);
|
||||
mesh.scene.scale.set(40, 40, 40);
|
||||
_this.plantCell = mesh.scene;
|
||||
scene.add(mesh.scene);
|
||||
});
|
||||
// 动物细胞
|
||||
loader.load(AnimalCellModel, function (mesh) {
|
||||
mesh.scene.traverse(function (child) {
|
||||
if (child.isMesh) {
|
||||
earthMeshes.push(child)
|
||||
child.castShadow = true;
|
||||
child.receiveShadow = true;
|
||||
child.material.metalness = 1;
|
||||
child.material.roughness = 0;
|
||||
}
|
||||
});
|
||||
mesh.scene.position.set(0, -8, 0);
|
||||
mesh.scene.scale.set(120, 120, 120);
|
||||
_this.animalCell = mesh.scene;
|
||||
});
|
||||
|
||||
controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.target.set(0, 0, 0);
|
||||
controls.enableDamping = true;
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
renderer.render(scene, camera);
|
||||
stats && stats.update();
|
||||
controls && controls.update();
|
||||
}
|
||||
}
|
||||
|
||||
handleToggle = () => {
|
||||
this.scene.remove(this.state.showAnimal ? this.animalCell : this.plantCell);
|
||||
this.scene.add(this.state.showAnimal ? this.plantCell : this.animalCell);
|
||||
this.setState({
|
||||
showAnimal: !this.state.showAnimal
|
||||
})
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<div id="container"></div>
|
||||
<button className="toggle_button" onClick={this.handleToggle}>查看{this.state.showAnimal ? '植物🌲' : '动物🐼'}细胞</button>
|
||||
{this.state.loadingProcess === 100 ? '' : (
|
||||
<div className="cell_loading">
|
||||
<div className="box">{this.state.loadingProcess} %</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -118,7 +118,7 @@ export default class City extends React.Component {
|
|||
|
||||
controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.target.set(0, 0, 0);
|
||||
controls.update();
|
||||
controls.enableDamping = true;
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
|
||||
stats = new Stats();
|
||||
|
|
@ -136,6 +136,7 @@ export default class City extends React.Component {
|
|||
renderer.render(scene, camera);
|
||||
stats && stats.update();
|
||||
TWEEN && TWEEN.update();
|
||||
controls && controls.update();
|
||||
}
|
||||
|
||||
// 增加点击事件,声明raycaster和mouse变量
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export default class Earth extends React.Component {
|
|||
|
||||
controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.target.set(0, 0, 0);
|
||||
controls.update();
|
||||
controls.enableDamping = true;
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +88,7 @@ export default class Earth extends React.Component {
|
|||
renderer.render(scene, camera);
|
||||
earth && (earth.rotation.y += 0.002)
|
||||
stats && stats.update();
|
||||
controls && controls.update();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 711 KiB |
|
|
@ -19,4 +19,27 @@
|
|||
0 5px 10px rgba(0,0,0,.2),
|
||||
0 10px 10px rgba(0,0,0,.2),
|
||||
0 20px 20px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
.grid_item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.three_logo {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 16px;
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
z-index: 2;
|
||||
background: url('./images/3d.png') no-repeat center;
|
||||
background-size: 100% 100%;
|
||||
filter: drop-shadow(0px 0px 8px rgba(0, 0, 0, .5));
|
||||
transition: all .5s linear;
|
||||
opacity: .85;
|
||||
}
|
||||
|
||||
.grid_item:hover .three_logo {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
|
|
@ -8,6 +8,10 @@ import cityImage from './images/city.png';
|
|||
import panoramicImage from './images/panoramic.png';
|
||||
import metaImage from './images/meta.png';
|
||||
import earthImage from './images/earth.png';
|
||||
import cellImage from './images/cell.png';
|
||||
import lunarImage from './images/lunar.png';
|
||||
import zeldaImage from './images/zelda.png';
|
||||
import scanImage from './images/scan.png';
|
||||
import './index.css';
|
||||
|
||||
const Item = styled(Paper)(({ theme }) => ({
|
||||
|
|
@ -20,27 +24,57 @@ const Item = styled(Paper)(({ theme }) => ({
|
|||
const workList = [
|
||||
{
|
||||
link: '#/city',
|
||||
title: '🏙 3D 数字城市',
|
||||
description: 'Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across all continents except Antarctica',
|
||||
title: '🏙 数字城市',
|
||||
description: 'Lizards are a widespread group of squamate reptiles.',
|
||||
image: cityImage,
|
||||
three: true
|
||||
},
|
||||
{
|
||||
link: '#/city',
|
||||
title: '🪐 3D META 元宇宙Logo',
|
||||
description: 'Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across all continents except Antarctica',
|
||||
link: 'https://dragonir.github.io/3d-meta-logo/',
|
||||
title: '🪐 脸书Meta元宇宙Logo',
|
||||
description: 'Lizards are a widespread group of squamate reptiles.',
|
||||
image: metaImage,
|
||||
three: true
|
||||
},
|
||||
{
|
||||
link: '#/city',
|
||||
title: '🕵️ 3D 全景侦探小游戏',
|
||||
description: 'Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across all continents except Antarctica',
|
||||
link: 'https://dragonir.github.io/3d-panoramic-vision/',
|
||||
title: '🕵️ 全景侦探小游戏',
|
||||
description: '使用Three.js全景功能实现侦探小游戏。',
|
||||
image: panoramicImage,
|
||||
three: true
|
||||
},
|
||||
{
|
||||
link: '#/earth',
|
||||
title: '🌏 3D Low Poly地球',
|
||||
description: 'Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across all continents except Antarctica',
|
||||
title: '🌏 Low Poly地球',
|
||||
description: 'Lizards are a widespread group of squamate reptiles.',
|
||||
image: earthImage,
|
||||
three: true
|
||||
},
|
||||
{
|
||||
link: '#/cell',
|
||||
title: '👻 细胞',
|
||||
description: '可以查看动物细胞和植物细胞的内部组成结构。',
|
||||
image: cellImage,
|
||||
three: true
|
||||
},
|
||||
{
|
||||
link: '#/lunar',
|
||||
title: '🐅 虎年春节创意页面',
|
||||
description: 'Lizards are a widespread group of squamate reptiles.',
|
||||
image: lunarImage,
|
||||
three: true
|
||||
},
|
||||
{
|
||||
link: 'https://dragonir.github.io/zelda-map/',
|
||||
title: 'Zelda地图',
|
||||
description: 'Lizards are a widespread group of squamate reptiles.',
|
||||
image: zeldaImage,
|
||||
},
|
||||
{
|
||||
link: 'https://dragonir.github.io/h5-scan-qrcode/',
|
||||
title: '扫码',
|
||||
description: 'Lizards are a widespread group of squamate reptiles.',
|
||||
image: scanImage,
|
||||
}
|
||||
];
|
||||
|
||||
|
|
@ -54,8 +88,11 @@ export default class Home extends React.Component {
|
|||
<Box sx={{ width: '100%' }} style={{ maxWidth: '1200px', margin: 'auto' }}>
|
||||
<Grid container rowSpacing={1} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
|
||||
{workList.map((item, index) => (
|
||||
<Grid item xs={6} key={index}>
|
||||
<Item elevation={0}><MediaCard link={item.link} title={item.title} image={item.image} description={item.description} /></Item>
|
||||
<Grid item xs={12} sm={6} md={4} key={index}>
|
||||
<Item elevation={0} className="grid_item">
|
||||
{item.three ? (<i className="three_logo"></i>) : '' }
|
||||
<MediaCard link={item.link} title={item.title} image={item.image} description={item.description} />
|
||||
</Item>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# Three.js
|
||||
|
||||
THREE.OrbitControls参数控制
|
||||
// Set to false to disable this control
|
||||
//鼠标控制是否可用
|
||||
|
|
|
|||
|
|
@ -43,14 +43,15 @@ export default class Lunar extends React.Component {
|
|||
|
||||
scene = new THREE.Scene();
|
||||
scene.background = new THREE.TextureLoader().load(bgTexture);
|
||||
scene.fog = new THREE.Fog(0xdddddd, 100, 120);
|
||||
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||
camera.position.set(100, 100, 100);
|
||||
camera.lookAt(new THREE.Vector3(0, 0, 0));
|
||||
|
||||
// 网格
|
||||
var grid = new THREE.GridHelper(100, 100, 0xfffc00, 0xfffc00);
|
||||
grid.position.set(0, -10, 0)
|
||||
grid.material.opacity = 0.1;
|
||||
var grid = new THREE.GridHelper(100, 100, 0xefefef, 0xefefef);
|
||||
grid.position.set(0, -8, 0);
|
||||
grid.material.opacity = 0.2;
|
||||
grid.material.transparent = true;
|
||||
scene.add(grid);
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ export default class Lunar extends React.Component {
|
|||
var planeMaterial = new THREE.ShadowMaterial({ opacity: .5 });
|
||||
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
|
||||
plane.rotation.x = -0.5 * Math.PI;
|
||||
plane.position.set(0, -10, 0);
|
||||
plane.position.set(0, -8, 0);
|
||||
plane.receiveShadow = true;
|
||||
scene.add(plane);
|
||||
|
||||
|
|
@ -69,7 +70,7 @@ export default class Lunar extends React.Component {
|
|||
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
|
||||
cube.position.set(0, 0, 0);
|
||||
light = new THREE.DirectionalLight(0xffffff, 1);
|
||||
light.intensity = 1.5;
|
||||
light.intensity = 1.2;
|
||||
light.position.set(20, 20, 8);
|
||||
light.castShadow = true;
|
||||
light.target = cube;
|
||||
|
|
@ -86,9 +87,17 @@ export default class Lunar extends React.Component {
|
|||
// const lightCameraHelper = new THREE.CameraHelper(light.shadow.camera);
|
||||
// scene.add(lightCameraHelper);
|
||||
|
||||
const ambientLight = new THREE.AmbientLight(0xefefef);
|
||||
// 环境光
|
||||
const ambientLight = new THREE.AmbientLight(0xffffff);
|
||||
scene.add(ambientLight);
|
||||
|
||||
// 聚光灯
|
||||
const spotLight = new THREE.SpotLight(0xffffff);
|
||||
spotLight.position.set(-20, 20, -2);
|
||||
spotLight.castShadow = false;
|
||||
spotLight.target = plane;
|
||||
scene.add(spotLight);
|
||||
|
||||
// 文字模型
|
||||
const fbxLoader = new FBXLoader();
|
||||
fbxLoader.load(textModel, mesh => {
|
||||
|
|
@ -97,8 +106,8 @@ export default class Lunar extends React.Component {
|
|||
meshes.push(mesh);
|
||||
child.castShadow = true;
|
||||
child.receiveShadow = true;
|
||||
child.material.metalness = 0;
|
||||
child.material.roughness = 1;
|
||||
child.material.metalness = .2;
|
||||
child.material.roughness = .8;
|
||||
child.material.color = new THREE.Color(0x111111);
|
||||
}
|
||||
});
|
||||
|
|
@ -108,7 +117,7 @@ export default class Lunar extends React.Component {
|
|||
group.add(mesh);
|
||||
});
|
||||
|
||||
// 老虎模型
|
||||
// 模型加载进度管理
|
||||
const manager = new THREE.LoadingManager();
|
||||
manager.onStart = (url, loaded, total) => {};
|
||||
manager.onLoad = () => {
|
||||
|
|
@ -134,7 +143,8 @@ export default class Lunar extends React.Component {
|
|||
child.castShadow = true;
|
||||
child.receiveShadow = true;
|
||||
child.material.metalness = 0;
|
||||
child.material.roughness = 1;
|
||||
child.material.roughness = .5;
|
||||
child.material.transparent = true;
|
||||
console.log(child)
|
||||
}
|
||||
});
|
||||
|
|
@ -155,11 +165,11 @@ export default class Lunar extends React.Component {
|
|||
controls.target.set(0, 0, 0);
|
||||
// 开启缓动动画
|
||||
controls.enableDamping = true;
|
||||
// controls.dampingFactor = 0.25;
|
||||
controls.maxDistance = 160;
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
|
||||
stats = new Stats();
|
||||
document.documentElement.appendChild(stats.dom);
|
||||
// 性能工具
|
||||
// stats = new Stats();
|
||||
// document.documentElement.appendChild(stats.dom);
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue