I have a D3 setup using "Nodes" and "Lines". When the graph first appears, it bounces in with gravity until it settles in the middle. Does anyone know of a way to have it appear automatically in the middle without the "bounce" sort of effect?
P.S I am using force layout
Calling start resets the cooling parameter, alpha; alpha decays exponentially as the layout converges on its solution, and then stops so as to avoid wasting the cpu. There's no jittering on start (other than coincident nodes, which is necessary to avoid a divide by zero). However, anytime you have conflicting forces and geometric constraints (links), it's natural to expect the layout to adjust when starting.
If you want to avoid this bounce, you either need to keep the graph permanently hot (say by calling d3.timer(function() { force.resume(); })) or you'd need to do something else, like adjust the alpha parameter manually to reheat gradually instead of instantaneously.
Edit: In 2.8.x, you can avoid the first bounce entirely by running the force layout synchronously on startup. For example: http://bl.ocks.org/1667139
Another strategy I've used before is to gradually increase the radii of each node from zero over the first, say, 50 or 100 force ticks. You can see what that looks like (in Protovis, but it would behave the same way in d3) in the Dorling cartograms on the one.org data site.
Related
I'm attempting to render a scrolling axis at 60 fps. It was nearly as simple as updating the scale's domain and calling axisGroupElement.call(axis) inside a loop. Unfortunately at different scales that produces some very smooth animations where the ticks and the text will jiggle.
http://jsfiddle.net/langdonx/fTcrU/11/
The jiggling probably depends on the width of the container and the length of the scale's domain... try changing the drop down for different results.
So, I thought I'd be creative and render the axis 3 times the size I needed and transform the entire group for a smoother scroll. That unfortunately produces nearly the same results.
I went a step further and moved the entire SVG element, which is a little smoother, but a huge hack.
There's also a problem where I can't get my own transform scrolling at the same rate the redraw scrolls at. It seems to fall behind over time. I thought I had it nailed down by calculating milliseconds per pixel, but that doesn't appear to be totally correct. It's interesting to see how it certain resolutions it'll tick along at 1px, store the remaining milliseconds, and then some ticks will adjust it 2px.
Is there anything I can do or is scrolling these irregular widths/time spans always going to produce animations that aren't smooth?
TIA!
The axis redraw example looks nicer because it sets the transform values more exactly as floating point numbers, whereas your calculation for transform produces integers.
I've amended your algorithm to produce floats, and now the "Redraw" and "Redraw and Transform" examples look identical.
http://jsfiddle.net/xJJHM/1/
The relevant change is
_left -= msPassed / _msPerPixel;
I tried to do the same with the left-positioning, but it turns out that you need integer values for that.
I found an article/video by Paul Irish which explains this in more detail: http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
I wanted to produce a visualization that contains a good deal of nodes with the d3 force layout (more than 500 hundred nodes). While it is working correctly with as much as 200 hundred nodes it gets very slow with about 500, in the sense that the layout hiccups from one frame to the next and events like mouseover on nodes are far from being responsive. This made me ask several questions.
Is there some kind of limit in the number of nodes after which it is not recommended to use the force layout ? If so, is there any other library that could handle the job ?
If I wanted to speed up the process with d3, which parts should be optimized ? I tried keeping the use of css/attributes markup minimal (just gave a radius and a fill color to nodes + stroke-width and stroke color to links) and reduce the use of interaction (mouseover events) but could there be any more optimization done to the force object which holds all of the information ? The size of data must play a certain role...
Thank you for your input !
One way of doing this would be to handle not every tick event, but only a fraction of them, e.g. skipping a specified number or dynamically adapting the number of events depending on other considerations.
If you want smooth movements, add a transition between the positions set in the handled tick events. You can of course combine these ideas as well and skip events while the transition is running, handling the first one after it has been completed.
I've seen this "The Scale of the Universe 2" and I just want to know if this can be done with javascript or jQuery or with HTML5 Canvas.
If you click an item (example the "Human") , an info will pop out beside it.
I searched for 3 days here if someone has a similar question. But I only saw Google Map like behavior where you can zoom in on the map cursor position.
Actually I want to make a "Timeline" like effect or, like the "Time Machine" Recovery on Mac OS X.
Fixed position of zoom. Not like a google map zoom, that you can pan and zoom anywhere.
Can I put (example "The human") images and text on a div?
Are there available articles/tutorials about this?
Options:
Javascript
jQuery
HTML5 Canvas and CSS3 Transform and scrolling it to Z-axis so you can zoom in/out.
Flash/Flex (Well I don't want to use lots of resources on CPU because I need it in a large resolution or in full screen.
It is possible to implement an infinite zoom in HTML canvas, this is the source code of a proof of concept that I implemented and here you can test it live.
It is actually quite tricky to implement, and most probably you'll need to use big decimals.
The approach I followed uses the same coordinate space as d3-zoom. Basically, you have three coordinates, x, y and k. K is the zoom. If k is 2 it means that you have doubled everything.
Now, if you want to do infinite zoom, it is very easy to reach k = 64, but that is already outside of float64 precision and you'll have a lot of artifacts, where translating in the image is not smooth, or you don't zoom in where you want.
One way to avoid those artifacts is to use coordinates that have infinite length, for example BigIntegers. To make my implementation easy and compatible with d3-zoom, I used big decimals instead, but I had to implement my own library of BigDecimals, basically infinite precission on the integer part and 32bits of precision on the decimal part. Of course, you also need to adapt the zooming library to support BigDecimals. Moreover, in the case of d3-zoom, a lot of calculations where done in the initial coordinate space (k=1) but division of floats will always have an error and it is also perceivable once you are deep enough. To avoid that you need to do all computations locally.
It might sound like a lot of hassle to insist on using the d3-zoom library, but zooming UX is actually tricky, specially if you combine that at different k, you'll need to consider scrolling, zooming on the phone, double tapping...
In case you want to use SVG transformations, then you'll need to fake it. You'll introduce nodes when they are barely visible, allow to scale them. However, most probably you'll also need to fake it when they are too big to avoid artifacts there.
There is no infinite zoom. However you can zoom in/out of an SVG image in HTML5 canvas.
SVG supports affine tranformation. You can set the required zoom/pan in the affine transform and show the relavant areas. The behavior/listener can be implemented in Javascript and the SVG can be rendered on HTML5 canvas.
As a starting point you can look at this example: http://www.html5canvastutorials.com/labs/html5-canvas-scaling-a-drawing-with-plus-and-minus-buttons/
This is totally doable in HTML5. Actually, any system able to display and zoom images should be able to. It's not one big image being zoomed, it's a big amount of images being zoomed (for instance the initial human is an image, which is scaled and moved out when you zoom in or out). The idea is splendid, but I don't really see any technical performance in it. As long as you correctly limit the number of images being resized and bitmapped, it should keep a decent FPS rate.
I'm trying to record exactly where the mouse moves on a web page (to the pixel). I have the following code, but there are gaps in the resulting data.
var mouse = new Array();
$("html").mousemove(function(e){
mouse.push(e.pageX + "," + e.pageY);
});
But, when I look at the data that is recorded, this is an example of what I see.
76,2 //start x,y
78,5 //moved right two pixels, down three pixels
78,8 //moved down three pixels
This would preferably look more like:
76,2 //start x,y
77,3 //missing
78,4 //missing
78,5 //moved right two pixels, down three pixels
78,6 //missing
78,7 //missing
78,8 //moved down three pixels
Is there a better way to store pixel by pixel mouse movement data? Are my goals too unrealistic for a web page?
You can only save that information as fast as it's given to you. The mousemove events fires at a rate that is determined by the browser, usually topping at 60hz. Since you can certainly move your pointer faster than 60px/second, you won't be able to fill in the blanks unless you do some kind of interpolation.
That sounds like a good idea to me, imagine the hassle (and performance drag) of having 1920 mousemove events firing at once when you jump the mouse to the other side of the screen - and I don't even think the mouse itself polls fast enough, gaming mice don't go further than 1000hz.
See a live framerate test here: http://jsbin.com/ucevar/
On the interpolation, see this question that implements the Bresenham's line algorithm which you can use to find the missing points. This is a hard problem, the PenUltimate app for the iPad implements some amazing interpolation that makes line drawings look completely natural and fluid, but there is nothing about it on the web.
As for storing the data, just push an array of [x,y] instead of a string. A slow event handler function will also slow down the refresh rate, since events will be dropped when left behind.
The mouse doesn't exist at every pixel when you move it. During the update cycle, it actually jumps from point to point in a smooth manner, so to the eye it looks like it hits every point in between, when in fact it just skips around willy-nilly.
I'd recommend just storing the points where the mouse move event was registered. Each interval between two points creates a line, which can be used for whatever it is you need it for.
And, as far as processing efficiency goes...
Processing efficiency is going to depend on a number of factors. What browser is being used, how much memory the computer has, how well the code is optimized for the data-structure, etc.
Rather than prematurely optimize, write the program and then benchmark the slow parts to find out where your bottlenecks are.
I'd probably create a custom Point object with a bunch of functions on the prototype and see how it performs
if that bogs down too much, I'd switch to using object literals with x and y set.
If that bogs down, I'd switch to using two arrays, one for x and one for y and make sure to always set x and y values together.
If that bogs down, I'd try something new.
goto 4
Is there a better way to store pixel by pixel mouse movement data?
What are your criteria for "better"?
Are my goals too unrealistic for a web page?
If your goal is to store a new point each time the cursor enters a new pixel, yes. Also note that browser pixels don't necessarily map 1:1 to screen pixels, especially in the case of CRT monitors where they almost certainly don't.
I am creating a platform game in JavaScript using canvas which is entirely tile-based. What is the best method of storing the blocks of items in the game (walls, floors, items)? The thing is every tile can be destroyed or created.
Currently I have a 2D array so I am able to quickly check if an item is at a specific X & Y position. The problem with this is when the user moves and the map needs to scroll, I need to reassign every block. And what happens when the item is at x = 0? I can't use negative indexes.
I would rather the scrolling analogue as aposed to a tile at a time. Also I plan on randomly generating maps as the user moves and if it hasn't previously been generated. So once something is generated, it should stay that way forever.
Another point I should mention is that it will also be multiplayer. So chunking the screen is a great idea until the cached data becomes dirty and needs to get the latest from the database. Gah I'm so new to all this; seems impossible, any help is greatly appreciated.
Since you have infinite levels I'd suggest a structure similar to what you already have, with a slight tweak.
Instead of storing everything in one big array, and moving stuff around inside that array every time the user moves (ouch) instead store 9 chunks of map (each one a size such that it's roughly twice the size of the screen), when the user approaches the edge of the current chunk, dispose the chunks which are offscreen, move all the chunks left, and load new ones into the gap.
Hopefully that was clear, but just in case, here's a diagram:
The lettered squares are the chunks of map, and the red square is the viewport (I drew it slightly too large, remember the viewport is smaller than the black squares). As the viewport moves right, you unload chunks A B and C, move all the others left, and load new data into the right most ones. Since a chunk is twice the width of the screen, you have the time it takes the user to cross the screen to generate/load the level into those chunks. If the user moves around the world fast, you can have a 4x4 set of chunks for extra buffering.
To address the returning to previous chunks of map. there are a couple of ways to do that:
Write out the chunks to hard disk when they're no longer in use (or whatever the equivalent would be in javascript)
Expand your chunk set infinitely in memory. Rather than an array of chunks have an assosciative array which takes x/y position of the chunk, and returns the chunk (or null, which indicates that the user has never been here before and you need to generate it).
Procedurally generate your levels, that's complex but means that once a chunk goes off screen you can just dispose it, and be confident you can regenerate exactly the same chunk again later
There are obviously lots of ways to do this.
If they levels aren't too large, you can keep your original design of a 2d array and use a variable to store the current x/y scroll position. This means that you store all of the map information in memory at all times, and only access the parts you need to display on the screen.
When painting you work out which tile is visible at current scroll position x/y, how many tiles fit on the screen with the current screen width and only paint the ones you need.
If you scroll whole tiles at a time, then its pretty easy. If its a more analog scrolling, you will need some finer grain control of where in the tile you start drawing, or you can cheat and draw the whole set of tiles to an in memory bitmap and then blit that to the drawing canvas with an negative offset.
I once defined this very thing in XML and JSON... I think the JSON serialization would be alot faster and more efficient (not to mention easy) to work with in JavaScript, especially since JSON lends itself so well to variable length lists as you would require for "N" levels in each game.
Using a standard format would also make it more reusable and (ideally) encourage more collaboration (if that's what you're looking for). You can check out my first attempt to create a Video Game schema for level structure.
As fileoffset says, there are many ways to do it, but I highly suggest keeping your level data (i.e. concepts) separate from your rendering (i.e. objects in motion, paths, speed, timing, x/y/z co-ordinate positioning, etc...).
Again, as the article said that area is the most quickly changing, and there's no telling if WebGL, SMIL+SVG, Canvas+Javascript, good ol' Flash/Actionscript or something else will be the best route for you, depending on your needs and the type of game you are developing.