Closed Shiuyin closed 1 year ago
If you dmove a group, all its contents are dmoved. That can indeed result in bbox e.g. if the group itself has groups. However, for your use case you should just rely on transforms instead. They will just move the whole group with no magic and it might even render faster by the browser:
group.translate(0, -10) // move by y -10
Thank you for your answer.
I would very much like to simply use .translate(), but currently MS Edge is bugged and renders the content of foreignObjects above those headers, even though the headers exist earlier in DOM than the foreignObject. This is related to .translate() as simply using .y() had less (but still some) of that problem.
Therefore, i currently cannot use translate...
Are there any other options?
No, not really. If Edge has the problem, chrome should have it, too. They both use the same rendering engine. Did you report the bug to the vendors already? Also you can try to use z-index on the content of the foreignObject maybe -1 works.
However, if your fix works for you, just go with that. You have more info about the dimensions of your elements avilable and therefore you can optimize for that.
I am currently running into this problem too (move() method being very slow). Will probably have to try setting x/y attributes directly too, but it would be nice if move() automatically chose the most performant method.
EDIT: I figured out that actually just setting x/y attributes together with transform="translate(x, y)" and transform-origin="x y" seems to be a simple performant way for placing items when you know what you want and all the values involved.
We have the same issue that moving a group with ~ 3000 objects (lines) with the .y(..) function on the group, is very slow. Interestingly this occurred after switching from svg.js v2.7 to v3.x. Investigating with the chrome profiler showed that with v3 the browser spends much more time layouting than with v2
svg3:
SVG 2:
With svg 2 the operation on the group takes 0.5ms layouting happens detached after the y(..) call has finished With svg 3 the operation takes 1300 ms and the layouting is "integrated" int the y(..) stacktrace
The general advice for big groups is: Use transforms over move/size svg.js v2 mapped move to translate for groups. But this was inconsistent and lead to unexpected bounding boxes. The current solution avoids these inconsistencies and prevents users that are not experts in svg to run into bugs. However, you can still explicitely use transforms
Closing this since this is a wontfix
This is somewhat related to https://github.com/svgdotjs/svg.js/issues/1214.
We have a huge chart being drawn with SVG.js that has a "sticky" header section consisting sometimes of up to hundreds or thousands of
rect
andtext
elements (The header itself is n simplegroup
objects, containing therects
andtexts
). To implement the sticky behaviour we listen toonScroll
listeners and then move the header sections to the new position. It looks a bit like this:When we implemented this we quickly realized that performance was bad. Scrolling in a tiny amount of randomly generated 70
rects
andtexts
, the Chrome performance tools show that > 50% of time is used by SVG.js in the.y()
call. The call chain ends always at.dmove()
which tries to get theBBox
and then position the elements according to theBBox
and some matrix math.At first I thought the text elements are (again) the culprit and removed them temporarily => Same problem.
In the end I implemented the following function, which is called by the function above instead of the
header.y()
:This will bring the scripting time needed by SVG.js down to way below 5% and works with even thousands of randomly generated test objects.
I am not (yet) enough knowledgeable about SVG to say if something like this logic could be implemented as the default behaviour for
.move()
or.dmove()
. At the end of the day, we just need to shift those header groups by a certain amount up or down. If the element's y attribute already has the correct coordinates prior to scrolling, what reason is there that a.dmove()
call needs to access allBBox
'es again instead of just incrementing or decrementing the y values in the attributes from before scrolling?Are there other ways I have missed that might help this particular case?
I have also tried:
ay()
=> Does exist only on text elements, which are not the problem.dmove()
=> Does access BBox as described abovecontain: paint
orbuffered-rendering: strict
to get Chrome to cache portions of the SVG and simply move it around when I use.y()
, without any effect.I think that in general trying to position via
BBox()
should be a last resort. Links I found the last hours trying to fix this problem like https://support.google.com/chrome/thread/118284571/any-one-suffers-from-the-newest-ver-92-rendering-some-heavy-svg-jobs?hl=en show thatBBox()
really is no good option (currently?) to use at 50+ elements. Any way to implement.move()
and it's related cousins to not rely onBBox()
would greatly help all users.