background
I recently learned WebGL
and Three.js
, so I want to decorate my homepage in combination with the acidic design style that is popular recently, and at the same time summarize some of the knowledge learned. This article mainly introduces that by using the React + three.js
technology stack, loading 3D model, adding
3D text, adding animation, click interaction, etc., with style design, to achieve the
🤢
acid style page full of design sense.
Basic knowledge
Three.js
Three.js
3D engine based on the native
WebGL
package and running in the browser. It can be used to create various 3D scenes, including cameras, light and shadow, materials and other objects. It is a very widely used 3D engine. You can learn more three.js official Chinese document
Acid design
term acid design is translated from
Acid Graphics
, which originated from acid house music, electronic dance music and hippie culture in the 1990s. In the field of design, this acidic aesthetic carries a
free proposition, grotesque graphics, bold and vivid colors, special material texture, and a variety of fonts to form a unique acidic design style.
In short, bright and highly saturated color combination; black-gray base and highly saturated
fluorescent color
colorful black dotted with the screen; full of futuristic, cool and technological sense
liquid metal,
glass,
aluminum foil plastic And other materials;
random elements, graphic layout;
repeating, cutting, combining
geometric figures, etc. are all acidic design styles. Acidic style has gradually become popular in music album covers, visual posters, book and movie covers, and web design.
Achieve effect
Online preview: https://tricell.fun
accomplish
3D model
Scene initialization
🌏
Create scene
scene = new THREE.Scene();
📷
Initialize the camera
PerspectiveCamera's
4 parameters respectively refer to: field of view, aspect ratio, near surface, and far surface.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置相机位置
camera.position.set(600, 20, -200);
// 相机聚焦到屏幕中央
camera.lookAt(new THREE.Vector3(0, 0, 0));
💡
Initialize the light source
Add HemisphereLight: Create a more natural light source for outdoor effects
light = new THREE.HemisphereLight(0xffffff, 0x444444);
light.position.set(0, 20, 0);
scene.add(light);
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 10);
light.castShadow = true;
scene.add(light);
Add AmbientLight:
var ambiColor = '#0C0C0C';
var ambientLight = new THREE.AmbientLight(ambiColor);
scene.add(ambientLight);
Add auxiliary tools (optional)
📦
Add auxiliary grid
GridHelper
can be used to add grid auxiliary lines, can also be used for decoration, through GridHelper(size, divisions, colorCenterLine, colorGrid)
achieve.
size
: Grid width, the default value is10
.divisions
: equal fraction, the default value is10
.colorCenterLine
: Center line color, the default value is0x444444
.colorGrid
: Grid line color, the default value is0x888888
.
var grid = new THREE.GridHelper(1000, 100, 0x000000, 0x000000);
grid.material.opacity = 0.1;
grid.material.transparent = true;
grid.position.set(0, -240, 0);
scene.add(grid);
📦
Add camera controls
Through the camera control OrbitControls
you can zoom, translate, and rotate the three-dimensional scene. What essentially changes is not the scene, but the parameters of the camera. OrbitControls.js
needs to be introduced separately during development.
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.update();
📦
add performance view plugin
stats
is an Three.js
, which is mainly used to detect the number of frames when the animation is running. stats.js
also needs to be introduced separately.
stats = new Stats();
container.appendChild(stats.dom);
Load the model
discus thrower statue
3D
model used in the example in this article is threedscans.com
and can be free at 16153a636408c5. There are multiple free model download sites at the end of this article. There are
free models with more than 200 pages. If you are interested, you can choose your own Download and use the favorite model. Of course, students with modeling ability can also use professional modeling software such as
blender
and 3dmax
Load obj
or fbx
model
It is necessary to separately import FBXLoader.js
or OBJLoader.js
. The model loading method of .fbx
and .obj
// var loader = new THREE.FBXLoader();
var loader = new THREE.OBJLoader();
loader.load(model, function (object) {
object.traverse(function (child) {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
object.rotation.y = Math.PI / 2;
object.position.set(0, -200, 0);
object.scale.set(0.32, 0.32, 0.32);
model = object;
scene.add(object);
});
Load gltf
model
GLTFLoader.js
needs to be introduced separately, and the .gltf
format model is slightly different. It should be noted that the traversal object of the model and the final added to the scene are object.scene
instead of object
.
var loader = new THREE.GLTFLoader();
loader.load(model, function (object) {
object.scene.traverse(function (child) {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
object.scene.rotation.y = Math.PI / 2;
object.scene.position.set(0, -240, 0);
object.scene.scale.set(0.33, 0.33, 0.33);
model = object.scene;
scene.add(object.scene);
});
The effect after adding the grid and loading the model is shown in the figure below.
Add turntable animation
Add the turntable animation effect by requestAnimationFrame
window.requestAnimationFrame()
tells the browser that it wants to execute an animation, and requires the browser to call the specified callback function to update the animation before the next redraw. This method needs to pass in a callback function as a parameter, and the callback function will be executed before the next browser redraw.
function animate () {
requestAnimationFrame(animate);
// 随着页面重绘不断改变场景的rotation.y来实现旋转
scene.rotation.y -= 0.015;
renderer.render(scene, camera);
}
Add click interaction
In the Three.js
scene, we need to click on a model to get its information, or do some other operations, we need to use Raycaster (ray casting), the principle is to emit a beam of rays at the position where you click with the mouse, and the objects in the ray are all Was recorded. The basic syntax is
Raycaster(origin, direction, near, far)
, where:
origin
: the starting point vector of the ray.direction
: The direction vector of the ray.near
: All returned results should be farthernear
The value cannot be negative, the default value is0
.far
: All returned results should be closer thanfar
. It cannot be smaller thannear
, and the default value isinfinity.
The basic steps of the code implementation are: get the coordinates of the mouse on the screen →
screen coordinates to standard device coordinates →
standard device coordinates to world coordinates →
get the world coordinates of the mouse in the scene →
according to the world coordinates and the camera to generate the ray projection direction unit vector →
according to The ray casting direction unit vector creates a ray projector object.
//声明raycaster和mouse变量
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
onMouseClick = event => {
// 将鼠标点击位置的屏幕坐标转成threejs中的标准坐标,以屏幕中心为原点,值的范围为-1到1.
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
// 通过鼠标点的位置和当前相机的矩阵计算出raycaster
raycaster.setFromCamera(mouse, camera);
// 获取raycaster直线和所有模型相交的数组集合
let intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
alert('HELLO WORLD')
// 可以通过遍历实现点击不同mesh触发不同交互,如:
let selectedObj = intersects[0].object;
if (selectedObj.name === 'car') {
alert('汽车🚗')
}
}
}
window.addEventListener('click', onMouseClick, false);
Add 3D text
Use TextGeometry(text : String, parameters : Object)
add 3D text, the following is the description of the attributes that can be set:
size
: Font size, generally the height of a capital letter.height
: The thickness of the text.weight
: The value isnormal
orbold
, indicating whether it is bold or not.font
: Font, the default ishelvetiker
, which needs to correspond to the referenced font file.style
: The value isnormal
oritalics
, indicating whether it is italicbevelThickness
: Chamfer thickness.bevelSize
: Chamfer width.curveSegments
: The number of arc segments, making the curve of the text smoother.bevelEnabled
: Boolean value, whether to use chamfer or not, meaning to cut at the edge.
var loader = new THREE.FontLoader();
loader.load('gentilis_regular.typeface.json', function (font) {
var textGeo = new THREE.TextGeometry('HELLO WORLD', {
font: font,
size: .8,
height: .8,
curveSegments: .05,
bevelThickness: .05,
bevelSize: .05,
bevelEnabled: true
});
var textMaterial = new THREE.MeshPhongMaterial({ color: 0x03c03c });
var mesh = new THREE.Mesh(textGeo, textMaterial);
mesh.position.set(0, 3.8, 0);
scene.add(mesh);
});
optimization
Now the model loading has been basically completed, but 3D
model is generally relatively large. After deployment, I found that the web page loads very slowly, which affects the user experience. It is very necessary to reduce the model size. After looking for a compression tool on the Internet for a long time, I found If you need to install the large-scale 3D modeling software, using
obj2gltf
can convert the larger OBJ
format model to the gltf
model, effectively optimizing the model size and improving the web page loading speed.
Install
npm install obj2gltf --save
Copy the obj model to the following directory
node_modules\obj2gltf\bin
Execute transcoding instructions
node obj2gltf.js -i demo.obj -o demo.gltf
FIG appear similar to the above, transcoding is complete, the file size before and after conversion contrast, in the present embodiment kas.obj
initial file size 9.7M
converted file kas.gltf
only 4.6M
, the volume reduced by half, then the model is loaded onto the page transformed , The naked eye can hardly see the change of the model effect, and the page loading speed has been significantly improved.
obj2gltf
can also be used as a library, through thenode service real-time conversion model, interested students can learn more through the link at the end of the article.
May be used3D
modeling software such asblender
other hand by reducing the modelnumber of faces and
reduce the volume compression optimization model for other ways, such optimization is more effective.
Complete code
var model = require('@/assets/models/kas.gltf');
var container, stats, controls;
var camera, scene, renderer, light, model;
class Kas extends React.Component {
render () {
return (
<div id="kas"></div>
)
}
componentDidMount () {
this.initThree();
}
initThree () {
init();
animate();
function init () {
container = document.getElementById('kas');
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000);
// 透视相机:视场、长宽比、近面、远面
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(600, 20, -200);
camera.lookAt(new THREE.Vector3(0, 0, 0));
// 半球光源:创建室外效果更加自然的光源
light = new THREE.HemisphereLight(0xffffff, 0x444444);
light.position.set(0, 20, 0);
scene.add(light);
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 10);
light.castShadow = true;
scene.add(light);
// 环境光
var ambiColor = '#0C0C0C';
var ambientLight = new THREE.AmbientLight(ambiColor);
scene.add(ambientLight);
// 网格
var grid = new THREE.GridHelper(1000, 100, 0x000000, 0x000000);
grid.material.opacity = 0.1;
grid.material.transparent = true;
grid.position.set(0, -240, 0);
scene.add(grid);
// 加载gltf模型
var loader = new THREE.GLTFLoader();
loader.load(model, function (object) {
object.scene.traverse(function (child) {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
object.scene.rotation.y = Math.PI / 2;
object.scene.position.set(0, -240, 0);
object.scene.scale.set(0.33, 0.33, 0.33);
model = object.scene;
scene.add(object.scene);
});
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearAlpha(0);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}, false);
stats = new Stats();
container.appendChild(stats.dom);
}
function animate () {
var clock = new THREE.Clock()
requestAnimationFrame(animate);
var delta = clock.getDelta();
scene.rotation.y -= 0.015;
renderer.render(scene, camera);
stats.update();
}
// 增加点击事件
//声明raycaster和mouse变量
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseClick(event) {
// 通过鼠标点击位置计算出raycaster所需要点的位置,以屏幕中心为原点,值的范围为-1到1.
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
// 通过鼠标点的位置和当前相机的矩阵计算出raycaster
raycaster.setFromCamera(mouse, camera);
// 获取raycaster直线和所有模型相交的数组集合
var intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
alert('HELLO WORLD')
}
}
window.addEventListener('click', onMouseClick, false);
}
}
Other design elements
This article mainly introduces 3D elements. Due to the limited length and time of the article (
bloggers are too lazy 😂) The implementation of other elements will not be explained in detail (maybe later there will be time to summarize and organize
maybe
) interested students can expand and read the following other Excellent article by Great God.
Fluid background
Static liquid background image can be achieved by
SVG filter
, you can read "Creating Patterns With SVG Filters" , to achieve dynamic fluid background, you can use Three.js combined with native GLSL to achieve, you can refer to "CodePen Shader Templatebc" .
Acidic fonts such as metal, neon, glitch effects, etc. can read my other article "Cyberpunk 2077 style visual effects in just a few steps with CSS" , or you can use design generation, due to time constraints, this project The metal effect text and the text in the banner header of this article are all online artistic font generation website . Interested students can try to design by themselves.
Further optimization in the future
#todo
Acidic style liquid background realization.#todo
3D model liquid metal effect.
three.js
Excellent case recommendation
Finally, I recommend a few very amazing three.js
projects to experience and learn together. Whether it is page interaction, visual design or performance optimization, they have achieved the ultimate, and you can learn a lot from them.
- github home page :
3D earth real-time display of global popular warehouses.
- kodeclubs : Low-
3D city third-person game.
- sneaker display :
720 degree sneaker dynamic display.
- sand sculpture dance : sand sculpture animal dancers.
- Zenly Software :
Zenly App
Chinese homepage.
Reference
- three.js: https://threejs.org
- obj2gltf: https://github.com/CesiumGS/obj2gltf
- More than 200 pages of free 3d models https://www.turbosquid.com
- Free 3D statue: https://threedscans.com
- Free 3D model: https://free3d.com
- Artistic font generation online: https://cooltext.com
- What is acid design: https://www.shejipi.com/361258.html
address of this article: 16153a636418bb https://segmentfault.com/a/1190000040753633
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。