Sejauh ini kita sudah belajar cara memulai proyek Three JS, elemen-elemen utama dari Three JS agar bisa memasukkan objek ke canvas Three JS, kita juga sudah belajar manipulasi objek 3D, buat animasi sederhana, dan manipulasi kamera. Tapi yang belum adalah bagaimana agar canvas ThreeJS kita full screen dan bisa responsif.

Full Screen

Buat full screen di ThreeJS gampang, kita cuma bermain CSS saja di sini dan sedikit perubahan di JavaScript, yang agak tricky nanti di bagian Resize.

Bikin viewport

ukuran canvas yang sebelumnya 800 * 600 kita ganti jadi seukuran tinggi dan lebar layar, di script.js kita ubah:

// Sizes
const sizes = {
    width: window.innerWidth,
    height: window.innerHeight
}

Sekarang lanjut ke style.css, tambahkan kode standar untuk responsif sebagai berikut:

*
{
    margin: 0;
    padding: 0;
}
 
.webgl
{
    position: fixed;
    top: 0;
    left: 0;
    outline: none;
}
 
html,
body
{
    overflow: hidden;
}

Resize

Nah bagian ini agak tricky tapi tidak sulit juga, seperti kata saya sebelumnya, kegiatan coding itu adalah segalanya tentang ngakalin.

Membuat responsif di ThreeJS tidak cukup hanya di CSS saja, karena banyak elemen-elemen ThreeJS yang butuh nilai aspect ratio, sedangkan aspect ratio seperti yang kita tahu dia adalah perbandingan nilai lebar dan tinggi, kalau lebar dan tinggi ini nilainya berubah-ubah berarti kita harus membuat objek-objek tersebut mendengarkan perubahan itu, kalau objek tersebut bisa mendengar perubahannya otomatis aspect ratio bisa berubah sendiri. Intinya gitu aja ya, objek harus bisa mengubah aspect ratio-nya sendiri otomatis berdasarkan perubahan ukuran layar / canvas.

Buat “kuping” untung mendengarkan perubahan

Kita buat “kuping” dulu biar objek-objek yang butuh aspect ratio bisa mendengarkan perubahan-perubahan ukuran layar.

window.addEventListener('resize', () => {
	console.log('saya mendengar ada perubahan ukuran')
})

Kode addEventListener adalah kode dasar untuk membuat “kuping” agar bisa mendengarkan. Mendengarkan apa? mendengarkan resize dari window, jadi kalau ada perubahan ukuran dari window makan akan memanggil apapun yang ada di dalam fungsi tersebut, kalau contoh di atas, tiap kali ukuran windows kita berubah pasti akan ada log saya mendengar ada perubahan ukuran.

Sekarang kita ubah, daripada munculin log doang ketika “mendengar” ada perubahan ukuran, kita update ukuran aspect ratio canvas untuk semua object kita seukuran layar. Pertama-tama kita buat dulu variable yang nampung nilai width dan height-nya.

window.addEventListener('resize', () => {
	// Update ukuran setiap ada perubahan ukuran
	sizes.width = window.innerWidth
	sizes.height = window.innerHeight
})

Nah, kita udah punya variabel sizes.width dan sizes.height untuk ukuran lebar dan tinggi yang bisa kita pakai nanti. Sekarang kita update dulu aspect ratio kamera

window.addEventListener('resize', () => {
	// Update ukuran setiap ada perubahan ukuran
	sizes.width = window.innerWidth
	sizes.height = window.innerHeight
	
	// Update aspect ratio camera
	camera.aspect = sizes.width / sizes.height
	camera.updateProjectionMatrix()
})

INFO

Setiap kali ada perubahan aspect ratio di camera, selalu panggil fungsi update-nya yaitu updateProjectionMatrix()

Selanjutnya, kita update aspect ratio dari canvas dan pasang di renderer supaya ukuran canvas otomatis berubah mengikut aspect ratio yang terbaru

window.addEventListener('resize', () =>
{
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight
 
    // Update camera
    camera.aspect = sizes.width / sizes.height
    camera.updateProjectionMatrix()
 
    // Update renderer
    renderer.setSize(sizes.width, sizes.height)
})

Trigger Full Screen

Kalau kalian pernah klik 2 kali di video YouTube atau Netflix jadi Full Screen, kita juga bisa melakukan itu di sini. Tidak ada hubungannya dengan fungsi ThreeJS, ini hanya JavaScript biasa, detail lengkapnya ada di sini https://developer.mozilla.org/docs/Web/API/Element/dblclick_event, sebagai catatan, cara ini belum support di Chrome Android.

window.addEventListener('dblclick', () =>
{
    const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement
 
    if(!fullscreenElement)
    {
        if(canvas.requestFullscreen)
        {
            canvas.requestFullscreen()
        }
        else if(canvas.webkitRequestFullscreen)
        {
            canvas.webkitRequestFullscreen()
        }
    }
    else
    {
        if(document.exitFullscreen)
        {
            document.exitFullscreen()
        }
        else if(document.webkitExitFullscreen)
        {
            document.webkitExitFullscreen()
        }
    }
})

Antialias

Kalau kalian pernah main game lalu ada opsi Antialias, itu menghilangkan gerigi-gerigi di objek 3D jadi lebih mulus, itu sebenarnya adalah Aspect Ratio dari layar kamu, kalau layar kamu punya nilai aspect ratio lebih dari 1, maka gerigi-gerigi itu tidak akan terlihat.

Nah, untuk menghilangkan gerigi itu caranya dengan setPixelRatio:

renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))

Lengkapnya kaya gini:

window.addEventListener('resize', () =>
{
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight
 
    // Update camera
    camera.aspect = sizes.width / sizes.height
    camera.updateProjectionMatrix()
 
    // Update renderer
    renderer.setSize(sizes.width, sizes.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})

Code Lengkap

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
 
/**
 * Base
 */
// Canvas
const canvas = document.querySelector('canvas.webgl')
 
// Scene
const scene = new THREE.Scene()
 
/**
 * Object
 */
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
 
/**
 * Sizes
 */
const sizes = {
    width: window.innerWidth,
    height: window.innerHeight
}
 
window.addEventListener('resize', () =>
{
    // Update sizes
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight
 
    // Update camera
    camera.aspect = sizes.width / sizes.height
    camera.updateProjectionMatrix()
 
    // Update renderer
    renderer.setSize(sizes.width, sizes.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})
 
/**
 * Fullscreen
 */
window.addEventListener('dblclick', () =>
{
    const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement
 
    if(!fullscreenElement)
    {
        if(canvas.requestFullscreen)
        {
            canvas.requestFullscreen()
        }
        else if(canvas.webkitRequestFullscreen)
        {
            canvas.webkitRequestFullscreen()
        }
    }
    else
    {
        if(document.exitFullscreen)
        {
            document.exitFullscreen()
        }
        else if(document.webkitExitFullscreen)
        {
            document.webkitExitFullscreen()
        }
    }
})
 
/**
 * Camera
 */
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
camera.position.z = 3
scene.add(camera)
 
// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true
 
/**
 * Renderer
 */
const renderer = new THREE.WebGLRenderer({
    canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
 
/**
 * Animate
 */
const clock = new THREE.Clock()
 
const tick = () =>
{
    const elapsedTime = clock.getElapsedTime()
 
    // Update controls
    controls.update()
 
    // Render
    renderer.render(scene, camera)
 
    // Call tick again on the next frame
    window.requestAnimationFrame(tick)
}
 
tick()

Sejauh ini kita cuma buat objek geometry kotak, selanjutnya kita akan mengenal lebih jauh tentang **Geometry** dan membuat geometri kita sendiri.