前言
很多小伙伴不知道vue中怎么写入js 这其实是由一些门道的 【大家不用着急】很快你就能使用这些简单指令完成一个 基本的threejs 小项目
先看一下效果图
这就是最终的效果 好像看起来并不是一个复杂的东西 没错 所有的东西都是由简单到复杂的
我不想先讲threejs那些理论和图 我打算混到这篇文章里,这样有助与理解这个项目,首先先准备工作 生成一个vue的脚手架 如果你还不会生成没关系,你可以先看vuecli的官方教程 自己安装vue生成一个 也可以参考别人写的博客
安装
命令行工具 必须先安装vue 有版本号
这篇文章是讲怎么安装vue的
vue-V
vue init webpack my-app
完成了一个vue脚手架
npm安装 vue-template-compiler three
npm i three
npm i vue-template-compiler
核心的实现代码
先把代码放到这里 这里我就会一断一断讲这个
<template>
<div>
<div id="container"></div>
</div>
</template>
<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
export default {
name: 'ThreeTest',
data() {
return {
camera: null,
scene: null,
renderer: null,
mesh: null,
controls:null,
meshCar:null
}
},
methods: {
init: function() {
/**
* 创建场景对象Scene
*/
this.scene = new THREE.Scene();
/**
* 创建网格模型
*/
// var geometry = new THREE.SphereGeometry(60, 40, 40); //创建一个球体几何对象
const geometryCar= new THREE.CylinderGeometry(50,50,100,25)
const geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff,
opacity:0.7,
// transparent:true,
// wireframe:true,
specular:0x4488ee,
shininess:12
}); //材质对象Material
this.mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
this.meshCar=new THREE.Mesh(geometryCar,material)
this.meshCar.position.set(250,0,0)
this.scene.add(this.mesh); //网格模型添加到场景中
this.scene.add(this.meshCar);
/**
* 光源设置
*/
//点光源
const point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300); //点光源位置
this.scene.add(point); //点光源添加到场景中
//环境光
const ambient = new THREE.AmbientLight(0x444444);
this.scene.add(ambient);
// console.log(scene)
// console.log(scene.children)
/**
* 相机设置
*/
const width = window.innerWidth; //窗口宽度
const height = window.innerHeight; //窗口高度
const k = width / height; //窗口宽高比
const s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
this.camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
this.camera.position.set(200, 300, 200); //设置相机位置
this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
/**
* 创建渲染器对象
*/
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(width, height);//设置渲染区域尺寸
this.renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
document.body.appendChild(this.renderer.domElement); //body元素中插入canvas对象
//执行渲染操作 指定场景、相机作为参数
this.controls = new OrbitControls(this.camera,this.renderer.domElement);//创建控件对象
// this.controls.addEventListener('change', this.render);
// renderer.render(scene, camera);
// 辅助坐标系 参数250表示坐标系大小,可以根据场景大小去设置
const axisHelper = new THREE.AxisHelper(250);
this.scene.add(axisHelper);
},
render() {
this.renderer.render(this.scene,this.camera);//执行渲染操作
this.mesh.rotateY(-0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(this.render);//请求再次执行渲染函数render
}
},
mounted() {
this.init();
this.render()
}
}
</script>
<style scoped>
#container {
height: 400px;
}
</style>
————————————— 续更 2021-06-12
直接讲js部分吧 其他部分也没什么好讲的
1.引入部分
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
这部分是引入three的 引入必须要使用 * as 千万不能用import THREE from 'three'
否则会报错 然后下面的是引用鼠标控制3D模块的插件, 当然这个工具是threejs 这个包里面已经有的 直接把他引出来用就可以了 如果你直接想用 new THREE.OrbitControls()
这样用不行哦, 这个方法并没有添加到three的方法里面
2.设置核心变量
export default {
name: 'ThreeTest',
data() {
return {
camera: null, // 相机
scene: null, // 场景
renderer: null, // 渲染器
mesh: null, // 模型1
controls:null, // 鼠标控制
meshCar:null // 模型2
}
// todo (下面的先不急着讲)
}
如注释所写,这些变量是一个基础3D模型里必不可少的,看着这个代码插入一些小知识,threejs的渲染的三个必不可少的东西
整个程序的结构
对比一下之前的代码 是不是清晰很多了? 而这里的代码将打开three的魅力 能让你更好的了解他
等会继续更
2021-6-14(今天端午节)
没人提点意见吗?我写的好没有动力啊 烦请小编继续给我置顶,这个系列我想从入门开始做到精通
3.(methods方法 模型创建)threejs创建
不知道大家对vue
熟悉不熟悉,真怕大家不会,methods
是vue提供写方法的地方
现在上代码
export default {
// ....
// todo
methods: {
init: function() {
/**
* 创建场景对象Scene
*/
this.scene = new THREE.Scene();
/**
* 创建网格模型
*/
// var geometry = new THREE.SphereGeometry(60, 40, 40); //创建一个球体几何对象
const geometryCar= new THREE.CylinderGeometry(50,50,100,25)
const geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff,
opacity:0.7,
// transparent:true,
// wireframe:true,
specular:0x4488ee,
shininess:12
}); //材质对象Material
this.mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
this.meshCar=new THREE.Mesh(geometryCar,material)
this.meshCar.position.set(250,0,0)
this.scene.add(this.mesh); //网格模型添加到场景中
this.scene.add(this.meshCar);
// ...todo
}
}
这个todo 就代表还有上下文,这段代码是介绍场景的 我写的 init()
方法是为了生成初始场景的这样,这个init()
方法还有下文啊 new THREE.Scene()
是直接通过three
new
出来一个新的场景
,这个时候你们不知道 new
就该打屁股了,赶紧去复习一下 项目中用了很多new
this.scene = new THREE.Scene();
是把生成的场景挂载到this.scene
,这样就可以通过响应式的方式去访问它,我会用这种方式去处理three生成的代码,所以大家务必知道这个思路,用好一个框架真的可以事半功倍。
接下来生成模型,大家可以看到我用的const
而不是 var
这个也请大家注意一下,我们写代码一定要规范,不能想用什么就用什么,习惯用var
后,将可能对团队带来麻烦,如果不清楚两者的区别,也请仔细百度一下 这边只是想让大家规范代码
const geometryCar= new THREE.CylinderGeometry(50,50,100,25)
const geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
就是这么生成一个模型的,看起来非常的简单实用,这边详情讲一下这个api
的用法
BoxGeometry()
这个方法里面几个参数 用法参照下面的自己填写就好了
BoxGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
width — X轴上面的宽度,默认值为1。
height — Y轴上面的高度,默认值为1。
depth — Z轴上面的深度,默认值为1。
widthSegments — (可选)宽度的分段数,默认值是1。
heightSegments — (可选)宽度的分段数,默认值是1。
depthSegments — (可选)宽度的分段数,默认值是1。
按照如上的顺序依次填写参数就可以使用
如果还想知道更多的直接去three的文档里找吧
threejs文档:www.yanhuangxueyuan.com/threejs/doc…
这里给你们列个表格吧
API | 生成模型 | 用列 |
---|---|---|
BoxGeometry() | 长方体 | new THREE.BoxGeometry(100, 100, 100) |
SphereGeometry() | 球体 | new THREE.SphereGeometry(60, 40, 40) |
CylinderGeometry() | 圆柱 | new THREE.CylinderGeometry( 50, 50, 100, 25 ) |
OctahedronGeometry() | 正八面体 | new THREE.OctahedronGeometry(50) |
DodecahedronGeometry() | 正十二面体 | new THREE.DodecahedronGeometry(50) |
IcosahedronGeometry() | 正二十面体 | new THREE.IcosahedronGeometry(50) |
当然你可以自定义形状
下次在更吧 先这样
2021-06-16(杭州下雨了,好大的雨)
换了一种代码高亮格式,怕你们看不清楚
接下半部分,讲完模型就可以讲讲应用材质了,材质就是下面这行
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff,
opacity:0.7,
// transparent:true,
// wireframe:true,
specular:0x4488ee,
shininess:12
}); //材质对象Material
熟悉css的看里面配置的属性就不会陌生,颜色color
透明度opacity
还有其他的属性,怕有些人理解起来困难就先将这些,反正这些也够用了,我后续会补充的,直接通过MeshLambertMaterial
three
里面的材质方法 生成这个 material
这个材质接创建好了 意思就是这个物体现在颜色是蓝色 处于透明状态0.7,大家可以用这个属性调出蓝色的水母的颜色,后续会做一个出来
this.mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
this.meshCar=new THREE.Mesh(geometryCar,material)
this.meshCar.position.set(250,0,0) // 将模型定位在离中心位置X轴250 的位置
this.scene.add(this.mesh); //网格模型添加到场景中
this.scene.add(this.meshCar);
这边我生成了两个模型,都是直接将生成的模型类别和材质添加进去的,然后将模型挂载到场景里面,这部分代码很好理解
4. (methods方法 添加光源)threejs创建
/**
* 光源设置
*/
//点光源
const point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300); //点光源位置
this.scene.add(point); //点光源添加到场景中
//环境光
const ambient = new THREE.AmbientLight(0x444444);
this.scene.add(ambient);
这部分和添加模型差不多,就是周围的光源设置,环境光顾名思义就是周围环境通过漫反射
产生的光,点光源就是从场景中的一个位置发出的散射光,这部分也很好理解,相信大家的物理都学得不错,你可以改变光的明暗来调整模型的亮度 const ambient = new THREE.AmbientLight(0x444444);
比如直接从环境光入手改成 0x888888
会发现模型亮度变的很大
5.(methods方法 相机创建)threejs创建
/**
* 相机设置
*/
const width = window.innerWidth; //窗口宽度
const height = window.innerHeight; //窗口高度
const k = width / height; //窗口宽高比
const s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
this.camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
this.camera.position.set(200, 300, 200); //设置相机位置
this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
创建相机找个就有点小小的技巧了,数学学的好的人很容易理解相机的摆放位置,这里讲一下 OrthographicCamera
这个API
正投影相机 OrthographicCamera
生活中的物体都是三维的,但是人的眼睛只能看到正面,不能看到被遮挡的背面,三维几何体在人眼睛中的效果就像一张相机拍摄的二维照片,你看到的是一个2D的投影图。 空间几何体转化为一个二维图的过程就是投影,不同的投影方式意味着投影尺寸不同的算法。
这个定义有点难懂啊,不理解的可以仔细阅读这段话,并认真查看这个图片
这个图片看完了可以看一下这篇文章 这样你就更加容易理解相机是个什么东西了 www.cnblogs.com/gaozhiqiang…
穿插优秀文章会让读者更容易理解,也算为优秀作者引流了
this.camera.position.set(200, 300, 200); //设置相机位置
这个就是将相机设置在x,y,z的方向上,这样就可以看清楚模型的具体位置了,要不相机就在原点处加载了,也就是this.camera.position.set(0, 0, 0);
相机直接就加载进模型里面了。但别忘了 this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
要不还是看不到模型
6.(methods方法 渲染器创建)
/**
* 创建渲染器对象
*/
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(width, height);//设置渲染区域尺寸
this.renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
document.body.appendChild(this.renderer.domElement); //body元素中插入canvas对象
//执行渲染操作 指定场景、相机作为参数
this.controls = new OrbitControls(this.camera,this.renderer.domElement);//创建控件对象
// this.controls.addEventListener('change', this.render);
// renderer.render(scene, camera);
this.renderer = new THREE.WebGLRenderer();
threejs的渲染模式是建立在webGL上的,所以这样引用创建,而其他代码我相信大家可以读懂,都是操作一些简单的
轨道控制器
this.controls = new OrbitControls(this.camera,this.renderer.domElement);//创建控件对象
这个轨道控制器通俗的理解就是你可以用鼠标拖拉移动了,当然它的玩法不止这些,在后续的文中我会一一介绍,鼠标左键点击旋转,右键拖动,滚轮放大缩小场景这些基本的功能
7.其他(一些小功能)
这篇文章总算是到头了,想必各位肯定是有收获的,也就剩下一个坐标系和 render
了,当然别写了一大堆忘了mounted
生命周期执行方法
// 辅助坐标系 参数250表示坐标系大小,可以根据场景大小去设置
const axisHelper = new THREE.AxisHelper(250);
this.scene.add(axisHelper);
这个写好就有如图的坐标系,这个纯属辅助理解这些模块都在什么位置
render() {
this.renderer.render(this.scene,this.camera);//执行渲染操作
this.mesh.rotateY(-0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(this.render);//请求再次执行渲染函数render
}
这个函数是执行之前的模型渲染器的,被称为开关 requestAnimationFrame
是一个动画执行api,js自带的,这样反复执行render
函数就可以达到渲染效果了,你们可以看到 this.mesh.rotateY(-0.01);//每次绕y轴旋转0.01弧度
正方体旋转了
mounted() {
this.init();
this.render()
}
挂载需要在vue
模块中执行的方法,嗯嗯,终于讲完了,这篇文章真的是干货满满,下一篇文章就要提升难度了,希望各位不要从入门到放弃啊,要从入门到精通再到神
学习本项目
安装的时候要注意,需要安装 vue-template-compiler 这个工具是可以让threejs在vue中运行的插件 这个必须要安装 注意版本号 一定要更vue的版本保持一致 ,否则会报错
` vue@2.6.13
`- vue-template-compiler@2.6.14
`This may cause things to work incorrectly. Make sure to use the same version for both. If you are using vue-loader@>=10.0, simply update vue-template-compiler. If you are using vue-loader@<10.0 or vueify, re-installing vue-loader/vueify should bump vue-template-compiler to the latest.```
说的就是vue@2.6.13 和 vue-template-compiler@2.6.14 的版本不一致
安装的时候最好用cnpm 安装 不清楚的可以百度一下cnpm 是怎么用的