MapConductor React SDK Samples

Three.js-Objekt (nur Web) | MapLibre | MapConductor React SDK

Three.js-Objekt (nur Web)-Beispiel des MapConductor React SDK mit MapLibre.

Dieses interaktive Beispiel zeigt Three.js-Objekt (nur Web) über die MapConductor-Abstraktion auf MapLibre.

Codebeispiel

import { useEffect, useMemo } from 'react';
import * as THREE from 'three';
import { createGeoPoint, createMapCameraPosition } from '@mapconductor/js-sdk-core';
import { useMapLoaded } from '@mapconductor/js-sdk-react';
import { MapLibreDesign, MapLibreMapView2D, useMapLibreViewState } from '@mapconductor/react-for-maplibre';


// (1) Die Karte erzeugen


const initialCamera = createMapCameraPosition({
  position: createGeoPoint({ latitude: 35.6812, longitude: 139.7671 }),
  zoom: 12,
});


const mapViewState = useMapLibreViewState({
  mapDesignType: MapLibreDesign.OsmBrightJa,
  cameraPosition: initialCamera,
});


// (2) Daten und Interaktionszustand vorbereiten
const position = useMemo(() => createGeoPoint({
  latitude: 35.6812,
  longitude: 139.7671,
}), []);


// (3) Die Karte und ihre Overlays rendern


function ThreeMapObject({ mapViewState, position }) {
  const isMapLoaded = useMapLoaded();


  useEffect(() => {
    if (!isMapLoaded) return;
    const holder = mapViewState.getMapViewHolder();
    if (!holder) return;


    const scene = new THREE.Scene();
    const camera = new THREE.OrthographicCamera(0, 1, 1, 0, 0.1, 1000);
    camera.position.z = 200;
    const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    const width = holder.mapView.clientWidth;
    const height = holder.mapView.clientHeight;
    renderer.setSize(width, height);
    camera.right = width;
    camera.top = height;
    camera.updateProjectionMatrix();
    renderer.domElement.style.position = 'absolute';
    renderer.domElement.style.inset = '0';
    holder.mapView.appendChild(renderer.domElement);


    const object = new THREE.Mesh(
      new THREE.TorusKnotGeometry(13, 4),
      new THREE.MeshNormalMaterial(),
    );
    scene.add(object);


    let frame = 0;
    const draw = () => {
      const offset = holder.toScreenOffset(position);
      if (offset && !(offset instanceof Promise)) {
        object.position.set(offset.x, height - offset.y, 0);
      }
      object.rotation.y += 0.02;
      renderer.render(scene, camera);
      frame = requestAnimationFrame(draw);
    };
    draw();


    return () => {
      cancelAnimationFrame(frame);
      renderer.domElement.remove();
      renderer.dispose();
    };
  }, [isMapLoaded, mapViewState, position]);


  return null;
}


<MapLibreMapView2D state={mapViewState}>
  <ThreeMapObject mapViewState={mapViewState} position={position} />
</MapLibreMapView2D>

Wie der Code funktioniert

Eine durchsichtige Three.js-Leinwand über die Karte legen und ihr 3D-Objekt mit der anbieterunabhängigen Projektion MapViewHolder.toScreenOffset() verankern.

useMapLoaded hält den Effekt zurück, bis die Karte existiert; dann liefert getMapViewHolder() einen Holder, dessen WebGL-Canvas über der Karte eingehängt wird.

In jedem Bild wandelt holder.toScreenOffset(position) die geografische Koordinate in einen Pixelversatz um, sodass das 3D-Objekt beim Bewegen der Karte an seinem Ort bleibt — derselbe Aufruf bei jedem Anbieter.