WebGL Yer Paylaşımı Görünümüyle 3D harita deneyimleri yaratın

1. Başlamadan önce

Bu codelab'de, vektör haritasını üç boyutlu olarak kontrol etmek ve oluşturmak için Maps JavaScript API'nin WebGL destekli özelliklerini nasıl kullanacağınızı öğrenebilirsiniz.

Nihai 3D PIN

Ön koşullar

Bu codelab'de, JavaScript ve Maps JavaScript API'yle ilgili orta düzeyde bilgiye sahip olduğunuz varsayılmaktadır. Maps JS API'sini kullanmayla ilgili temel bilgileri öğrenmek için Web sitenize (JavaScript) codelab'inize harita ekleyin.

Neler öğreneceksiniz?

  • JavaScript için vektör haritasının etkin olduğu bir Harita Kimliği oluşturuluyor.
  • Programlı yatırma ve döndürme ile haritayı kontrol etme.
  • WebGLOverlayView ve Three.js ile haritada 3D nesneler oluşturma.
  • moveCamera ile kamera hareketleri canlandırılıyor.

Gerekenler

  • Faturalandırmanın etkin olduğu bir Google Cloud Platform hesabı
  • Maps JavaScript API'nin etkin olduğu bir Google Maps Platform API anahtarı
  • JavaScript, HTML ve CSS ile ilgili orta düzeyde bilgi
  • İstediğiniz bir metin düzenleyici veya IDE
  • Node.js

2. Hazırlanın

Aşağıdaki etkinleştirme adımı için Maps JavaScript API'yi etkinleştirmeniz gerekir.

Google Haritalar Platformu'nu kurma

Henüz bir Google Cloud Platform hesabınız ve faturalandırmanın etkin olduğu bir projeniz yoksa faturalandırma hesabı ve proje oluşturmak için lütfen Google Haritalar Platformu'nu Kullanmaya Başlama kılavuzuna bakın.

  1. Cloud Console'da proje açılır menüsünü tıklayın ve bu codelab için kullanmak istediğiniz projeyi seçin.

  1. Google Cloud Marketplace'te bu codelab için gerekli olan Google Haritalar Platformu API'lerini ve SDK'larını etkinleştirin. Bunu yapmak için bu video veya bu dokümanlardaki adımları uygulayın.
  2. Cloud Console'un Kimlik Bilgileri sayfasında API anahtarı oluşturun. Bu video veya bu dokümanlardaki adımları uygulayabilirsiniz. Google Haritalar Platformu'na gönderilen tüm istekler bir API anahtarı gerektirir.

Node.js kurulumu

Bu dizin yoksa https://nodejs.org/ adresine giderek Node.js çalışma zamanını bilgisayarınıza indirip yükleyin.

Node.js, bu codelab için bağımlılıkları yüklemeniz gereken npm paket yöneticisiyle birlikte gelir.

Proje başlangıç şablonunu indirin

Bu codelab'e başlamadan önce başlangıç projesi şablonunu ve çözüm çözümünün tamamını indirmek için aşağıdakileri yapın:

  1. Bu kod laboratuvarı için GitHub kod deposunu https://github.com/googlecodelabs/maps-platform-101-webgl/ adresinden indirin veya çatallayın. Başlangıç projesi, /starter dizininde bulunur ve codelab'i tamamlamak için ihtiyacınız olan temel dosya yapısını içerir. Üzerinde çalışmanız gereken her şey /starter/src dizininde bulunur.
  2. Başlangıç projesini indirdikten sonra, /starter dizininde npm install komutunu çalıştırın. Bu, package.json içinde listelenen gerekli tüm bağımlıları yükler.
  3. Bağımlılarınız yüklendikten sonra dizinde npm start komutunu çalıştırın.

Başlangıç projesi, yerel olarak yazdığınız kodu derleyip çalıştıran webpack-dev-server'ı kullanmanız için ayarlandı. webpack-dev-server, kodda her değişiklik yaptığınızda uygulamanızı tarayıcıda otomatik olarak yeniden yükler.

Çalışan çözüm kodunun tamamını görmek istiyorsanız yukarıdaki kurulum adımlarını /solution dizininde tamamlayabilirsiniz.

API anahtarınızı ekleme

Başlangıç uygulaması, haritayı JS API Yükleyicisi ile yüklemek için gereken tüm kodu içerir. Böylece, tek yapmanız gereken API anahtarınızı ve Harita Kimliğinizi sağlamaktır. JS API Yükleyici, HTML JS API'sini satır içinde script gibi bir etiketle satır içi yüklemenin geleneksel yöntemini soyutlayan basit bir kitaplıktır ve JavaScript kodundaki her şeyi yönetmenize olanak tanır.

API anahtarınızı eklemek için başlangıç projesinde aşağıdakileri yapın:

  1. app.js'yi açın.
  2. apiOptions nesnesinde API anahtarınızı apiOptions.apiKey değeri olarak ayarlayın.

3. Harita kimliği oluşturma ve kullanma

Maps JavaScript API'nin WebGL tabanlı özelliklerini kullanmak için, vektör haritasının etkin olduğu bir Harita Kimliğine ihtiyacınız vardır.

Harita kimliği oluşturma

Harita Kimliği Oluşturma

  1. Google Cloud konsolunda "Google Haritalar Platformu' > "Harita Yönetimi'"ne gidin.
  2. "YENİ HARİTA KİMLİĞİ OLUŞTUR''u tıklayın.
  3. "Harita adı'" alanına Harita Kimliğiniz için bir ad girin.
  4. "Harita türü' açılır listesinde "JavaScript'"ı seçin. "JavaScript Seçenekleri' görünür.
  5. "JavaScript Seçenekleri' altında, "Vektör' radyo düğmesi", "Yatır' onay kutusu"nu ve "Rotasyon' onay kutusunu" işaretleyin.
  6. Optional. "Açıklama' alanına, API anahtarınız için bir açıklama girin.
  7. "İleri' düğmesini tıklayın. "Harita Kimliği Ayrıntıları' sayfası görünür.

    Harita Ayrıntıları sayfası
  8. Harita kimliğini kopyalayın. Bunu, haritayı yüklemek için bir sonraki adımda kullanacaksınız.

Harita kimliği kullanma

Vektör haritasını yüklemek için, Haritalar'ı örneklediğiniz sırada özelliklere bir Harita Kimliği sağlamanız gerekir. İsteğe bağlı olarak, Maps JavaScript API'yi yüklerken aynı Harita Kimliğini de sağlayabilirsiniz.

Harita kimliğinizle harita yüklemek için aşağıdakileri yapın:

  1. Harita kimliğinizi mapOptions.mapId değeri olarak ayarlayın.

    Harita oluşturduğunuzda Harita Kimliği sağlarsanız Google Haritalar Platformu'na belirli bir örnek için haritalarınızdan hangisinin yükleneceği bildirilir. Aynı Harita Kimliğini birden fazla uygulamada veya aynı uygulama içinde birden fazla görünümde yeniden kullanabilirsiniz.
    const mapOptions = {
      "tilt": 0,
      "heading": 0,
      "zoom": 18,
      "center": { lat: 35.6594945, lng: 139.6999859 },
      "mapId": "YOUR_MAP_ID"
    };
    

Tarayıcınızda çalışan uygulamayı kontrol edin. Eğme ve döndürme özelliğinin etkinleştirildiği vektör haritası başarıyla yüklenmelidir. Eğme ve döndürme özelliğinin etkin olup olmadığını kontrol etmek için üst karakter tuşunu basılı tutun ve farenizi sürükleyin veya klavyenizdeki ok tuşlarını kullanın.

Harita yüklenmezse apiOptions içinde geçerli bir API anahtarı sağladığınızdan emin olun. Harita eğik değilse ve döndürmüyorsa apiOptions ve mapOptions konumlarında yatırma ve döndürme özelliğinin etkin olduğu bir Harita Kimliği sağladığınızdan emin olun.

Yatırılmış Harita

app.js dosyanız şu şekilde görünmelidir:

    import { Loader } from '@googlemaps/js-api-loader';

    const apiOptions = {
      "apiKey": 'YOUR_API_KEY',
    };

    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. WebGLOverlayView'u uygulama

WebGLOverlayView, vektör taban haritasını oluşturmak için kullanılan aynı WebGL oluşturma bağlamına doğrudan erişim sağlar. Yani, WebGL'yi ve popüler WebGL tabanlı grafik kitaplıklarını kullanarak 2D ve 3D nesneleri doğrudan harita üzerinde oluşturabilirsiniz.

WebGLOverlayView, kullanabileceğiniz haritaya ait WebGL oluşturma bağlamının yaşam döngüsüne beş kanca sunar. Aşağıda her kancanın kısa bir açıklaması ve neden kullanılması gerektiği açıklanmıştır:

  • onAdd(): Bir WebGLOverlayView örneğinde setMap çağırarak yer paylaşımı bir haritaya eklendiğinde çağrılır. Burada, WebGL bağlamına doğrudan erişimi gerektirmeyen WebGL ile ilgili her türlü işlemi yapmanız gerekir.
  • onContextRestored(): WebGL bağlamı kullanılabilir olduğunda ancak herhangi bir şey oluşturulmadan önce çağrılır. Burada nesneleri başlatmalı, bağlamayı bağlamalı ve WebGL bağlamına erişmesi gereken ancak onDraw() çağrısının dışında gerçekleştirilebilecek her şeyi yapmalısınız. Bu sayede, haritanın gerçek oluşturmak için aşırı yüklenmeye gerek kalmadan ihtiyacınız olan her şeyi ayarlayabilirsiniz. Bu da GPU'yu yoğun olarak kullanır.
  • onDraw(): WebGL, haritayı oluşturmaya başladıktan sonra ve istediğiniz diğer her şey için kare başına bir kez çağrılır. Harita oluşturma sırasında performans sorununa neden olmamak için onDraw() içinde mümkün olduğunca az çalışmanız gerekir.
  • onContextLost(): Herhangi bir nedenle WebGL oluşturma bağlamı kaybolduğunda çağrılır.
  • onRemove(): Bir WebGLOverlayView örneğinde setMap(null) çağrılarak yer paylaşımı haritadan kaldırıldığında aranır.

Bu adımda WebGLOverlayView öğesinin bir örneğini oluşturur ve yaşam döngüsü kancalarından üçünü uygularsınız: onAdd, onContextRestored ve onDraw. İşlerin temiz ve takip edilmesini kolaylaştırmak için bu codelab'in başlangıç şablonunda sağlanan initWebGLOverlayView() işlevinde, yer paylaşımıyla ilgili tüm kod işlenecektir.

  1. WebGLOverlayView() örneği oluşturun.

    Bindirme, google.maps.WebGLOverlayView bölgesindeki Maps JS API tarafından sağlanmaktadır. Başlamak için, aşağıdaki talimatları uygulayarak bir örnek oluşturun: initWebGLOverlayView():
    const webGLOverlayView = new google.maps.WebGLOverlayView();
    
  2. Yaşam döngüsü kancalarını uygulayın.

    Yaşam döngüsü kancalarını uygulamak için initWebGLOverlayView() öğesine aşağıdakileri ekleyin:
    webGLOverlayView.onAdd = () => {};
    webGLOverlayView.onContextRestored = ({gl}) => {};
    webGLOverlayView.onDraw = ({gl, coordinateTransformer}) => {};
    
  3. Yer paylaşımı örneğini haritaya ekleyin.

    Şimdi, bindirme örneğinde setMap() çağrın ve aşağıdakileri initWebGLOverlayView() ekleyerek haritaya geçirin:
    webGLOverlayView.setMap(map)
    
  4. initWebGLOverlayView Hizmetleri İçin Arayın.

    Son adım, app.js komutunun en altında hemen çağrılan işleve aşağıdakini ekleyerek initWebGLOverlayView() işlemini yürütmektir:
    initWebGLOverlayView(map);
    

initWebGLOverlayView ve hemen çağrılan fonksiyonunuz aşağıdaki gibi görünecektir:

    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);
    })();

WebGLOverlayView uygulamak için ihtiyacınız olan tek şey bu. Ardından, Three.js'yi kullanarak 3D bir nesne oluşturmak için ihtiyacınız olan her şeyi ayarlarsınız.

5. Üç.js sahnesi oluşturma

WebGL, her nesnenin tüm yönlerini manuel olarak tanımlamanızı gerektirdiği için biraz karmaşık olabilir. İşleri kolaylaştırmak için bu codelab'de WebGL'nin yanında basitleştirilmiş bir soyutlama katmanı sunan popüler grafik kitaplığı Three.js'yi kullanacaksınız. Three.js, WebGL oluşturucu oluşturmaktan yaygın 2D ve 3D nesne şekillerini çizmeye ve kameraları, nesne dönüşümlerini denetlemeye kadar her şeyi yapan çeşitli kolaylık işlevleriyle birlikte gelir.

Three.js'de herhangi bir şeyi görüntülemek için gereken üç temel nesne türü vardır:

  • Sahne: Tüm nesnelerin, ışık kaynaklarının, dokuların vb. oluşturulduğu "kapsayıcı".
  • Kamera: Sahnenin bakış açısını temsil eden bir kamera. Birden çok kamera türü kullanılabilir ve tek bir sahneye bir veya daha fazla kamera eklenebilir.
  • Oluşturucu: Sahnedeki tüm nesnelerin işlenmesini ve gösterilmesini sağlayan bir oluşturucu. Three.js'de WebGLRenderer en yaygın şekilde kullanılır, ancak istemcinin WebGL'yi desteklememesi durumunda yedek olarak başka birkaç seçenek de sunulur.

Bu adımda, Three.js için gereken tüm bağımlılıkları yükler ve temel bir sahne oluşturursunuz.

  1. üç.js yükle

    Bu codelab için iki bağımlılığa ihtiyacınız vardır: Three.js kitaplığı ve GLTF Yükleyici, GL Geçiş Biçimi (gLTF) içinde 3D nesneler yüklemenize olanak tanıyan bir sınıf. Three.js, birçok farklı 3D nesne biçimi için özel yükleyiciler sunar, ancak gLTF kullanılması önerilir.

    Aşağıdaki kodda, Three.js kitaplığının tamamı içe aktarılır. Bir üretim uygulamasında büyük olasılıkla yalnızca ihtiyacınız olan sınıfları içe aktarmak istersiniz, ancak bu codelab'de işleri basit tutmak için kitaplığın tamamını içe aktarın. Ayrıca, GLTF Yükleyicinin varsayılan kitaplıkta yer almadığını ve bağımlılıkta ayrı bir yoldan içe aktarılması gerektiğini unutmayın. Bu, Three.js tarafından sağlanan tüm yükleyicilere erişebildiğiniz yoldur.

    Three.js ve GLTF Yükleyicisi'ni içe aktarmak için aşağıdakileri app.js üst bölümüne ekleyin:
    import * as THREE from 'three';
    import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js';
    
  2. Bir üç.js sahnesi oluşturun.

    Bir sahne oluşturmak için onAdd kancasına aşağıdaki öğeleri ekleyerek Three.js Scene sınıfını örneklendirin:
  3. Sahneye kamera ekleyin.

    Daha önce de belirtildiği gibi, kamera sahnenin görüntüleme perspektifini temsil eder ve Three.js'nin sahnedeki nesnelerin görsel oluşturmayı nasıl işlediğini belirler. Kamera olmadan sahne etkili bir şekilde görülmez. Yani, nesneler oluşturulmayacağı için görünmez.

    Three.js, oluşturucunun nesneleri perspektif ve derinlik gibi konularda nasıl ele alacağını etkileyen çeşitli kameralar sunmaktadır. Bu sahnede, insan gözünün sahneyi algılama biçimini taklit edecek şekilde tasarlanmış Three.js'de en sık kullanılan kamera türü olan PerspectiveCamera'i kullanacaksınız. Bu, kameradan uzaktaki nesnelerin daha yakın nesnelerden daha küçük olacağı, sahnenin kaybolacağı ve daha fazlasının olacağı anlamına gelir.

    Sahneye perspektif kamerası eklemek için aşağıdakileri onAdd kancaya ekleyin:
    camera = new THREE.PerspectiveCamera();
    
    Ayrıca PerspectiveCamera ve uzak uçaklar, en boy oranı ve görüş alanı (fov) gibi görüş açısını meydana getiren özellikleri yapılandırabilirsiniz. Toplu olarak bu özellikler, 3D üzerinde çalışırken bu codelab'in kapsamı dışında değerlendirilmesi gereken önemli bir kavram olan görüntüleme frizumu olarak bilinir. Varsayılan PerspectiveCamera yapılandırması yeterlidir.
  4. Sahneye ışık kaynakları ekleyin.

    Varsayılan olarak, Three.js sahnesinde oluşturulan nesneler, bunlara uygulanan dokulardan bağımsız olarak siyah görünür. Bunun nedeni, üçlü bir sahnenin nesnelerin gerçek dünyada nasıl davrandığını taklit etmesidir.Buradaki renkler, görünürlükteki nesneden yansıyan bir görüntüye bağlıdır. Özetle, ışık ve renk yok.

    Three.js, kullanacağınız iki farklı ışık türü sağlar:

  5. AmbientLight: Tablodaki tüm nesneleri tüm açılardan eşit şekilde aydınlatan bir ışık kaynağı sağlar. Bu işlem, tüm nesnelerdeki dokuların görünür olmasını sağlamak için sahneye temel bir ışık miktarı sağlar.
  6. DirectionalLight: Sahnedeki yönden gelen bir ışık sağlar. Konumlandırılmış bir ışığın gerçek dünyada nasıl çalışacağından farklı olarak, DirectionalLight ışığından gelen ışık ışınları paraleldir ve ışık kaynağından uzağa geldiklerinde yayılmaz ve dağılmaz.

    Birleştirilmiş ışık efektleri oluşturmak için her bir ışığın rengini ve yoğunluğunu yapılandırabilirsiniz. Örneğin, aşağıdaki kodda ortam ışığı tüm sahne için yumuşak beyaz bir ışık sunarken yön ışığı, nesnelere aşağı doğru eğimli bir ikincil ışık verir. Yönlü ışık söz konusu olduğunda, açı position.set(x, y ,z) kullanılarak ayarlanır. Burada her değer, ilgili eksene göre değişir. Böylece, örneğin position.set(0,1,0) ışığı, doğrudan y ekseninde, sahnenin hemen üzerine gelecek şekilde konumlandırır.

    Sahneye ışık kaynaklarını eklemek için onAdd kancasına aşağıdakileri ekleyin:
    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);
    

onAdd kancanız artık şu şekilde görünmelidir:

    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);
    }

Sahneniz artık kuruldu ve oluşturulmaya hazır. Ardından, WebGL oluşturucuyu yapılandıracak ve sahneyi oluşturacaksınız.

6. Sahne oluşturun

Sahnenizi oluşturma zamanı. Şu ana kadar Three.js ile oluşturduğunuz her şey kod olarak başlatılmıştır, ancak aslında WebGL oluşturma bağlamında oluşturulmadığından mevcut değildir. WebGL, canvas API'yi kullanarak tarayıcıda 2D ve 3D içerik oluşturur. Canvas API'yı daha önce kullandıysanız muhtemelen HTML tuvalinin context özelliğine aşinasınızdır. Bu örnekte her şey oluşturulur. Bunun farkında olmadığınızda bunun, tarayıcıda WebGLRenderingContext API aracılığıyla OpenGL grafik oluşturma bağlamını açığa çıkaran bir arayüz olduğunu görebilirsiniz.

Three.js, WebGL oluşturucunun işlenmesini kolaylaştırmak için WebGL oluşturma bağlamını nispeten daha kolay hale getiren bir sarmalayıcı olan WebGLRenderer sağlar.Böylece üçgen, tarayıcıda sahneler oluşturabilir. Ancak bu durumda, tarayıcıdaki üçlü JavaScript sahnesi haritanın oluşturulmasıyla yeterli değildir. Three.js, harita ile tam olarak aynı oluşturma bağlamında oluşturulmalıdır, böylece hem harita hem de Three.js sahnesindeki tüm nesneler aynı dünya alanında oluşturulur. Bu, oluşturucunun haritadaki nesneler ve sahnedeki nesneler arasındaki etkileşimleri (ör. tıkanma) işlemesini sağlar. Bu yöntem, bir nesnenin arkasındaki nesnelerin görünümden gizleneceğini söylemenin daha eğlenceli bir yoludur.

Çok karmaşık, değil mi? Neyse ki Three.js tekrar kurtarmaya geliyor.

  1. WebGL oluşturucuyu ayarlama.

    Yeni Three.js WebGLRenderer örneği oluşturduğunuzda, sahnenizin oluşturulmasını istediğiniz belirli bir WebGL oluşturma bağlamını sağlayabilirsiniz. onContextRestored kancasına iletilen gl bağımsız değişkenini hatırlıyor musunuz? Bu gl nesnesi, haritanın WebGL oluşturma bağlamıdır. Tek yapmanız gereken, bağlam, zemini ve özelliklerini WebGLRenderer örneğine sunmaktır. Bunların tümüne gl nesnesi aracılığıyla ulaşılabilir. Bu kodda oluşturucunun autoClear özelliği de false olarak ayarlanır. Böylece oluşturucu, her karedeki çıkışı temizlemez.

    Oluşturucuyu yapılandırmak için onContextRestored kancasına aşağıdakileri ekleyin:
    renderer = new THREE.WebGLRenderer({
      canvas: gl.canvas,
      context: gl,
      ...gl.getContextAttributes(),
    });
    renderer.autoClear = false;
    
  2. Sahneyi oluşturun.

    Oluşturucu yapılandırıldıktan sonra WebGLOverlayView örneğinde requestRedraw çağrısı yaparak yer paylaşımlı karenin yeniden oluşturulması gerektiğini belirtirken oluşturucuda render çağrısı yapın ve oluşturulması için Three.js sahnesini ve kamerasını iletin. Son olarak, WebGL oluşturma bağlamının durumunu temizleyin. WebGL Yer Paylaşımı Görünümü kullanımı paylaşılan GL durumuna dayalı olduğundan, GL durumu çakışmalarını önlemek için bu önemli bir adımdır. Her çizim çağrısının sonunda durum sıfırlanmazsa GL durum çakışmaları oluşturucunun başarısız olmasına neden olabilir.

    Bunu yapmak için, aşağıdaki kareleri onDraw çerçevesine ekleyerek her karenin yürütülmesini sağlayın:
    webGLOverlayView.requestRedraw();
    renderer.render(scene, camera);
    renderer.resetState();
    

onContextRestored ve onDraw kancalarınız artık şu şekilde görünmelidir:

    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. Haritada 3D model oluşturma

Tamam, her şeyi tamamladınız. WebGl Overlay View oluşturup Three.js sahnesi oluşturdunuz, ancak bir sorun var: Burada hiçbir şey yok. Dolayısıyla, şimdi sahnede bir 3D nesne oluşturma zamanı. Bunun için daha önce içe aktardığınız GLTF Yükleyiciyi kullanmanız gerekir.

3D modeller birçok farklı biçimde olabilir ancak 3.js için boyut ve çalışma zamanı performansı nedeniyle gLTF biçimi tercih edilir. Bu codelab'de, sahnede oluşturabileceğiniz bir model zaten /src/pin.gltf dilinde sağlanmıştır.

  1. Model yükleyici örneği oluşturun.

    Aşağıdakileri onAdd klasörüne ekleyin:
    loader = new GLTFLoader();
    
  2. Bir 3D model yükleyin.

    Model yükleyiciler eşzamansız olup model tam olarak yüklendikten sonra bir geri çağırma yürütür. pin.gltf dosyasını yüklemek için aşağıdaki URL'ye onAdd öğesini ekleyin:
    const source = "pin.gltf";
    loader.load(
      source,
      gltf => {}
    );
    
  3. Modeli sahneye ekleyin.

    Artık loader geri çağırmasına aşağıdaki modeli ekleyerek modeli sahneye ekleyebilirsiniz. gltf.scene öğesinin eklendiğini unutmayın. gltf:
    scene.add(gltf.scene);
    
  4. Kamera projeksiyon matrisini yapılandırın.

    Modelin haritada doğru şekilde oluşturulması için gereken son şey, kameranın projeksiyon matrisini Three.js sahnesinde ayarlamaktır. Projeksiyon matrisi, rotasyon, kırma ve ölçek gibi dönüşümlerle birlikte üç boyutlu alanda bir noktayı tanımlayan bir Three.js Matrix4 dizisi olarak belirtilir.

    WebGLOverlayView örneğinde, projektör matrisi, oluşturucuya ana haritayla göreli olarak üçlü ve üçlü sahnenin nerede ve nasıl oluşturulacağını bildirmek için kullanılır. Ancak bir sorun var. Haritadaki konumlar enlem ve boylam koordinat çiftleri olarak belirtilirken, Three.js sahnesindeki yerler Vector3 koordinatları olarak belirtilir. Tahmin edebileceğiniz gibi, iki sistem arasındaki dönüşümün hesaplanması kolay değildir. WebGLOverlayView bu sorunu çözmek için fromLatLngAltitude yaşam döngüsü kancasına fromLatLngAltitude adlı bir işlev içeren bir coordinateTransformer nesnesi iletir. fromLatLngAltitude Bir LatLngAltitude veya LatLngAltitudeLiteral nesnesi alır ve isteğe bağlı olarak sahne için bir dönüşüm tanımlayan bir dizi bağımsız değişken alır. Daha sonra, bunları sizin için bir model görüntüleme projeksiyonu (MVP) matrisine dahil eder. Tek yapmanız gereken, Three.js sahnesinin harita üzerinde nerede oluşturulmasını istediğinizi ve sahnenin nasıl dönüştürülmesini istediğinizi belirtir. Gerisini WebGLOverlayView yapar. Ardından MVP matrisini Three.js Matrix4 dizisine dönüştürüp kamera projeksiyon matrisini buna ayarlayabilirsiniz.

    Aşağıdaki kodda ikinci bağımsız değişken WebGl Overlay View'a, Three.js sahnesinin rakımı yerden 120 metre yüksekte olmasını sağlayarak modelin kayan konumda görünmesini sağlar.

    Kamera projeksiyon matrisini ayarlamak için onDraw kancasına aşağıdakileri ekleyin:
    const latLngAltitudeLiteral = {
        lat: mapOptions.center.lat,
        lng: mapOptions.center.lng,
        altitude: 120
    }
    const matrix = transformer.fromLatLngAltitude(latLngAltitudeLiteral);
    camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
    
  5. Modeli dönüştürün.

    Raptiyenin haritaya dik baktığını fark etmeyeceksiniz. 3D grafiklerde, dünya alanının yönü belirleyen kendi x, y ve z eksenlerine ek olarak her nesnenin, bağımsız bir eksen grubu olan kendi nesne alanı vardır.

    Bu modelde, normalde y eksenine bakan parmağını "üst&#39" olarak değerlendirdiğimiz tasarımla oluşturulmamıştır. Bu nedenle, nesneyi rotation.set yöntemini çağırarak dünya alanına göre istenen şekilde uyarlamanız gerekir. Three.js'de, döndürmenin derece değil, radyan cinsinden belirtildiğini unutmayın. Genellikle dereceleri düşünmek daha kolaydır. Bu nedenle, degrees * Math.PI/180 formülü kullanılarak uygun dönüşümün yapılması gerekir.

    Ayrıca, model biraz küçük olduğundan scale.set(x, y ,z) seçeneğini çağırarak tüm eksenlerde eşit olarak ölçeklendirilir.

    Modeli döndürmek ve ölçeklendirmek için onAdd öğesinin geri çağırmasındanscene.add(gltf.scene) loader geri çağırmasına ekleyin. Bu işlem gLTF'yi sahneye ekler:
    gltf.scene.scale.set(25,25,25);
    gltf.scene.rotation.x = 180 * Math.PI/180;
    

Bu raptiye artık haritaya göre dik konumdadır.

Dikişli Toka

onAdd ve onDraw kancalarınız artık şu şekilde görünmelidir:

    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();
    }

Sırada kamera animasyonları var.

8. Kamerayı canlandırma

Harita üzerinde bir model oluşturduğunuza ve her şeyi üç boyutlu olarak taşıyabileceğinize göre, şimdi yapmak isteyebileceğiniz bir sonraki şey bu hareketi programlı olarak kontrol etmektir. moveCamera işlevi, haritanın orta, yakınlaştırma, yatırma ve başlık özelliklerini aynı anda ayarlamanıza olanak tanır ve böylece kullanıcı deneyimi üzerinde hassas bir kontrole sahip olmanızı sağlar. Ayrıca, animasyon döngüsünde moveCamera saniyede yaklaşık 60 kare kare hızında kareler arasında değişken geçişler oluşturulması için çağrılabilir.

  1. Modelin yüklenmesini bekleyin.

    Sorunsuz bir kullanıcı deneyimi oluşturmak için gLTF modeli yüklenene kadar kamerayı hareket ettirmeyi beklemeniz gerekir. Bunu yapmak için yükleyicinin onLoad etkinlik işleyicisini onContextRestored kancasına ekleyin:
    loader.manager.onLoad = () => {}
    
  2. Animasyon döngüsü oluşturun.

    Animasyon döngüsü oluşturmanın birden çok yolu vardır (ör. setInterval veya requestAnimationFrame kullanma). Bu durumda Three.js oluşturucunun setAnimationLoop işlevini kullanırsınız. Bu, Three.js her yeni kare oluşturduğunda geri çağırmada belirttiğiniz tüm kodları otomatik olarak çağırır. Animasyon döngüsü oluşturmak için önceki adımda onLoad etkinlik işleyiciye aşağıdakileri ekleyin:
    renderer.setAnimationLoop(() => {});
    
  3. Animasyon döngüsünde kamera konumunu ayarlayın.

    Ardından, haritayı güncellemek için moveCamera numaralı telefonu arayın. Burada, haritayı yüklemek için kullanılan mapOptions nesnesindeki özellikler kamera konumunu tanımlamak için kullanılır:
    map.moveCamera({
      "tilt": mapOptions.tilt,
      "heading": mapOptions.heading,
      "zoom": mapOptions.zoom
    });
    
  4. Kamerayı her karede güncelleyin.

    Son adım. Sonraki kare için kamera konumunu ayarlamak üzere her bir karenin sonundaki mapOptions nesnesini güncelleyin. Bu kodda if ifadesi, maksimum 67,5 eğme değerine ulaşana kadar yatırmayı artırmak için kullanılır.Ardından kamera, tam 360 derece döndürmeyi tamamlayana kadar başlık her karede biraz değiştirilir. İstenen animasyon tamamlandıktan sonra, animasyonun sürekli olarak çalışmaması için null setAnimationLoop animasyonuna aktarılır.
    if (mapOptions.tilt < 67.5) {
      mapOptions.tilt += 0.5
    } else if (mapOptions.heading <= 360) {
      mapOptions.heading += 0.2;
    } else {
      renderer.setAnimationLoop(null)
    }
    

onContextRestored kancanız artık şu şekilde görünmelidir:

    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. Tebrikler

Tarifeye göre her şey yolundaysa artık büyük bir 3D raptiyenin bulunduğu aşağıdaki gibi bir haritanız olacaktır:

Nihai 3D PIN

Öğrendikleriniz

Bu codelab'de bir dizi şey öğrendiniz. Öne çıkan noktaları aşağıda bulabilirsiniz:

  • WebGLOverlayView ve yaşam döngüsü kancalarını uyguluyoruz.
  • Three.js, haritaya entegre ediliyor.
  • Kameralar ve aydınlatma dahil olmak üzere Three.js sahnesi oluşturmayla ilgili temel bilgiler.
  • Three.js kullanarak 3D modelleri yükleme ve değiştirme.
  • moveCamera kullanarak harita için kamerayı kontrol etme ve animasyon ekleme.

Sonraki adım

WebGL ve genel olarak bilgisayar grafikleri karmaşık bir konu olduğundan öğrenilecek çok şey var. Başlamanıza yardımcı olacak birkaç kaynak: