Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Three.js as background of website possible?

I've been looking at using three.js for a fun experiment on a site. I would like to use a current experiment (for which I already have the code for) and use it as a background for my site.

Anybody know how to do this?

I saw it done here: http://janjorissen.be/

Three JS API: https://github.com/mrdoob/three.js/wiki/API-Reference

like image 279
Katzumi Avatar asked Mar 28 '12 05:03

Katzumi


3 Answers

I'm going to add yet another answer. I'd use

canvas {
  width: 100vw;
  height: 100vh;
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  z-index: -9999;
}

Here's why:

Many people use canvas { width: 100%; height: 100% } but that arguably doesn't make a lot of sense. You don't want the canvas to be 100% of the body. You want it to 100% of the screen/window. That's what canvas { width: 100vw; height: 100vh; } does. It's 100% of the viewport width and viewport height.

This means you don't need to set the body to height: 100% which also would not make sense, especially if the page is taller than the window/screen

display: block; fixes some issues with scrollbars on certain browsers. Some pages use html, body { overflow: none; } but again that doesn't make sense if your page ends up needing to be taller than the screen/window.

position: fixed; makes the canvas position relative to the top of window so it won't scroll with the page. If you use position: absolute then the canvas will scroll off the top if the page is taller than the screen/window. For example this page.

top: 0; left 0; puts it at the top left. Without that it would default to it's default position which is inside the body's margins. Often this is solved by setting body { margin: 0; } but generally that means you end up needing some other container to add a margin back in otherwise your normal content gets positioned at the edge of the window.

z-index: -9999; is there to try to force it further back than anything else just in case the page itself is using some negative values for z-index

Here's an example as a snippet

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);

var canvas = document.querySelector("canvas");
var renderer = new THREE.WebGLRenderer({canvas: canvas});
renderer.setClearColor(0xF0F0F0);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({ 
  color: 0x00ff00, 
  wireframe: true,
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 1;

function resize() {
  var width = canvas.clientWidth;
  var height = canvas.clientHeight;
  if (width != canvas.width || height != canvas.height) {
    renderer.setSize(width, height, false);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
  }
}

function render(time) {
    time *= 0.001;
    resize();
    cube.rotation.x = time;
    cube.rotation.y = time * 0.31;
	renderer.render(scene, camera);
	requestAnimationFrame(render);
}
render();
canvas {
  width: 100vw;
  height: 100vh;
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  z-index: -9999;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js"></script>

<canvas></canvas>
<div>
  some content that is in front of the canvas
</div>

And here's an example outside SO so you can view it easier full size.

iframes work as well

Note that there's the issue that if your canvas animation is interactive the elements in front of the canvas will eat the mouse/touch events. There's no easy solution I know of for that. You can mark everything but that canvas/iframe as pointer-events: none and mark the canvas/iframe as pointer-events: auto but then you run into the issue that no text on your page can be selected and no links can be clicked. You could then say set <a> tags to have pointer-events: auto so links work but I'm sure there will be issues here and there depending on what info is on your page (trying to copy an email address, or a location address, etc...)

One note: most three.js examples are structured different (less flexible) by referencing window.innerWidth and window.innerHeight and putting the canvas inside a div with an id="canvas" for some reason.

Here's a snippet using that structure. There's several more lines of code, redundant calls to renderer.setSize and setting the camera aspect in 2 places (not very D.R.Y.) but as far as this Q&A is concerned the only difference is #canvas instead of canvas as the CSS to size the div instead of the canvas.

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

var renderer = new THREE.WebGLRenderer();
document.getElementById("canvas").appendChild(renderer.domElement);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xF0F0F0);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({ 
  color: 0x00ff00, 
  wireframe: true,
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 1;

function onResize() {
  renderer.setSize(window.innerWidth, window.innerHeight);
  
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
}

window.addEventListener('resize', onResize);

function render(time) {
    time *= 0.001;
    cube.rotation.x = time;
    cube.rotation.y = time * 0.31;
	renderer.render(scene, camera);
	requestAnimationFrame(render);
}
render();
#canvas {
  width: 100vw;
  height: 100vh;
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  z-index: -9999;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js"></script>

<div id="canvas"></div>
<div>
  some content that is in front of the canvas
</div>
like image 169
gman Avatar answered Sep 21 '22 21:09

gman


usually i use iframe for that. Thus you dont have conflict with the base page.

<style>
iframe {
    z-index : -9999;
    position: absolute;
    top : 0;
    left    : 0;
    width   : 100%;
    height  : 100%;
    margin  : 0;
    padding : 0;
}
</style>
<iframe src="http://example.com/"></iframe> 

an example of it https://github.com/jeromeetienne/www.jetienne.com/blob/master/index-webgl.html#L128 for the source http://jetienne.com/index-webgl.html for the living code

like image 45
Jerome Etienne Avatar answered Sep 19 '22 21:09

Jerome Etienne


This is not an actual background, but a 100% width/height element that is displaying the animation, with the rest of the content "elevated" using z-index or similar above that fake background.

like image 44
Félix Saparelli Avatar answered Sep 21 '22 21:09

Félix Saparelli