首頁  >  問答  >  主體

修改標題:在 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粉891237912255 天前417

全部回覆(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
  • 取消回覆