如何使用ThreeJS创建场景以及相机,方法及过程是什么
Admin 2022-09-01 群英技术资讯 337 次浏览
最近公司要做一个2.5D插件,然后自己学旋转角度不太好,然后就使用了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 mesh1 = new THREE.Mesh(boxGeom1, mat1) const point = [] point.push(mesh.position) // mesh的位置 point.push(mesh1.position) // mesh1的位置 // 点对点的线 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(mesh1) 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 mesh1 = new THREE.Mesh(textGeom, mat1) mesh1.position.set(attr.x, attr.y, attr.z) if (attr.rotation !== undefined) { mesh1.rotation.set(attr.rotation.x, attr.rotation.y, attr.rotation.z) } mesh1.scale.set(0.8, 0.8, 0.8) if (attr.group !== undefined) { attr.group.add(mesh1) plane.add(attr.group) } else { plane.add(mesh1) } 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
属性介绍(以下都是个人理解,如果有不清楚的欢迎指出):
正交摄像机OrthographicCamera
属性介绍:
角度计算:
如果设计刚好给你出了一个图,表示3d的位置等,这块需要一个角度计算,就需要改动摄像机的位置,以及lookAt属性:
this.camera.position.set(x, y, z) this.camera.lookAt(x, y, z)
这个属性的设置需要自己设置(目前算法还不太了解,之后可能了解了会更新一下),把自己想象成一个摄像机,摆在哪里看到的效果都是不一样的,然后lookAt就是你眼睛看哪个位置,可以看的偏移一点这样的效果
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍了antdesign-vue结合sortablejs实现两个table相互拖拽排序功能,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
这篇文章主要介绍了原生JS实现音乐播放器的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
这篇文章给大家分享的是JavaScript冒泡排序的相关内容,很多朋友对于JavaScript冒泡排序不是很理解,对此这篇给大家讲讲JavaScript冒泡排序的实现及实现原因,对大家学习冒泡排序有一定的参考价值,有需要的朋友可以了解看看,接下来就跟随小编一起学习一下吧。
这篇文章给大家分享的是jQuery中实现增加tr行的方法。小编觉得挺实用的,因此分享给大家做个参考,文中的示例代码介绍得很详细,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。
这篇文章主要为大家介绍了网络请求方案原生网络请求和js网络请求库的过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008