<!-- index.html -->
<script src="path/to/three.js"></script>复制代码
或
npm install three --save // or use yarn add three.js alternatively
import * as THREE from 'three';复制代码
如果想要把3D渲染的场景在HTML中展示,我们就需要制定一个简单的<div>元素,并为其制定一个唯一的ID作为钩子。这个<div id="scene-container"/>
被称为"divider element",它不会告诉浏览器会其内部会怎样,或者会显示什么,只是起到将周围其它元素与其内部隔开而已。scene-container这个ID,会被当做钩子与相关的js代码建立关联,告诉js/app.js哪里去放置渲染后的3D场景。
<body>
<h1>广告示例</h1>
<div id="scene-container"> // This div will hold our scene
</div>
<script src="js/app.js"></script>
</body>function init() {
container = document.querySelector('#scene-container'); // where to drawn
scene = new THREE.Scene();
createCamera();
createControls();
createLights();
createMeshes();
createRenderer();
renderer.setAnimationLoop(() => {
update();
render();
});
}复制代码
当app.js拿到钩子的位置后,
container = document.querySelector('#scene-container'),
就会生成在其内部添加一个<canvas>
元素。所有的three.js WebGL场景都会被画到这个<canvas/>
上。three.js会把控制权交给底层的WebGL,WebGL会调用显卡(graphics card)来生成图片或一些列图片(如果有动画效果的话),最后这些渲染结果会被在canvas上展示。
如果我们想要生成下图这个简单的demo,应该怎么来做呢?在上文中,我们提到了Three.js主要有三大组件,场景(Scene), 相机(Camera)和渲染器(Render)。在这里会以这个简单的demo情形为例子,讲解一下从代码细节上我们怎么能够实现这一渲染过程。基本要做的就是布置好场景,创建物体,放好摄像机,开拍!
首先需要做的是创建一个场景,并给场景设置一个背景色。因为本人是个女孩子,就设置成我所偏爱的紫色了。
// create a Scene
scene = new THREE.Scene();
scene.background = new THREE.Color('#9370DB');复制代码
scene.add( object )复制代码
反之,如果不想要某个物体了(做动画效果时),就用
scene.remove( object )复制代码
有了场景,就往里面加物体了,其实物体可以被理解为我们3D场景中的演员。3D计算机图形中,物体通常是用Mesh来生成的。Mesh中又包括geometry,也就是需要声明的物体的形状;以及material,即物体的材质。通过下面的代码,我们制造出来一个长宽高分别为2单位长度的正方体,给其附上了橙色的一般材质,并把它加入了场景中。
// create a geometry - here is a box
const geometry = new THREE.BoxBufferGeometry(2, 2, 2);
// create a orange Standard material
const material = new THREE.MeshStandardMaterial({ color: '#FF6347' });
// create a Mesh containing the geometry and material
mesh = new THREE.Mesh(geometry, material);
// add the mesh to the scene object
scene.add(mesh);复制代码
在有了场景和演员之后,就要开始拍大片了。那么,相机需要放在什么位置,其视角又应该如何设定呢?相机配置的参数稍微有点复杂,我们慢慢来看。
首先需要明确的是,为了在2D的浏览器上展示出人眼感觉的3D图像,我们的相机就要模拟人眼的成像原理。这里使用的是PerspectiveCamera,透视相机,基本成像原理用大白话来说,就是“近大远小”。透视原理的相机,需要4个参数,来定义其能看到范围(专业名称叫viewing frustum)。这四个参数分别为:fov, aspect, near, far。near是定义从相机多近的位置开始渲染场景,far是指相机能看到多远,这两个截面内的物体,才属于相机的可视范围。
fov是field of view的缩写,定义了视场的角度。aspect是渲染输出结果的横向长度和纵向长度的比值。由于这个例子会选用整个窗口作为输出界面,就用窗口的长宽比。这个长宽比决定了水平视场和垂直视场的比例关系。
// set up the options for a perspective camera
const fov = 35; // fov = Field Of View
const aspect = container.clientWidth / container.clientHeight;
const near = 0.1;
const far = 100;
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
// every object is initially created at ( 0, 0, 0 )
// move the camera back a bit so that we can view the scene
camera.position.set(0, 0, 10);复制代码
由于在上面添加物体的时候,我们并未声明具体位置,所以物体就被放置在了默认的位置(0,0,0)。所以这里,我们需要把相机的位置稍微往后一点,这样才能看到物体。
之后,我们可以再增加一个灯光,实现光照效果。灯光有很多效果可以选择,我们这里选用了最简单的光照效果,DirectionalLight。该效果是模拟单一光源的,从某个位置向四处发射光线,例如太阳。
// Create a directional light
const light = new THREE.DirectionalLight(0xffffff, 3.0);
// move the light back and up a bit
light.position.set(10, 10, 10);
// remember to add the light to the scene
scene.add(light);复制代码
在有了场景,物体,灯光后,就需要renderer来生成2D图像了,并将其插入canvas元素内。当调用WebGLRenderer,会自动生成一个HTML <canvas/>
。这里需要用renderer.setSize()来定义canvas画布的大小。在最初,这个canvas会被存在renderer.domElement里。之后采用浏览器内置的方法appendChild,将其插入到上文提到的HTML的钩子元素<div id="scene-container"/>
中。
container = document.querySelector('#scene-container');
......
// create a WebGLRenderer and set its width and height
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// add the automatically created canvas element to the page
container.appendChild(renderer.domElement);复制代码
之后要做的就是,告诉renderer我们所建立的场景和相机,让其渲染产生图像。
renderer.render( scene, camera );复制代码
代码写到这里,我们得到了这样的一个静态2D图像。
为了达到3D动态效果,我们需要让物体或相机动起来。这里,我们用比较简单的方法,让正方体运动起来。在animate函数不停地调用自己,利用requestAnimationFrame来处理调用频率。让正方体在每次函数调用时,在X,Y,Z方向都旋转一点点。并且每次都重新调用渲染函数,生成新的图像。
这些连续变化的图片连起来,就形成了我们想要的动画效果。
function animate() {
// call animate recursively
requestAnimationFrame(animate);
// increase the mesh rotation each frame
mesh.rotation.z += 0.01;
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}复制代码
-Three.js广告业务中的应用(个人瞎想...原创哦!!!)
在长篇介绍完Three.js之后,想必小伙伴们已经对它有了初步的了解。那么如何把自己业余时间的学习,与业务联系在一起呢?在此,发挥脑洞的时刻到了。由于本人是广告部门的,所以就初步地瞎想了一些可能用到的场景,如果小伙伴们有更cool的想法,欢迎一起讨论。
下面是自己初步做的一些小demo,欢迎轻拍~~~
1. 3D banner 广告 - 可以把banner广告立体化,用户可以从多角度来改变视角观赏巨幅banner,就有种大街上广告牌的感觉。
2. 3D交互式广告 - 可以把广告牌放置在一个3D空间里,然后用户探索式地去发现广告
此处简单地做了个例子,用户驾驶着可以飞的骑车,在浩瀚的太空中环游,并浏览广告
3. 3D动画广告 - 适合用在一些官网首页,用于效果宣传
4. 3D文字广告 - 通过3D变化 增强观看者对文字关键字的记忆
总的来说,我觉得Three.js在广告业务中的应用可以总结为两个方向(原创):
1)2D广告的图片直接依附于3D空间展示 - 因为2D空间是3D空间的一个子集,那么目前比较流行的2D图片广告,其实可以作为3D空间的一个面,依附于3D空间里。后续的开发基本就是增加各种物体与这个面的交互;
2)将广告创意直接涉及到3D界面里 - 让3D场景中的物体表达出广告的信息,例如后两种广告。更复杂的一点设想是,打造一个3D场景,例如城市街景,然后以游戏探索的方式,把广告加入进去。
以上就是我在业余时间初步学习Three.js并基于业务的一些想法,因为也是刚刚利用业余时间接触这个技术捏,如果有不足的地方,欢迎指出!如果有感兴趣的小伙伴,欢迎点赞留言我,我们一起探索!