Membangun dengan Chrome

Membawa balok LEGO® ke Web Multi-Perangkat

Build with Chrome, eksperimen yang menyenangkan untuk pengguna Chrome desktop yang awalnya diluncurkan di Australia, dirilis ulang pada tahun 2014 dengan ketersediaan global, kolaborasi dengan THE LEGO® MOVIE™, dan dukungan yang baru ditambahkan untuk perangkat seluler. Dalam artikel ini, kami akan membagikan beberapa pembelajaran dari project tersebut, terutama terkait peralihan dari pengalaman khusus desktop ke solusi multilayar yang mendukung input mouse dan sentuh.

Histori Build dengan Chrome

Versi pertama Build with Chrome diluncurkan di Australia pada tahun 2012. Kami ingin menunjukkan kekuatan web dengan cara yang benar-benar baru dan menghadirkan Chrome kepada audiens yang benar-benar baru.

Situs ini memiliki dua bagian utama: mode "Buat" tempat pengguna dapat membuat kreasi menggunakan balok LEGO, dan mode "Jelajahi" untuk menjelajahi kreasi di Google Maps versi LEGO.

3D interaktif sangat penting untuk memberikan pengalaman pembuatan LEGO terbaik kepada pengguna. Pada tahun 2012, WebGL hanya tersedia untuk publik di browser desktop, sehingga Build ditargetkan sebagai pengalaman khusus desktop. Jelajah menggunakan Google Maps untuk menampilkan kreasi, tetapi saat diperbesar cukup dekat, peta akan beralih ke implementasi WebGL yang menampilkan kreasi dalam 3D, yang masih menggunakan Google Maps sebagai tekstur pelat dasar. Kami berharap dapat membangun lingkungan tempat penggemar LEGO dari segala usia dapat mengekspresikan kreativitas mereka dengan mudah dan intuitif serta menjelajahi kreasi satu sama lain.

Pada tahun 2013, kami memutuskan untuk memperluas Build with Chrome ke teknologi web baru. Di antara teknologi tersebut adalah WebGL di Chrome untuk Android, yang secara alami akan memungkinkan Build with Chrome berkembang menjadi pengalaman seluler. Untuk memulai, pertama-tama kita mengembangkan prototipe sentuh sebelum mempertanyakan hardware untuk "Alat Builder" guna memahami perilaku gestur dan respons taktil yang mungkin kita hadapi melalui browser dibandingkan dengan aplikasi seluler.

Front-end Responsif

Kita perlu mendukung perangkat dengan input sentuh dan mouse. Namun, menggunakan UI yang sama di layar sentuh kecil ternyata menjadi solusi yang kurang optimal karena keterbatasan ruang.

Di Build, ada banyak interaktivitas yang terjadi: memperbesar dan memperkecil, mengubah warna bata, dan tentu saja memilih, memutar, dan menempatkan bata. Ini adalah alat yang sering digunakan pengguna, jadi penting bagi mereka untuk memiliki akses cepat ke semua hal yang sering mereka gunakan, dan mereka harus merasa nyaman berinteraksi dengannya.

Saat mendesain aplikasi sentuh yang sangat interaktif, Anda akan mendapati bahwa layar terasa kecil dengan cepat dan jari pengguna cenderung menutupi sebagian besar layar saat berinteraksi. Hal ini menjadi jelas bagi kami saat menggunakan Builder. Anda benar-benar harus mempertimbangkan ukuran layar fisik, bukan piksel dalam grafik saat melakukan desain. Oleh karena itu, penting untuk meminimalkan jumlah tombol dan kontrol agar ruang layar sebanyak mungkin dapat digunakan untuk konten yang sebenarnya.

Tujuan kami adalah membuat Build terasa alami di perangkat sentuh, bukan hanya menambahkan input sentuh ke implementasi desktop asli, tetapi membuatnya terasa seperti benar-benar ditujukan untuk sentuh. Kami akhirnya memiliki dua variasi UI, satu untuk desktop dan tablet dengan layar besar dan satu untuk perangkat seluler dengan layar yang lebih kecil. Jika memungkinkan, sebaiknya gunakan satu implementasi dan memiliki transisi yang lancar di antara mode. Dalam kasus kami, kami memutuskan bahwa ada perbedaan pengalaman yang signifikan antara kedua mode ini sehingga kami memutuskan untuk mengandalkan titik henti sementara tertentu. Kedua versi memiliki banyak fitur yang sama dan kami mencoba melakukan sebagian besar hal hanya dengan satu implementasi kode, tetapi beberapa aspek UI berfungsi secara berbeda di antara keduanya.

Kami menggunakan data agen pengguna untuk mendeteksi perangkat seluler, lalu memeriksa ukuran area pandang untuk memutuskan apakah UI seluler layar kecil harus digunakan. Agak sulit untuk memilih titik henti sementara untuk "layar besar", karena sulit untuk mendapatkan nilai ukuran layar fisik yang andal. Untungnya, dalam kasus ini, tidak masalah jika kita menampilkan UI layar kecil di perangkat sentuh dengan layar besar, karena alat ini akan tetap berfungsi dengan baik, hanya saja beberapa tombol mungkin terasa sedikit terlalu besar. Pada akhirnya, kita menetapkan titik henti sementara ke 1.000 piksel; jika Anda memuat situs dari jendela yang lebih lebar dari 1.000 piksel (dalam mode lanskap), Anda akan mendapatkan versi layar besar.

Mari kita bahas sedikit tentang dua ukuran dan pengalaman layar:

Perangkat layar besar, dengan dukungan mouse dan sentuh

Versi layar besar ditayangkan ke semua komputer desktop dengan dukungan mouse dan ke perangkat sentuh dengan layar besar (seperti Google Nexus 10). Versi ini mirip dengan solusi desktop asli dalam jenis kontrol navigasi yang tersedia, tetapi kami menambahkan dukungan sentuh dan beberapa gestur. Kami menyesuaikan UI bergantung pada ukuran jendela, sehingga saat pengguna mengubah ukuran jendela, UI dapat dihapus atau diubah ukurannya. Kita melakukannya menggunakan kueri media CSS.

Contoh: Jika tinggi yang tersedia kurang dari 730 piksel, kontrol penggeser zoom dalam mode Jelajahi akan disembunyikan:

@media only screen and (max-height: 730px) {
    .zoom-slider {
        display: none;
    }
}

Layar kecil, hanya dukungan sentuh

Versi ini ditayangkan ke perangkat seluler dan tablet kecil (perangkat target Nexus 4 dan Nexus 7). Versi ini memerlukan dukungan multi-sentuh.

Pada perangkat layar kecil, kita perlu memberikan ruang layar sebanyak mungkin untuk konten, jadi kami melakukan beberapa penyesuaian untuk memaksimalkan ruang, sebagian besar dengan memindahkan elemen yang jarang digunakan agar tidak terlihat:

  • Pemilih bata Build diperkecil menjadi pemilih warna saat mem-build.
  • Kami mengganti kontrol zoom dan orientasi dengan gestur multi-kontrol.
  • Fungsi layar penuh Chrome juga berguna untuk mendapatkan ruang layar ekstra.
Mem-build di perangkat layar besar
Mem-build di perangkat layar besar. Pemilih bata selalu terlihat dan ada beberapa kontrol di sisi kanan.
Mem-build di perangkat berlayar kecil
Mem-build di layar kecil. Pemilih brick diperkecil dan beberapa tombol telah dihapus.

Dukungan dan Performa WebGL

Perangkat sentuh modern memiliki GPU yang cukup canggih, tetapi masih jauh dari perangkat desktop. Jadi, kami tahu bahwa kami akan mengalami beberapa tantangan terkait performa, terutama dalam mode Jelajahi 3D yang mengharuskan kami merender banyak kreasi secara bersamaan.

Secara kreatif, kami ingin menambahkan beberapa jenis batu bata baru dengan bentuk yang kompleks dan bahkan transparansi -- fitur yang biasanya sangat berat di GPU. Namun, kami harus kompatibel dengan versi sebelumnya dan terus mendukung kreasi dari versi pertama, sehingga kami tidak dapat menetapkan batasan baru, seperti mengurangi jumlah total brick dalam kreasi secara signifikan.

Pada versi pertama Build, kami memiliki batas maksimum brick yang dapat digunakan dalam satu pembuatan. Ada "brick-meter" yang menunjukkan jumlah bata yang tersisa. Dalam penerapan baru, kami memiliki beberapa brick baru untuk memengaruhi brick-meter lebih dari brick standar, sehingga sedikit mengurangi total jumlah maksimum brick. Ini adalah salah satu cara untuk menyertakan brick baru sekaligus tetap mempertahankan performa yang baik.

Dalam mode Jelajahi 3D, ada banyak hal yang terjadi secara bersamaan; pemuatan tekstur pelat dasar, pemuatan kreasi, menganimasikan dan merender kreasi, dan sebagainya. Hal ini memerlukan banyak hal dari GPU dan CPU, jadi kami melakukan banyak profiling frame di Chrome DevTools untuk mengoptimalkan bagian ini sebanyak mungkin. Di perangkat seluler, kami memutuskan untuk memperbesar sedikit kreasi sehingga kita tidak perlu merender banyak kreasi secara bersamaan.

Beberapa perangkat mengharuskan kami meninjau dan menyederhanakan beberapa shader WebGL, tetapi kami selalu menemukan cara untuk mengatasinya dan melanjutkan.

Mendukung perangkat non-WebGL

Kami ingin situs dapat digunakan meskipun perangkat pengunjung tidak mendukung WebGL. Terkadang ada cara untuk merepresentasikan 3D dengan cara yang disederhanakan menggunakan solusi kanvas atau fitur CSS3D. Sayangnya, kami tidak menemukan solusi yang cukup baik untuk mereplikasi fitur Build dan Jelajahi 3D tanpa menggunakan WebGL.

Untuk konsistensi, gaya visual kreasi harus sama di semua platform. Kita mungkin bisa mencoba solusi 2,5D, tetapi hal ini akan membuat kreasi terlihat berbeda dalam beberapa hal. Kami juga harus mempertimbangkan cara memastikan kreasi yang dibuat dengan versi pertama Build with Chrome akan terlihat sama dan berjalan lancar di versi baru situs seperti di versi pertama.

Mode Jelajahi 2D masih dapat diakses oleh perangkat non-WebGL, meskipun Anda tidak dapat membuat kreasi baru atau menjelajahi dalam 3D. Jadi, pengguna masih bisa mendapatkan gambaran tentang kedalaman project dan apa yang dapat mereka buat menggunakan alat ini jika mereka menggunakan perangkat yang mendukung WebGL. Situs mungkin tidak terlalu berharga bagi pengguna tanpa dukungan WebGL, tetapi setidaknya situs tersebut akan berfungsi sebagai teaser dan mendorong mereka untuk mencobanya.

Terkadang, mempertahankan versi penggantian untuk solusi WebGL tidak mungkin dilakukan. Ada banyak kemungkinan alasannya; performa, gaya visual, biaya pengembangan dan pemeliharaan, dan sebagainya. Namun, jika Anda memutuskan untuk tidak menerapkan penggantian, Anda setidaknya harus menangani pengunjung yang tidak mengaktifkan WebGL, menjelaskan alasan mereka tidak dapat mengakses situs sepenuhnya, dan memberikan petunjuk cara mengatasi masalah tersebut dengan menggunakan browser yang mendukung WebGL.

Pengelolaan Aset

Pada tahun 2013, Google memperkenalkan versi baru Google Maps dengan perubahan UI yang paling signifikan sejak peluncurannya. Jadi, kami memutuskan untuk mendesain ulang Build with Chrome agar sesuai dengan UI Google Maps baru, dan dengan demikian mempertimbangkan faktor lain dalam desain ulang tersebut. Desain baru ini relatif datar dengan warna solid yang bersih dan bentuk sederhana. Hal ini memungkinkan kami menggunakan CSS murni pada banyak elemen UI, sehingga meminimalkan penggunaan gambar.

Di Jelajahi, kita perlu memuat banyak gambar; gambar thumbnail untuk kreasi, tekstur peta untuk pelat dasar, dan terakhir kreasi 3D yang sebenarnya. Kami sangat berhati-hati untuk memastikan tidak ada kebocoran memori saat kami terus memuat gambar baru.

Kreasi 3D disimpan dalam format file kustom yang dikemas sebagai gambar PNG. Dengan menyimpan data kreasi 3D sebagai gambar, kita dapat meneruskan data secara langsung ke shader yang merender kreasi.

Untuk semua gambar buatan pengguna, desain memungkinkan kami menggunakan ukuran gambar yang sama untuk semua platform, sehingga meminimalkan penggunaan penyimpanan dan bandwidth.

Mengelola Orientasi Layar

Anda mungkin lupa seberapa banyak rasio aspek layar berubah saat beralih dari mode potret ke lanskap atau sebaliknya. Anda perlu mempertimbangkan hal ini sejak awal saat beradaptasi untuk perangkat seluler.

Di situs tradisional yang mengaktifkan scroll, Anda dapat menerapkan aturan CSS untuk mendapatkan situs responsif yang mengatur ulang konten dan menu. Selama Anda dapat menggunakan fungsi scroll, hal ini cukup mudah dikelola.

Kami juga menggunakan metode ini dengan Build, tetapi kami agak terbatas dalam cara menyelesaikan tata letak, karena kami perlu membuat konten terlihat setiap saat dan tetap memiliki akses cepat ke sejumlah kontrol dan tombol. Untuk situs konten murni seperti situs berita, tata letak yang fleksibel sangatlah masuk akal, tetapi untuk aplikasi game seperti milik kami, hal ini menjadi masalah. Menemukan tata letak yang berfungsi dalam orientasi lanskap dan potret menjadi tantangan tersendiri, sambil tetap mempertahankan ringkasan konten yang baik dan cara berinteraksi yang nyaman. Pada akhirnya, kami memutuskan untuk tetap menggunakan Build dalam mode lanskap saja dan memberi tahu pengguna untuk memutar perangkat mereka.

Jelajahi jauh lebih mudah diselesaikan dalam kedua orientasi. Kita hanya perlu menyesuaikan tingkat zoom 3D bergantung pada orientasi untuk mendapatkan pengalaman yang konsisten.

Sebagian besar tata letak konten dikontrol oleh CSS, tetapi beberapa hal terkait orientasi perlu diterapkan di JavaScript. Kami mendapati bahwa tidak ada solusi lintas perangkat yang baik untuk menggunakan window.orientation guna mengidentifikasi orientasi, sehingga pada akhirnya kami hanya membandingkan window.innerWidth dan window.innerHeight untuk mengidentifikasi orientasi perangkat.

if( window.innerWidth > window.innerHeight ){
  //landscape
} else {
  //portrait
}

Menambahkan Dukungan Sentuh

Menambahkan dukungan sentuh ke konten web cukup mudah. Interaktivitas dasar, seperti peristiwa klik, berfungsi sama di desktop dan perangkat yang mendukung sentuh, tetapi jika menyangkut interaksi lanjutan, Anda juga perlu menangani peristiwa sentuh: touchstart, touchmove, dan touchend. Artikel ini membahas dasar-dasar cara menggunakan peristiwa ini. Internet Explorer tidak mendukung peristiwa sentuh, tetapi menggunakan Peristiwa Pointer (pointerdown, pointermove, pointerup). Peristiwa Pointer telah dikirim ke W3C untuk standarisasi, tetapi untuk saat ini hanya diterapkan di Internet Explorer.

Dalam mode Jelajahi 3D, kami menginginkan navigasi yang sama dengan penerapan Google Maps standar; menggunakan satu jari untuk menggeser peta dan mencubit dua jari untuk melakukan zoom. Karena kreasi tersebut dalam 3D, kami juga menambahkan gestur putar dua jari. Hal ini biasanya memerlukan penggunaan peristiwa sentuh.

Praktik yang baik adalah menghindari komputasi yang berat, seperti mengupdate atau merender 3D di pengendali peristiwa. Sebagai gantinya, simpan input sentuh dalam variabel dan bereaksi terhadap input dalam loop render requestAnimationFrame. Hal ini juga mempermudah implementasi mouse secara bersamaan, Anda hanya menyimpan nilai mouse yang sesuai dalam variabel yang sama.

Mulai dengan melakukan inisialisasi objek untuk menyimpan input dan menambahkan pemroses peristiwa touchstart. Di setiap pengendali peristiwa, kita memanggil event.preventDefault(). Hal ini untuk mencegah browser terus memproses peristiwa sentuh, yang dapat menyebabkan beberapa perilaku yang tidak terduga seperti men-scroll atau menskalakan seluruh halaman.

var input = {dragStartX:0, dragStartY:0, dragX:0, dragY:0, dragDX:0, dragDY:0, dragging:false};
plateContainer.addEventListener('touchstart', onTouchStart);

function onTouchStart(event) {
  event.preventDefault();
  if( event.touches.length === 1){
    handleDragStart(event.touches[0].clientX , event.touches[0].clientY);
    //start listening to all needed touchevents to implement the dragging
    document.addEventListener('touchmove', onTouchMove);
    document.addEventListener('touchend', onTouchEnd);
    document.addEventListener('touchcancel', onTouchEnd);
  }
}

function onTouchMove(event) {
  event.preventDefault();
  if( event.touches.length === 1){
    handleDragging(event.touches[0].clientX, event.touches[0].clientY);
  }
}

function onTouchEnd(event) {
  event.preventDefault();
  if( event.touches.length === 0){
    handleDragStop();
    //remove all eventlisteners but touchstart to minimize number of eventlisteners
    document.removeEventListener('touchmove', onTouchMove);
    document.removeEventListener('touchend', onTouchEnd);
    //also listen to touchcancel event to avoid unexpected behavior when switching tabs and some other situations
    document.removeEventListener('touchcancel', onTouchEnd);
  }
}

Kita tidak melakukan penyimpanan input yang sebenarnya di pengendali peristiwa, tetapi di pengendali terpisah: handleDragStart, handleDragging, dan handleDragStop. Hal ini karena kita juga ingin dapat memanggilnya dari pengendali peristiwa mouse. Perlu diingat bahwa meskipun tidak mungkin, pengguna dapat menggunakan sentuh dan mouse secara bersamaan. Daripada menangani kasus tersebut secara langsung, kami hanya memastikan tidak ada yang meledak.

function handleDragStart(x ,y ){
  input.dragging = true;
  input.dragStartX = input.dragX = x;
  input.dragStartY = input.dragY = y;
}

function handleDragging(x ,y ){
  if(input.dragging) {
    input.dragDX = x - input.dragX;
    input.dragDY = y - input.dragY;
    input.dragX = x;
    input.dragY = y;
  }
}

function handleDragStop(){
  if(input.dragging) {
    input.dragging = false;
    input.dragDX = 0;
    input.dragDY = 0;
  }
}

Saat melakukan animasi berdasarkan touchmove, sering kali berguna untuk menyimpan juga perpindahan delta sejak peristiwa terakhir. Misalnya, kami menggunakannya sebagai parameter untuk kecepatan kamera saat bergerak di semua pelat dasar di Jelajahi, karena Anda tidak menarik pelat dasar, tetapi sebenarnya Anda memindahkan kamera.

function onAnimationFrame() {
  requestAnimationFrame( onAnimationFrame );

  //execute animation based on input.dragDX, input.dragDY, input.dragX or input.dragY
 /*
  /
  */

  //because touchmove is only fired when finger is actually moving we need to reset the delta values each frame
  input.dragDX=0;
  input.dragDY=0;
}

Contoh tersemat: Menarik objek menggunakan peristiwa sentuh. Implementasi serupa seperti saat menarik peta Jelajahi 3D di Build with Chrome: http://cdpn.io/qDxvo

Gestur Multi-kontrol

Ada beberapa framework atau library, seperti Hammer atau QuoJS, yang dapat menyederhanakan pengelolaan gestur multi-sentuh, tetapi jika Anda ingin menggabungkan beberapa gestur dan mendapatkan kontrol penuh, terkadang sebaiknya lakukan dari awal.

Untuk mengelola gestur cubit dan putar, kita menyimpan jarak dan sudut antara dua jari saat jari kedua diletakkan di layar:

//variables representing the actual scale/rotation of the object we are affecting
var currentScale = 1;
var currentRotation = 0;

function onTouchStart(event) {
  event.preventDefault();
  if( event.touches.length === 1){
    handleDragStart(event.touches[0].clientX , event.touches[0].clientY);
  }else if( event.touches.length === 2 ){
    handleGestureStart(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY );
  }
}

function handleGestureStart(x1, y1, x2, y2){
  input.isGesture = true;
  //calculate distance and angle between fingers
  var dx = x2 - x1;
  var dy = y2 - y1;
  input.touchStartDistance=Math.sqrt(dx*dx+dy*dy);
  input.touchStartAngle=Math.atan2(dy,dx);
  //we also store the current scale and rotation of the actual object we are affecting. This is needed to support incremental rotation/scaling. We can't assume that an object is always the same scale when gesture starts.
  input.startScale=currentScale;
  input.startAngle=currentRotation;
}

Dalam peristiwa touchmove, kita kemudian terus mengukur jarak dan sudut antara kedua jari tersebut. Perbedaan antara jarak awal dan jarak saat ini kemudian digunakan untuk menetapkan skala, dan perbedaan antara sudut awal dan sudut saat ini digunakan untuk menetapkan sudut.

function onTouchMove(event) {
  event.preventDefault();
  if( event.touches.length  === 1){
    handleDragging(event.touches[0].clientX, event.touches[0].clientY);
  }else if( event.touches.length === 2 ){
    handleGesture(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY );
  }
}

function handleGesture(x1, y1, x2, y2){
  if(input.isGesture){
    //calculate distance and angle between fingers
    var dx = x2 - x1;
    var dy = y2 - y1;
    var touchDistance = Math.sqrt(dx*dx+dy*dy);
    var touchAngle = Math.atan2(dy,dx);
    //calculate the difference between current touch values and the start values
    var scalePixelChange = touchDistance - input.touchStartDistance;
    var angleChange = touchAngle - input.touchStartAngle;
    //calculate how much this should affect the actual object
    currentScale = input.startScale + scalePixelChange*0.01;
    currentRotation = input.startAngle+(angleChange*180/Math.PI);
    //upper and lower limit of scaling
    if(currentScale<0.5) currentScale = 0.5;
    if(currentScale>3) currentScale = 3;
  }
}

Anda berpotensi menggunakan perubahan jarak antara setiap peristiwa touchmove dengan cara yang mirip seperti contoh dengan menarik, tetapi pendekatan tersebut sering kali lebih berguna jika Anda menginginkan gerakan yang berkelanjutan.

function onAnimationFrame() {
  requestAnimationFrame( onAnimationFrame );
  //execute transform based on currentScale and currentRotation
  /*
  /
  */

  //because touchmove is only fired when finger is actually moving we need to reset the delta values each frame
  input.dragDX=0;
  input.dragDY=0;
}

Anda juga dapat mengaktifkan penarikan objek saat melakukan gestur cubit dan putar jika mau. Dalam hal ini, Anda akan menggunakan titik tengah di antara dua jari sebagai input ke pengendali penarikan.

Contoh tersemat: Memutar dan menskalakan objek dalam 2D. Mirip dengan cara penerapan peta di Jelajahi: http://cdpn.io/izloq

Dukungan Mouse dan Sentuh di Hardware yang Sama

Saat ini ada beberapa komputer laptop, seperti Chromebook Pixel, yang mendukung input mouse dan sentuh. Hal ini dapat menyebabkan beberapa perilaku yang tidak terduga jika Anda tidak berhati-hati.

Satu hal yang penting adalah Anda tidak boleh hanya mendeteksi dukungan sentuh, lalu mengabaikan input mouse, tetapi mendukung keduanya secara bersamaan.

Jika Anda tidak menggunakan event.preventDefault() di pengendali peristiwa sentuh, beberapa peristiwa mouse yang diemulasi juga akan diaktifkan, agar sebagian besar situs yang tidak dioptimalkan untuk sentuh tetap berfungsi. Sebagai contoh, untuk satu ketukan di layar, peristiwa ini dapat diaktifkan dalam urutan yang cepat dan dalam urutan ini:

  1. touchstart
  2. touchmove
  3. touchend
  4. mouseover
  5. mousemove
  6. mousedown
  7. mouseup
  8. click

Jika Anda memiliki interaksi yang sedikit lebih kompleks, peristiwa mouse ini dapat menyebabkan beberapa perilaku yang tidak terduga, dan mengacaukan penerapan Anda. Sebaiknya gunakan event.preventDefault() di pengendali peristiwa sentuh dan kelola input mouse di pengendali peristiwa terpisah. Anda harus menyadari bahwa menggunakan event.preventDefault() di pengendali peristiwa sentuh juga akan mencegah beberapa perilaku default, seperti scroll dan peristiwa klik.

"Di Build with Chrome, kami tidak ingin zoom terjadi saat seseorang mengetuk dua kali pada situs, meskipun hal itu merupakan standar di sebagian besar browser. Jadi, kita menggunakan tag meta viewport untuk memberi tahu browser agar tidak melakukan zoom saat pengguna mengetuk dua kali. Hal ini juga menghapus penundaan klik 300 md, yang meningkatkan responsivitas situs. (Jeda klik ada untuk membedakan antara sekali ketuk dan ketuk dua kali saat zoom ketuk dua kali diaktifkan.)

<meta name="viewport" content="width=device-width,user-scalable=no">

Ingat bahwa saat menggunakan fitur ini, Anda harus membuat situs dapat dibaca di semua ukuran layar, karena pengguna tidak akan dapat memperbesar.

Input Mouse, Sentuh, dan Keyboard

Dalam mode Jelajahi 3D, kami ingin ada tiga cara untuk menavigasi peta: mouse (menarik), sentuh (menarik, mencubit untuk memperbesar dan memutar), serta keyboard (menavigasi dengan tombol panah). Semua metode navigasi ini berfungsi sedikit berbeda, tetapi kami menggunakan pendekatan yang sama pada semuanya; menetapkan variabel di pengendali peristiwa dan menindaklanjutinya dalam loop requestAnimationFrame. Loop requestAnimationFrame tidak perlu mengetahui metode mana yang digunakan untuk menavigasi.

Sebagai contoh, kita dapat menetapkan gerakan peta (dragDX dan dragDY) dengan ketiga metode input. Berikut adalah implementasi keyboard:

document.addEventListener('keydown', onKeyDown );
document.addEventListener('keyup', onKeyUp );

function onKeyDown( event ) {
  input.keyCodes[ "k" + event.keyCode ] = true;
  input.shiftKey = event.shiftKey;
}

function onKeyUp( event ) {
  input.keyCodes[ "k" + event.keyCode ] = false;
  input.shiftKey = event.shiftKey;
}

//this needs to be called every frame before animation is executed
function handleKeyInput(){
  if(input.keyCodes.k37){
    input.dragDX = -5; //37 arrow left
  } else if(input.keyCodes.k39){
    input.dragDX = 5; //39 arrow right
  }
  if(input.keyCodes.k38){
    input.dragDY = -5; //38 arrow up
  } else if(input.keyCodes.k40){
    input.dragDY = 5; //40 arrow down
  }
}

function onAnimationFrame() {
  requestAnimationFrame( onAnimationFrame );
  //because keydown events are not fired every frame we need to process the keyboard state first
  handleKeyInput();
  //implement animations based on what is stored in input
   /*
  /
  */

  //because touchmove is only fired when finger is actually moving we need to reset the delta values each frame
  input.dragDX = 0;
  input.dragDY = 0;
}

Contoh tersemat: Menggunakan mouse, sentuh, dan keyboard untuk menavigasi: http://cdpn.io/catlf

Ringkasan

Menyesuaikan Build dengan Chrome untuk mendukung perangkat sentuh dengan berbagai ukuran layar telah menjadi pengalaman belajar. Tim tidak memiliki banyak pengalaman dalam melakukan tingkat interaktivitas ini di perangkat sentuh dan kami banyak belajar selama prosesnya.

Tantangan terbesarnya ternyata adalah cara memecahkan masalah pengalaman pengguna dan desain. Tantangan teknisnya adalah mengelola banyak ukuran layar, peristiwa sentuh, dan masalah performa.

Meskipun ada beberapa tantangan dengan shader WebGL di perangkat sentuh, ini adalah sesuatu yang berfungsi hampir lebih baik dari yang diharapkan. Perangkat menjadi semakin canggih dan penerapan WebGL meningkat dengan cepat. Kami merasa bahwa kami akan lebih banyak menggunakan WebGL di perangkat dalam waktu dekat.

Sekarang, jika Anda belum melakukannya, bangun sesuatu yang luar biasa.