Three.js und WordPress Elementor

Bei Form und Zeichen stehen wir verschiedenen Anforderungen bei der Entwicklung moderner Websites und Web-Apps für unsere Kunden gegenüber. Für eines unserer Projekte benötigten wir eine einfache Lösung, um ein 3D-Modell auf einer statischen Website zu präsentieren. Aufgrund des schnellen Workflows nutzen wir WordPress zur Erstellung statischer Websites wie Unternehmenswebsites oder Projektwebsites. Wir suchten nach Tools, die die Leistungsfähigkeit von WebGL nutzen, um 3D-Modelle direkt auf Websites zu laden und fanden Three.js. Three.js ist eine JavaScript-Bibliothek zur einfachen Erstellung und Darstellung von 3D-Grafiken in Webbrowsern mittels WebGL, die unter der MIT-Lizenz veröffentlicht wurde.
Jetzt arbeiteten wir an der Integration von Three.js mit WordPress, um eine effiziente und optimierte Lösung für bessere Seitenladegeschwindigkeit und einfache Verwaltung mehrerer 3D-Modelle zu schaffen, die auf der Website geladen werden.

Die Verwendung benutzerdefinierter Dateitypen ermöglichen

Der erste Schritt ist es, die Dateitypen unserer 3D-Modelle in der WordPress Medienbibliothek zu erlauben. Standardmäßig sind 3D-Dateitypen wie FBX nicht zugelassen. Wenn Sie Ihre Dateien über FTP oder SSH hochladen möchten, können Sie diesen Schritt überspringen.
Uploading model.fbx failed, because this file type is not allowed by default
Uploading model.fbx failed, because this file type is not allowed by default
Um benutzerdefinierte Dateitypen zu erlauben, empfehle ich die Verwendung von File Upload Types von WPForms. Nach der Installation und Aktivierung können Sie nach den benötigten Dateitypen suchen und diese aktivieren. Für unser Projekt brauchten wir FBX. FBX wird von einer Vielzahl von 3D-Modellierungsprogrammen unterstützt und ist auch in Three.js gut implementiert. Leider ist FBX nicht in der Dateitypen-Liste des Plugins enthalten, daher müssen wir einen benutzerdefinierten Dateityp hinzufügen, indem wir auf den Link unterhalb der Überschrift „Add File Upload Types“ klicken.
The file type FBX is not listed
The file type FBX is not listed
Um FBX hinzuzufügen, müssen wir einen Namen, den MIME-Typ und die Erweiterung eingeben. Als Namen haben wir „FBX 3D-Datei“ gewählt. Der MIME-Typ kann von digipres.com abgerufen werden. In unserem Fall ist es „application/octet-stream“.
Adding a custom file type
Wenn wir nun erneut versuchen, das Modell hochzuladen, funktioniert es wie gewünscht.
Uploading of the model works
Uploading of the model works

Hinzufügen von benutzerdefinierten Skripten mit Elementor

Hier sind die verschiedenen Möglichkeiten, um benutzerdefinierte Skripte zu einer WordPress-Website hinzuzufügen. Da wir Elementor für unsere WordPress-Websites verwenden, nutzen wir das integrierte Tool von Elementor. Für Entwicklungszwecke können Sie den folgenden Code verwenden, um Three.js auf Ihrer Website zu laden:
				
					<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/three@0.152.0/build/three.module.js",
      "three/addons/": "https://unpkg.com/three@0.152.0/examples/jsm/"
    }
  }
</script>
				
			

Beachten Sie, dass Sie die Three.js-Version ändern können, indem Sie sie in den Links ändern. In unserem Fall haben wir Version 0.152.0 verwendet. Die neuesten Releases finden Sie unter github.com.

Stellen Sie außerdem sicher, dass Sie alle Skripts herunterladen und sie in einer Produktionsumgebung von Ihrem Server aus bereitstellen.

Um die Seitenladezeit zu optimieren, sollten Sie dieses Skript nur auf Seiten laden, die Three.js verwenden.

GLTF Modelle in Elementor laden

Um ein Modell auf einer Seite zu laden, müssen wir das HTML-Element von Elementor verwenden. Auf der Three.js-Beispielseite können Sie das verwendete Script-Tag finden, indem Sie die Website inspizieren. Mit ein paar Anpassungen können wir diese Beispiele auf unserer Elementor-Seite verwenden.
wordpress elementor three.js gltf example
Wir haben dieses Beispiel verwendet und es responsiv gemacht, indem wir die Breite jedes Mal ändern, wenn das Größenänderungsereignis ausgelöst wird. Beachten Sie, dass wir ein DIV-Element als Container für das 3D-Modell hinzugefügt haben. Wenn Sie mehr als ein Modell auf einer einzigen Seite hinzufügen, müssen Sie unterschiedliche IDs für Ihre Container verwenden.
				
					<script type="module">
 import * as THREE from 'three';
 import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

 let camera, scene, renderer;
 let width = 500;
 let height = 400;

 init();
 render();

 function init() {
  const container = document.getElementById("container");
  width = container.parentNode.offsetWidth;

  camera = new THREE.PerspectiveCamera(45, width / height, 0.25, 20);
  camera.position.set(- 1.8, 0.6, 2.7);

  scene = new THREE.Scene();

  new RGBELoader()
   .setPath('https://threejs.org/examples/textures/equirectangular/')
   .load('royal_esplanade_1k.hdr', function (texture) {
    texture.mapping = THREE.EquirectangularReflectionMapping;

    scene.background = texture;
    scene.environment = texture;

    render();

    // model
    const loader = new GLTFLoader().setPath('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/');
    loader.load('DamagedHelmet.gltf', function (gltf) {
     scene.add(gltf.scene);
     render();
    });
   });

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
  renderer.toneMappingExposure = 1;
  container.appendChild(renderer.domElement);

  const controls = new OrbitControls(camera, renderer.domElement);
  controls.addEventListener('change', render); // use if there is no animation loop
  controls.minDistance = 2;
  controls.maxDistance = 10;
  controls.target.set(0, 0, - 0.2);
  controls.update();

  window.addEventListener('resize', onWindowResize);
 }

 function onWindowResize() {
  width = container.parentNode.offsetWidth;
  camera.aspect = width / height;
  camera.updateProjectionMatrix();

  renderer.setSize(width, height);

  render();
 }

 function render() {
  renderer.render(scene, camera);
 }
</script>
<div id="container"></div>
				
			

FBX Modelle laden

Wenn wir unser FBX-Modell laden, müssen wir die Beleuchtung einrichten. Three.js bietet ein tolles Beispiel für ein FBX-Modell mit Animation. Wir können denselben Ansatz wie zuvor verwenden, um den Code an unsere Bedürfnisse anzupassen. Für das FBX-Modell haben wir jedoch mehrere direkte Lichter und ein Halbkugellicht hinzugefügt, um unser Objekt richtig zu beleuchten.
				
					<script type="module">
	import * as THREE from 'three';

	import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
	import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

	import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';

	let camera, scene, renderer, mixer;

	let width = 600;
	const height = 400;

	const container = document.getElementById("container");

	width = container.parentNode.offsetWidth;

	init();
	render();

	function init() {
		camera = new THREE.PerspectiveCamera(45, width / height, 1, 2000);
		camera.position.set(300, 100, 300);

		scene = new THREE.Scene();

		const hemiLight = new THREE.HemisphereLight(0xffffff, 0xcccccc, 5);
		hemiLight.position.set(0, 400, 0);
		scene.add(hemiLight);

		const dirLight = new THREE.DirectionalLight(0xffffff, 2.5);
		dirLight.position.set(0, 200, 200);
		dirLight.castShadow = true;
		dirLight.shadow.camera.top = 180;
		dirLight.shadow.camera.bottom = - 100;
		dirLight.shadow.camera.left = - 120;
		dirLight.shadow.camera.right = 120;
		scene.add(dirLight);

		const dirLight2 = new THREE.DirectionalLight(0xffffee, 1);
		dirLight2.position.set(400, 0, -100);
		dirLight2.castShadow = true;
		dirLight2.shadow.camera.top = 180;
		dirLight2.shadow.camera.bottom = -100;
		dirLight2.shadow.camera.left = - 120;
		dirLight2.shadow.camera.right = 120;
		scene.add(dirLight2);

		const dirLight3 = new THREE.DirectionalLight(0xffffff, .5);
		dirLight3.position.set(-400, 0, 0);
		dirLight3.castShadow = true;
		dirLight3.shadow.camera.top = 180;
		dirLight3.shadow.camera.bottom = -100;
		dirLight3.shadow.camera.left = - 120;
		dirLight3.shadow.camera.right = 120;
		scene.add(dirLight3);

		// ground
		const mesh = new THREE.Mesh(
			new THREE.PlaneGeometry(2000, 2000),
			new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false })
		);
		mesh.rotation.x = - Math.PI / 2;
		mesh.receiveShadow = true;
		scene.add(mesh);

		const grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000);
		grid.material.opacity = 0.2;
		grid.material.transparent = true;
		scene.add(grid);

		scene.background = new THREE.Color().setHex(0xeeeeee);

		// model
		const loader = new FBXLoader();
		loader.load('https://threejs.org/examples/models/fbx/Samba Dancing.fbx', function (object) {
			mixer = new THREE.AnimationMixer(object);

			if (object.animations.length) {
				const action = mixer.clipAction(object.animations[0]);
				action.play();
			}

			object.traverse(function (child) {
				if (child.isMesh) {
					child.castShadow = true;
					child.receiveShadow = true;
				}
			});

			scene.add(object);

			render();
		});

		renderer = new THREE.WebGLRenderer({ antialias: true });
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(width, height);
		renderer.toneMapping = THREE.ACESFilmicToneMapping;
		renderer.toneMappingExposure = 1;
		renderer.shadowMap.enabled = true;
		container.appendChild(renderer.domElement);

		const controls = new OrbitControls(camera, renderer.domElement);
		controls.addEventListener('change', render); // use if there is no animation loop
		controls.minDistance = 100;
		controls.maxDistance = 500;
		controls.target.set(0, 0, - 0.2);
		controls.update();

		window.addEventListener('resize', onWindowResize);
	}

	function onWindowResize() {
		width = container.parentNode.offsetWidth;

		camera.aspect = width / height;
		camera.updateProjectionMatrix();

		renderer.setSize(width, height);

		render();
	}

	function render() {
		renderer.render(scene, camera);
	}
</script>
<div id="container"></div>
				
			

Teilen Sie unseren Beitrag

Hat Ihnen die Lektüre dieses Beitrags gefallen? Wenn ja, würden wir uns freuen, wenn Sie sich einen Moment Zeit nehmen und ihn mit Ihren Freunden und Kollegen in den sozialen Medien teilen. Das Teilen wertvoller Inhalte hilft uns, Wissen zu verbreiten und andere zu inspirieren. Vielen Dank für Ihre Unterstützung!
Facebook
Twitter
LinkedIn
Pinterest

Vielen Dank

Wir haben Ihre Nachricht erhalten und melden uns bei Ihnen.