-
-
Notifications
You must be signed in to change notification settings - Fork 461
Description
Describe the bug
Gradients are silently inserted as child elements of the scene graph and never removed. Additionally, gradients do not support gradient.remove() syntax.
Over long periods of creation and destruction of elements, unused gradients begin to clog the scene graph and noticeably impact performance.
I understand that gradients are likely shared objects and that tracking their orphaned status may be tricky. However, i have spent months tracking down this issue and finally narrowed it down to this most unlikely thing. I am building an artificial life environment that runs for long periods of time while creating and destroying thousands of SVG objects. This was dragging down frame rates and inflating the size of exported scene graphs to .svg files.
The issue is consistent across all three rendering contexts.
If there is an easier way to handle this that i have overlooked, please advise.
To Reproduce
Steps to reproduce the behavior:
- Create any gradient.
- Create any visual element ( line, path, etc ).
- Attach gradient as either stroke or fill.
- Remove the visual element. ( element.remove() )
- Observe that gradient remains.
Expected behavior
Gradients with no referencing elements should be deleted.
Environment (please select one):
- Code executes in browser (e.g: using script tag to load library)
- Packaged software (e.g: ES6 imports, react, angular, vue.js)
- Running headless (usually Node.js)
Desktop:
- Device: Laptop
- OS: Linux
- Browser: Firefox 136
.html Working Example
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/two.js/0.8.15/two.min.js"></script>
</head>
<body id="body">
<div class="shape-container" style="height: 100px; width: 100px">
<div id="two_canvas"></div>
</div>
<script>
// setup
let two = new Two({ fitted: true, type: 'SVGRenderer' });
let elem = document.getElementById('two_canvas');
two.appendTo(elem);
// baseline
console.log('before starting:', two.scene.children.length);
// create a line
let line = two.makeLine(0, 0, 100, 100);
console.log('after line created:', two.scene.children.length);
// create a gradient (child count unexpectedly increases)
let stops = [
new Two.Stop(0, '#000'),
new Two.Stop(0.5, '#AAA'),
new Two.Stop(1, '#FFF'),
];
let grad = two.makeLinearGradient(0, 0, 1, 1, ...stops);
console.log('after creating gradient:', two.scene.children.length);
// attach gradient to line stroke
line.stroke = grad;
console.log(
'after attaching gradient to line stroke:',
two.scene.children.length
);
// remove line (gradient is not removed automatically))
line.remove();
console.log('after removing line:', two.scene.children.length);
// removing gradient possible, but only manually
two.remove(grad);
console.log(
'after removing gradient manually',
two.scene.children.length
);
// gradient is a child element, but grad.remove() is not a function
console.log(two.scene.children);
</script>
</body>
</html>
References:
The project I am building with two.js has a demo here: https://leiavoia.net/vectorcosm/
Thank you all for your efforts on this library. It's been a lot of fun to work with on my project!