{"id":285,"date":"2025-02-20T11:56:00","date_gmt":"2025-02-20T03:56:00","guid":{"rendered":"https:\/\/mitongxue.cn\/?p=285"},"modified":"2026-06-08T16:28:49","modified_gmt":"2026-06-08T08:28:49","slug":"threejs%e5%85%a8%e6%99%af%e7%9c%8b%e6%88%bf%e7%9b%b8%e5%85%b3%e5%b0%81%e8%a3%85","status":"publish","type":"post","link":"https:\/\/mitongxue.cn\/index.php\/2025\/02\/20\/threejs%e5%85%a8%e6%99%af%e7%9c%8b%e6%88%bf%e7%9b%b8%e5%85%b3%e5%b0%81%e8%a3%85\/","title":{"rendered":"ThreeJS\u5168\u666f\u770b\u623f\u76f8\u5173\u5c01\u88c5"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">\u623f\u95f4\u51e0\u4f55\u4f53<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>import * as THREE from \"three\";\n\nexport class Room { \n  constructor(\n    public name: string,\n    public roomPrefix: string,\n    public textureUrl: string,\n    public scene: THREE.Scene = new THREE.Scene(),\n    public position: THREE.Vector3 = new THREE.Vector3(0, 0, 0),\n    public euler: THREE.Euler = new THREE.Euler(0, 0, 0),\n  ) { \n\n    \/\/ \u521b\u5efa\u7acb\u65b9\u4f53\n    const geometry = new THREE.BoxGeometry(10, 10, 10);\n    geometry.scale(1, 1, -1);\n\n    const arr = &#91;\n      `${roomPrefix}_r`,\n      `${roomPrefix}_l`,\n      `${roomPrefix}_u`,\n      `${roomPrefix}_d`,\n      `${roomPrefix}_f`,\n      `${roomPrefix}_b`,\n    ];\n    const boxMaterials: THREE.MeshBasicMaterial&#91;] = &#91;];\n\n    arr.forEach((item) => { \n      const texture = new THREE.TextureLoader().load(\n        textureUrl + item + \".jpg\"\n      );\n      boxMaterials.push(new THREE.MeshBasicMaterial({ map: texture }));\n    })\n\n    const box = new THREE.Mesh(geometry, boxMaterials);\n    box.position.copy(position);\n    box.rotation.copy(euler);\n    scene.add(box);\n  }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u4f4d\u7f6eSprite<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>import * as THREE from \"three\";\n\nexport class PositionSprite {\n  sprite: THREE.Sprite;\n  callbacks: any&#91;];\n  constructor(\n    text: string,\n    position: THREE.Vector3,\n    scene: THREE.Scene,\n    camera: THREE.Camera\n  ) {\n    this.callbacks = &#91;];\n\n    \/\/ \u5b9a\u4e49canvas\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = 1024;\n    canvas.height = 1024;\n    const context = canvas.getContext(\"2d\")!;\n    context.fillStyle = \"rgba(100,100,100,.7)\";\n    context.fillRect(0, 256, canvas.width, canvas.height \/ 2);\n    context.textAlign = \"center\";\n    context.textBaseline = \"middle\";\n    context.font = \"bold 200px Arial\";\n    context.fillStyle = \"white\";\n    context.fillText(text, canvas.width \/ 2, canvas.height \/ 2);\n\n    const texture = new THREE.CanvasTexture(canvas);\n    const material = new THREE.SpriteMaterial({\n      map: texture,\n      transparent: true,\n    })\n\n    const sprite = new THREE.Sprite(material);\n    sprite.position.copy(position);\n    this.sprite = sprite;\n    scene.add(sprite);\n\n    let pointer = new THREE.Vector2();\n    let raycaster = new THREE.Raycaster();\n    window.addEventListener('click', (event: MouseEvent) => { \n      pointer.x = (event.clientX \/ window.innerWidth) * 2 - 1;\n      pointer.y = -(event.clientY \/ window.innerHeight) * 2 + 1;\n      raycaster.setFromCamera(pointer, camera);\n      const intersects = raycaster.intersectObject(sprite);\n      if (intersects.length > 0) { \n        \/\/ \u89e6\u53d1\u56de\u8c03\n        this.callbacks.forEach((callback) => {\n          callback();\n        })\n      }\n    })\n  }\n  onClick(callback: () => void) {\n    this.callbacks.push(callback);\n  }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u4fe1\u606f\u63d0\u793aSprite<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>import * as THREE from \"three\";\n\nexport class TooltipSprite { \n  sprite: THREE.Sprite;\n  constructor(\n    public url: string,\n    public position: THREE.Vector3,\n    public scene: THREE.Scene,\n    public camera: THREE.Camera,\n    public userData: Record&lt;string, any> = {}\n  ) { \n    const tooltipTexture = new THREE.TextureLoader().load(url);\n    const tooltipMaterial = new THREE.SpriteMaterial({\n      map: tooltipTexture,\n      transparent: true,\n    });\n\n    const tooltipSprite = new THREE.Sprite(tooltipMaterial);\n    tooltipSprite.position.copy(position);\n    tooltipSprite.scale.set(0.2, 0.2, 0.2);\n    tooltipSprite.userData = userData;\n    this.sprite = tooltipSprite;\n    scene.add(tooltipSprite);\n  }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u623f\u95f4\u51e0\u4f55\u4f53 \u4f4d\u7f6eSprite \u4fe1\u606f\u63d0\u793aSprite<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,11],"tags":[],"class_list":["post-285","post","type-post","status-publish","format-standard","hentry","category-js","category-front"],"featured_image_urls":{"full":"","thumbnail":"","medium":"","medium_large":"","large":"","1536x1536":"","2048x2048":""},"author_info":{"info":["\u9648 \u67d0\u4eba"]},"category_info":"<a href=\"https:\/\/mitongxue.cn\/index.php\/category\/front\/js\/\" rel=\"category tag\">JS<\/a> <a href=\"https:\/\/mitongxue.cn\/index.php\/category\/front\/\" rel=\"category tag\">\u524d\u7aef<\/a>","tag_info":"\u524d\u7aef","comment_count":"0","_links":{"self":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/285","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/comments?post=285"}],"version-history":[{"count":1,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/285\/revisions"}],"predecessor-version":[{"id":286,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/285\/revisions\/286"}],"wp:attachment":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/media?parent=285"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/categories?post=285"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/tags?post=285"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}