qq最新版本怎么画生日蛋糕(Three)

首页教程更新时间:2023-05-16 08:07:25

作为整天和 UI 打交道的前端工程师,是否想在他(她)生日的时候用代码送上一份惊喜呢?

不妨用 Three.js 做个 3D 的蛋糕送给 ta,既浪漫又能展现你技术的魅力。

这篇文章我们就来学习下如何用 Three.js 画一个蛋糕。

图片

代码地址:https://github.com/QuarkGluonPlasma/threejs-exercize

Three.js 相关基础

Three.js 是通过场景 Scene 来管理所有的物体的,加到 Scene 的物体还可以分个组:

const scene = new THREE.Scene();

scene.add(xxx);

const group = new THREE.Group();

group.add(yyy);

group.add(zzz);

scene.add(group);

想要把 Scene 中的所有物体渲染出来,需要指定一个相机 camera,然后用 renderer 来渲染,如果有动画效果,要用 requestAnimationFrame 来一帧帧不断渲染。

const renderer = new THREE.WebGLRenderer();

function render() {

renderer.render(scene, camera);

requestAnimationFrame(render);

}

render();

相机 camera 分为从一个点去看的透视相机 PerspectiveCamera,还有从一个面去投影的正交相机 OrthographicCamera。

图片

图片

透视相机的特点是近大远小,而正交的则不是,就是一个平行投影,大小不变。

三维世界还需要指定一个光源,不然是全黑的,光源种类很多,常用的有这些:

点光源:从一个点发射光线,就像灯泡一样。

平行光:平行的光线

环境光:均匀照射每个地方

聚光灯:舞台聚光灯的光源

三维场景中的物体有很多种,比如永远面向相机的平面是 Sprite(我们做“漫天花雨”效果用的那个),还有由三角形构成的物体叫做 Mesh。

图片

Mesh 比较常用,它是由一个个三角形构成的几何体,还可以在每个面上贴图。所以,参数有两个,几何体 Geometry 和材质 Material。

比如圆柱体就是一个 Mesh,创建它的时候要指定圆柱几何体 CylinderBufferGeometry 和每个面的材质 Material。

const 圆柱几何体 = new THREE.CylinderBufferGeometry(上圆半径, 下圆半径, 高度, 侧面分段数量);

const 侧面材质 = new THREE.MeshBasicMaterial({map: 纹理图片});

const 上面材质 = new THREE.MeshBasicMaterial({color: 'red'});

const 下面材质 = new THREE.MeshBasicMaterial({color: 'red'});

const 圆柱 = new THREE.Mesh(圆柱几何体, [侧面材质, 上面材质, 下面材质]);

MeshBasicMaterial 是基础的材质,可以通过 color 来指定颜色,也可以通过 map 来指定纹理图片 texture。

各种 Mesh 中比较特殊是文字,它用的是 TextGeometry,文字需要从一个 xxx.typeface.json 中加载。

而这种 json 文件可以用字体文件 ttf 来转换得到。用ttf 转 typeface.json 的这个网站来转:

图片

之后就可以显示文字了:

const fontLoader = new THREE.FontLoader();

fontLoader.load('./font/xxx.typeface.json', function (font) {

var textGeometry = new THREE.TextGeometry('文字', 参数);

const textMaterial = [

new THREE.MeshBasicMaterial({color: '字体颜色'}),

new THREE.MeshBasicMaterial({color: '侧面颜色'}),

];

const text = new THREE.Mesh(textGeometry, textMaterial);

});

这些就是我们会用到的 Three.js 基础,简单做个小结:

Three.js 是通过 Scene 来管理各种物体的,物体还可以分下组。

物体中常见的有 Mesh 和 Sprite 等,Sprite 是永远面向相机的一个平面,Mesh 是由三角形构成的三维物体。Mesh 要指定几何体Geometry 和材质 Material,常用的材质可以是颜色或者纹理贴图。其中文字 TextGeometry 比较特殊,需要一个 typeface.json 的文件,这个可以由 ttf 转换得到。

场景中的物体准备好之后,还需要设置下光源 Light 和相机 Camera,相机主要有从点去看的透视相机和从一个平面去投影的正交相机,之后就可以通过渲染器 Renderer 渲染出来了,结合 requestAnimationFrame 来一帧帧的渲染。

基础学完之后,正式开始画蛋糕了。

画 3D 蛋糕

蛋糕其实就是由 4 个圆柱体加上文字构成的,每个圆柱体都设置了不同的位置,圆柱体的侧面和上下面都贴上不同的贴图,就是一个蛋糕。

我们先准备蛋糕的贴图:

图片

图片

图片

图片

使用纹理加载器 TextureLoader 去加载他们:

const cakeTexture1 = new THREE.TextureLoader().load('img/cake1.png');

const cakeTexture2 = new THREE.TextureLoader().load('img/cake2.png');

const cakeTexture3 = new THREE.TextureLoader().load(`img/cake3.png`);

const cakeTexture4 = new THREE.TextureLoader().load('img/cake4.png');

然后构成纹理贴图的材质:

const cakeMaterail1 = new THREE.MeshBasicMaterial({map: cakeTexture1});

const cakeMaterail2 = new THREE.MeshBasicMaterial({map: cakeTexture2});

const cakeMaterail3 = new THREE.MeshBasicMaterial({map: cakeTexture3});

const cakeMaterail4 = new THREE.MeshBasicMaterial({map: cakeTexture4});

除了纹理贴图的材质外,再准备个颜色构成的材质:

const pinkMaterial = new THREE.MeshBasicMaterial({color: 'pink'});

然后创建 4 个圆柱体的物体(Mesh),使用不同的贴图材质和颜色材质:

const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);

const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);

圆柱体的几何体 CylinderBufferGeometry 的参数分别是 上面圆的半径,下面圆的半径,高度,侧面的分割次数。

上面圆半径保持一致,这样才是圆柱体。侧面分割次数设置为 40,这样比较圆滑。

之后还设置下位移,然后就可以加到蛋糕分组里了。

我们用同样的方式创建四个圆柱体,设置不同的大小和位置,贴不同的图:

const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);

const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);

cakePart1.translateY(45)

const cakeGeometry2 = new THREE.CylinderBufferGeometry(120, 120, 70, 40);

const cakePart2 = new THREE.Mesh(cakeGeometry2,[cakeMaterail3, pinkMaterial, pinkMaterial]);

cakePart2.translateY(-25)

const cakeGeometry3 = new THREE.CylinderBufferGeometry(140, 140, 60, 40);

const cakePart3 = new THREE.Mesh(cakeGeometry3, [cakeMaterail2, pinkMaterial, pinkMaterial]);

cakePart3.translateY(-90)

const cakeGeometry4 = new THREE.CylinderBufferGeometry(160, 160, 10, 40);

const cakePart4 = new THREE.Mesh(cakeGeometry4, [cakeMaterail4, cakeMaterail4, cakeMaterail4]);

cakePart4.translateY(-120)

cake.add(cakePart1)

cake.add(cakePart2)

cake.add(cakePart3)

cake.add(cakePart4)

如果对坐标位置拿不准,可以在 Scene 中加上一个坐标的辅助工具 AxisHelper。参数是坐标轴长度。

const axisHelper = new THREE.AxisHelper(2500);

scene.add(axisHelper);

图片

然后是文字的部分,这个要先通过字体文件 ttf 转成 typeface.json 的文件,然后用 fontLoader 来加载,之后创建相应的 Mesh:

fontLoader.load('./font/guang.typeface.json', function (font) {

var textGeometry = new THREE.TextGeometry('光光', {

font: font,

size: 30,

height: 5,

bevelEnabled: true,

bevelSize: 10,

});

const textMaterial = ['white', 'red'].map(color => new THREE.MeshBasicMaterial({color}));

const text = new THREE.Mesh(textGeometry, textMaterial);

text.translateY(90)

text.translateX(-45)

cake.add(text);

});

TextGeometry 需要设置的参数有字体大小 size,厚度 height,以及边缘是否是曲面 bevelEnabled,和曲面的大小 bevelSize。

我们这里的效果是需要开启曲面的。

图片

4 个圆柱体画完了,文字也画完了,那蛋糕就算是画完了,之后设置下光源、相机,就可以用 Renderer 渲染了。

光源使用环境光,因为要均匀的照射:

const light = new THREE.AmbientLight(0xCCCCCC);

scene.add(light);

相机使用正交相机,因为不需要近大远小的透视效果:

const width = window.innerWidth;

const height = window.innerHeight;

//窗口宽高比

const k = width / height;

//三维场景显示范围的高度

const s = 200;

const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);

camera.position.set(0, 100, 500)

camera.lookAt(scene.position);

正交相机的参数分别是左右上下远近的三维视野范围,我们指定高度为 200,然后根据窗口的宽高比算出宽度。远近可以设置一个比较大的范围。

之后就可以用 Renderer 来渲染了。把渲染出的 canvas 的 dom 挂载到 body 上。

const renderer = new THREE.WebGLRenderer();

renderer.setSize(width, height);

//设置背景颜色

renderer.setClearColor(0xFFFFFF, 1);

document.body.appendChild(renderer.domElement);

function render() {

renderer.render(scene, camera);

cake.rotation.y = 0.005;

requestAnimationFrame(render)

}

render()

在每帧 render 之前,还做了个围绕 y 轴的自动旋转。

还要支持手动的旋转,这个直接使用 Three.js 的轨道控制器 OrbitControls 就行。

const controls = new THREE.OrbitControls(camera);

参数是相机,因为这种视野的改变就是通过改变相机位置和朝向来实现的。

创建了 Scene 中的蛋糕的每一部分,设置好了光源、相机,用渲染器做了一帧帧的渲染,并且添加了用鼠标来改变视角的轨道控制器之后,就完成了 3D 蛋糕的制作。

我们来看下效果:

图片

代码地址:https://github.com/QuarkGluonPlasma/threejs-exercize

全部代码:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>生日蛋糕</title>

<style>

body {

margin: 0;

overflow: hidden;

}

</style>

<script src="./js/three.js"></script>

<script src="./js/OrbitControls.js"></script>

</head>

<body>

<script>

const width = window.innerWidth;

const height = window.innerHeight;

//窗口宽高比

const k = width / height;

//三维场景显示范围的宽度

const s = 200;

const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);

const fontLoader = new THREE.FontLoader();

const scene = new THREE.Scene();

const cake = new THREE.Group();

const renderer = new THREE.WebGLRenderer();

function create() {

renderer.setSize(width, height);

//设置背景颜色

renderer.setClearColor(0xFFFFFF, 1);

document.body.appendChild(renderer.domElement);

camera.position.set(0, 100, 500)

camera.lookAt(scene.position);

const light = new THREE.AmbientLight(0xCCCCCC);

scene.add(light);

const axisHelper = new THREE.AxisHelper(2500);

scene.add(axisHelper);

const cakeTexture1 = new THREE.TextureLoader().load('img/cake1.png');

const cakeTexture2 = new THREE.TextureLoader().load('img/cake2.png');

const cakeTexture3 = new THREE.TextureLoader().load(`img/cake3.png`);

const cakeTexture4 = new THREE.TextureLoader().load('img/cake4.png');

const cakeMaterail1 = new THREE.MeshBasicMaterial({map: cakeTexture1});

const cakeMaterail2 = new THREE.MeshBasicMaterial({map: cakeTexture2});

const cakeMaterail3 = new THREE.MeshBasicMaterial({map: cakeTexture3});

const cakeMaterail4 = new THREE.MeshBasicMaterial({map: cakeTexture4});

const pinkMaterial = new THREE.MeshBasicMaterial({color: 'pink'});

const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);

const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);

cakePart1.translateY(45)

const cakeGeometry2 = new THREE.CylinderBufferGeometry(120, 120, 70, 40);

const cakePart2 = new THREE.Mesh(cakeGeometry2,[cakeMaterail3, pinkMaterial, pinkMaterial]);

cakePart2.translateY(-25)

const cakeGeometry3 = new THREE.CylinderBufferGeometry(140, 140, 60, 40);

const cakePart3 = new THREE.Mesh(cakeGeometry3, [cakeMaterail2, pinkMaterial, pinkMaterial]);

cakePart3.translateY(-90)

const cakeGeometry4 = new THREE.CylinderBufferGeometry(160, 160, 10, 40);

const cakePart4 = new THREE.Mesh(cakeGeometry4, [cakeMaterail4, cakeMaterail4, cakeMaterail4]);

cakePart4.translateY(-120)

cake.add(cakePart1)

cake.add(cakePart2)

cake.add(cakePart3)

cake.add(cakePart4)

fontLoader.load('./font/guang.typeface.json', function (font) {

var textGeometry = new THREE.TextGeometry('光光', {

font: font,

size: 30,

height: 5,

bevelEnabled: true,

bevelSize: 10,

});

const textMaterial = ['white', 'red'].map(color => new THREE.MeshBasicMaterial({color}));

const text = new THREE.Mesh(textGeometry, textMaterial);

text.translateY(90)

text.translateX(-45)

cake.add(text);

});

scene.add(cake);

}

function render() {

renderer.render(scene, camera);

cake.rotation.y = 0.005;

requestAnimationFrame(render)

}

create()

render()

const controls = new THREE.OrbitControls(camera);

</script>

</body>

</html>

总结

本文我们用 Three.js 来实现了 3D 蛋糕的效果。

首先我们学习了下 Three.js 的基础:通过 Scene 来管理物体,物体可以分组,物体包括 Mesh、Sprite 等,Mesh 是三角形构成的 3D 物体,要分别指定几何体 Geometry 和材质 Material。材质可以是纹理(Texture)贴图、也可以是颜色。其中文字的 Mesh 需要做 ttf 到 typeface.json 的转换,加载这个 json 才能显示文字。

物体创建完了之后,还要设置相机、灯光等,然后通过渲染器来一帧帧的渲染。

调试的时候还可以添加 AxisHelper 坐标系辅助工具来辅助开发。

然后我们实现了 3D 蛋糕:

通过 4 个圆柱体 文字来画的,圆柱体用了不同的纹理贴图材质,设置了不同的位置,然后组成蛋糕的 group。

设置了环境光,使用了正交相机,还启用了轨道控制器 OrbitControls,来实现鼠标拖拽改变相机位置,进而改变视野角度的效果。

下个他(她)的生日,不妨试试用 Three.js 画个蛋糕送给他(她),或许会有不一样的收获哦。

,
图文教程
相关文章
热门专题
推荐软件
奇热小说
奇热小说
下载
QQ2019手机版
QQ2019手机版
下载
王者荣耀
王者荣耀
下载
百度浏览器迷你版
百度浏览器迷你版
下载
2345浏览器手机版
2345浏览器手机版
下载
网易邮箱
网易邮箱
下载
爱奇艺
爱奇艺
下载
网易云音乐
网易云音乐
下载
WPSOffice
WPSOffice
下载
优酷
优酷
下载
谷歌浏览器(Chrome)
谷歌浏览器(Chrome)
下载
迅雷看看播放器
迅雷看看播放器
下载
UC浏览器
UC浏览器
下载
QQ音乐
QQ音乐
下载
阿里旺旺买家版v9.12.10C官方版
阿里旺旺买家版v9.12.10C官方版
下载
360安全卫士v12.1官方版
360安全卫士v12.1官方版
下载
猜你喜欢
海贼无双4
海贼无双4
下载
美味餐厅9安卓版
美味餐厅9安卓版
下载
真三国无双7猛将传郭淮伪觉醒装mod
真三国无双7猛将传郭淮伪觉醒装mod
下载
IE7.0beta1
IE7.0beta1
下载
门窗测量大师
门窗测量大师
下载
朵拉教英语app
朵拉教英语app
下载
图腾方块大作战2
图腾方块大作战2
下载
灵域仙魔GM版
灵域仙魔GM版
下载
B安管家
B安管家
下载
拆了老王家
拆了老王家
下载
海象金服
海象金服
下载
双系统启动菜单自动修复工具(BCDautofix)V1.0.5
双系统启动菜单自动修复工具(BCDautofix)V1.0.5
下载
南昌+
南昌+
下载
兔子伪装术
兔子伪装术
下载
虚拟家庭2金钱修改器
虚拟家庭2金钱修改器
下载
山西农安通
山西农安通
下载