在本文中,我们将创建一个产品的3D模型,并将其在产品卡中渲染。到本文结束时,您将能够在网站上渲染3D模型。
下载3D模型
首先,您需要通过使用3D应用程序或从Internet下载它们来获得3D模型。我选择了简单的方法,并从open3dmodel.com免费下载了它们。确保它具有GLB文件扩展名。如果没有GLB文件扩展名,我们可以使用Blender将其导出为GLB。
GLB是GLTF的二进制容器格式,它比GLTF和其他3D模型扩展更轻巧。这使得更容易在网站上加载和渲染。
设置环境
首先,我们需要创建一个新的React应用程序。
npx create-react-app 3d-product
然后,我们需要安装将在此项目中使用的依赖项。我们将使用Three.js库,@react-three/fiber和@react-three/drei。
我们可以使用NPM安装它们
npm install three @react-three/fiber @react-three/drei
或使用纱线
yarn install three @react-three/fiber @react-three/drei
三。js用于制作3D场景, @react-three/fiber用于在场景中重新渲染模型。而 @react-three/drei是有用的助手的集合,并且针对 @react-three/fiber
制作模型的反应组件
安装依赖项后,我们需要将GLB文件掩盖到可重复使用的React组件中。我们可以通过在包含GLB文件的目录中运行此命令来轻松地做到这一点:
npx gltfjsx model.glb
运行此命令后,将生成新的JavaScript文件。会这样:
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
export function Model(props) {
const { nodes, materials } = useGLTF('/model.glb')
return (
<group {...props} dispose={null}>
<group position={[0.67, -1.61, 3]} rotation={[Math.PI / 2, 0, 0]} scale={0.1}>
<group position={[-37.27, -6.54, 0.15]} rotation={[1.57, -0.02, 3.13]}>
<group position={[-25.76, -1.15, 0]}>
<mesh geometry={nodes.Outsole_1.geometry} material={materials['706a6a']} position={[-0.19, 3.95, -5.76]} rotation={[0, 0, -3.14]} scale={[-0.98, -0.89, -0.98]} />
<mesh geometry={nodes.Plate.geometry} material={materials.Physical10} />
<mesh geometry={nodes.Toe.geometry} material={nodes.Toe.material} />
<mesh geometry={nodes._polySurface204.geometry} material={nodes._polySurface204.material} />
<mesh geometry={nodes._polySurface205.geometry} material={materials.fef7f7} position={[40.76, 12.34, -22.15]} />
<mesh geometry={nodes.Above.geometry} material={materials.Standard5} />
<mesh geometry={nodes.Below.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.Stripe.geometry} material={materials.Standard6} />
</group>
<group position={[-25.76, -1.15, 0]}>
<group position={[-20.21, 47.7, -0.77]}>
<mesh geometry={nodes.Tongue_2.geometry} material={materials.Physical9} position={[20.21, -48.47, 0.65]} />
<mesh geometry={nodes.Tongue_Binding.geometry} material={materials.Physical12} position={[20.21, -48.47, 0.65]} />
<mesh geometry={nodes.Tongue_Lining.geometry} material={materials.d3ebc} position={[20.21, -48.47, 0.65]} />
</group>
<mesh geometry={nodes.Binding.geometry} material={materials.Physical7} />
<mesh geometry={nodes.Insole.geometry} material={materials.Physical15} />
<mesh geometry={nodes.Lining.geometry} material={materials.Physical11} />
<mesh geometry={nodes.Tag.geometry} material={materials.ffffff} position={[-15.88, 44.52, -24.34]} />
<mesh geometry={nodes.Vamp.geometry} material={nodes.Vamp.material} />
<mesh geometry={nodes.Plugs.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.polySurface381.geometry} material={materials.b0b0b0} position={[9.17, 63.25, -14.78]} />
<mesh geometry={nodes.polySurface382.geometry} material={materials.b0b0b0} position={[-9.44, 55.79, -14.22]} />
<mesh geometry={nodes.polySurface383.geometry} material={materials.b0b0b0} position={[-18.66, 52.34, -13.55]} />
<mesh geometry={nodes.polySurface384.geometry} material={materials.b0b0b0} position={[-27.95, 48.98, -12.7]} />
<mesh geometry={nodes.polySurface385.geometry} material={materials.b0b0b0} position={[7.41, 65.1, 14.03]} />
<mesh geometry={nodes.polySurface386.geometry} material={materials.b0b0b0} position={[-11.22, 58.21, 12.89]} />
<mesh geometry={nodes.polySurface387.geometry} material={materials.b0b0b0} position={[-1.43, 61.81, 13.27]} />
<mesh geometry={nodes.polySurface388.geometry} material={materials.b0b0b0} position={[-20.21, 54.94, 12.28]} />
<mesh geometry={nodes.polySurface389.geometry} material={materials.b0b0b0} position={[-29.67, 51.27, 11.98]} />
<mesh geometry={nodes.polySurface390.geometry} material={materials.b0b0b0} position={[-0.28, 59.54, -14.63]} />
<mesh geometry={nodes.polySurface370.geometry} material={materials.b0b0b0} position={[109.3, 61.76, -0.46]} />
<mesh geometry={nodes.polySurface392.geometry} material={materials.b0b0b0} position={[92.65, 44.44, -0.95]} />
<mesh geometry={nodes.Lace_1_1.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.Lace_2.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.Lace_3.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.Lace_4.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.Lace_5.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.Lace_6.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.Lace_7.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes._polySurface207.geometry} material={materials.Physical2} />
<mesh geometry={nodes.polySurface394.geometry} material={materials.Physical1} />
<mesh geometry={nodes.pasted__stitch24.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.pasted__stitch25.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.pasted__stitch26.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.pasted__stitch27.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch10.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch11.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch14.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch15.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch16.geometry} material={materials.b0b0b0} position={[-21.2, 47.81, -1.23]} />
<mesh geometry={nodes.stitch17.geometry} material={materials.b0b0b0} position={[0, -0.77, -0.12]} />
<mesh geometry={nodes.stitch18.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch19.geometry} material={materials.b0b0b0} />
<mesh geometry={nodes.stitch20.geometry} material={materials.b0b0b0} />
</group>
</group>
</group>
</group>
)
}
useGLTF.preload('/model.glb')
P.S。每个模型都有其自己的独特文件结构。因此,如果您生成的文件看起来不像我的,请勿惊慌。
然后,您必须将GLB文件移至 public 目录中,以使其可用于React。
设计场景
为了设计3D场景,您需要在场景中添加相机,灯和模型。您需要编辑app.js并使其看起来像这样:
import './App.css';
import { React, Suspense } from 'react';
import { Canvas } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
import { Model } from './Model';
function App() {
return (
<div className='App'>
<Canvas
camera={{ position: [100, 80, 50], fov: 11 }}
style={{
width: '20vw',
height: '38vh',
border: '1px solid black'
}}
>
<ambientLight intensity={1.25} />
<directionalLight position={[0,-2,0]} intensity={2} />
<directionalLight position={[0,2,0]} intensity={2} />
<directionalLight position={[-2,0,0]} intensity={2} />
<directionalLight position={[2,0,0]} intensity={2} />
<Suspense fallback={null}>
<Model position={[0, 0, 0]} />
</Suspense>
<OrbitControls enableZoom={false}/>
</Canvas>
</div>
);
}
export default App;
P.S。每个模型的规模大小都不同,因此以前的变量可能不适合所有模型。
要克服此问题,您需要修改相机位置和视场(FOV)。另外,如果您的场景太亮或黑暗,您将不得不修改光强度。
另外,如果要启用Zoom功能,则必须用sixsistance = {}和maxDistance = {}替换OrbitControls中的EnableZoom。同样,您需要根据模型刻度输入值。
然后,您需要编辑app.css以在屏幕中间进行场景。
body{
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
添加CSS后,您的网站将看起来像:
设计产品卡
您可以自由设计任何您认为适合该项目的UI/UX。我决定使用艺术家Maria Marin的nuemorphic design。
结果
最后,让我们使用此命令运行项目:
npm start
我的产品卡看起来像这样:
github:3D-Product-Card
P.S.您必须在全屏桌面模式下查看它,因为它尚未响应。