DOMException: Failed to execute 'structuredClone' on 'Window': function onRotationChange() {
quaternion.setFromEuler(rotation, false);
} could not be cloned.
at _saveSceneFile (http://127.0.0.1:3000/js/util/index.js?t=1722985500415:235:45)
at saveScene (http://127.0.0.1:3000/js/util/index.js?t=1722985500415:227:37)
at CityMgr.onSaveModel (http://127.0.0.1:3000/js/cityMgr.js?t=1722985500415:236:5)
at CityUI.onToolSelected (http://127.0.0.1:3000/js/cityUI.js?t=1722985500415:55:26)
at HTMLButtonElement.<anonymous> (http://127.0.0.1:3000/js/util/index.js?t=1722985500415:117:47)
I think it’s quite possible you’re just overloading threejs toJSON which uses naive recursion to generate json output. Or its possible there is some circular reference in there that is tripping it up, but generally the classes are designed to prevent that.
More generally/ironically… the json format isn’t really great for serialization. If you’re trying to save the scene you can use the GLTFExporter to save it as gltf/glb. If you’re trying to serialize your app state, you might be better off space and time wise by serializing the game datastructures themselves, independent of the scene graph.
May I ask what you need the json format of the scene for?
I am a beginner in Three.js.
I tried with a little help from gpt, just a little bit beyond the follow-through level, but I got the same answer, which is disappointing.
Rather than a special strategy for me, I would appreciate it if you could give me a simple sample like you mentioned.
I want to save and open it so that the user can do additional work.
I have already written the code using pako because of the file size.
The code below also failed.
function _saveSceneFile(scene) {
const exporter = new GLTFExporter();
debugger
// Remove circular references from userData
scene.traverse((object) => {
if (object.userData) {
removeCircularReferences(object.userData);
}
});
exporter.parse(scene, (result) => {
const output = JSON.stringify(result, null, 2);
saveString(output, filename);
}, { binary: false });
}
// Helper function to remove circular references from userData
function removeCircularReferences(obj, seen = new WeakSet()) {
if (obj && typeof obj === 'object') {
if (seen.has(obj)) {
return;
}
seen.add(obj);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object') {
removeCircularReferences(obj[key], seen);
}
}
}
}
}
// Helper function to save a string as a file
function saveString(text) {
try {
const blob = new Blob([text], { type: 'text/plain' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = _getFilename('.json');
link.click();
URL.revokeObjectURL(url); // URL 해제
} catch (err) {
console.log(err);
}
}
I want to provide the user with a format that can save and open files only in Three.js.
Please help me.
Ohh that’s interesting… I see in the code you posted, about removing circular references?
That is interesting, because it’s possible that that is what caused your stack overflow when using toJSON()?
.userData is a field on object3ds that is meant for holding your own custom data, and will attempt to get serialized by toJSON… and if it contains complex data or circular references… that might explain the original error.
It might be worth doing something like:
scene.traverse(e=>e.userData={});
scene.toJSON()
And see if the error goes away?
If so… then maybe you can continue with toJSON()
If you use the GLTFExporter, you will get a gltf file out, that can be loaded in other apps like blender or viewed in online viewers, but won’t necessarily be able to load back into you game without a bunch more work.