Tentang codelab ini
1. Sebelum memulai
Codelab ini mengajarkan cara menggunakan fitur dengan teknologi WebGL dari Maps JavaScript API untuk mengontrol dan merender pada peta vektor dalam tiga dimensi.
Prasyarat
Codelab ini mengasumsikan bahwa Anda memiliki pengetahuan yang cukup terkait JavaScript dan Maps JavaScript API. Untuk mempelajari dasar-dasar penggunaan Maps JS API, coba Tambahkan peta ke codelab situs (JavaScript) Anda.
Yang akan Anda pelajari
- Membuat ID Peta dengan peta vektor untuk JavaScript yang diaktifkan.
- Mengontrol peta dengan kemiringan dan rotasi terprogram.
- Merender objek 3D pada peta dengan
WebGLOverlayView
dan Three.js. - Menganimasikan gerakan kamera dengan
moveCamera
.
Yang akan Anda perlukan
- Akun Google Cloud Platform dengan penagihan diaktifkan
- Kunci API Google Maps Platform dengan Maps JavaScript API diaktifkan
- Pengetahuan yang cukup tentang JavaScript, HTML, dan CSS
- Editor teks atau IDE pilihan Anda
- Node.js
2. Mulai persiapan
Untuk langkah pengaktifan di bawah, Anda harus mengaktifkan Maps JavaScript API.
Menyiapkan Google Maps Platform
Jika Anda belum memiliki akun Google Cloud Platform dan project dengan penagihan diaktifkan, lihat panduan Memulai Google Maps Platform untuk membuat akun penagihan dan project.
- Di Cloud Console, klik menu drop-down project, lalu pilih project yang ingin Anda gunakan untuk codelab ini.
- Aktifkan API dan SDK Google Maps Platform yang diperlukan untuk codelab ini di Google Cloud Marketplace. Untuk melakukannya, ikuti langkah-langkah dalam video ini atau dokumentasi ini.
- Buat kunci API di halaman Kredensial di Cloud Console. Anda dapat mengikuti langkah-langkah dalam video ini atau dokumentasi ini. Semua permintaan ke Google Maps Platform memerlukan kunci API.
Penyiapan Node.js
Jika Anda belum memilikinya, buka https://nodejs.org/ untuk mendownload dan menginstal runtime Node.js di komputer.
Node.js disertai dengan npm, sebuah pengelola paket yang Anda perlukan untuk menginstal dependensi untuk codelab ini.
Mendownload template permulaan project
Sebelum memulai codelab ini, lakukan hal berikut untuk mendownload template project permulaan, serta kode solusi lengkap:
- Download atau fork repositori GitHub untuk codelab ini di https://github.com/googlecodelabs/maps-platform-101-webgl/. Project permulaan berada di direktori
/starter
dan menyertakan struktur file dasar yang Anda butuhkan untuk menyelesaikan codelab. Semua yang Anda butuhkan ada di direktori/starter/src
. - Setelah mendownload project permulaan, jalankan
npm install
di direktori/starter
. Tindakan ini akan menginstal semua dependensi yang diperlukan yang tercantum dipackage.json
. - Setelah dependensi diinstal, jalankan
npm start
di direktori.
Project permulaan telah disiapkan agar Anda dapat menggunakan webpack-dev-server, yang mengompilasi dan menjalankan kode yang Anda tulis secara lokal. webpack-dev-server juga otomatis memuat ulang aplikasi Anda di browser setiap kali Anda membuat perubahan kode.
Jika ingin melihat kode solusi lengkap berjalan, Anda dapat menyelesaikan langkah-langkah penyiapan di atas pada direktori /solution
.
Menambahkan kunci API
Aplikasi awal menyertakan semua kode yang diperlukan untuk memuat peta dengan JS API Loader, sehingga Anda hanya perlu menyediakan kunci API dan ID Peta. JS API Loader adalah library sederhana yang memisahkan metode tradisional pemuatan Maps JS API secara inline di template HTML menggunakan tag script
, sehingga Anda dapat menangani semuanya di kode JavaScript.
Untuk menambahkan kunci API, lakukan hal berikut pada project permulaan:
- Buka
app.js
. - Di objek
apiOptions
, tetapkan kunci API Anda sebagai nilaiapiOptions.apiKey
.
3. Buat dan gunakan ID Peta
Untuk menggunakan fitur berbasis WebGL dari Maps JavaScript API, Anda memerlukan ID Peta dengan peta vektor diaktifkan.
Membuat ID Peta
- Di Google Cloud Console, buka 'Google Maps Platform' > 'Pengelolaan Peta'.
- Klik 'BUAT ID PETA BARU'.
- Di kolom 'Nama peta', masukkan nama untuk ID Peta Anda.
- Pada menu dropdown 'Jenis peta', pilih 'JavaScript'. 'Opsi JavaScript' akan muncul.
- Di bagian 'Opsi JavaScript', pilih tombol pilihan 'Vektor', kotak centang 'Kemiringan', dan kotak centang 'Rotasi'.
- Opsional. Di kolom 'Deskripsi', masukkan deskripsi untuk kunci API Anda.
- Klik tombol 'Berikutnya'. Halaman 'Detail ID Peta' akan muncul.
- Salin ID Peta. Anda akan menggunakan ID Peta ini pada langkah berikutnya untuk memuat Peta.
Menggunakan ID Peta
Untuk memuat peta vektor, Anda harus memasukkan ID Peta sebagai properti pada opsi saat membuat instance Peta. Secara opsional, Anda juga dapat memasukkan ID Peta yang sama saat memuat Maps JavaScript API.
Untuk memuat peta dengan ID Peta Anda, lakukan hal berikut:
- Tetapkan ID Peta Anda sebagai nilai
mapOptions.mapId
.
Dengan memasukkan ID Peta saat membuat instance peta, Google Maps Platform akan mengetahui peta mana yang akan dimuat untuk instance tertentu. Anda dapat menggunakan kembali ID Peta yang sama di beberapa aplikasi atau tampilan dalam aplikasi yang sama.const mapOptions = {
"tilt": 0,
"heading": 0,
"zoom": 18,
"center": { lat: 35.6594945, lng: 139.6999859 },
"mapId": "YOUR_MAP_ID"
};
Periksa aplikasi yang berjalan di browser Anda. Peta vektor dengan kemiringan dan rotasi yang diaktifkan harus berhasil dimuat. Untuk memeriksa apakah kemiringan dan rotasi diaktifkan, tahan tombol shift, lalu tarik dengan mouse atau gunakan tombol panah pada keyboard.
Jika peta tidak dimuat, pastikan Anda telah memasukkan kunci API yang valid dalam apiOptions
. Jika peta tidak miring dan berputar, pastikan Anda telah memasukkan ID Peta yang telah mengaktifkan kemiringan dan rotasi di apiOptions
dan mapOptions
.
File app.js
Anda sekarang akan terlihat seperti ini:
import { Loader } from '@googlemaps/js-api-loader';
const apiOptions = {
"apiKey": 'YOUR_API_KEY',
"version": "beta"
};
const mapOptions = {
"tilt": 0,
"heading": 0,
"zoom": 18,
"center": { lat: 35.6594945, lng: 139.6999859 },
"mapId": "YOUR_MAP_ID"
}
async function initMap() {
const mapDiv = document.getElementById("map");
const apiLoader = new Loader(apiOptions);
await apiLoader.load();
return new google.maps.Map(mapDiv, mapOptions);
}
function initWebGLOverlayView (map) {
let scene, renderer, camera, loader;
// WebGLOverlayView code goes here
}
(async () => {
const map = await initMap();
})();
4. Terapkan WebGLOverlayView
WebGLOverlayView
memberi Anda akses langsung ke konteks untuk proses rendering WebGL yang sama dengan yang digunakan untuk merender peta dasar vektor. Dengan demikian, Anda dapat merender objek 2D dan 3D langsung di peta menggunakan WebGL, serta library grafik berbasis WebGL yang populer.
WebGLOverlayView
mengekspos lima hook ke dalam siklus proses konteks untuk rendering WebGL dari peta yang dapat Anda gunakan. Berikut adalah deskripsi singkat tentang masing-masing hook dan kegunaannya:
onAdd()
: Dipanggil saat overlay ditambahkan ke peta dengan memanggilsetMap
pada instanceWebGLOverlayView
. Di hook ini, Anda harus melakukan tindakan yang berkaitan dengan WebGL yang tidak memerlukan akses langsung ke konteks WebGL.onContextRestored()
: Dipanggil saat konteks WebGL tersedia, tetapi sebelum proses rendering berjalan. Di hook ini, Anda harus menginisialisasi objek, melakukan binding pada status, dan melakukan hal lain yang memerlukan akses ke konteks WebGL, tetapi dapat dilakukan di luar panggilanonDraw()
. Tindakan ini memungkinkan Anda menyiapkan semua yang dibutuhkan tanpa menambahkan kelebihan overhead ke proses rendering peta yang sebenarnya, yang sudah menggunakan GPU secara intensif.onDraw()
: Dipanggil sekali per frame setelah WebGL mulai merender peta dan hal lain yang Anda minta. Anda harus melakukan tindakan seminimal mungkin dionDraw()
agar tidak menyebabkan masalah performa dalam proses rendering peta.onContextLost()
: Dipanggil saat konteks untuk proses rendering WebGL hilang karena alasan apa pun.onRemove()
: Dipanggil saat overlay dihapus dari peta dengan memanggilsetMap(null)
pada instanceWebGLOverlayView
.
Pada langkah ini, Anda akan membuat instance WebGLOverlayView
dan menerapkan tiga hook siklus prosesnya: onAdd
, onContextRestored
, dan onDraw
. Agar teratur dan mudah diikuti, semua kode untuk overlay akan ditangani di fungsi initWebGLOverlayView()
yang disediakan di template permulaan untuk codelab ini.
- Buat instance
WebGLOverlayView()
.
Overlay diberikan oleh Maps JS API digoogle.maps.WebGLOverlayView
. Untuk memulai, buat instance dengan menambahkan kode berikut keinitWebGLOverlayView()
:const webGLOverlayView = new google.maps.WebGLOverlayView();
- Terapkan hook siklus proses.
Untuk menerapkan hook siklus proses, tambahkan kode berikut keinitWebGLOverlayView()
:webGLOverlayView.onAdd = () => {};
webGLOverlayView.onContextRestored = ({gl}) => {};
webGLOverlayView.onDraw = ({gl, coordinateTransformer}) => {}; - Tambahkan instance overlay ke peta.
Sekarang, panggilsetMap()
pada instance overlay dan teruskan peta dengan menambahkan kode berikut keinitWebGLOverlayView()
:webGLOverlayView.setMap(map)
- Panggil
initWebGLOverlayView
.
Langkah terakhir adalah menjalankaninitWebGLOverlayView()
dengan menambahkan kode berikut ke fungsi yang langsung dipanggil di bagian bawahapp.js
:initWebGLOverlayView(map);
Fungsi yang langsung dipanggil dan initWebGLOverlayView
sekarang akan terlihat seperti ini:
async function initWebGLOverlayView (map) {
let scene, renderer, camera, loader;
const webGLOverlayView = new google.maps.WebGLOverlayView();
webGLOverlayView.onAdd = () => {}
webGLOverlayView.onContextRestored = ({gl}) => {}
webGLOverlayView.onDraw = ({gl, coordinateTransformer}) => {}
webGLOverlayView.setMap(map);
}
(async () => {
const map = await initMap();
initWebGLOverlayView(map);
})();
Hanya itu yang Anda butuhkan untuk menerapkan WebGLOverlayView
. Selanjutnya, Anda akan menyiapkan semua yang diperlukan untuk merender objek 3D pada peta menggunakan Three.js.
5. Siapkan tampilan three.js
Menggunakan WebGL bisa jadi sangat rumit karena Anda harus mendefinisikan semua aspek dari setiap objek secara manual dan hal lainnya. Untuk mempermudah, Anda akan menggunakan Three.js, sebuah library grafik populer yang menyediakan lapisan abstraksi sederhana di atas WebGL, pada codelab ini. Three.js dilengkapi dengan berbagai fungsi praktis yang bisa digunakan untuk apa saja, mulai dari membuat perender WebGL, menggambar bentuk objek 2D dan 3D umum, hingga mengontrol kamera, transformasi objek, dan banyak lagi.
Ada tiga jenis objek dasar di Three.js yang diperlukan untuk menampilkan apa pun:
- Tampilan: "Penampung" tempat semua objek, sumber cahaya, tekstur, dll. dirender dan ditampilkan.
- Kamera: Kamera yang merepresentasikan sudut pandang tampilan. Terdapat beberapa jenis kamera, dan satu atau beberapa kamera dapat ditambahkan ke satu tampilan.
- Perender: Perender yang menangani pemrosesan dan penampilan semua objek dalam tampilan. Di Three.js,
WebGLRenderer
paling sering digunakan, tetapi beberapa fungsi lain tersedia sebagai pengganti jika klien tidak mendukung WebGL.
Pada langkah ini, Anda akan memuat semua dependensi yang diperlukan untuk Three.js dan menyiapkan tampilan dasar.
- Muat Three.js
Anda akan memerlukan dua dependensi untuk codelab ini: library Three.js dan GLTFLoader, class yang memungkinkan Anda memuat objek 3D di GL Transmission Format (glTF). Three.js menawarkan loader khusus untuk berbagai format objek 3D, tetapi sebaiknya gunakan glTF.
Pada kode di bawah, seluruh library Three.js diimpor. Dalam aplikasi produksi, Anda mungkin hanya ingin mengimpor class yang dibutuhkan, tetapi untuk codelab ini, impor seluruh library guna memudahkan Anda. Perhatikan juga bahwa GLTFLoader tidak disertakan dalam library default, dan perlu diimpor dari jalur terpisah pada dependensi - jalur ini adalah tempat Anda dapat mengakses semua loader yang disediakan oleh Three.js.
Untuk mengimpor Three.js dan GLTFLoader, tambahkan kode berikut ke bagian atasapp.js
:import * as THREE from 'three';
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js'; - Buat tampilan three.js.
Untuk membuat tampilan, buat instance classScene
Three.js dengan menambahkan kode berikut ke hookonAdd
:scene = new THREE.Scene();
- Tambahkan kamera ke tampilan.
Seperti yang telah disebutkan, kamera merepresentasikan sudut pandang tampilan, dan menentukan cara Three.js menangani rendering visual objek dalam tampilan. Tanpa kamera, tampilan tidak "terlihat" secara efektif, yang berarti objek tidak akan muncul karena tidak akan dirender.
Three.js menawarkan berbagai jenis kamera yang memengaruhi cara perender memperlakukan objek sehubungan dengan sudut pandang dan kedalamannya. Dalam tampilan ini, Anda akan menggunakanPerspectiveCamera
, jenis kamera yang paling sering digunakan di Three.js, yang dirancang untuk meniru cara mata manusia melihat tampilan. Artinya, objek yang lebih jauh dari kamera akan tampak lebih kecil daripada objek yang lebih dekat, tampilan akan terlihat semakin kecil saat semakin jauh, dan lainnya.
Untuk menambahkan kamera perspektif ke tampilan, tambahkan kode berikut ke hookonAdd
: Dengancamera = new THREE.PerspectiveCamera();
PerspectiveCamera
, Anda juga dapat mengonfigurasi atribut yang membentuk sudut pandang, termasuk bidang dekat dan jauh, rasio lebar tinggi, dan ruang pandang (fov). Secara kolektif, atribut ini membentuk frustum sudut pandang, sebuah konsep penting untuk dipahami saat mengerjakan 3D, tetapi di luar cakupan codelab ini. KonfigurasiPerspectiveCamera
default sudah cukup. - Tambahkan sumber cahaya ke tampilan.
Secara default, objek yang dirender dalam tampilan Three.js akan berwarna hitam, apa pun tekstur yang diterapkan pada objek tersebut. Warna hitam ini muncul karena tampilan Three.js meniru bagaimana objek terlihat di dunia nyata, yang visibilitas warnanya bergantung pada cahaya yang memantul dari objek. Singkatnya, tanpa cahaya, tidak akan ada warna.
Three.js menyediakan berbagai jenis cahaya dan Anda akan menggunakan dua jenis cahaya berikut: AmbientLight
: Memberikan sumber cahaya menyebar yang menerangi semua objek di tampilan secara merata dari semua sudut. Jenis cahaya ini akan memberikan cahaya dasar pada tampilan untuk memastikan tekstur pada semua objek terlihat.DirectionalLight
: Memberikan cahaya yang berasal dari satu arah pada tampilan. Berbeda dari cara kerja cahaya yang diposisikan di dunia nyata, cahaya yang memancar dariDirectionalLight
semuanya merambat lurus dan tidak menyebar maupun membaur saat menjauh dari sumber cahaya.
Anda dapat mengonfigurasi warna dan intensitas setiap cahaya untuk membuat efek pencahayaan gabungan. Misalnya, pada kode di bawah ini, cahaya ruangan memancarkan cahaya putih lembut untuk seluruh tampilan, sedangkan cahaya terarah memancarkan cahaya sekunder yang mengenai objek dengan sudut menurun. Dalam kasus cahaya terarah, sudut ditetapkan menggunakanposition.set(x, y ,z)
, yang masing-masing nilainya relatif terhadap sumbunya. Jadi, misalnya,position.set(0,1,0)
akan memosisikan cahaya langsung di atas tampilan pada sumbu y yang mengarah lurus ke bawah.
Untuk menambahkan sumber cahaya ke tampilan, tambahkan kode berikut ke hookonAdd
:const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 );
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.25);
directionalLight.position.set(0.5, -1, 0.5);
scene.add(directionalLight);
Hook onAdd
Anda sekarang akan terlihat seperti ini:
webGLOverlayView.onAdd = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 );
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.25);
directionalLight.position.set(0.5, -1, 0.5);
scene.add(directionalLight);
}
Tampilan Anda kini sudah siap dan dapat dirender. Selanjutnya, Anda akan mengonfigurasi perender WebGL dan merender tampilan.
6. Render tampilan
Saatnya merender tampilan. Sejauh ini, semua yang telah Anda buat dengan Three.js diinisialisasi dalam kode, tetapi pada dasarnya tampilan tersebut tidak ada karena belum dirender ke dalam konteks untuk proses rendering WebGL. WebGL merender konten 2D dan 3D di browser menggunakan Canvas API. Jika sudah pernah menggunakan Canvas API sebelumnya, Anda mungkin terbiasa dengan context
kanvas HTML, tempat untuk merender semua hal. Anda mungkin tidak mengetahui bahwa ini adalah antarmuka yang mengekspos konteks untuk proses rendering grafik OpenGL melalui API WebGLRenderingContext
di browser.
Untuk mempermudah penggunaan perender WebGL, Three.js menyediakan WebGLRenderer
, sebuah wrapper yang memudahkan konfigurasi konteks untuk proses rendering WebGL sehingga Three.js dapat merender tampilan di browser. Namun, untuk peta, merender tampilan Three.js di browser bersama peta saja tidak cukup. Three.js harus dirender ke dalam konteks untuk proses rendering yang sama persis dengan peta, sehingga peta dan objek apa pun dari tampilan Three.js dirender ke ruang dunia yang sama. Tindakan ini memungkinkan perender menangani interaksi antara objek pada peta dan objek dalam tampilan, seperti oklusi, yang merupakan cara keren dalam menyebut objek akan menyembunyikan objek di belakangnya agar tidak terlihat.
Tampaknya cukup rumit, bukan? Untungnya, Three.js siap membantu lagi.
- Siapkan perender WebGL.
Saat membuat instanceWebGLRenderer
Three.js baru, Anda dapat memberikan konteks spesifik untuk proses rendering WebGL yang diinginkan sebagai tempat untuk merender tampilan Anda. Ingat argumengl
yang diteruskan ke hookonContextRestored
? Objekgl
tersebut adalah konteks untuk proses rendering WebGL dari peta. Anda hanya perlu menyediakan konteks, kanvasnya, dan atributnya ke instanceWebGLRenderer
. Semua hal tersebut tersedia melalui objekgl
. Dalam kode ini, propertiautoClear
dari perender juga ditetapkan kefalse
sehingga perender tidak menghapus outputnya dari setiap frame.
Untuk mengonfigurasi perender, tambahkan kode berikut ke hookonContextRestored
:renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false; - Render tampilan.
Setelah perender dikonfigurasi, panggilrequestRedraw
pada instanceWebGLOverlayView
untuk menginformasikan overlay bahwa penggambaran ulang diperlukan saat frame berikutnya dirender, lalu panggilrender
pada perender dan teruskan kamera serta tampilan Three.js yang ingin dirender ke perender. Terakhir, hapus status konteks untuk proses rendering WebGL. Langkah ini penting dilakukan untuk menghindari konflik status GL, karena penggunaan Tampilan Overlay WebGL bergantung pada status GL yang dibagikan. Jika status tidak direset pada akhir setiap panggilan gambar, konflik status GL dapat menyebabkan perender gagal.
Untuk melakukan ini, tambahkan kode berikut ke hookonDraw
sehingga reset status ini dijalankan di setiap frame:webGLOverlayView.requestRedraw();
renderer.render(scene, camera);
renderer.resetState();
Hook onContextRestored
dan onDraw
Anda sekarang akan terlihat seperti ini:
webGLOverlayView.onContextRestored = ({gl}) => {
renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
}
webGLOverlayView.onDraw = ({gl, transformer}) => {
webGLOverlayView.requestRedraw();
renderer.render(scene, camera);
renderer.resetState();
}
7. Render model 3D pada peta
Semua yang Anda butuhkan sudah siap. Anda telah menyiapkan Tampilan Overlay WebGL dan membuat tampilan Three.js, tetapi ada satu masalah: tidak ada apa pun di dalamnya. Jadi, langkah berikutnya adalah merender objek 3D dalam tampilan. Untuk melakukan hal ini, Anda akan menggunakan GLTFLoader yang Anda impor sebelumnya.
Model 3D tersedia dalam berbagai format, tetapi untuk Three.js, format gLTF lebih disarankan karena ukuran dan performa runtime-nya. Di codelab ini, model yang akan Anda render dalam tampilan sudah disediakan untuk Anda di /src/pin.gltf
.
- Buat instance loader model.
Tambahkan kode berikut keonAdd
:loader = new GLTFLoader();
- Muat model 3D.
Loader model bersifat asinkron dan menjalankan callback setelah model dimuat sepenuhnya. Untuk memuatpin.gltf
, tambahkan kode berikut keonAdd
:const source = "pin.gltf";
loader.load(
source,
gltf => {}
); - Tambahkan model ke tampilan.
Sekarang, Anda dapat menambahkan model ke tampilan dengan menambahkan kode berikut ke callbackloader
. Perhatikan bahwa yang ditambahkan adalahgltf.scene
, bukangltf
:scene.add(gltf.scene);
- Konfigurasi matriks proyeksi kamera.
Langkah terakhir yang perlu Anda lakukan agar model dirender dengan benar pada peta adalah menyetel matriks proyeksi kamera di tampilan Three.js. Matriks proyeksi ditetapkan sebagai arrayMatrix4
Three.js, yang menentukan titik dalam ruang tiga dimensi beserta transformasinya, seperti rotasi, pergeseran, skala, dan lainnya.
Dalam kasusWebGLOverlayView
, matriks proyeksi digunakan untuk menginformasikan perender tempat dan cara merender tampilan Three.js secara relatif terhadap peta dasar. Namun, ada satu masalah. Lokasi pada peta ditetapkan sebagai pasangan koordinat lintang dan bujur, sedangkan lokasi pada tampilan Three.js merupakan koordinatVector3
. Seperti yang mungkin sudah Anda duga, menghitung konversi antara kedua sistem tersebut bukanlah hal yang mudah. Untuk mengatasi perbedaan ini,WebGLOverlayView
meneruskan objekcoordinateTransformer
ke hook siklus prosesOnDraw
yang berisi fungsi bernamafromLatLngAltitude
. FungsifromLatLngAltitude
mengambil objekLatLngAltitude
atauLatLngAltitudeLiteral
, dan secara opsional sekumpulan argumen yang menentukan transformasi untuk tampilan, lalu mengubahnya ke matriks proyeksi tampilan model (MVP) untuk Anda. Anda hanya perlu menentukan lokasi pada peta tempat Anda ingin tampilan Three.js dirender, serta transformasi yang diinginkan untuk tampilan, danWebGLOverlayView
akan melakukan sisanya. Selanjutnya, Anda dapat mengubah matriks MVP ke arrayMatrix4
Three.js dan menetapkan matriks proyeksi kamera ke array tersebut.
Pada kode di bawah, argumen kedua menginformasikan Tampilan Overlay WebGL untuk menetapkan ketinggian tampilan Three.js ke 120 meter di atas permukaan tanah, sehingga model akan tampak mengambang.
Untuk menetapkan matriks proyeksi kamera, tambahkan kode berikut ke hookonDraw
:const latLngAltitudeLiteral = {
lat: mapOptions.center.lat,
lng: mapOptions.center.lng,
altitude: 120
}
const matrix = transformer.fromLatLngAltitude(latLngAltitudeLiteral);
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix); - Lakukan transformasi pada model.
Anda akan melihat pin yang tidak tegak lurus terhadap peta. Dalam grafik 3D, selain ruang dunia yang memiliki sumbu x, y, dan z sendiri untuk menentukan orientasi, setiap objek juga memiliki ruang objeknya sendiri dengan pasangan sumbu independen.
Dalam kasus model ini, model tidak dibuat dengan yang biasa kita anggap sebagai 'bagian atas' pin yang menghadap ke sumbu y, sehingga Anda harus mengubah objek untuk mengorientasikannya sesuai yang diinginkan yang relatif terhadap ruang dunia dengan memanggilrotation.set
pada objek tersebut. Perhatikan bahwa di Three.js, rotasi ditetapkan dalam radian, bukan derajat. Umumnya, satuan derajat lebih mudah untuk dibayangkan, sehingga konversi yang sesuai harus dibuat menggunakan formuladegrees * Math.PI/180
.
Selain itu, model ini berukuran sedikit kecil, sehingga Anda juga akan menskalakannya secara merata di semua sumbu dengan memanggilscale.set(x, y ,z)
.
Untuk memutar dan menskalakan model, tambahkan kode berikut dalam callbackloader
darionAdd
sebelumscene.add(gltf.scene)
yang menambahkan glTF ke tampilan:gltf.scene.scale.set(25,25,25);
gltf.scene.rotation.x = 180 * Math.PI/180;
Sekarang pin diletakkan tegak lurus relatif terhadap peta.
Hook onAdd
dan onDraw
Anda sekarang akan terlihat seperti ini:
webGLOverlayView.onAdd = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // soft white light
scene.add( ambientLight );
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.25);
directionalLight.position.set(0.5, -1, 0.5);
scene.add(directionalLight);
loader = new GLTFLoader();
const source = 'pin.gltf';
loader.load(
source,
gltf => {
gltf.scene.scale.set(25,25,25);
gltf.scene.rotation.x = 180 * Math.PI/180;
scene.add(gltf.scene);
}
);
}
webGLOverlayView.onDraw = ({gl, transformer}) => {
const latLngAltitudeLiteral = {
lat: mapOptions.center.lat,
lng: mapOptions.center.lng,
altitude: 100
}
const matrix = transformer.fromLatLngAltitude(latLngAltitudeLiteral);
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
webGLOverlayView.requestRedraw();
renderer.render(scene, camera);
renderer.resetState();
}
Selanjutnya adalah animasi kamera.
8. Animasikan kamera
Setelah Anda merender model pada peta dan dapat memindahkan semua objek dalam tiga dimensi, hal berikutnya yang harus Anda lakukan adalah mengontrol gerakan tersebut secara terprogram. Fungsi moveCamera
memungkinkan Anda menetapkan pusat, zoom, kemiringan, dan arah properti pada peta secara bersamaan, sehingga memberi Anda kontrol yang lebih mendetail atas pengalaman pengguna. Selain itu, moveCamera
dapat dipanggil dalam loop animasi untuk membuat transisi yang halus antar-frame pada kecepatan frame mendekati 60 frame per detik.
- Tunggu hingga model dimuat.
Agar dapat menciptakan pengalaman pengguna yang lancar, Anda harus menunggu untuk mulai menggerakkan kamera hingga model glTF dimuat. Untuk melakukan ini, tambahkan pengendali peristiwaonLoad
loader ke hookonContextRestored
:loader.manager.onLoad = () => {}
- Buat loop animasi.
Ada lebih dari satu cara untuk membuat loop animasi, seperti menggunakansetInterval
ataurequestAnimationFrame
. Dalam hal ini, Anda akan menggunakan fungsisetAnimationLoop
dari perender Three.js, yang akan otomatis memanggil kode yang Anda deklarasikan dalam callback-nya setiap kali Three.js merender frame baru. Untuk membuat loop animasi, tambahkan kode berikut ke pengendali peristiwaonLoad
di langkah sebelumnya:renderer.setAnimationLoop(() => {});
- Tetapkan posisi kamera di loop animasi.
Selanjutnya, panggilmoveCamera
untuk memperbarui peta. Di sini, properti dari objekmapOptions
yang dipakai untuk memuat peta digunakan untuk menentukan posisi kamera:map.moveCamera({
"tilt": mapOptions.tilt,
"heading": mapOptions.heading,
"zoom": mapOptions.zoom
}); - Perbarui kamera untuk setiap frame.
Langkah terakhir. Perbarui objekmapOptions
di bagian akhir setiap frame guna menetapkan posisi kamera untuk frame berikutnya. Dalam kode ini, pernyataanif
digunakan untuk meningkatkan kemiringan hingga mencapai nilai kemiringan maksimum sebesar 67,5 derajat, lalu arah pada setiap frame berubah sedikit sampai kamera menyelesaikan rotasi penuh 360 derajat. Setelah animasi yang diinginkan selesai,null
diteruskan kesetAnimationLoop
untuk membatalkan animasi agar tidak berjalan terus-menerus.if (mapOptions.tilt < 67.5) {
mapOptions.tilt += 0.5
} else if (mapOptions.heading <= 360) {
mapOptions.heading += 0.2;
} else {
renderer.setAnimationLoop(null)
}
Hook onContextRestored
Anda sekarang akan terlihat seperti ini:
webGLOverlayView.onContextRestored = ({gl}) => {
renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
loader.manager.onLoad = () => {
renderer.setAnimationLoop(() => {
map.moveCamera({
"tilt": mapOptions.tilt,
"heading": mapOptions.heading,
"zoom": mapOptions.zoom
});
if (mapOptions.tilt < 67.5) {
mapOptions.tilt += 0.5
} else if (mapOptions.heading <= 360) {
mapOptions.heading += 0.2;
} else {
renderer.setAnimationLoop(null)
}
});
}
}
9. Selamat
Jika semuanya berjalan sesuai rencana, Anda akan melihat peta dengan pin 3D besar yang terlihat seperti ini:
Yang telah Anda pelajari
Dalam codelab ini, Anda telah mempelajari banyak hal; berikut adalah sorotannya:
- Menerapkan
WebGLOverlayView
dan hook siklus prosesnya. - Mengintegrasikan Three.js ke peta.
- Dasar-dasar pembuatan tampilan Three.js, termasuk kamera dan pencahayaan.
- Memuat dan memanipulasi model 3D menggunakan Three.js.
- Mengontrol dan menganimasikan kamera untuk peta menggunakan
moveCamera
.
Apa selanjutnya?
WebGL, dan grafik komputer secara umum, adalah topik yang kompleks, jadi selalu ada banyak hal yang perlu dipelajari. Berikut ini beberapa referensi untuk membantu Anda memulai:
- Dokumentasi Tampilan Overlay WebGL
- Mulai menggunakan WebGL.
- Dokumentasi Tiga.js
- Bantu kami membuat konten yang menurut Anda paling berguna dengan menjawab pertanyaan di bawah: «codelabs/maps-platform/shared/_next-lab-survey.lab.md» Apakah codelab yang Anda inginkan tidak tercantum di atas? Ajukan permintaan codelab yang diinginkan bersama topik baru di sini.