首页  >  问答  >  正文

修改标题:在 3D 表面上呈现 2D 图像的困难

我正在编写来自 youtube 的代码教程,但遇到了一个问题,我有 13 个二十面体几何球成功渲染到我的屏幕上。然而,视频让我在球上显示的二维图像不可见。我的控制台中没有错误。这个项目是Three.js 和tailwindcss。没有打字稿。

注意:这是我的第一个 thrre.js 项目,我仍然是遵循自学路线的软件开发新手。感谢您的耐心、理解和帮助。非常感谢您。

主要问题 如何从“技术”获取图标图像以正确渲染到球的侧面?

目的似乎是使其看起来类似于带有公司徽标的高尔夫球,就像您可以在任何高尔夫球场或练习场找到的那样。

我已经尝试解决这个问题一个多星期了,但我完全被难住了。

我在 YouTube 上关注的教程在这里:https://www.youtube.com/watch?v=0fYi8SGA20k&t=6190s

以下是与该问题最相关的代码文件。如果有用的话我很乐意提供更多。以下是包含显示球的组件的 Tech.jsx 文件:

import { BallCanvas } from './canvas'
import { SectionWrapper } from '../hoc'
import { technologies } from '../constants/index'

const TechComponent = () => {
  return (
    <div className='flex flex-row flex-wrap justify-center gap-10'>
      {technologies.map((technology) => (
        <div className='w-28 h-28' key={technology.name}>
            <BallCanvas icon={technology.icon} />
        </div>
      ))}
    </div>
  )
}


const Tech = SectionWrapper(TechComponent, "about");

export default Tech;

接下来是将 Balls.jsx 文件导入 Tech.jsx:

import { Suspense } from 'react'
import { Canvas } from '@react-three/fiber'
import { Decal, Float, OrbitControls, Preload, useTexture } from '@react-three/drei'

import CanvasLoader from '../Loader'
import PropTypes from 'prop-types';

const Ball = (props) => {
  const [decal] = useTexture([props.imgURL])

  return (
    
    <Float speed={1.75} rotationIntensity={1} floatIntensity={2}>
      <ambientLight intensity={0.25}/>
      {/* eslint-disable-next-line react/no-unknown-property */}
      <directionalLight position={[0, 0, 0.05]} />
      {/* eslint-disable-next-line react/no-unknown-property */}
      <mesh castShadow receiveShadow>
        {/* eslint-disable-next-line react/no-unknown-property */}
        <icosahedronGeometry attach="geometry" args={[4, 3]} />
        {/* eslint-disable-next-line react/no-unknown-property */}
        <meshStandardMaterial color="#fff8eb" polygonOffset polygonOffsetFactor={-5} flatShading />
        <Decal position={[0, 0, 1]} map={decal}/> 
        {/*decal not loading*/}
      </mesh>
    </Float>
  )
}

const BallCanvas = ({ icon }) => {
  return (
    <Canvas
      frameloop="demand"
      shadows
      camera={{ position: [20, 3, 5], fov:25}}
      gl={{ preserveDrawingBuffer: true}}
      >
        <Suspense fallback={<CanvasLoader />}>
          <OrbitControls 
            enableZoom={false}
          />
          <Ball imgURL={icon}/>
        </Suspense>

        <Preload all />
    </Canvas>
  )
}

Ball.propTypes = {
  imgURL: PropTypes.string.isRequired,
};

BallCanvas.propTypes = {
  icon: PropTypes.string.isRequired,
};

export default BallCanvas;

接下来是index.js 文件中的一个片段,其中包含导航信息以定位需要显示的图标。这将是进口和“技术”常数。请注意,这些文件确实都存在于我的项目中,当我单击它们时,它们会显示在 vscode 窗口中:

import {
    mobile,
    backend,
    creator,
    web,
    javascript,
    typescript,
    html,
    css,
    reactjs,
    redux,
    tailwind,
    nodejs,
    mongodb,
    git,
    figma,
    docker,
    meta,
    starbucks,
    tesla,
    shopify,
    carrent,
    jobit,
    tripguide,
    threejs,
  } from "../assets";

const technologies = [
    {
      name: "HTML 5",
      icon: html,
    },
    {
      name: "CSS 3",
      icon: css,
    },
    {
      name: "JavaScript",
      icon: javascript,
    },
    {
      name: "TypeScript",
      icon: typescript,
    },
    {
      name: "React JS",
      icon: reactjs,
    },
    {
      name: "Redux Toolkit",
      icon: redux,
    },
    {
      name: "Tailwind CSS",
      icon: tailwind,
    },
    {
      name: "Node JS",
      icon: nodejs,
    },
    {
      name: "MongoDB",
      icon: mongodb,
    },
    {
      name: "Three JS",
      icon: threejs,
    },
    {
      name: "git",
      icon: git,
    },
    {
      name: "figma",
      icon: figma,
    },
    {
      name: "docker",
      icon: docker,
    },
  ];

然后我们有我的 package.json 和 tailwind.config.js 只是为了保持理智。

第一个package.json:

{
  "name": "portfolio-rob-2023",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@emailjs/browser": "^3.11.0",
    "@react-three/drei": "^9.66.6",
    "@react-three/fiber": "^8.13.0",
    "@types/three": "^0.152.0",
    "framer-motion": "^10.12.8",
    "maath": "^0.5.3",
    "prop-types": "^15.8.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-parallax-tilt": "^1.7.140",
    "react-router-dom": "^6.11.1",
    "react-tilt": "^1.0.2",
    "react-vertical-timeline-component": "^3.6.0",
    "three": "^0.152.2"
  },
  "devDependencies": {
    "@types/node": "^20.1.1",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@vitejs/plugin-react": "^4.0.0",
    "autoprefixer": "^10.4.14",
    "eslint": "^8.38.0",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.3.4",
    "postcss": "^8.4.23",
    "tailwindcss": "^3.3.2",
    "vite": "^4.3.2"
  }
}

最后是 tailwind.config.js:

@type {import('tailwindcss').Config}
module.exports = {
  content: [
    "./src/**/*.{js,jsx}"
  ],

  mode: "jit",
  theme: {
    extend: {
      colors: {
        primary: "#050816",
        secondary: "#aaa6c3",
        tertiary: "#151030",
        "black-100": "#100d25",
        "black-200": "#090325",
        "white-100": "#f3f3f3",
      },
      boxShadow: {
        card: "0px 35px 120px -15px #211e35",
      },
      screens: {
        xs: "450px",
      },
      backgroundImage: {
        "hero-pattern": "url('/src/assets/herobg.png')",
      },
    },
  },
  plugins: [],
};

` 我尝试过在普通球上显示图标,但只能让它们在 3d 球的整个表面上拉伸,并且存在多个“no-undefined”的 es linting 问题。它还涉及完全删除 Ball.jsx 文件并使用更基本的网格重写。这是非常不令人满意的,但是如果我能够在任何 3D 球的侧面显示徽标,那么在这一点上将是一个巨大的胜利。如前所述,我需要能够看到每个球上的图标/徽标。

P粉891237912P粉891237912305 天前458

全部回复(1)我来回复

  • P粉852578075

    P粉8525780752024-01-11 16:57:15

    更新你的 Balls.jsx 文件,我是这样做的:

    import { Suspense } from "react";
    import PropTypes from "prop-types";
    import { Canvas } from "@react-three/fiber";
    import {
      Decal,
      Float,
      OrbitControls,
      Preload,
      useTexture,
    } from "@react-three/drei";
    
    import CanvasLoader from "../Loader";
    
    const BallCanvas = ({ icon }) => {
      return (
        
          }>
            
            
          
    
          
        
      );
    };
    
    const Ball = ({ icon }) => {
      const [decal] = useTexture([icon]);
    
      return (
        
          
          
          
            
            
            
          
        
      );
    };
    
    BallCanvas.propTypes = {
      icon: PropTypes.string.isRequired,
    };
    
    export default BallCanvas;

    回复
    0
  • 取消回复