Penggunaan bentuk 3D (atau yang biasa disebut sebagai 3 Dimensi) pada sektor front-end suatu website, masih sering digunakan hingga saat ini, baik dalam bentuk first impression maupun sebagai media navigasi. Adapun penggunaannya dapat disajikan dalam bentuk statis (seperti gambar 3D) maupun dikemas dalam bentuk animasi (seperti 3D Parallax).
Sebagai bentuk penerapan dari animasi 3D, pada artikel kali ini, kita akan membuat animasi 3D Reveal menggunakan bahasa pemrograman Javascript melalui snippet Three.js dan TweenMax.
Langkah:
1. Persiapkan text editor (notepad, sublime text, dan sebagainya) sebagai media pengetikan syntax nantinya.
2. Buatlah file yang bernama index.html yang berisikan kode sebagai berikut:
<html> <head> <title>Inwepo 3D Reveal</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script> <style> </style> </head> <body> <script> </script> </body> </html>
3. Pada bagian <style>, masukkan kode berikut:
html,body { height: 100%; } body { display: flex; justify-content: center; text-align: center; color: #fff; } .cover-container { max-width: 42em; } #page { visibility: hidden; } #reveal-effect { position: fixed; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; } body { background: #fff; } body.loaded { background-color: #333333; } body.loaded #page { visibility: visible; } body.loaded #reveal-effect { opacity: 1; } body.revealed #reveal-effect { display: none; }
Nantinya, bagian <style> akan memiliki struktur kode sebagai berikut:
<style> html,body { height: 100%; } body { display: flex; justify-content: center; text-align: center; color: #fff; } .cover-container { max-width: 42em; } #page { visibility: hidden; } #reveal-effect { position: fixed; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; } body { background: #fff; } body.loaded { background-color: #333333; } body.loaded #page { visibility: visible; } body.loaded #reveal-effect { opacity: 1; } body.revealed #reveal-effect { display: none; } </style>
4. Pada bagian <body>, masukkan kode berikut:
<div id="page"> <div class="cover-container d-flex h-100 p-3 mx-auto flex-column"> <main role="main" class="inner cover"> <h1 class="cover-heading">Inwepo 3D Reveal Effect</h1> <p class="lead">dibuat menggunakan ThreeJS dan TweenMax.</p> <p class="lead"> <a href="#" id="trigger">Tampilkan Efek</a> </p> </main> </div> </div> <canvas id="reveal-effect"></canvas>
Nantinya, bagian <body> akan memiliki struktur kode sebagai berikut:
<body> <div id="page"> <div class="cover-container d-flex h-100 p-3 mx-auto flex-column"> <main role="main" class="inner cover"> <h1 class="cover-heading">Inwepo 3D Reveal Effect</h1> <p class="lead">dibuat menggunakan ThreeJS dan TweenMax.</p> <p class="lead"> <a href="#" id="trigger">Tampilkan Efek</a> </p> </main> </div> </div> <canvas id="reveal-effect"></canvas> <script> </script> </body>
5. Pada bagian <script>, masukkan kode berikut:
let renderer, scene, camera, cameraCtrl; let width, height, cx, cy, wWidth, wHeight; const TMath = THREE.Math; let conf = { color: 0xffffff, objectWidth: 12, objectThickness: 3, ambientColor: 0x808080, light1Color: 0xffffff, shadow: false, perspective: 75, cameraZ: 75, }; let objects = []; let geometry, material; let hMap, hMap0, nx, ny; init(); function init() { renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('reveal-effect'), antialias: true, alpha: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); camera = new THREE.PerspectiveCamera(conf.perspective, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = conf.cameraZ; scene = new THREE.Scene(); geometry = new THREE.BoxGeometry(conf.objectWidth, conf.objectWidth, conf.objectThickness); window.addEventListener('load', initScene); document.getElementById('trigger').addEventListener('click', initScene); animate(); }; function initScene() { onResize(); scene = new THREE.Scene(); initLights(); initObjects(); } function initLights() { scene.add(new THREE.AmbientLight(conf.ambientColor)); let light = new THREE.PointLight(0xffffff); light.position.z = 100; scene.add(light); } function initObjects() { objects = []; nx = Math.round(wWidth / conf.objectWidth) + 1; ny = Math.round(wHeight / conf.objectWidth) + 1; let mesh, x, y; for (let i = 0; i < nx; i++) { for (let j = 0; j < ny; j++) { material = new THREE.MeshLambertMaterial({ color: conf.color, transparent: true, opacity: 1 }); mesh = new THREE.Mesh(geometry, material); x = -wWidth / 2 + i * conf.objectWidth; y = -wHeight / 2 + j * conf.objectWidth; mesh.position.set(x, y, 0); objects.push(mesh); scene.add(mesh); } } document.body.classList.add('loaded'); startAnim(); } function startAnim() { document.body.classList.remove('revealed'); objects.forEach(mesh => { mesh.rotation.set(0, 0, 0); mesh.material.opacity = 1; mesh.position.z = 0; let delay = TMath.randFloat(1, 2); let rx = TMath.randFloatSpread(2 * Math.PI); let ry = TMath.randFloatSpread(2 * Math.PI); let rz = TMath.randFloatSpread(2 * Math.PI); TweenMax.to(mesh.rotation, 2, { x: rx, y: ry, z: rz, delay: delay }); TweenMax.to(mesh.position, 2, { z: 80, delay: delay + 0.5, ease: Power1.easeOut }); TweenMax.to(mesh.material, 2, { opacity: 0, delay: delay + 0.5 }); }); setTimeout(() => { document.body.classList.add('revealed'); }, 4500); } function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); }; function onResize() { width = window.innerWidth; cx = width / 2; height = window.innerHeight; cy = height / 2; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); size = getRendererSize(); wWidth = size[0]; wHeight = size[1]; } function getRendererSize() { const cam = new THREE.PerspectiveCamera(conf.perspective, camera.aspect); const vFOV = cam.fov * Math.PI / 180; const height = 2 * Math.tan(vFOV / 2) * Math.abs(conf.cameraZ); const width = height * cam.aspect; return [width, height]; }
Nantinya, bagian <script> akan memiliki struktur kode sebagai berikut:
<script> let renderer, scene, camera, cameraCtrl; let width, height, cx, cy, wWidth, wHeight; const TMath = THREE.Math; let conf = { color: 0xffffff, objectWidth: 12, objectThickness: 3, ambientColor: 0x808080, light1Color: 0xffffff, shadow: false, perspective: 75, cameraZ: 75, }; let objects = []; let geometry, material; let hMap, hMap0, nx, ny; init(); function init() { renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('reveal-effect'), antialias: true, alpha: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); camera = new THREE.PerspectiveCamera(conf.perspective, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = conf.cameraZ; scene = new THREE.Scene(); geometry = new THREE.BoxGeometry(conf.objectWidth, conf.objectWidth, conf.objectThickness); window.addEventListener('load', initScene); document.getElementById('trigger').addEventListener('click', initScene); animate(); }; function initScene() { onResize(); scene = new THREE.Scene(); initLights(); initObjects(); } function initLights() { scene.add(new THREE.AmbientLight(conf.ambientColor)); let light = new THREE.PointLight(0xffffff); light.position.z = 100; scene.add(light); } function initObjects() { objects = []; nx = Math.round(wWidth / conf.objectWidth) + 1; ny = Math.round(wHeight / conf.objectWidth) + 1; let mesh, x, y; for (let i = 0; i < nx; i++) { for (let j = 0; j < ny; j++) { material = new THREE.MeshLambertMaterial({ color: conf.color, transparent: true, opacity: 1 }); mesh = new THREE.Mesh(geometry, material); x = -wWidth / 2 + i * conf.objectWidth; y = -wHeight / 2 + j * conf.objectWidth; mesh.position.set(x, y, 0); objects.push(mesh); scene.add(mesh); } } document.body.classList.add('loaded'); startAnim(); } function startAnim() { document.body.classList.remove('revealed'); objects.forEach(mesh => { mesh.rotation.set(0, 0, 0); mesh.material.opacity = 1; mesh.position.z = 0; let delay = TMath.randFloat(1, 2); let rx = TMath.randFloatSpread(2 * Math.PI); let ry = TMath.randFloatSpread(2 * Math.PI); let rz = TMath.randFloatSpread(2 * Math.PI); TweenMax.to(mesh.rotation, 2, { x: rx, y: ry, z: rz, delay: delay }); TweenMax.to(mesh.position, 2, { z: 80, delay: delay + 0.5, ease: Power1.easeOut }); TweenMax.to(mesh.material, 2, { opacity: 0, delay: delay + 0.5 }); }); setTimeout(() => { document.body.classList.add('revealed'); }, 4500); } function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); }; function onResize() { width = window.innerWidth; cx = width / 2; height = window.innerHeight; cy = height / 2; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); size = getRendererSize(); wWidth = size[0]; wHeight = size[1]; } function getRendererSize() { const cam = new THREE.PerspectiveCamera(conf.perspective, camera.aspect); const vFOV = cam.fov * Math.PI / 180; const height = 2 * Math.tan(vFOV / 2) * Math.abs(conf.cameraZ); const width = height * cam.aspect; return [width, height]; } </script>
6. Save file yang telah dimodifikasi sebelumnya. Lalu, buka file index.html melalui browser kamu. Jika berhasil, nantinya halaman website akan menampilkan konten teks menyertakan animasi reveal yang dikemas dalam bentuk 3D pada awalannya. Sesuaikan penggunaan 3D Reveal dengan website yang telah kamu buat.
Demikian tutorial cara membuat animasi 3D Reveal dengan Javascript. Semoga bermanfaat.