ThreeJS example of how to use a fixed scene background image.
A Pen by kenichi miyata on CodePen.
<div class="outer"> | |
<div class="inner"> | |
<div id="container"></div> | |
</div> | |
</div> | |
<div class="outer"> | |
<div class="inner"> | |
<div id="debug-container"> | |
<div class="flex-row outputs"> | |
<div id="v1" class="out">Visual Debug 1</div> | |
<div id="v2" class="out">Visual Debug 2</div> | |
<div id="v3" class="out">Visual Debug 3</div> | |
<div id="v4" class="out">Visual Debug 4</div> | |
</div> | |
<button class='clear-debug' onClick="html('out','')">CLEAR DEBUG</button> | |
<div id="out">Debug (#out)<br></div> | |
</div> | |
</div> | |
</div> |
// Author: darcey@aftc.io | |
// Libs: aftc.js, three | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
var Application = function(){ | |
var args = {}; | |
var params = { | |
dom: { | |
container:false, | |
}, | |
lights: { | |
light1:false, | |
light2:false, | |
}, | |
textures: { | |
tex1:false, | |
}, | |
materials: { | |
mat1:false, | |
}, | |
geom: { | |
geom1:false, | |
}, | |
meshes: { | |
mesh1:false, | |
}, | |
groups: { | |
gr1:false, | |
}, | |
scene: false, renderer: false, camera: false, controls: false,// ThreeJS | |
center: new AFTC.Point(0,0), // Center point | |
start: new AFTC.Point(0,0), // Start point | |
previous: new AFTC.Point(0,0), // Previous point | |
target: new AFTC.Point(0,0), // Target point | |
pos: new AFTC.Point(0,0), // Generic x,y point | |
w:0, h:0, // I typically put window.innerWidth & innerHeight in these | |
t:0, // time | |
running: false | |
}; | |
// constructor | |
function init(){ | |
log("Application.init()"); | |
html("v1","html(\"v1\",str)"); | |
html("v2","html(\"v2\",str)"); | |
html("v3","html(\"v3\",str)"); | |
html("v4","html(\"v4\",str)"); | |
if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); | |
// Var ini | |
params.dom.container = getElementById("container"); | |
//params.dom.container.getBoundingClientRect().width; | |
params.w = Math.round(parseFloat(getComputedStyle(params.dom.container).width)); | |
params.h = Math.round(parseFloat(getComputedStyle(params.dom.container).height)); | |
params.center.x = params.w/2; | |
params.center.y = params.h/2; | |
// scene / rednerer and attach to dom | |
params.scene = new THREE.Scene(); | |
params.renderer = new THREE.WebGLRenderer( { antialias: true } ); | |
params.renderer.setPixelRatio( window.devicePixelRatio ); | |
params.renderer.setSize( params.w, params.h ); | |
params.renderer.setClearColor("#0C7CA5", 0); | |
params.dom.container.appendChild( params.renderer.domElement ); | |
// camera | |
params.camera = new THREE.PerspectiveCamera( 60, params.w / params.h, 1, 5000 ); | |
params.camera.position.set( 4.1, 6.4, 12 ); | |
params.scene.add( params.camera ); | |
// controls | |
params.controls = new THREE.OrbitControls( params.camera, params.renderer.domElement ); | |
// params.controls.minDistance = 5; | |
// params.controls.maxDistance = 10; | |
params.controls.maxPolarAngle = Math.PI / 2; | |
// stats | |
params.stats = new Stats() | |
document.body.appendChild(params.stats.dom); | |
// helpers | |
params.scene.add( new THREE.AxesHelper( 5 ) ); | |
// Lights | |
setupLights(); | |
// Load assets, load check or onComplete will call setupScene after | |
loadAssets(); | |
// GUI | |
setupDatGUI(); | |
// Template is using confined space no need for resize | |
//window.addEventListener( 'resize', resizeHandler, false ); | |
// Animate and Render | |
animate(); | |
} | |
// - - - - - - - - - - - - - - - - - | |
// lights | |
function setupLights(){ | |
log("Application.setupLights()"); | |
params.lights.light1 = new THREE.AmbientLight( 0x222222 ); | |
params.camera.add( params.lights.light1 ); | |
params.lights.light2 = new THREE.PointLight( 0xffffff, 1 ); | |
params.camera.add( params.lights.light2 ); | |
} | |
// - - - - - - - - - - - - - - - - - | |
function loadAssets(){ | |
log("Application.loadAssets()"); | |
var xhr1 = AFTC.XHR({ | |
url: "https://dev.aftc.io/utils/GetImageAsString.php?src=http://dev.aftc.io/assets/img/OldBridge.jpg", | |
onError: function (e){ | |
log(e); | |
}, | |
onCancel: function (e){ | |
log(e); | |
}, | |
onComplete: function (response) { | |
var loader = new THREE.TextureLoader(); | |
loader.load( | |
response, | |
// onLoad callback | |
function ( texture ) { | |
params.textures.bg = texture; | |
setupScene(); | |
}, | |
// onProgress callback currently not supported | |
undefined, | |
// onError callback | |
function ( err ) { | |
console.error( 'An error happened.' ); | |
} | |
); | |
} | |
}); | |
} | |
// - - - - - - - - - - - - - - - - - | |
// Whats on the scene if you know what i mean | |
function setupScene(){ | |
log("Application.setupScene()"); | |
// Set scene background | |
params.scene.background = params.textures.bg; | |
// Groups / Containers | |
params.groups.gr1 = new THREE.Group(); | |
params.scene.add( params.groups.gr1 ); | |
// CODE BELOW WILL USE BASE64 IMAGE STRING PASTED INTO VARIABLE FOR TEXTURE | |
// SLOWS CODEPEN DOWN TO A HALT ON LARGE IMAGES AND MORE THAN 1 IS A PAIN | |
// NOT RECOMENDED TO USE | |
// var loader = new THREE.TextureLoader(); | |
// loader.load( | |
// params.images.img1, | |
// // onLoad callback | |
// function ( texture ) { | |
// params.textures.image1 = texture; | |
// params.materials.bg = new THREE.MeshBasicMaterial( { | |
// map: texture | |
// } ); | |
// params.scene.background = params.textures.image1; | |
// }, | |
// // onProgress callback currently not supported | |
// undefined, | |
// // onError callback | |
// function ( err ) { | |
// console.error( 'An error happened.' ); | |
// } | |
// ); | |
params.materials.mat1 = new THREE.MeshLambertMaterial( { | |
color: 0xffffff, | |
opacity: 0.8, | |
transparent: true | |
} ); | |
params.geom.geom1 = new THREE.BoxGeometry( 4, 4, 4 ); | |
params.meshes.mesh1 = new THREE.Mesh( params.geom.geom1, params.materials.mat1 ); | |
//params.meshes.mesh1.material.side = THREE.BackSide; // back faces | |
// params.meshes.mesh1.renderOrder = 0; | |
params.groups.gr1.add( params.meshes.mesh1 ); | |
} | |
// - - - - - - - - - - - - - - - - - | |
function setupDatGUI(){ | |
log("Application.setupDatGUI()"); | |
// dat.gui | |
params.gui = new dat.GUI(); | |
params.options = { | |
rotationX: 0.01, | |
rotationY: 0.01, | |
rotationZ: 0.01 | |
}; | |
params.gui.add(params.options, 'rotationX', -0.1, 0.1); | |
params.gui.add(params.options, 'rotationY', -0.1, 0.1); | |
params.gui.add(params.options, 'rotationZ', -0.1, 0.1); | |
params.gui.close(); | |
} | |
// - - - - - - - - - - - - - - - - - | |
function animate() { | |
requestAnimationFrame( animate ); | |
if (params.groups.gr1){ | |
params.groups.gr1.rotation.x += params.options.rotationX; | |
params.groups.gr1.rotation.y += params.options.rotationY; | |
params.groups.gr1.rotation.z += params.options.rotationZ; | |
} | |
render(); | |
} | |
// - - - - - - - - - - - - - - - - - | |
function render() { | |
var msg = "x:" + params.camera.position.x.toFixed(1); | |
msg += " y:" + params.camera.position.y.toFixed(1); | |
msg += " z:" + params.camera.position.z.toFixed(1); | |
html("v1",msg); | |
if (params.stats){ | |
params.stats.update(); | |
} | |
params.renderer.render( params.scene, params.camera ); | |
} | |
// - - - - - - - - - - - - - - - - - | |
function resizeHandler(){ | |
params.camera.aspect = window.innerWidth / window.innerHeight; | |
params.camera.updateProjectionMatrix(); | |
params.renderer.setSize( window.innerWidth, window.innerHeight ); | |
} | |
// - - - - - - - - - - - - - - - - - | |
function _start(){ | |
log("Application._start()"); | |
} | |
// - - - - - - - - - - - - - - - - - | |
function _stop(){ | |
log("Application._stop()"); | |
} | |
// - - - - - - - - - - - - - - - - - | |
// Utils | |
function util(){ | |
// eg | |
} | |
// - - - - - - - - - - - - - - - - - | |
// Public | |
this.start = function(){ | |
}; | |
this.stop = function(){ | |
}; | |
// - - - - - - - - - - - - - - - - - | |
// Constructor simulation | |
init(); | |
// - - - - - - - - - - - - - - - - - | |
} | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
// Globals | |
var app1; | |
function start(){ | |
log("start()"); | |
app1.start(); | |
} | |
function stop(){ | |
log("stop()"); | |
app1.stop(); | |
} | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
// DOM Ready | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
onReady(function(){ | |
logTo("out"); | |
log("Darcey@AFTC.io"); | |
log("<span style='color:#FFCC00'>Left mouse hold / touch drag to move</a>"); | |
app1 = new Application(); | |
//app1.strat(); | |
}); | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
<script src="https://cdn.jsdelivr.net/npm/aftc.js@1.5.15/dist/aftc.min.js"></script> | |
<script src="https://threejs.org/examples/js/Detector.js"></script> | |
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script> | |
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.1/dat.gui.js"></script> |
/* Generics */ | |
body { | |
font-family: Arial; | |
font-size: 12px; | |
background: #000000; | |
color: #ffffff; | |
} | |
a { | |
color: #FFCC00; | |
text-decoration: none; | |
} | |
a:hover { | |
text-decoration: underline; | |
} | |
button { | |
cursor: pointer; | |
} | |
.outer { | |
width: 100%; | |
} | |
.inner { | |
width: 760px; | |
margin: auto; | |
} | |
.flex-row { | |
display: flex; | |
flex-wrap: nowrap; | |
justify-content: center; | |
} | |
/* Debug */ | |
#debug-container { | |
width: 760px; | |
background: #161616; | |
} | |
#debug-container .btn { | |
display: block; | |
width: 23.5%; | |
margin: 2px; | |
padding: 3px; | |
box-sizing: border-box; | |
} | |
#debug-container .btn button { | |
width: 100%; | |
font-size: 12px; | |
font-weight: bold; | |
background: #cccccc; | |
} | |
#debug-container .btn button:hover { | |
width: 100%; | |
background: #ffffff; | |
} | |
#debug-container .in { | |
display: block; | |
width: 23.5%; | |
margin: 2px; | |
padding: 3px; | |
box-sizing: border-box; | |
} | |
#debug-container .in .input-label { | |
font-size: 12px; | |
} | |
#debug-container .in input { | |
width: 100%; | |
box-sizing: border-box; | |
} | |
#debug-container .out { | |
display: block; | |
width: 23.5%; | |
margin: 2px; | |
padding: 3px; | |
font-family: "courier"; | |
font-size: 11px; | |
border: 1px solid #676767; | |
box-sizing: border-box; | |
} | |
#debug-container #out { | |
max-height: 200px; | |
overflow: auto; | |
margin: 10px 10px 20px 10px; | |
padding: 3px; | |
font-family: "courier"; | |
font-size: 11px; | |
border: 1px solid #676767; | |
} | |
#debug-container .clear-debug { | |
display: block; | |
margin: 10px auto -7px auto; | |
font-size: 10px; | |
background: #999999; | |
color: #000000; | |
border: none; | |
outline: none; | |
} | |
#debug-container .clear-debug:hover { | |
background: #FFFFFF; | |
color: #000000; | |
} | |
#container { | |
width: 760px; | |
height: 400px; | |
border: 1px solid #1b2735; | |
} |
ThreeJS example of how to use a fixed scene background image.
A Pen by kenichi miyata on CodePen.