background
Year of the Tiger 🐅
Spring Festival is approaching, this article uses the React
+ Three.js
technology stack to realize the interesting 3D
creative page. Knowledge contained herein include: ShadowMaterial
, MeshPhongMaterial
two basic materials, using LoadingManager
display model loading progress, OrbitControls
easing animation, TWEEN
between simple motion tween effects.
accomplish
👀
online preview, already adapted to mobile terminal: https://dragonir.github.io/3d/#/lunar
Introduce resources
Wherein GLTFLoader
, FBXLoader
for added models, OrbitControls
user orbit control lens, TWEEN
for generating inter-tween.
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";
scene initialization
This part of the content is mainly used to initialize the scene and parameters. For a detailed explanation, you can click the link at the end of the article to read my previous article, and I will not repeat it in this article.
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
// 场景
scene = new THREE.Scene();
scene.background = new THREE.TextureLoader().load(bgTexture);
// 雾化效果
scene.fog = new THREE.Fog(0xdddddd, 100, 120);
// 摄像机
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(100, 100, 100);
camera.lookAt(new THREE.Vector3(0, 0, 0));
// 平行光
const cube = new THREE.Mesh(new THREE.BoxGeometry(0.001, 0.001, 0.001), new THREE.MeshLambertMaterial({ color: 0xdc161a }));
cube.position.set(0, 0, 0);
light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(20, 20, 8);
light.target = cube;
scene.add(light);
// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
// 聚光灯
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-20, 20, -2);
scene.add(spotLight);
💡
Fog scene fog
In this example, when the page is model 161dcd6a0e98f1 is loaded from far to near, and the function that the color changes from white to color is realized by Fog
. Fog
class defines linear fog, and the density of fog increases linearly with distance, that is, the fog effect of objects in the scene changes linearly with distance.
Constructor : Fog(color, near, far)
.
color
attribute: Indicates the color of the fog. For example, if it is set to red, the distant object in the scene is black, the closest object in the scene is its own color, and the color of the object between the farthest and the closest is the mixture of the object's own color and the fog color.near
property: Indicates the minimum distance to apply the fog effectnear
from the active camera will not be affected by the fog.far
property: Indicates the maximum distance to apply the fog effectfar
from the active camera will not be affected by the fog.
Create the ground
In the present embodiment using the background image, I need a both display the background is transparent, the material can produce a shadow generate ground, then uses the ShadowMaterial
material.
var planeGeometry = new THREE.PlaneGeometry(100, 100);
var planeMaterial = new THREE.ShadowMaterial({ opacity: .5 });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(0, -8, 0);
plane.receiveShadow = true;
scene.add(plane);
💡
ShadowMaterial
This material can receive shadows, but is otherwise completely transparent.
constructor : ShadowMaterial(parameters: Object)
parameters
: (optional) An object that defines the appearance of the material, with one or more properties.
special attributes :
.isShadowMaterial[Boolean]
: Used to check if this class or a derived class is a shadow material. The default value istrue
. Since it is usually used for internal optimization, this property value should not be changed..transparent[Boolean]
: Defines whether this material is transparent or not. The default istrue
.
Create a magic circle
Create a cool spinning self-illuminating circular magic circle on the bottom ground of the tiger 🐅
cycle = new THREE.Mesh(new THREE.PlaneGeometry(40, 40), new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load(cycleTexture),
transparent: true
}));
cycle.rotation.x = -0.5 * Math.PI;
cycle.position.set(0, -9, 0);
cycle.receiveShadow = true;
scene.add(cycle);
Magic Array's sticker:
💡
MeshPhongMaterial
A material for glossy surfaces with specular highlights. This material uses the non-physical Blinn-Phong
model to calculate reflectance.
constructor : MeshPhongMaterial(parameters: Object)
parameters
: (optional) An object that defines the appearance of the material, with one or more properties.
special properties :
.emissive[Color]
: The emissive (light) color of the material, basically an inherent color unaffected by other lights. Default is black..emissiveMap[Texture]
: Sets the emission (glow) map. The default value isnull
. The emission map color is adjusted by the emission color and intensity. If you have an emission map, be sure to set the emission color to something other than black..emissiveIntensity[Float]
: Emitted light intensity. Adjust the glow color. Defaults to1
..shininess[Float]
:specular
, the higher the value, the brighter it is. The default value is30
..specular[Color]
: The specular color of the material. The default is0x111111
for the colorColor
. This defines the glossiness and glossy color of the material..specularMap[Texture]
: The specular map value affects how much the specular and the environment map affect the surface. The default value isnull
.
AndMeshLambertMaterial
used inLambertian
different models, can simulate the glossy surface of the material (e.g., painted wood) having a specular highlights. UsePhong
calculation coloring coloring model, calculates the shadow of each pixel, andMeshLambertMaterial
usedGouraud
compared to the model, the model is more accurate results, but at the expense of some performance.MeshStandardMaterial
andMeshPhysicalMaterial
also use this shading model. WhenMeshStandardMaterial
orMeshPhysicalMaterial
, performance is generally higher at the expense of some graphics precision.
text model
Use FBXLoader
to load the 061dcd6a0e9ef9 text model of Gong Xi 3D
const fbxLoader = new FBXLoader();
fbxLoader.load(textModel, mesh => {
mesh.traverse(child => {
if (child.isMesh) {
meshes.push(mesh);
child.castShadow = true;
child.receiveShadow = true;
// 调节材质的金属度、粗糙度、颜色等样式
child.material.metalness = .2;
child.material.roughness = .8;
child.material.color = new THREE.Color(0x111111);
}
});
mesh.position.set(4, 6, -8);
mesh.rotation.set(-80, 0, 0);
mesh.scale.set(.32, .32, .32);
group.add(mesh);
});
📹
3D
Text generation tutorial Portal: iBlender Chinese version plug-in foreigners teach you to use Chinese fonts Font 3D Chinese And Japanese Characters Blender plug-in tutorial
tiger model
Tiger model gltf
format, using GLTFLoader
loading process model, found 🕷 bug
, loader
can not read to the model volume total
value, then using a common loader LoadingManager
to manage model loading progress.
const manager = new THREE.LoadingManager();
manager.onStart = (url, loaded, total) => {};
manager.onLoad = () => {};
manager.onProgress = async(url, loaded, total) => {
if (Math.floor(loaded / total * 100) === 100) {
this.setState({ loadingProcess: Math.floor(loaded / total * 100) });
} else {
this.setState({ loadingProcess: Math.floor(loaded / total * 100) });
}
};
const gltfLoader = new GLTFLoader(manager);
gltfLoader.load(tigerModel, mesh => {
mesh.scene.traverse(child => {
if (child.isMesh) {
child.castShadow = true;
child.material.metalness = 0;
child.material.roughness = .8;
child.material.transparent = true;
child.material.side = THREE.DoubleSide;
child.material.color = new THREE.Color(0xffffff);
}
});
mesh.scene.rotation.y = Math.PI * 9 / 8;
mesh.scene.position.set(0, -4, 2);
mesh.scene.scale.set(.75, .75, .75);
// 💡 加载模型自身动画
let meshAnimation = mesh.animations[0];
mixer = new THREE.AnimationMixer(mesh.scene);
let animationClip = meshAnimation;
let clipAction = mixer.clipAction(animationClip).play();
animationClip = clipAction.getClip();
group.add(mesh.scene);
scene.add(group)
});
💡
LoadingManager Loader Manager
Its function is to process and keep track of loaded and pending data. If the hardening manager is not set manually, a default global instance loader manager is created and used for the loader. In general, the default load manager is sufficient, but sometimes it is necessary to set up separate loaders, for example, when you want to display separate load bars for objects and textures.
Constructor : LoadingManager(onLoad: Function, onProgress: Function, onError: Function)
onLoad
: optional, this function will be called when all loaders are loaded.onProgress
: optional, this function will be called when each item is complete.onError
: optional, this function will be called when a loader encounters an error.
attribute :
.onStart[Function]
: Called when loading starts. Parameters:url
loaded itemsurl
;itemsLoaded
currently has the number of add-ons;itemsTotal
total of the number of add-ons required. This method is undefined by default..onLoad[Function]
: This function will be called when all items are loaded. By default, this method is undefined unless passed in the constructor..onProgress[Function]
: This method loads each item and is called when the load is complete. Parameters:url
loaded itemsurl
;itemsLoaded
currently has the number of add-ons;itemsTotal
total of the number of add-ons required. By default, this method is undefined unless passed in the constructor..onError[Function]
: This method will be called on any item loading error. Parameters:url
of the wrong entryurl
. By default, this method is undefined unless passed in the constructor.
Add camera movement tweens
After the model is loaded, by using a combination TWEEN.js
achieve camera 📷
mobile roaming, that is, to see when you open the page model nearly progressively larger from far and animated.
const Animations = {
animateCamera: (camera, controls, newP, newT, time = 2000, callBack) => {
var tween = new TWEEN.Tween({
x1: camera.position.x,
y1: camera.position.y,
z1: camera.position.z,
x2: controls.target.x,
y2: controls.target.y,
z2: controls.target.z,
});
tween.to({
x1: newP.x,
y1: newP.y,
z1: newP.z,
x2: newT.x,
y2: newT.y,
z2: newT.z,
}, time);
tween.onUpdate(function (object) {
camera.position.x = object.x1;
camera.position.y = object.y1;
camera.position.z = object.z1;
controls.target.x = object.x2;
controls.target.y = object.y2;
controls.target.z = object.z2;
controls.update();
});
tween.onComplete(function () {
controls.enabled = true;
callBack();
});
tween.easing(TWEEN.Easing.Cubic.InOut);
tween.start();
},
}
export default Animations;
Example of calling:
Animations.animateCamera(camera, controls, { x: 0, y: 5, z: 21 }, { x: 0, y: 0, z: 0 }, 2400, () => {});
💡
TWEEN.js
Is a tween animation library that can achieve many animation effects. It makes an object easing from one state to another in a certain period of time. TWEEN.js
essence of 061dcd6a0ea2ec is a series of easing function algorithms. Combining Canvas
and Three.js
can easily achieve many effects.
basically uses :
var tween = new TWEEN.Tween({x: 1}) // position: {x: 1}
.delay(100) // 等待100ms
.to({x: 200}, 1000) // 1s时间,x到200
.onUpdate(render) // 变更期间执行render方法
.onComplete(() => {}) // 动画完成
.onStop(() => {}) // 动画停止
.start(); // 开启动画
📌
make the animation really move, you need to call the update
method requestAnimationFrame
TWEEN.update()
Easing Type :
TWEEN.js
most powerful part of 061dcd6a0ea3b5 is that it provides many commonly used easing animation types, specified api easing()
As used in the example:
tween.easing(TWEEN.Easing.Cubic.InOut);
chained calls to :
TWEEN.js
support chained calls, such as in after the end of the animation to be performed A
animation B, can do
tweenA.chain(tweenB)
take advantage of chained calls back and forth to create a cyclical animation:
var tweenA = new TWEEN.Tween(position).to({x: 200}, 1000);
var tweenB = new TWEEN.Tween(position).to({x: 0}, 1000);
tweenA.chain(tweenB);
tweenB.chain(tweenA);
tweenA.start();
Controller jog movement
controls.enableDamping
can be set to true
to enable the easing effect when the mouse moves the scene, resulting in motion inertia. After opening, 3D
more realistic.
controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.enableDamping = true;
controls.maxDistance = 160;
💡
THREE.OrbitControls Parameter control list
//鼠标控制是否可用
controls.enabled = true;
//聚焦坐标
controls.target = new THREE.Vector3();
//最大最小相机移动距离(PerspectiveCamera 景深相机)
controls.minDistance = 0;
controls.maxDistance = Infinity;
//最大最小鼠标缩放大小(OrthographicCamera正交相机)
controls.minZoom = 0;
controls.maxZoom = Infinity;
//最大仰视角和俯视角,范围是0到Math.PI
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI;
//水平方向视角限制,范围[-Math.PI, Math.PI]
controls.minAzimuthAngle = - Infinity;
controls.maxAzimuthAngle = Infinity;
//惯性滑动,滑动大小默认0.25,若开启,那么controls.update()需要加到动画循环函数中
controls.enableDamping = false;
controls.dampingFactor = 0.25;
//滚轮是否可控制zoom,zoom速度默认1
controls.enableZoom = true;
controls.zoomSpeed = 1.0;
//是否可旋转,旋转速度
controls.enableRotate = true;
controls.rotateSpeed = 1.0;
//是否可平移,默认移动速度为7px
controls.enablePan = true;
// 点击箭头键时移动的像素值
controls.keyPanSpeed = 7.0;
//是否自动旋转,自动旋转速度。默认每秒30圈,如果是enabled,那么controls.update()需要加到动画循环函数中
controls.autoRotate = false;
// 当fps为60时每转30s
controls.autoRotateSpeed = 2.0;
//是否能使用键盘
controls.enableKeys = true;
//默认键盘控制上下左右的键
controls.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
//鼠标点击按钮
controls.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
Finally don't forget to add the window scaling fit method and the requestAnimationFrame
update method.
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
let time = clock.getDelta();
// 老虎动画
mixer && mixer.update(time);
// 补间动画
TWEEN && TWEEN.update();
// 控制器
controls && controls.update();
// 魔法阵
cycle && (cycle.rotation.z += .01);
}
Loading page 3D text style
3D
mainly realized by superimposing multiple layers of text-shadow
.
.loading {
font-size: 64px;
color: #FFFFFF;
text-shadow: 0 1px 0 hsl(174,5%,80%),
0 2px 0 hsl(174,5%,75%),
0 3px 0 hsl(174,5%,70%),
0 4px 0 hsl(174,5%,66%),
0 5px 0 hsl(174,5%,64%),
0 6px 0 hsl(174,5%,62%),
0 7px 0 hsl(174,5%,61%),
0 8px 0 hsl(174,5%,60%),
0 0 5px rgba(0,0,0,.05),
0 1px 3px rgba(0,0,0,.2),
0 3px 5px rgba(0,0,0,.2),
0 5px 10px rgba(0,0,0,.2),
0 10px 10px rgba(0,0,0,.2),
0 20px 20px rgba(0,0,0,.3);
}
Effect
The final effect is shown in the figure below. If you are interested, you can preview it online. It has been adapted to the mobile terminal. by this accelerated 161dcd6a0ea624 cerebellum axe 🐅 animation.
Summarize
The main knowledge points involved in this article include:
Fog
scene foggingShadowMaterial
Shadow MaterialMeshPhongMaterial
mesh materialLoadingManager
Loader ManagerTWEEN.js
tweenTHREE.OrbitControls
parameter controlCSS
3D
Text style
appendix
To learn about scene initialization, lighting, shadows, and other mesh geometry, read my other articles. If you think the article is helpful to you, don't forget to one-click three-link 😂 .
- [1]. Use Three.js to achieve cool acid style 3D pages
- [2]. Three.js implements Facebook Metaverse 3D dynamic Logo
- [3]. Three.js implements a 3D panoramic detective game
- [4]. Model source: sketchfab
Author of this article: dragonir
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。