您好,登錄后才能下訂單哦!
本篇內容主要講解“ThreeJS從創建場景到使用功能實例代碼分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“ThreeJS從創建場景到使用功能實例代碼分析”吧!
首先,要創建一個場景,以及一個相機(相機分為透視相機和正交攝像機,區別在后面會解釋),代碼如下
export default class ThreeComponent extends React.Component<any, any> { private mount: any private camera: any private scene: any private renderer: any componentDidMount() { this.init() this.renders() } init = () => { // 相機 this.camera = new THREE.PerspectiveCamera(30, this.mount.clientWidth / this.mount.clientHeight, 1, 2500) this.camera.position.set(500, 800, 1300) this.camera.lookAt(30, 0, 0) // 場景 this.scene = new THREE.Scene() this.scene.background = new THREE.Color(0x000000) this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }) this.renderer.setClearColor(0xEEEEEE, 0.0) this.renderer.setPixelRatio(window.devicePixelRatio) this.renderer.setSize(this.mount.clientWidth, this.mount.clientHeight) this.mount.appendChild(this.renderer.domElement) window.addEventListener('resize', () => this.onWindowResize.bind(this)) } onWindowResize = () => { this.camera.aspect = this.mount.clientWidth / this.mount.clientHeight this.camera.updateProjectionMatrix() this.renderer.setSize(this.mount.clientWidth, this.mount.clientHeight) this.renders() } renders = () => { this.renderer.render(this.scene, this.camera) } render() { return ( <div id='canvas' style={{ width: '100%', height: '100%' }} ref={(mount) => { this.mount = mount }}/> ) } }
相機和平面創建完成,接來下我這邊是直接創建一個平面放到場景中,代碼如下
const geometry = new THREE.PlaneGeometry(800, 400) // 設置透明以及顏色 const material = new THREE.MeshBasicMaterial({ color: 0x091A20, transparent: true, opacity: 0.8 }) const plane = new THREE.Mesh(geometry, material) // 這邊操作的是旋轉還是位置 plane.rotation.x = 300.1 plane.rotation.y = 0 plane.rotation.z = 49.8 plane.rotation.y = 0 plane.position.x = 120 plane.position.y = 200 this.scene.add(plane)
const image = require('../../assets/images/test.png').default // 因為添加圖片加載是異步的,所以在load方法中操作,每次加載之后都要執行一遍renders方法,重新渲染場景 new THREE.TextureLoader().load(image, (texture) => { // 設置透明度,以及基礎材質的map const mat = new THREE.MeshBasicMaterial({ map: texture, transparent: true }) const geom = new THREE.BoxGeometry(100, 100) const mesh = new THREE.Mesh(geom, mat) mesh.receiveShadow = true mesh.rotation.z = 19.7 mesh.position.x = 0 mesh.position.y = -30 // 往plane平面中添加,這樣就可以直接放到plane中,位置就是plane的位置 plane.add(mesh) this.renders() })
首先要說,因為正常ThreeJs的line不能設置線寬,所以要用到的MeshLine,github地址為: MeshLine
// 這里引入MeshLine import { MeshLine, MeshLineMaterial, MeshLineRaycast } from 'three.meshline' const mat = new THREE.MeshBasicMaterial({ map: texture1, transparent: true }) const boxGeom = new THREE.BoxGeometry(60, 150) const mesh = new THREE.Mesh(boxGeom, mat) const mat1 = new THREE.MeshBasicMaterial({ map: texture2, transparent: true }) const boxGeom1 = new THREE.BoxGeometry(60, 150) const mesh2 = new THREE.Mesh(boxGeom1, mat1) const point = [] point.push(mesh.position) // mesh的位置 point.push(mesh2.position) // mesh2的位置 // 點對點的線 const line = new MeshLine() line.setPoints(point) const lineMaterial = new MeshLineMaterial({ color: new THREE.Color(0xffffff), lineWidth: 10, transparent: true, opacity: 0.5 }) // 添加線 const lineMesh = new THREE.Mesh(line.geometry, lineMaterial) plane.add(mesh) plane.add(mesh2) plane.add(lineMesh) // 更新完之后在執行一遍render,把東西渲染到畫布中 this.renders()
const axesHelper = new THREE.AxesHelper(800) this.scene.add(axesHelper)
// 縮放功能對應mesh進行縮放,每個mesh添加后都有固定的position, rotation, scale 屬性 mesh.position.set(x, y, z) mesh.rotation.set(x, y, z) mesh.scale.set(x, y, z) // 也可以這樣, scale, rotation 都可以這么設置 mesh.position.x = 0 mesh.position.y = 0 mesh.position.z = 0
添加文字使用threeJS官方的添加文字需要導入json文件,而且還需要中文配置,所以使用起來占用內存會比較大,所以當前項目中使用的是Canvas導入文字圖片
//創建canvas const canvas = document.getElementById('text-canvas') as HTMLCanvasElement const ctx = canvas?.getContext('2d') as any canvas.width = 100 canvas.height = 100 ctx.fillStyle = 'transparent' ctx.fillRect(0, 0, 100, 100) ctx.fillStyle = '#FFFFFF' ctx.font = `normal ${attr.fontSize ?? 14}px "楷體"` ctx.fillText(text.length > 5 ? text.substr(0, 5) + '...' : text, 0, 40) // 導出圖片路徑 const url = canvas.toDataURL('image/png') // 設置圖片位置等信息 new THREE.TextureLoader().load(url, (texture: any) => { const textGeom = new THREE.PlaneGeometry(200, 200) const mat1 = new THREE.MeshBasicMaterial({ map: texture, transparent: true }) const mesh2 = new THREE.Mesh(textGeom, mat1) mesh2.position.set(attr.x, attr.y, attr.z) if (attr.rotation !== undefined) { mesh2.rotation.set(attr.rotation.x, attr.rotation.y, attr.rotation.z) } mesh2.scale.set(0.8, 0.8, 0.8) if (attr.group !== undefined) { attr.group.add(mesh2) plane.add(attr.group) } else { plane.add(mesh2) } this.renders() })
這邊畫圖的話我就不畫了,這塊只是稍微的解釋一下,具體的可以看一下搜到的文章:正交相機的應用
簡單來說
正交攝像機的特點就是:場景中遠處的物體和近處的物體是一樣大的
透視攝像機的特點就是:場景中物體遵循近大遠小的擺列,如果物體在最近,物體相對就會比較大
下面就是怎么使用這兩個相機:
// 透視攝像機 this.camera = new THREE.PerspectiveCamera(30, this.mount.clientWidth / this.mount.clientHeight, 1, 2500) // 正交攝像機 this.camera = new THREE.OrthographicCamera(width / -4, width / 4, height / 4, height / -4, -100, 10000)
透視攝像機PerspectiveCamera
屬性介紹(以下都是個人理解,如果有不清楚的歡迎指出):
fov 攝像機視錐體垂直視野角度 (就是從攝像機看視角的角度有多大)
aspect 攝像機視錐體長寬比 (通常就是你整個場景的長寬比)
near 攝像機視錐體近端面 (就是攝像機最近看到的距離)
far 攝像機視錐體遠端面 (攝像機最遠看到的距離,和near組合起來就相當于你攝像機從某個位置到某個位置的整體能看到的一個面)
正交攝像機OrthographicCamera
屬性介紹:
left 攝像機視錐體左側面。
right 攝像機視錐體右側面。
top 攝像機視錐體上側面。
bottom 攝像機視錐體下側面。
上面四個屬性推薦配置為場景的長款比,如代碼所示(使這個等式成立: | left / right | = 1,| top / buttom | = 1),如果不成立,可能看到的效果不太一樣
near
far
以上兩個屬性通透視攝像機原理
角度計算:
如果設計剛好給你出了一個圖,表示3d的位置等,這塊需要一個角度計算,就需要改動攝像機的位置,以及lookAt屬性:
this.camera.position.set(x, y, z) this.camera.lookAt(x, y, z)
這個屬性的設置需要自己設置(目前算法還不太了解,之后可能了解了會更新一下),把自己想象成一個攝像機,擺在哪里看到的效果都是不一樣的,然后lookAt就是你眼睛看哪個位置,可以看的偏移一點這樣的效果。
到此,相信大家對“ThreeJS從創建場景到使用功能實例代碼分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。