In the past I've done quite a bit in javascript, including some DOM manipulation.
From there I've learned that reflows/repaints can be a big performance issue in some cases, and should generally be limited to a minimum. Like for example when adding a group of divs you should add all at once (attach them to a div outside of the DOM, then attach that) rather than attaching them one-by-one. The same goes for repaints, which can be triggered by changing CSS properties of an element. Though I must admit I have never looked into repaints that much, so I might be wrong about that last part.
Does this also apply to SVG (seeing it uses a kind of DOM it seems plausible)? And is there a difference for different SVG elements? For example it would make sense that an animation element doesn't create a reflow since it isn't a new SVG element, but more like a property.
Something I'm not sure about are repaints for SVG, do they even exist the same way they do for CSS/HTML? After all SMIL animations already create frames, so a thing like a "repaint" might not make any difference, since the new frame was going to be rendered anyways.
Anyone with a deeper understanding of the inner workings of SMIL who could clarify these things for me?
Your information is out of date. UAs batch up reflows these days so that you don't need to attach divs outside the DOM any more.
SVG doesn't really have reflows as it's basically all absolutely positioned so changing the position of one element only has an effect on that element and any descendants. SVG DOM changes just cause repaints. Sometimes even repaints are not necessary if the appropriate data is in graphics memory, for instand translate transforms are often handled almost entirely by the graphics hardware renderer without repainting these days. SMIL animation is also hooked into this mechanism.
If SVG content has a translate attribute it is stored in a separate layer. Layers can be updated without rerendering in many cases e.g. translation as graphics system can just draw the layers where they need to go.
There's more documentation about how this works in Firefox here but other UAs work in a similar fashion.
Related
I'm working on a web app; one of it's design requirements is several large CSS3 animations.
Specifically - it have a large <div> that will be transitioned around the screen in response to user input.
Because of the way the app is designed, the "content" of that <div> could be implemented as a large static graphic (e.g., .jpg or .png) set as the <div>'s background.
Or, the content could also be implemented with standard HTML. (The content layout itself is a "little" tricky - it'd require several floated or positioned nested div elements and spans, but nothing crazy.)
My question is - which option is likely to result in the best (smoothest) animations?
(I can obviously test this myself, but it's often hard to judge the smoothness of an animation, especially across a dozen different browsers on a wide range of devices. I also realize that there are other considerations - e.g., maintenance. But in this case, I'm focused entirely on animation performance.)
I'm wondering if browsers are generally better at animating/rendering simple DOM elements WITH graphic backgrounds, or more complex DOM elements (with lots of children) WITHOUT graphic elements?
Also - are there other guidelines? E.g.,
Do browsers animate certain types of graphic elements better than others? (E.g., .png vs .jpg)
Do browsers animate an element better when it's child elements have position:absolute, when the child elements are floated, or when the child element's positions are determined by the regular document flow?
Do things like opacity, drop-shadow, or 3D transforms on nested elements adversely impact animation of the parent element?
Does animation performance degrade in relation to the complexity of the element? E.g., does an element with a dozen levels of nested DOM elements animation less smoothly than a simple element with just a text node?
I have an intuition about these things (deeply nested DOM elements will animate less smoothly than a simple element), but my intuition is often wrong. So, I'm wondering if there are "rules" about what's more or less work for the browser.
What else should I consider when large elements with lots of child elements are animated?
Your answers will depend on the specific rendering strategy used by each implementation, but if you are OK with using WebKit's strategy as the "general" strategy then all your answers lie in this document:
http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
First a "RenderObject" clone of the DOM Tree is created
After this, the tree is traversed and each RenderObject is either incorporated into the RenderLayer of their closest ancestor
OR into a new RenderLayer if one of these is true about the RenderObject:
It's the root object for the page
It has explicit CSS position properties (relative, absolute or a transform)
It is transparent
Has overflow, an alpha mask or reflection
Has a CSS filter
Corresponds to <canvas> element that has a 3D (WebGL) context or an accelerated 2D context
Corresponds to a <video> element
After this, the tree is traversed and each RenderLayer is either incorporated into the GraphicsLayer of their closest ancestor
OR into a new GraphicsLayer if one of these is true about the RenderLayer:
Layer has 3D or perspective transform CSS properties
Layer is used by <video> element using accelerated video decoding
Layer is used by a <canvas> element with a 3D context or accelerated 2D context
Layer is used for a composited plugin
Layer uses a CSS animation for its opacity or uses an animated webkit transform
Layer uses accelerated CSS filters
Layer has a descendant that is a compositing layer
Layer has a sibling with a lower z-index which has a compositing layer (in other words the layer is rendered on top of a composited layer)
So knowing how this generally works and going on a hunch here I would have to say first minimize things that lead to the creation of a new GraphicsLayer then after that minimize things that lead to the creation of a new RenderLayer. You can probably get away with a good amount of DOM node nesting or whatever you were talking about as long as the extra nodes aren't leading to creations of new RenderLayers or GraphicsLayers.
Also regarding your idea about sending over bitmap images of DOM element vectors instead of the vectors themselves. I really doubt it would faster. It just doesn't make any sense to me that a PNG or a JPEG would somehow be a more efficient way to represent DOM nodes than vectors. But hey I didn't code Webkit so I guess the only way to really know is to profile it.
I'm implementing a HTML5 game using canvas. Now I'm thinking about making all text overlays like tooltips, speechbubbles, infowindows and so on using HTML elements with position absolute over the canvas. So I can use many effects and transitions CSS3 offers.
But I'm not sure about performance. These overlays have to be added and removed frecuently (is something MMORPG like, so there will be a lot of speechbubbles and so on).
There are probably 2 questions regarding performance:
DOM traversal to add/remove. Maybe a cache can help?
HTML and CSS3 itself.
The other option is to manage these elements in the canvas itself, drawing them each frame. But maybe I have then again a performance penalty, because of the extra code, timeouts and stuff I would have to add, to achieve similar effects like in CSS3. And traversal of some data structure would be needed anyways.
Any advices, opinions, experiences?
Thanks in advance.
Consider using only one of the mentioned two technology. May be you can release that application in mobile or tablet. I think on these devices would be issues with handling both the same time. And another thing: if you stay in canvas there would be no worries about compatibility. Its not a techy but a thought-provoking answer.
The single best reason for using the DOM for UI elements in HTML5 games is event handling.
If you draw everything on canvas you will need to write your own logic to handle clicks and decide what has been clicked on, which can soon become very complex, expecialy if you have multiple layers of interface.
With DOM elements (especially when using a library like jQuery) this is trivial, and you can create a rich and interactive UI with minimal effort.
The only downside I can think of is that you may encounter browser inconsistencies, especially if using CSS3, but again jQuery will help with this.
I suppose another downside is that once you go down the DOM route, your game is always going to be a browser game, whereas if it was 100% canvas, there would always be the possibility of porting the code to another language and making it native, but I guess that would only be a downside for some people.
One way to approach this is to use a "dynamic" image map behind your canvas object. Then you can use the dom as required. Note you will need to pass the clicks on the canvas through to the image map.
Bit of background
I've been producing a Flash-driven webcomic for three years now, incorporating some basic animation, a synced soundtrack and zoom-drag page viewing. The recent Flash-bashing, my desire to reach iHandhelds and my preference for open versus proprietary means that I want to make the move to HTML5 techniques this year. In the long-term, I think the writing's on the wall for Adobe's product, and I'm not entirely convinced that's a bad thing.
I'm relatively comfortably with both CSS and HTML, having worked a little in web design before. However, JavaScript is a foreign country to me, and I simply wanted to get some advice as to
whether what I want to achieve can be accomplished consistently across all browsers and
what the best techniques/approaches to the problem would be.
Any advice, even general principles, are very welcome. I've already sought out several HTML5 tutorials and introductions, which lead me to believe that the canvas element will be foundational to my plan; however while all the individual problems I face have been answered by many blogposts and guides, combining the various solutions into a single entity is something I'm not currently able to figure out, as I'm not certain of the limitations of the new HTML5 tags, or of best practice.
If I'm successful in achieving what I'm after, I'm going to post the full code online with an explanation of all the elements. Webcomics might not be a huge domain, but having a resource that did this would have made my life a lot easier - hopefully it'll help someone else in a similar position.
What I'm after
Here's a diagram giving the basics of the design requirements. I'll explain the elements, and the desired extras, below.
(Perhaps the simplest way to demonstrate what I'm after would be for interested folks head over to my website and see how my comic currently works. This isn't a plug - it would simply give the quickest insight.)
At core, I'm after a viewer that will:
display text (SVG image) in a canvas element above an raster image the page's panel art
both images should be zoom-and-draggable in sync but should ideally fade in separately, with the raster image coming first, followed by the SVG image
I'm guessing that the best way to accomplish this would be to layer two canvas elements one above the other using z-index, with the SVG file in the uppermost element. These could then be nested, as in the diagram, within a div element that would carry the zoom-drag function. Is this a reasonable approach, or are there more efficient options?
The next and previous buttons are self-explanatory. Would it best to have each page (bearing in mind some will involve animation and music) on a separate page, or to have all pages within a chapter on a single page, with the buttons making them visible progressively? I imagine this would have a great impact on loading speeds.
Finally, I'd like to have the viewer capable of displaying fullscreen if the reader desires. I imagine this could be accomplished by using Javascript to make the canvas elements and their surrounding div switch between different CSS giving a px-defined size and 100% height and width. Is this a good approach? Is it possible to apply the size change to the div element only and have the canvas elements automatically follow suit, possibly by defining their size via % in CSS?
Desired extras
At various points in the comic I make use of basic animation techniques - simple movements of layered raster images across the viewing pane. This would be simple to accomplish, I imagine, using Javascript; am I correct in thinking that applying overflow:hidden to the wrapping div will prevent images larger than the viewing area from spilling outside the viewer area?
I also want to synchronise audio with some of these animations. I understand that synchronising canvas events with the audio would be the best way to do this on, permitting both to begin activity only upon page loading or next button click.
That's about everything. As said, any advice at whatever level would be greatly appreciated, even if it's 'yes' or 'no' to the various questions I've asked. At root, it would also be good to know if HTML5 is the best option for what I'm after or whether (with gritted teeth) I should stick to Flash for now and go after handhelds using Adobe AIR.
What is the correct approach if you plan to implement a (complex, interactive) network diagramm in "HTML5", which is part of a modelling tool - for example to let the user design a workflow?
Is SVG the right approach or using directly Javascript/Canvas?. Is there any productive application out there, which has proved that this is doable in HTML5 (the network model can be quite complex), especially regarding performance?
I do not need any implementation details, just a hint to the 'correct' technology if you would be 'forced' to do this in HTML5...
Thanks.
svg now has support from ie9. canvas is supported in most modern browsers and css is supported by all.
svg has the advantage of beeing scalable (the 'image' is a vector map, so the user can have it in every size he prefers), but the performance of beeing rendered is a bit crappy. You can bind some events to the elements..
canvas is like GDLib or ImageMagick, you have a white sheet, where you can plot onto. So if you do a change, you first have to clear the canvas and redraw everything. You don't know onto what element a user has clicked onto and only can bind events generally for the whole canvas element.
Using HTML and the DOM with CSS would be an alternative, since you just could start moving elements of the network arround and can bind events to nodes of your network. But lines are quite hard to implement (can use a rotated div with top-border)
I personally would go for a hybrid between svg and plain html, but then again, I don't know every use-case of your application.
I'm developing a web application that has a certain layout.
I'm mainly using CSS for styling the buttons and using divs and styling them for other layout items.
The problem is that sometimes I need a layout item to be non-rectangular.
Also- designing SVG is easeer and sometimes may produce better results.
My question is: should I use CSS always for the layout, and for instance- combine divs to achieve the non-rectangular effect- or should I use SVG for some of the layout items?
Also- what about the buttons- CSS or SVG?
Thanks!
Bear in mind that SVG isn't supported in older browsers. In particular, in IE8 and earlier. Using SVG will therefore limit your audience.
It is possible to rig older versions of IE to support SVG - there are a number of Javascript libraries which can convert SVG into VML, which was Microsoft's proprietary alternative to SVG. However, this does mean you're running Javascript code unnecessarily; you could cause performance issues in IE, or worse, it could load slow enough that the layout redraws after its loaded.
Therefore, for cross-browser compatiblity reasons, I would suggest not using SVG for your basic page layout.
Where I would use SVG is for graphs and charts, etc. For these, I would use the Raphael javascript library, which makes drawing SVG very easy, and also renders it as VML in IE, without you having to do any explicit conversion.
For creating non-square elements in CSS, there is a hack which uses the CSS borders to draw triangles and other shapes. This works in all browsers (with some minor caveats in IE6), so is great for creating spot-effects like marker arrows and speech bubbles.
See http://jonrohan.me/guide/css/creating-triangles-in-css/ for more info on this.
Great for spot effects, but should stress that I wouldn't recommend it for complex shapes; I have seen some people drawing entire pictures using it -- see http://www.cssplay.co.uk/menu/fivestar and other hacks on the same site -- but as I say, I wouldn't suggest actually doing this, except just to demo a hack like this guy.
Hope that helps.
[EDIT]
Per the OP's comments, he only wants to add a rectangular protruding part to a larger rectangular <div>, so in fact the shape he's trying to create isn't all that complex after all; in fact, it sounds a lot like a tab. Given this, the best recommendation by far is to forget about drawing it with SVG, and simply create two divs: one for the main content and one for the tab. If necessary, a third div can be created to wrap the other two. This may be helpful for referencing the two others together via CSS or Javascript.
I tend to advise you not using SVG for the layout, it's not really its purpose. It's best suited for diagrams, pictograms, charts or maps etc.
using SVG will have disavantages:
-First, support: IE<9 doesnt support SVG, or you'd need an external plugin.
-Integration: it's easy to have SVG inside HTML, but emmbeding HTML in SVG is quite unpractical.
-flow in layout: you can draw shapes easily, but placing blocks/text has to be done manually. in html two consecutive blocks will be displayed one below the second. In SVG you have to place them absolutely, ensure text inside them isn't too long cause their size won't adjust automatically.
I'm almost sure it would be easier to layout with HTML+CSS. And now with CSS3 you can rotate blocks, round borders, cast shadow. I would like to know which particular layout cause you problems.
We are in 2017 now, I belive that all major browsers support SVG.
So I would say SVG is a good option. You will probably need to use JavaScript to adjust elements on the screen and make them responsive, because SVG does not provide things such as flexbox, tables, float, etc. The advantage with that is that you will have more flexibility and will not have to deal with the limitations and side effects of CSS.