Hello,
I have general issue with my lack of understanding of including multiple, mutually dependent javascripts into a plugin. So some help, examples or tutorial about that would be great to have and learn.
As I am not sure whom to address this question I also announced it in Beginning development group.
At the moment I try to include three.js into my plugin and I succeeded.
But when I try to include another javascript from the same bundle which are related through GLOBAL object "THREE" I receive error message in the web browser (undefined object "THREE").
Here is my code in short:
start.php
...
init(){
...
elgg_define_js('three', [
'src' => elgg_get_simplecache_url('three.js'),
'exports' => 'THREE',
]);
elgg_define_js('OrbitControls', [ 'src' => elgg_get_simplecache_url('OrbitControls.js'), // 'deps' => ['THREE'], // 'exports' => 'THREE.OrbitControls', ]);
elgg_define_js('OBJLoader', [ 'src' => elgg_get_simplecache_url('OBJLoader.js'), // 'deps' => ['THREE'], ]);
...
}
...
my_plugin/view.php
...
elgg_require_js("my_plugin/three_my_app");
...
my_plugin/views/default/js/my_plugin/three_my_app.js
define(function(require) {
var elgg = require("elgg");
var $ = require("jquery");
var THREE = require("three");
window.THREE = THREE;
require('OBJLoader');
require('OrbitControls');
// these need to be accessed inside more than one function so we'll declare them first
let container;
let camera;
let controls;
let renderer;
let scene;
const mixers = [];
const clock = new THREE.Clock();
function init() {
container = document.querySelector( '#container' );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x8FBCD4 );
initCamera();
initControls();
initLights();
loadModels();
initRenderer();
renderer.setAnimationLoop( () => {
update();
render();
} );
}
function initCamera() {
camera = new THREE.PerspectiveCamera( 35, container.clientWidth / container.clientHeight, 1, 1000 );
camera.position.set( -50, 50, 150 );
}
function initControls() {
controls = new THREE.OrbitControls( camera, container );
}
....
....
});
<?php
return [
'default' => [
'/' => [
__DIR__ . '/vendors/three-js/build/',
__DIR__ . '/vendors/three-js/loaders/',
__DIR__ . '/vendors/three-js/libs/',
__DIR__ . '/vendors/three-js/controls/',
],
],
];
I found on the internet the solution for regular web developers but I don't know how to include that into elgg.
2. And Maybe someone can explain where and how to properly include the following code:
define('three', ['three.js'], function ( THREE ) {
window.THREE = THREE;
return THREE;
});
info@elgg.org
Security issues should be reported to security@elgg.org!
©2014 the Elgg Foundation
Elgg is a registered trademark of Thematic Networks.
Cover image by RaĆ¼l Utrera is used under Creative Commons license.
Icons by Flaticon and FontAwesome.
1. You don't need to define OrbitControls.js and OBJLoader.js but three.js only because these scripts calls with main build.
2. elgg_get_simplecache_url('three.js') assume that your JS is located at root path.
So recommend to register a view name in views.php of your plugin, or use the full view name.
For example, make
Download the latest release and unzip it in
Now define your JS as:
If you want to use the simple cache then add this view name in views.php of your plugin:
With it you can use this:
3. We've fixed the same issues with global/document and global/window functions in another plugins.
Create in /mod/your_awesome_plugin/vendor/ new folder global with 2 files:
Define these scripts in start.php:
In your three_my_app.js use:
4. You don't need to duplicate the same pages/discussion on community.
Thank you RvR for your help.
I would like to get working the same code as written in this tutorial:
https://codesandbox.io/s/github/looeee/discoverthree.com-examples/tree/master/1-first-steps/5-camera-controls?from-embed
It uses Three.js & OrbitControls.js only and with it I would be happy to understand how to setup it in elgg.
Regarding your advices... when I do everything you wrote I receive error message:
"Uncaught TypeError: THREE.OrbitControls is not a constructor"
in file: "my_plugin/views/default/js/my_plugin/three_my_app.js"
- at the line:
controls = new THREE.OrbitControls( camera, container );
..............................................................................................................
Alternatively if I try to include javascript file OrbitControls.js from "..\vendors\three\examples\js\controls\" - path with: require('OrbitControls'); - in three_my_app.js I receive another error message:
Uncaught Error: Module name "OrbitControls" has not been loaded yet for context: _. Use require([])
https://requirejs.org/docs/errors.html#notloaded
at makeError (require.js:168)
at Object.localRequire [as require] (require.js:1436)
at requirejs (require.js:1797)
In this scenario I defined OrbitControls in start.php init() with : elgg_define_js(...);.
Please look at three.js bundle.
Three.js is located in three\build\ folder , not in root.
Then OrbitControls.js is in three\examples\js\controls\ folder.
Many guys even out of elgg community has issues to put OrbitControls.js to work.
Thus the Three developers started to develop another OrbitControls.js in "three\examples\jsm" folder.
The isuue with this javascript file is "import" key word in OrbitControls.js.
Do you have idea what to do?
BR,
V
As a reminder, I just showed a way and methods but not the solution.
However, I spent the time to answer your question.