· Create the world is committed to creating the first “cloud CAD” collaborative design platform integrating viewing, modeling, assembly and rendering in China.

At the request of readers, we hope to set up a professional WEBGL and Threejs industry QQ communication group for front-end developers in Chengdu-Chongqing area to facilitate discussion. There are webGL and Threejs in the group, welcome to join! — Click the link to join the group chat [three.js/ webGL Chongqing Union Group] : jq.qq.com/?_wv=1027&k…

screenshots

In the browser, there are two effective ways to capture the screen. The old Canvas.todataURL and the new Canvas.toblob

It’s easy to think of a way to take a screen shot

   <canvas id="c"></canvas>
   <button id="screenshot" type="button">Save...</button>
Copy the code
   const elem = document.querySelector('#screenshot');
   elem.addEventListener('click'.() = > {
       canvas.toBlob((blob) = > {
           saveBlob(blob, `screencapture-${canvas.width}x${canvas.height}.png`);
       });
   });
    
   const saveBlob = (function() {
       const a = document.createElement('a');
       document.body.appendChild(a);
       a.style.display = 'none';
       return function saveData(blob, fileName) {
           const url = window.URL.createObjectURL(blob); a.href = url; a.download = fileName; a.click(); }; } ());Copy the code

The actual test came down to an all-black screenshot

The problem is that, for performance and compatibility reasons, the browser clears the drawing buffer of the WebGL canvas by default after you have drawn it.

The solution is to call the render code before capturing.

Something needs to be tweaked in the code. Let’s isolate the rendering code.

   const state = {
   time: 0};function render(time) {
   time *= 0.001;
   function render() {
       if (resizeRendererToDisplaySize(renderer)) {
           const canvas = renderer.domElement;
           camera.aspect = canvas.clientWidth / canvas.clientHeight;
           camera.updateProjectionMatrix();
       }

       cubes.forEach((cube, ndx) = > {
           const speed = 1 + ndx * 1.;
           const rot = time * speed;
           const rot = state.time * speed;
           cube.rotation.x = rot;
           cube.rotation.y = rot;
       });

       renderer.render(scene, camera);

       requestAnimationFrame(render);
   }
    
   function animate(time) {
       state.time = time * 0.001;

       render();

       requestAnimationFrame(animate);
   }
   requestAnimationFrame(animate);
Copy the code

Now Render only cares about the actual rendering, we can call it before capturing the canvas.

   const elem = document.querySelector('#screenshot');
   elem.addEventListener('click'.() = > {
       render();
       canvas.toBlob((blob) = > {
           saveBlob(blob, `screencapture-${canvas.width}x${canvas.height}.png`);
       });
   });
Copy the code

The effect is normal

Please refer the case threejsfundamentals.org/threejs/thr…

Prevents the canvas from being cleared

Suppose you want the user to draw with an animated object. You need to pass preserveDrawingBuffer: true when creating the WebGLRenderer. This prevents the browser from clearing the canvas, otherwise three.js should not clear the canvas.

   const canvas = document.querySelector('#c');
   const renderer = new THREE.WebGLRenderer({canvas});
   const renderer = new THREE.WebGLRenderer({
       canvas,
       preserveDrawingBuffer: true.alpha: true}); renderer.autoClearColor =false;
Copy the code

Specific examples can reference: threejsfundamentals.org/threejs/thr…

This would not be a solution if we made a serious drawing program, because the browser would still clear the canvas when we changed the resolution. We are changing the resolution based on its display size. When a window changes size, its display size changes too. This includes the browser adding a status bar when a user downloads a file, even in a different TAB. It also includes how long it takes the user to turn the phone and browser from portrait to landscape.

Transparent canvas

By default, three.js makes the canvas opaque. If you want the canvas to be transparent to the WebGLRenderer when alpha: True is created

   const canvas = document.querySelector('#c');
   const renderer = new THREE.WebGLRenderer({canvas});
   const renderer = new THREE.WebGLRenderer({
       canvas,
       alpha: true});Copy the code

PremultipliedAlpha can be set to premultipliedAlpha

   const canvas = document.querySelector('#c');
   const renderer = new THREE.WebGLRenderer({
       canvas,
       alpha: true.premultipliedAlpha: false});Copy the code

Three.js defaults to canvas using premultipliedAlpha: true but defaults to material output premultipliedAlpha: false.

If you want to get a better idea of when and when not to use pre-ride Alpha,

Set a simple example with a transparent canvas.

   function makeInstance(geometry, color, x) {
   const material = new THREE.MeshPhongMaterial({color});
   const material = new THREE.MeshPhongMaterial({
       color,
       opacity: 0.5}); .Copy the code

Add some HTML content

   <body>
       <canvas id="c"></canvas>
       <div id="content">
           <div>
               <h1>Cubes-R-Us!</h1>
               <p>We make the best cubes!</p>
           </div>
       </div>
   </body>
Copy the code

And some CSS to put the canvas in front

   body {
       margin: 0; {} # Cwidth: 100%;
       height: 100%;
       display: block;
       position: fixed;
       left: 0;
       top: 0;
       z-index: 2; pointer-events: none; } # content {font-size: 7vw; font-family: sans-serif; text-align: center; width:100%;
       height: 100%;
       display: flex;
       justify-content: center;
       align-items: center;
   }
Copy the code

The renderings are as follows

Animate your background to three.js

A common problem is how to make a three.js animation the background of a web page.

There are two obvious approaches.

  • Will the canvas CSSpositionSet up thefixedFor the in
C # {position: fixed;
       left: 0;
       top: 0; . }Copy the code

You can basically see the exact solution in the previous example. Simply set the Z-index to -1 and the cube will appear after the text.

One minor drawback of this solution is that your JavaScript has to be integrated with the page, and if you have a complex page, then you need to make sure that the JavaScript in your three.js visualization doesn’t conflict with JavaScript doing other things in the page.

  • useiframe

For example, insert an iframe into your web page

   <iframe id="background" src="threejs-responsive.html">
   <div>
       Your content goes here.
   </div>
Copy the code

We then style the iframe to fill the window and be in the background, which is basically the same code we used for the canvas above, but we also need to set the border to None because iframe has a border by default.

{# backgroundposition: fixed;
       width: 100%;
       height: 100%;
       left: 0;
       top: 0;
       z-index: -1;
       border: none;
       pointer-events: none;
   }
Copy the code

The renderings are as follows

Source: translation threejsfundamentals.org/threejs/les…

Write in the last

This article introduces the content related to screenshot of three. js. Screenshot is a very common requirement in daily work. I hope it will be helpful to you.

This article is published from the cloud Map 3D big front end team, the article is not authorized to be reproduced in any form.