Open dan-fritchman opened 2 weeks ago
I should add: leafing through that same browser console, it does appear that our application's content is in the two.scene
; it has a big hierarchy of children
(generally deeply nested Group
s).
Hmmm, that is sufficiently vague. Couple things stand out as potential next steps:
Generally, if you're not using the makeXYZ
methods on a specific instance. You'll need to do this:
const two = new Two({ type: Two.Types.webgl, autostart: true }).appendTo(document.body);
// If you haven't autostarted you need
// to call two.update();
const rectangle = new Two.Rectangle(x, y, width, height);
two.add(rectangle);
With groups as intermediaries it is possible that all the nested elements in a group could get missed on the update invocation. But, without an example it's hard to know for sure.
autostart
. Just tested with it turned off, and running update()
in the debug console, to no avail. With groups as intermediaries it is possible that all the nested elements in a group could get missed on the update invocation. But, without an example it's hard to know for sure.
What do ya mean there? Is there anything we could dig into? Or something about the conditions which might make that happen?
Thanks again!
Could you export one scene in SVG? Then I could import it into Two.js using WebGL and it should produce the same error.
What I mean regarding groups, is if you can tell me the exact order that elements are added then maybe I can reproduce the issue.
To confirm, this only happens with simple paths? Or also with text and images?
This could give a hint because Text and Images are not based on Two.Path. All other primitive shapes are.
OK that makes sense, I'll export some SVGs.
To more quickly answer your question - we use text, but no images. And definitely lots of Path
s and Group
s.
OK attaching an example SVG.
That is generated with the (I think recommended method), something like:
svgString = (): Result<string> => {
this.two.update();
const { innerHTML } = this.twoParentDiv;
// Stick that `xmlns` attribute in there, so most readers will accept it.
const s = innerHTML.replace(
"<svg",
'<svg xmlns="http://www.w3.org/2000/svg"'
);
return Result.Ok(s);
};
Just double-checked that swapping to the webgl renderer renders this blank.
🤔 There are some differences. But when I load this SVG into the same webpage with a WebGL and an SVG instance they both render:
Left is WebGL Right is SVG
This is the code:
const a = new Two({
type: Two.Types.webgl,
autostart: true,
width: 400,
height: 400
}).appendTo(document.body);
const b = new Two({
type: Two.Types.svg,
autostart: true,
width: 400,
height: 400
}).appendTo(document.body);
a.renderer.domElement.style.border = '1px solid #ccc';
b.renderer.domElement.style.border = '1px solid #ccc';
a.add(a.load('./736.svg', (svg) => { svg.scale = 0.25 }));
b.add(b.load('./736.svg', (svg) => { svg.scale = 0.25 }));
An unrelated note: if at all possible I would highly recommend making the grid a single path.
Very interesting indeed!
I guess that points to something about how we load/ add elements and eventually update
/ render
?
And one big path sounds like a pretty good idea.
I suppose just "snaking" that around offscreen would get it done.
Yep, it would reduce the draw calls
FWIW passing that SVG content to two.load
in the dev-console of our app running the WebGL back-end does in fact render that SVG content. (And continues to render nothing from our other groups.)
Hmm, that would indicate that there's something you're doing (or not doing) that two.load
does.
This is all the method does once the content is loaded and available in the DOM
for (i = 0; i < dom.temp.children.length; i++) {
elem = dom.temp.children[i];
child = this.interpret(elem, false, false);
if (child !== null) {
group.add(child);
}
}
Is it possible that transforming (scaling & positioning) a group works differently in the webgl renderer than in the others?
We are generally transforming the coordinates in some external data into on-screen ones with something like this:
// Apply to a `Two.Shape`.
// Notably `Two.Group` is a `Shape`, and is the most common use-case.
apply: (t: CoordTransform, shape: Shape) => {
const { scale, offset } = t;
// Note y-axis inversion is applied right here!
shape.scale = new Vector(scale, -scale);
shape.position = new Vector(offset.x, offset.y);
},
Usually the shape
argument to this function is a Group
, which is in turn the sole child of our two.scene
group.
This doesn't seem to be updating as it does with the other renderers. I'm wondering if everything is rendering, but is just off-screen due to a misunderstanding of this coordinate transform.
I'll try to make a minimal demo case.
OK yeah that's it, or something to do with it.
Here's a minimal example:
https://codepen.io/dan-fritchman/pen/vYqqLwz
import Two from 'https://cdn.skypack.dev/two.js@latest';
const two = new Two({
type: Two.Types.svg,
fullscreen: true,
autostart: true
}).appendTo(document.body);
// Create a single child group
const g = new Two.Group();
g.addTo(two);
// Add a rectangle to it
const r = new Two.Rectangle(100,-100,100,100);
r.fill = "red";
r.addTo(g);
// Now scale and shift the parent group
g.scale = new Two.Vector(1, -1);
g.position = new Two.Vector(100, 100);
two.render();
Looks like:
Change to:
type: Two.Types.webgl,
And it looks like this:
This is probably gonna be a pretty crappy bug report, but I'm not really sure what to report.
In our application SVG and Canvas have always worked. WebGL has never worked. It just renders a blank canvas.
It's a big complicated application; I'm not sure how to peel off a minimal repro case.
Currently using Two v0.8.14. Mostly in current Chrome, but also tried in Firefox & Safari, all on current MacOS. And I did notice something today: calling functions like
makeRectangle
andmakeCircle
on ourTwo
instance in the browser developer console does get them to show up:And noting, our application generally does not use those
makeXyz
functions. We do something more like:I guess the question is: does anything come to mind as to why that combination wouldn't work?