您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“ThreeJS從創(chuàng)建場景到使用功能實(shí)例代碼分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“ThreeJS從創(chuàng)建場景到使用功能實(shí)例代碼分析”吧!
首先,要?jiǎng)?chuàng)建一個(gè)場景,以及一個(gè)相機(jī)(相機(jī)分為透視相機(jī)和正交攝像機(jī),區(qū)別在后面會(huì)解釋),代碼如下
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 = () => { // 相機(jī) 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 }}/> ) } }
相機(jī)和平面創(chuàng)建完成,接來下我這邊是直接創(chuàng)建一個(gè)平面放到場景中,代碼如下
const geometry = new THREE.PlaneGeometry(800, 400) // 設(shè)置透明以及顏色 const material = new THREE.MeshBasicMaterial({ color: 0x091A20, transparent: true, opacity: 0.8 }) const plane = new THREE.Mesh(geometry, material) // 這邊操作的是旋轉(zhuǎn)還是位置 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 // 因?yàn)樘砑訄D片加載是異步的,所以在load方法中操作,每次加載之后都要執(zhí)行一遍renders方法,重新渲染場景 new THREE.TextureLoader().load(image, (texture) => { // 設(shè)置透明度,以及基礎(chǔ)材質(zhì)的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() })
首先要說,因?yàn)檎hreeJs的line不能設(shè)置線寬,所以要用到的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的位置 // 點(diǎn)對點(diǎn)的線 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) // 更新完之后在執(zhí)行一遍render,把東西渲染到畫布中 this.renders()
const axesHelper = new THREE.AxesHelper(800) this.scene.add(axesHelper)
// 縮放功能對應(yīng)mesh進(jìn)行縮放,每個(gè)mesh添加后都有固定的position, rotation, scale 屬性 mesh.position.set(x, y, z) mesh.rotation.set(x, y, z) mesh.scale.set(x, y, z) // 也可以這樣, scale, rotation 都可以這么設(shè)置 mesh.position.x = 0 mesh.position.y = 0 mesh.position.z = 0
添加文字使用threeJS官方的添加文字需要導(dǎo)入json文件,而且還需要中文配置,所以使用起來占用內(nèi)存會(huì)比較大,所以當(dāng)前項(xiàng)目中使用的是Canvas導(dǎo)入文字圖片
//創(chuàng)建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) // 導(dǎo)出圖片路徑 const url = canvas.toDataURL('image/png') // 設(shè)置圖片位置等信息 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() })
這邊畫圖的話我就不畫了,這塊只是稍微的解釋一下,具體的可以看一下搜到的文章:正交相機(jī)的應(yīng)用
簡單來說
正交攝像機(jī)的特點(diǎn)就是:場景中遠(yuǎn)處的物體和近處的物體是一樣大的
透視攝像機(jī)的特點(diǎn)就是:場景中物體遵循近大遠(yuǎn)小的擺列,如果物體在最近,物體相對就會(huì)比較大
下面就是怎么使用這兩個(gè)相機(jī):
// 透視攝像機(jī) this.camera = new THREE.PerspectiveCamera(30, this.mount.clientWidth / this.mount.clientHeight, 1, 2500) // 正交攝像機(jī) this.camera = new THREE.OrthographicCamera(width / -4, width / 4, height / 4, height / -4, -100, 10000)
透視攝像機(jī)PerspectiveCamera
屬性介紹(以下都是個(gè)人理解,如果有不清楚的歡迎指出):
fov 攝像機(jī)視錐體垂直視野角度 (就是從攝像機(jī)看視角的角度有多大)
aspect 攝像機(jī)視錐體長寬比 (通常就是你整個(gè)場景的長寬比)
near 攝像機(jī)視錐體近端面 (就是攝像機(jī)最近看到的距離)
far 攝像機(jī)視錐體遠(yuǎn)端面 (攝像機(jī)最遠(yuǎn)看到的距離,和near組合起來就相當(dāng)于你攝像機(jī)從某個(gè)位置到某個(gè)位置的整體能看到的一個(gè)面)
正交攝像機(jī)OrthographicCamera
屬性介紹:
left 攝像機(jī)視錐體左側(cè)面。
right 攝像機(jī)視錐體右側(cè)面。
top 攝像機(jī)視錐體上側(cè)面。
bottom 攝像機(jī)視錐體下側(cè)面。
上面四個(gè)屬性推薦配置為場景的長款比,如代碼所示(使這個(gè)等式成立: | left / right | = 1,| top / buttom | = 1),如果不成立,可能看到的效果不太一樣
near
far
以上兩個(gè)屬性通透視攝像機(jī)原理
角度計(jì)算:
如果設(shè)計(jì)剛好給你出了一個(gè)圖,表示3d的位置等,這塊需要一個(gè)角度計(jì)算,就需要改動(dòng)攝像機(jī)的位置,以及l(fā)ookAt屬性:
this.camera.position.set(x, y, z) this.camera.lookAt(x, y, z)
這個(gè)屬性的設(shè)置需要自己設(shè)置(目前算法還不太了解,之后可能了解了會(huì)更新一下),把自己想象成一個(gè)攝像機(jī),擺在哪里看到的效果都是不一樣的,然后lookAt就是你眼睛看哪個(gè)位置,可以看的偏移一點(diǎn)這樣的效果。
到此,相信大家對“ThreeJS從創(chuàng)建場景到使用功能實(shí)例代碼分析”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。