8. threejs study notes-renderer and front-end UI interface

Friendly links: threejs Chinese documentation

Table of contents

1. three.js Canvas canvas layout

Canvas element

Case source code "CSS layout case.html"

 threejs Canvas canvas size settings

Canvas changes with the window 

2. threejs transparency

.setClearAlpha() method

background transparent alpha: true

 3. Threejs saves the rendering result as an image

Hyperlink element a download file

Configure webgl renderer

Button binding mouse events 

3. Deep conflict (model flickering)

Mesh model coincidence rendering test

Change model position

4. Model loading progress bar

Progress bar HTML, CSS, JavaScript code

threejs code

1. three.js Canvas canvas layout

Canvas element

Canvas is one of the elements of HTML. The CSS layout rules of the Canvas element are similar to other HTML elements such as div and img. Webgl relies on canvas implementation. Threejs is encapsulated based on webgl, so it naturally also relies on canvas. Specifically, the three fields The scene is rendered to the canvas.

<!-- canvas元素默认是行内块元素 -->
<canvas style="background-color: #ff0000;" width="300" height="180"></canvas>

Case source code "CSS layout case.html"

<head>
    <style>
        body {
            overflow: hidden;
            margin: 0px;
        }
    </style>
</head>
<body style="background: #555555;">
    <div style="height: 55px;background-color: #444444;">上面布局</div>
    <!-- 下 -->
    <div>
        <div id="left" style="position: absolute;top: 60px;background-color: #444444;width: 195px;">下面左侧布局</div>
        <div id="webgl" style="position: absolute;top: 60px;left: 200px;background-color: #444444;">下面右侧布局</div>
    </div>
    <script>
        const width = window.innerWidth - 200;
        const height = window.innerHeight - 60;
        document.getElementById('left').style.height = height + 'px';
        document.getElementById('webgl').style.width = width + 'px';
        document.getElementById('webgl').style.height = height + 'px';
    </script>
</body>

 threejs Canvas canvas size settings

  • The width of the canvas canvas: window.innerWidth minus the left div element width of 195px and the layout spacing of 5px
  • The height of the canvas canvas: window.innerHeight minus the top div element height of 55px and the layout spacing of 5px
// 200表示左侧div元素宽度195px+间距5px
const width = window.innerWidth - 200; //canvas画布高度
//60表示顶部div元素高度55px+间距5px
const height = window.innerHeight - 60; //canvas画布宽度
...
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
renderer.setSize(width, height);

Canvas changes with the window 

// 画布跟随窗口变化
window.onresize = function () {
    const width = window.innerWidth - 200; //canvas画布高度
    const height = window.innerHeight - 60; //canvas画布宽度
    renderer.setSize(width, height);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
};

2. threejs transparency

 When rendering a model through Three.js, you do not want the canvas to have a background color, that is, the canvas is completely transparent. You can see the HTML element graphics and text superimposed behind the canvas through the canvas, presenting a three-dimensional model suspended on the web page. The effect above.

.setClearAlpha() method

Change background transparency value

renderer.setClearAlpha(0.8);

background transparent alpha: true

// 在构造函数参数中设置alpha属性的值
const renderer = new THREE.WebGLRenderer({
  alpha: true
});

 3. Threejs saves the rendering result as an image

Hyperlink element a download file

Before learning the following content, if you are interested, you can choose to supplement the front-end related knowledge. Specifically, synthesize a file through the hyperlink element a and download it.

<button type="button" name="button" onclick="saveFile()">下载</button>
<script>
  function saveFile() {
    // 创建一个超链接元素,用来下载保存数据的文件
    const link = document.createElement('a');
    // 通过超链接herf属性,设置要保存到文件中的数据
    link.href = window.URL.createObjectURL(new Blob(['一些数据']));
    link.download = '文件名称.txt';//下载文件名
    link.click();//js代码触发超链接元素a的鼠标点击事件,开始下载文件到本地
  }
</script>

Configure webgl renderer

// WebGL渲染器设置
const renderer = new THREE.WebGLRenderer({
    //想把canvas画布上内容下载到本地,需要设置为true
    preserveDrawingBuffer:true,
});

Button binding mouse events 

Canvas canvas can obtain pixel information on the canvas through the .toDataURL() method. canvas.toDataURL("image/png"); means to obtain pixel data in png format, which can be directly assigned to the .herf attribute of hyperlink element a and downloaded locally.

// 鼠标单击id为download的HTML元素,threejs渲染结果以图片形式下载到本地
document.getElementById('download').addEventListener('click',function(){
    // 创建一个超链接元素,用来下载保存数据的文件
    const link = document.createElement('a');
    // 通过超链接herf属性,设置要保存到文件中的数据
    const canvas = renderer.domElement; //获取canvas对象
    link.href = canvas.toDataURL("image/png");
    link.download = 'threejs.png'; //下载文件名
    link.click(); //js代码触发超链接元素a的鼠标点击事件,开始下载文件到本地
})

3. Deep conflict (model flickering)

During development, if there are two overlapping rectangular plane Mesh, and you preview it through the browser, when you rotate the 3D scene, you will find that the model flickers when rendering.

This phenomenon is mainly due to the overlap of two Mesh, and the computer GPU cannot tell who is in front and who is behind. This phenomenon can be called deep conflict Z-fighting.

Mesh model coincidence rendering test

// 两个矩形平面Mesh重合,产生闪烁
// 闪烁原因:两个矩形面位置重合,GPU无法分清谁在前谁在后
const geometry = new THREE.PlaneGeometry(250, 250);
const material = new THREE.MeshLambertMaterial({
    color: 0x00ffff,
    side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);

const geometry2 = new THREE.PlaneGeometry(300, 300); 
const material2 = new THREE.MeshLambertMaterial({
    color: 0xff6666,
    side: THREE.DoubleSide,
});
const mesh2 = new THREE.Mesh(geometry2, material2);

Change model position

Change the position of the Mesh and increase the distance between the two meshes so that they do not overlap.

mesh2.position.z = 1;

4. Model loading progress bar

During project development, many large 3D models load very slowly. At this time, it is often necessary to add a progress bar to indicate the loading progress of the model.

Progress bar HTML, CSS, JavaScript code

<head>
    <style>
        /* 进度条css样式 */
        #container {
            position: absolute;
            width: 400px;
            height: 16px;
            top: 50%;
            left:50%;
            margin-left: -200px;
            margin-top: -8px;
            border-radius: 8px;           
            border: 1px solid #009999;          
            overflow: hidden;
        }
        #per {
            height: 100%;
            width: 0px;
            background: #00ffff;
            color: #00ffff;
            line-height: 15px;          
        }
    </style>
</head>
<body style="background-color: #001111;">
    <div id="container">
        <!-- 进度条 -->
        <div id="per"> </div>
    </div>
    <script>        
        const percentDiv = document.getElementById("per");// 获取进度条元素
        percentDiv.style.width = 0.8*400 + "px";//进度条元素长度
        percentDiv.style.textIndent = 0.8*400 + 5 +"px";//缩进元素中的首行文本
        percentDiv.innerHTML =  "80%";//进度百分比
    </script>
</body>

threejs code

For the .load() method of the model loader, parameter one is the model path; parameter two is a function that is called after loading; parameter three is a function that will be called every time the model loads part of the content. It is generally called multiple times during the loading process until the model is loaded. jiu

const percentDiv = document.getElementById("per"); // 获取进度条元素
loader.load("../工厂.glb", function (gltf) {
    model.add(gltf.scene);
    // 加载完成,隐藏进度条
    // document.getElementById("container").style.visibility ='hidden';
    document.getElementById("container").style.display = 'none';
}, function (xhr) {
    // 控制台查看加载进度xhr
    // 通过加载进度xhr可以控制前端进度条进度   
    const percent = xhr.loaded / xhr.total;
    console.log('加载进度' + percent);
     
   
    percentDiv.style.width = percent * 400 + "px"; //进度条元素长度
    percentDiv.style.textIndent = percent * 400 + 5 + "px"; //缩进元素中的首行文本
    // Math.floor:小数加载进度取整
    percentDiv.innerHTML = Math.floor(percent * 100) + '%'; //进度百分比
})

 Some of the materials in the article are selected from Threejs Chinese website: Three.js Chinese website

 

Guess you like

Origin blog.csdn.net/weixin_60645637/article/details/131488026