Use three.js in Jekyll Blog (1)

 

This is the 1st post in the Use three.js in Jekyll Blog series (»). In this post, I’ll get started with three.js by trying a simple example.

Introduction

My goal is to create some fancy demos on my blog, and three.js, a popular JavaScript 3D library, can be very useful to that end. The Use three.js in Jekyll Blog series will record my journey in learning three.js. Hopefully I can learn the basics of HTML, CSS and JS as well.

Before we start

Create a container

To resize and locate the 3D content in jekyll blog posts, we need to create a container as the canvas.

The simplest example looks like this:

<div id='cube'></div>

This is a common way I found to maintain the aspect ratio. Here the outer div controls the aspect ratio, while the inner div holds the 3D content. A more elegant way is shown here.

.threejs {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 aspect ratio */
}
.threejs > * {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
<div class='threejs'>
    <div id='cube'></div>
</div>

Note that the inner div’s id will be used to get container’s width and height while initialzing three.js.

var container = document.getElementById('cube');
var width = container.clientWidth;
var height = container.clientHeight;

Learn how to make this responsive in three.js, i.e., automatically resize the content when the window is resized.

Include the library

This can be done by adding the following line

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.min.js"></script>

where the src comes from CDN or a local copy of the minified library.

TODO: control this in the front matter like other Markdown enhancements.

Hello, cube!

The spinning cube demo is originally obtained from here and a great explaination can be found here. Essentially, we need to set up three things: scene, camera and renderer to display the 3D content using three.js.

Scene

Here is a unit cube.

// scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
geometry = new THREE.BoxGeometry(1, 1, 1);
material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

Camera

Here is a perspective camera. 70 is the field of view (FOV) in degrees, width / height is the aspect ratio, 0.01 is the near clipping plane, and 10 is the far clipping plane.

// camera
camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 10);
camera.position.z = 2;

Renderer

Here is a WebGL renderer. Don’t forget to append it as the container’s child.

// renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
container.appendChild(renderer.domElement);

The line with setPixelRatio can improve display quality on mobile devices.

Animation

Here is the so-called render or animate loop.

// animation
function animate() {
  requestAnimationFrame(animate);
  mesh.rotation.x += 0.005;
  mesh.rotation.y += 0.01;
  renderer.render(scene, camera);
}