I have a huge SVG which has lots of graphical elements, on mouse wheel zoom event gets triggered which re-paints the whole SVG.
With some profiling I could break down the time taken in such event,
Calculations needed to transform the SVG are taking 1-2ms.
Upon applying the transform, the paint operation is taking 500ms-1.5sec(very sluggish user experience).
As I understand, the paint operation would depend on the render tree of the SVG/HTML which is quite big in this case.
I thought of trying the following ways to improve the user experience
Use 'debouncing' so that I will coalesce mulitple scroll events into
one signal within a given interval.
Possibly use 'requestAnimationFrame' with 'debouncing'.
Look for ways to optimize the render tree of the SVG although I feel
this is difficult in my case because of other constraints.
Are these the right ways or am I moving in the wrong direction?
What other techniques could be used for a smoother user experience in such cases when re-painting is inevitable?
Related
I've just started out with SVG and have gathered enough information to see that animating these objects is not the same as animating canvas objects. With canvas objects, the canvas is redrawn on every frame, but it seems like with SVG you aren't supposed to be thinking in terms of frames and FPS, but rather in terms of seconds and delays by using the built in <animate> tag.
While I appreciate all the out of the box functionality for SVG animations, I've built up quite an understanding (and library) for how to get my animations working together on canvas using the frames and a timeline paradigm.
I know there is timeline and scheduling support for SVG with libraries like GSAP or SVG.js but I much prefer thinking in terms of FPS and and frameCount.
I was wondering if I might be able to continue using this paradigm, but instead simply update the attributes of my SVG objects on each frame iteration and let the DOM re-render the positions instead of figuring out a way to describe the animation in the <animate> tag.
I'm completely open to suggestions if using the <animate> tag isn't as finicky as I think it is for scheduling my animations/getting them to move together and any suggestions would be much appreciated.
My animation needs aren't to the likes of high performance websites, I just want to step through them to show people some math concepts as they progress.
Updating SVG element attributes is a completely fine way to go about animating them. It can be more performant than clearing all elements in your main SVG tag, and redrawing - but that depends on the drawing, browser, and animation details. But, SVG renders surprisingly quickly, so if you are just stepping through tailored frames to demonstrate a concept, and if it would be more convenient to think of each frame independently, you should be completely fine to also clear and redraw. If your project is intended for a website, make sure to test your implementation on Chrome and Firefox at least as they have slight differences.
I'm developing a D3 application that utilizes a lot of text. Since there is alot of text elements, panning around using D3 zoom causes some lag. Is there a way in which I can improve the performance of my application? I'm happy to hear any suggestions, you guys might have. I've been thinking about paginating my data and detecting pan events but my UI is very complex and the user has the freedom of placing things the way he wants so I am not sure how to go about implementing a pan/pagination solution.
Such an open question is bound to get very opinion-based answers, and without more context you're also bound to get some useless ones, but here you go: it depends on what you want and what you mean by "a significant amount".
Supposing that significant amount is > 1000 elements, consider using canvas instead of SVG. Sure, if you can click on individual text nodes, that's more of a hassle, but it should be really good at panning/zooming.
If that is not possible, look at your code. Are you repositioning all text nodes individually? If so, place them all inside one g node and give that node a transform and zoom. In other words, make that node responsible for all global movement, and place the text nodes only relative to each other.
If that is also not possible, consider removing text nodes if they're outside the bounds of the SVG. Repositioning invisible nodes takes a lot of computation power, be smart about it. This is probably the most complex solution, so try it last.
In order to have a reasonable performance with a lot of svg paths, svg text and svg textpath elements on a leaflet map, I wonder how D3 handles elements which are currently not on screen.
So for example when I zoom in to an area such as Washington State, 99.9% of the world is not shown - is D3 default behaviour to draw all the other elements regardless?
I am basing my project on Mike Bostocks d3 + leaflet example. There are no viewports/ viewbox attributes used - is it done somewhere else? Thanks for your input.
I think there's two parts to this question
Drawing of SVG DOM elements that are off screen
As #LarsKotthoff mentions, it's probably not worth worrying about these, as the browser will probably do a better job than you of optimising them away.
Processing of data that will result in SVG DOM elements being drawn off screen.
I think this is where you can make a difference. If you have data manipulation/processing that is expensive, then processing things that will not be displayed seems like a waste of cycles. The only way I can think of improving this situation is to determine as early as possible whether something will be off screen or not. If it is going to be off screen, then ignore it when doing any further data processing.
In these situations though, you need a way to detect when it moves into view or out of view and either process or not, as appropriate. This may result in some additional overhead that makes it not worth doing.
Your individual situation will determine how effective this can be for you, but if you have a specific example, then users here may be able to assist with re-factoring to help performance.
There are also other things you can do, like re-thinking the visualisation to require less elements in the first place. In my experience performance has not really been an issue until such a point that there is so much information on screen that the value of the visualisation has been diminished. Removing the extraneous information has resulted in improved performance and improved comprehension of the visualisation. Of course, this is my particular experience and there are definitely times when that won't apply.
I am trying to build a network graph (like a network for brain) to display millions of nodes. I would like to know to what extent I can push the d3 js to in terms of adding more network nodes on one graph?
Like for example, http://linkedjazz.org/network/ and http://fatiherikli.github.io/programming-language-network/#foundation:Cappuccino
I am not that familiar with d3.js (though I am a JS dev), I just want to know if d3.js is the right tool to build a massive network visualization (one million nodes +) before I start looking at some other tools.
My requirements are simply: build a interactive web based network visualization that can scale
Doing a little searching myself, I found the following D3 Performance Test.
Be Careful, I locked up a few of my browser tabs trying to push this to the limit.
Some further searching led me to a possible solution where you can pre-render the d3.js charts server side, but I'm not sure this will help depending on your level of interaction desired.
That can be found here.
"Scaling" is not really an abstract question, it's all about how much you want to do and what kind of hardware you have available. You've defined one variable: "millions of nodes". So, the next question is what kind of hardware will this run on? If the answer is "anything that hits my website", the answer is "no, it will not scale". Not with d3 and probably not with anything. Low cost smartphones will not handle millions of nodes. If the answer is "high end workstations" the answer is "maybe".
The only way to know for sure is to take the lowest-end hardware profile you plan to support and test it. Can you guarantee users have access to a 64GB 16 core workstation? An 8GB 2 core laptop? Whatever it is, load up a page with whatever the maximum number of nodes is and sketch in something to simulate the demands of the type of interaction you want and see if it works.
How much d3 scales is very dependent on how you go about using it.
If you use d3 to render lots of svg elements, browsers will start to have performance issues in the upper thousands of elements. You can render up to about 100k elements before the browser crashes, but at that point user interaction is basically useless.
It is possible, however, to render lots and lots of lines or circles with a canvas. In canvas, everything is rendered in a single image file. Rather than creating a new element for each node or line, you draw a line in the image file for it. The downside of this is that animation is a bit more difficult, since you can't move elements in a canvas, only draw on top of a canvas or redraw the whole thing. This isn't impossible, but would be computationally expensive with a million nodes.
Since canvas doesn't have nodes, if you want to use the enter/exit/update paradigm with it, you have to put placeholder elements in the DOM. Here's a good example of how to do that: DOM-to-canvas with D3.
Since the memory costs of canvas don't scale with the number of nodes, it makes for a very scalable solution for large visualizations, but workarounds are required to get it to be interactive.
The 2nd part of the question is, which javascript library is better/easier to manipulate images with? I won't be actually drawing any shapes or anything. Other info: I'll be using jQuery and don't need to support all browsers, just webkit.
Edit:
More information: the current design is to layout/draw several rows/columns of images in a grid-like layout, with the image in the center being in "focus" (a little larger, with a border or something and some text next to it). The tricky thing is that we want the whole canvas of images to appear to slide/glide over to bring another random image into focus. So obviously the number of images in this grid needs to exceed what is visible in the viewport so that when the transition occurs there are always images occupying the canvas. Other than moving the images around, I won't be blurring them or otherwise modifying them. Eventually we will add user interactions like clicking/touching on a visible image to bring it to focus manually.
Let me know if this is not clear or still confusing.
I ran across scripty2 which seems like an alternative to using canvas/SVG for my purposes. I also started farting around with EaselJS last night, and it seems like this might work, but I'm wondering if it'll end up being more work/complex than just using standard HTML/CSS and a tool like Scripty2 to aid with animations and click/touch events. Just looking for any suggestions. Thanks!
The answer depends on your manipulation and animation.
If it's just translations, CSS wins for speed compared to canvas. I haven't tested, but I feel confident it easily beats SVG for the same sort of thing.
If you're going to be doing non-affine transformations or otherwise messing with the images (e.g. blurring them) you clearly want Canvas.
If you need event handlers per object, you clearly want a retained-mode drawing system like SVG or HTML+CSS. I haven't done enough CSS3 transforms to say how they compare in terms of speed to SVG, but they clearly do not have the robust transformation DOM of SVG.
This is a rather subjective question (or suite of questions) and you haven't yet given sufficient information for a clear answer to be possible.