You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js:如何在IcosahedronGeometry球体表面正确渲染2D图标?

问题描述

跟着YouTube的代码教程开发基于Three.js和TailwindCSS的项目(无TypeScript),已成功渲染13个IcosahedronGeometry球体,但球体上的2D图标无法显示,控制台无报错。作为Three.js新手,折腾一周无果,需求是让图标像高尔夫球logo一样显示在球体侧面。此前修改Ball.jsx仅能让图标拉伸覆盖球体,还触发ESLint的"no-undefined"问题,效果不佳。


核心代码文件

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

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;

constants/index.js 片段

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

{
  "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: [],
};

内容的提问来源于stack exchange,提问作者Rabbie Wordie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:16:58