العرض المركّب باستخدام WebGL

عرض نموذج

باستخدام ميزة "عرض التراكب باستخدام WebGL"، يمكنك إضافة محتوى إلى خرائطك باستخدام WebGL مباشرةً، أو باستخدام مكتبات الرسومات الشائعة مثل Three.js. توفّر ميزة "عرض التراكب باستخدام WebGL" إمكانية الوصول المباشر إلى سياق عرض WebGL نفسه الذي تستخدمه "منصة خرائط Google" لعرض الخريطة الأساسية المستندة إلى المتجهات. يقدّم هذا الاستخدام لسياق العرض المشترَك مزايا، مثل حجب العمق باستخدام هندسة المباني الثلاثية الأبعاد، والقدرة على مزامنة المحتوى المكوّن من رسومات ثنائية أو ثلاثية الأبعاد مع عرض الخريطة الأساسية. يمكن أيضًا ربط الأجسام المعروضة باستخدام عرض التراكب WebGL بخطّي العرض والطول، حتى تتحرك عند سحب الخريطة أو تكبيرها أو تصغيرها أو تمريرها أو إمالتها.

المتطلبات

لاستخدام ميزة "عرض التراكب باستخدام WebGL"، يجب تحميل الخريطة باستخدام رقم تعريف خريطة مع تفعيل الخريطة الموجّهة. ننصحك بشدة بتفعيل الميل والدوران عند إنشاء معرّف الخريطة، للسماح بالتحكم الكامل في الكاميرا الثلاثية الأبعاد. الاطّلاع على النظرة العامة للتعرّف على التفاصيل

إضافة العرض المركّب باستخدام WebGL

لإضافة التراكب إلى خريطتك، نفِّذ google.maps.WebGLOverlayView، ثم مرِّره إلى مثيل الخريطة باستخدام setMap:

// Create a map instance.
const map = new google.maps.Map(mapDiv, mapOptions);

// Create a WebGL Overlay View instance.
const webglOverlayView = new google.maps.WebGLOverlayView();

// Add the overlay to the map.
webglOverlayView.setMap(map);

خطافات مراحل النشاط

يوفّر "العرض المركّب باستخدام WebGL" مجموعة من أدوات الربط التي يتمّ استدعاؤها في أوقات مختلفة في رحلة حياة سياق عرض WebGL للخريطة الأساسية المستندة إلى المتجهات. وتعدّ هذه المخطّطات المرجعية لمراحل النشاط هي المكان الذي يتم فيه إعداد أي محتوى تريده عرضه في التراكب ورسمه وإزالته.

  • يتمّ استدعاء onAdd() عند إنشاء التراكب. استخدِم هذه الطريقة لجلب أو إنشاء هياكل بيانات وسيطة قبل رسم التراكب التي لا تحتاج إلى الوصول الفوري إلى سياق عرض WebGL.
  • يتمّ استدعاء onContextRestored({gl}) بعد أن يصبح سياق العرض متاحًا. استخدِمه لإعداد أي حالة WebGL أو ربطها، مثل shaders وGL buffer objects وما إلى ذلك. يأخذ onContextRestored() مثيل WebGLStateOptions يحتوي على حقل واحد:
    • gl هو اسم معرِّف للعنصر WebGLRenderingContext الذي تستخدمه الخريطة الأساسية.
  • onDraw({gl, transformer}) يعرض المشهد على الخريطة الأساسية. مَعلمات onDraw() هي عنصر WebGLDrawOptions يتضمّن حقلَين:
    • gl هو اسم معرِّف للعنصر WebGLRenderingContext الذي تستخدمه الخريطة الأساسية.
    • يوفّر transformer دوالّ مساعدة للتحويل من إحداثيات الخريطة إلى مصفوفة عرض النموذج، والتي يمكن استخدامها لتحويل إحداثيات الخريطة إلى المساحة العالمية ومساحة الكاميرا ومساحة الشاشة.
  • يتمّ استدعاء onContextLost() عند فقدان سياق العرض لأي سبب، وهو المكان الذي يجب فيه تنظيف أيّ حالة GL حالية، لأنّه لم يعُد مطلوبًا.
  • يعدّل onStateUpdate({gl}) حالة GL خارج حلقة التقديم، ويُستخدَم عند استدعاء requestStateUpdate. تأخذ هذه الطريقة مثيلًا WebGLStateOptions يحتوي على حقل واحد:
    • gl هو اسم معرِّف للعنصر WebGLRenderingContext الذي تستخدمه الخريطة الأساسية.
  • يتمّ استدعاء onRemove() عند إزالة التراكب من الخريطة باستخدام WebGLOverlayView.setMap(null)، وهو المكان الذي يجب فيه إزالة كل العناصر الوسيطة.

على سبيل المثال، في ما يلي تنفيذ أساسي لجميع أدوات الربط الخاصة بدورة الحياة:

const webglOverlayView = new google.maps.WebGLOverlayView();

webglOverlayView.onAdd = () => {
  // Do setup that does not require access to rendering context.
}

webglOverlayView.onContextRestored = ({gl}) => {
  // Do setup that requires access to rendering context before onDraw call.
}

webglOverlayView.onStateUpdate = ({gl}) => {
  // Do GL state setup or updates outside of the render loop.
}

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Render objects.
}

webglOverlayView.onContextLost = () => {
  // Clean up pre-existing GL state.
}

webglOverlayView.onRemove = () => {
  // Remove all intermediate objects.
}

webglOverlayView.setMap(map);

إعادة ضبط حالة GL

يعرِض "العرض المركّب باستخدام WebGL" سياق عرض WebGL للخريطة الأساسية. وبسبب هذا، من المهم جدًا إعادة ضبط حالة GL على حالتها الأصلية عند الانتهاء من عرض الأجسام. من المرجّح أن يؤدي عدم إعادة ضبط حالة GL إلى حدوث تعارضات في حالة GL، ما سيؤدي إلى تعذُّر عرض كلٍّ من الخريطة وأي عناصر تحدّدها.

يتم عادةً التعامل مع إعادة ضبط حالة GL في ميزة onDraw() hook. على سبيل المثال، يوفّر مكتبة Three.js دالة مساعدة تزيل أي تغييرات على حالة GL:

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Specify an object to render.
  renderer.render(scene, camera);
  renderer.resetState();
}

إذا تعذّر عرض الخريطة أو العناصر، من المرجّح جدًا أنّه لم تتم إعادة ضبط حالة GL.

عمليات تحويل الإحداثيات

يتم تحديد موضع عنصر على الخريطة المتجهّة من خلال تقديم مزيج من إحداثيات خطوط العرض والطول، بالإضافة إلى الارتفاع. أمّا الرسومات المجسمة، فتتم تحديدها في مساحة العالم أو مساحة الكاميرا أو مساحة الشاشة. لتسهيل تحويل إحداثيات الخريطة إلى هذه المساحة المُستخدَمة بشكلٍ شائع، يوفّر العرض المركّب باستخدام WebGL الدالة المساعِدة coordinateTransformer.fromLatLngAltitude(latLngAltitude, rotationArr, scalarArr) في العنصر onDraw() الذي يأخذ ما يلي ويُعرِض Float64Array:

  • latLngAltitude: إحداثيات خط العرض/خط الطول/الارتفاع إما على شكل LatLngAltitude أو LatLngAltitudeLiteral
  • rotationArr: Float32Array من زوايا دوران Euler المحدّدة بالدرجات
  • scalarArr: Float32Array من القيم السلفية لتطبيقها على المحور الأساسي

على سبيل المثال، يستخدم الرمز البرمجي التالي fromLatLngAltitude() لإنشاء مصفوفة تصوير كاميرا في Three.js:

const camera = new THREE.PerspectiveCamera();
const matrix = coordinateTransformer.fromLatLngAltitude({
    lat: mapOptions.center.lat,
    lng: mapOptions.center.lng,
    altitude: 120,
});
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);

مثال

في ما يلي مثال بسيط على استخدام Three.js، وهي مكتبة WebGL مفتوحة المصدر ورائجة، لوضع جسم ثلاثي الأبعاد على الخريطة. للحصول على جولة إرشادية كاملة حول استخدام ميزة "العرض المركّب باستخدام WebGL" لإنشاء المثال الذي يظهر أمامك في أعلى هذه الصفحة، يمكنك تجربة الدرس التطبيقي حول إنشاء تجارب خرائط مُسرَّعة باستخدام WebGL.

const webglOverlayView = new google.maps.WebGLOverlayView();
let scene, renderer, camera, loader;

webglOverlayView.onAdd = () => {
  // Set up the Three.js scene.
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera();
  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // Soft white light.
  scene.add(ambientLight);

  // Load the 3D model with GLTF Loader from Three.js.
  loader = new GLTFLoader();
  loader.load("pin.gltf");
}

webglOverlayView.onContextRestored = ({gl}) => {
  // Create the Three.js renderer, using the
  // maps's WebGL rendering context.
  renderer = new THREE.WebGLRenderer({
    canvas: gl.canvas,
    context: gl,
    ...gl.getContextAttributes(),
  });
  renderer.autoClear = false;
}

webglOverlayView.onDraw = ({gl, transformer}) => {
  // Update camera matrix to ensure the model is georeferenced correctly on the map.
  const matrix = transformer.fromLatLngAltitude({
      lat: mapOptions.center.lat,
      lng: mapOptions.center.lng,
      altitude: 120,
  });
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);

  // Request a redraw and render the scene.
  webglOverlayView.requestRedraw();
  renderer.render(scene, camera);

  // Always reset the GL state.
  renderer.resetState();
}

// Add the overlay to the map.
webglOverlayView.setMap(map);