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.
Related
I'm trying to improve my D3 force directed graph's performance. Currently it uses SVG elements but as soon as the number of nodes reaches 500 and links ~ 2000 it becomes almost impossible to use. I'm looking at some alternative ways of rendering the graph.
Canvas seems to be a nice option :
http://bl.ocks.org/mbostock/3180395
But is it possible to attach images to nodes on canvas as it's done here:
http://bl.ocks.org/eesur/be2abfb3155a38be4de4
Thanks
You can use drawImage(). Here's some documentation
And yeah, canvas is a good approach or speeding things up — within reason. The force layout itself takes a bunch of CPU cycles no matter how you render it, and your numbers are already quite high for that. Also, while rendering 500 circles into a canvas at 60fps (fps = frames per second) should be doable, rendering 2000 links in addition will already start slowing things down too. Still, it'll be much better than SVG.
In order to know whether — and how much — your optimizations are improving performance, consider using something like stats.js
I am planning on creating a real-time multiplayer platformer game in HTML5 using javascript. After searching about 4 hours on the webs, i couldn't find an up-to-date answer on the eternal question: rendering my game with DOM will be faster than rendering it inside a canvas? The game will be the whole document. 2/4 players will be jumping on the map and will shoot at each other, bombs will explode. So? What will it be. I remember I made 2 years ago a draw application with DOM and it worked kinda smoothly, but i guess canvas speed is better nowadays? Thank you guys.
P.S. I think of using Dart too.
I use canvas, and would say to do the same since it's a direct drawing mode. However, you should absolutely make sure it is forced into hardware acceleration wherever possible. You do this by setting the style of the <canvas> element into transform:translateZ(0); (or different browser interpretations of that, e.g. -webkit-transform:translateZ(0);). Manipulating the DOM can be slow now that canvas is closer and closer to native code, especially with simple methods to get the most performance out of it.
My games seem to do pretty well on different platforms with this - not universally well on every single platform (older Android OSes lag, but their JS & browser rendering engines weren't that fast to begin with), but quite well on many platforms.
Canvas is the best choice for the type of game you are describing, but some DOM elements are still very useful even using canvas, for example, asking the player's name, or creating a menú or profile section inside the game. You can render a div with absolute position on top of your canvas when you need to display DOM elements, and do all the "game stuff" like drawing and animate sprites in the canvas element.
The reason why Canvas is the best choice is simple. I'm pretty sure that you can't or it would be really hard to do things like this without the canvas element:
http://galloman.github.io/ss2d/samples/skeletons2.html
More at: http://ss2d.wordpress.com/support/
Intent on creating a canvas-based game in javascript I stand before a choice:
Should I performance-wise keep all the stuff happening in the screen in one canvas (all the moving characters, sprites) and redraw it at constant rate of, say, 60 FPS or should I break the scene into several smaller canvases thus removing the need of redundant redrawing of the scene? I could even create separate canvas elements for the characters' limbs and then do most of the animation by simply manipulating the CSS of the given canvas element (rotation, positioning, opacity).
To me the latter sounds way more plausible and easier to implement, but is it also faster? Also, shouldn't I perhaps use SVG, keep the characters and sprites as elements inside of it and manipulate their XML and CSS properties directly?
So what do you think is the most fitting solution to a scene with severals sprites and characters:
One canvas object redrawn manually (and wastefully) at FPS rate
Several canvas elements, redrawn manually in a more reasonable fashion
Structured vector graphics document like SVG / VML manipulated via DOM
I am mainly concerned about the performance differences, but the legibility of the logical code behind is also of interest (I, having already worked with canvas before, am for example fairly sure that the redrawing function for the entire canvas would be one hard-to-maintain beast of a script).
DOM manipulations are slow in comparison to GPU-accelerated canvas operations, so I would stay away from SVG and VML.
As far as structuring your canvas code goes, it certainly doesn't make sense (especially for performance reasons) to clear and re-draw the entire canvas because the player moved or performed an action. Based on your description here, I'm guessing that your game will be 2D. These types of games lend themselves extremely well to layering unless you're doing something rather complex like Paper Mario. You should be looking at the issue from an object-oriented viewpoint and encapsulating your drawing procedures and objects together as appropriate.
For instance, create a player object that maintains a small canvas representing the character. All the logic needed to maintain the character's state is kept within the object and any changes made to it need not worry about other components of the game's visual representation. Likewise, do the same for the background, user interface, and anything else you can abstract into a layer (within reason). For example, if you're doing a parallax game, you might have a foreground, background, character, and user interface layer.
Ultimately you will need to maintain the state of the different components in your game individually. Player animations, background clouds moving, trees swaying, etc. will all be managed by appropriate objects. Since you will already have that type of code structure setup, it makes sense to just maintain major components on separate canvas elements and composite them together as needed for better performance. If the character moves in the bottom left corner of a scene with a static background, you don't need to re-draw the top right corner (or 95% of the scene, for that matter). If you're considering full-screen capabilities, this is definitely a performance concern.
There's a rule in programming, that you should never try and optimize something before you have a speed problem with it. You'll spend more time trying to figure out how to code something in the best way than to actually code, and will never finish anything.
Draw them all on your canvas at a fixed rate. That's how it's done. If you start creating a canvas for each limb and element and manipulate them using CSS, you're wasting the potential of canvas. Might as well just use images. That's how they did it before canvas. That's the problem canvas was made to solve.
If you ever encounter speed issues, then you can start hammering at them. Check out these slides for some tips (related video). This guy's blog also has some handy tips on canvas performance.
1.) I found a canvas API called EaselJS, it does an amazing job of creating a display list for each elements you draw. They essentially become individually recognizable objects on the canvas (on one single canvas)
2.) Then I saw on http://simonsarris.com/ about this tutorial that can do drag and drop, it makes use of a hidden canvas concept for selection.
3.) And the third approach, a working approach, http://www.lucidchart.com/ , which is exactly what I'm trying to achieve, basically have every single shape on a different canvas, and use to position them. There's a huge amount of canvas.
The question is, what is the easiest way to achieve interactive network diagram as seen on http://www.lucidchart.com/
A side question is, is it better to get text input through positioning on canvas or using multiple canvas (one for rendering text) as in LucidChart
I'm the person who made the tutorials in 2. There's a lot going on here, so I'll try to explain a bit.
I use a hidden canvas for selection simply because it is easy to learn and will work for ANY kind of object (text, complex paths, rectangles, semi-transparent images). In the real diagramming library that I am writing, I don't do anything of the sort, instead I use a lot of math to determine selection. The hidden-canvas method is fine for less than 1000 objects, but eventually performance starts to suffer.
Lucidchart actually uses more than one canvas per object. And it doesn't just have them in memory, they are all there the DOM. This is an organizational choice on their part, a pretty weird one in my opinion. SVG might have made their work a lot easier if thats what they are going to do, as if seems they are doing a lot of footwork just to be able to emulate how SVG works a bit. There aren't too many good reasons to have so many canvases in the DOM if you can avoid it.
It seems to me that the advantage of them doing it that way is that if they have 10,000 objects, when you click, you only have to look at the one (small) canvas that is clicked for selection testing, instead of the entire canvas. So they did it to make their selection code a little shorter. I'd much rather only have one canvas in the DOM; their way seems needlessly messy. The point of canvas is to have a fast rendering surface instead of a thousand divs representing objects. But they just made a thousand canvases.
Anyway, to answer your question, the "easiest" way to achieve interactive network diagrams like lucidchart is to either use a library or use SVG (or an SVG library). Unfortunately there aren't too many yet. Getting all the functionality yourself in Canvas is hard but certainly doable, and will afford you better performance than SVG, especially if you plan on having more than 5,000 objects in your diagrams. Starting with EaselJS for now isn't too bad of an idea, though you'll probably find yourself modifying more and more of it as you get deeper into your project.
I am making one such interactive canvas diagramming library for Northwoods Software, but it won't be done for a few more months.
To answer the question that is sort-of in your title: The fastest method of doing interactiveness such as hit-testing is using math. Any high-performance canvas library with the features to support a lot of different types of objects will end up implementing functions like getNearestIntersectionPoint, getIntersectionsOnRect, pathContainsPoint, and so on.
As for your side question, it is my opinion that creating a text field on top of the canvas when a user wants to change text and then destroying it when the user is done entering text is the most intuitive-feeling way to get text input. Of course you need to make sure the field is positioned correctly over the text you are editing and that the font and font sizes are the same for a consistent feel.
Best of luck with your project. Let me know how it goes.
Using SVG (and maybe libraries as Raphael)!!
Then any element can receive mouse events.
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.