I am using CSS animations to move two rectangle div tags across the screen. Each one is like a pole (taller than it is wide). The animations make each div rotate so it is at an angle before going back to pointing upwards.
One animation is triggered by the user, and the other is constantly moving itself towards the other div.
I have tried using getBoundingClientRect() to detect when the corner of one div intercepts the div that is moving towards it. I also used jQuery to get the .position() of them, but they return left: 0.
The div that is moving across the screen is done using the margin-left property.
Are there any methods I should be looking into or does anyone have a solution to a similar problem?
Thanks,
DH
You should use transform: translate to move them.
Also, since you're moving the elements in javascript you should just keep their state stored in memory and do your collision detection entirely in javascript.
There should be no need to use DOM APIs for this.
There's no method on the DOM for you to be able to detect overlapping objects. I would suggest using a geometric model of the scene and doing the trigonometry yourself to see when there is an intersection between the two boxes. Animating your objects explicitly using JS is also easier, since you wouldn't have to worry about getting out of sync with the browser's CSS animations or transitions.
You'd basically be looking for a line-line intersection.
Related
Introductory information:
I've made a fixed menu button to show the navigation menu when using a mobile device. For this application I'm using the Headroom.js script to make the button smaller when scrolling downwards to ensure that it doesn't block too much of the content. The animation/transition is applied by adding a class with the given changes.
In the original method i changed the size and look of the button by changing height/width of the parent element and padding of the child element with CSS (and css transition).
The new method, which I've read could/should be better according to various sites, is changing the size of the button by using transform: scale(). Note that i'm also moving the element a bit by also applying translate3d(20px,20px,0) in this method. However, it feels a bit smoother when scrolling using the transform: scale() method (could be a placebo effect though), but using chrome dev tools' timeline gives me seemingly inconclusive results.
Therefore a part of my question is also how I should evaluate the best method. Is timeline in Chrome Dev tools the best option, or is there a better way to do it? And which elements of the timeline should I base my choices on? and the other thing is, based on your interpretation of the images and/or tests combined with your knowledge, which method performs the best (or should perform the best in theory)?
Beneath you can see two examples of the timeline with each method.
Changing height/width and padding (original method):
Method using transform: scale() to change the size:
Also you can try the different methods in fiddles here:
link: Original method changing height/width and padding
link to new method: using transform:scale
Please ignore the poor layout of everything; especially the button. The ugly image inside the menu button is just to show, that there's an image included in the layout on my own page and to take that into performance considerations. The images in the back is also included since it's a webshop with a lot of images which could influence performance.
CSS for added class that makes the changes in the original method:
.mobile-nav.headroom--unpinned {
height: 40px;
width: 40px;
}
.headroom--unpinned .mobile-content{
padding-top:4px;
}
CSS for the added class using transform:scale():
.mobile-nav.headroom--unpinned {
transform:scale(.5) translate3d(20px,20px,0);
}
So to summarize my questions:
How do I evaluate which methods has the best performance, and which method would you say performs the best?
A final note: I know that the methods are different (animating different things and more elements in the original method) but these are the 2 options which i prefer as it is right now.
I believe you are missing the point, Chris: the reason why no other property but transform and opacity should ever be animated is because they don't trigger a repaint in anything else, even if the element is in the document flow (and because you can basically do anything with these two alone in like 95% of the cases).
From the "hit-on-performance" point of view, there are two types of animations:
those that trigger a repaint in other elements than the animated element
those that do not.
That's the main reason behind recommending animations by transform, opacity or position:relative;left|right|top|left. Because they don't actually move the element in flow, thus not triggering a repaint to every single other element in flow after the one being animated.
Now, if the said parent was positioned absolute (which I assume to be the case), it wouldn't have triggered a repaint to the rest of DOM anyway so the differences between that method and transform would have been minor. Inconclusive, as you put it. In theory, repainting two elements instead of one should be slower.
If you need to test, make 10k clones and trigger animation on all of them, with each method.
That will be conclusive.
If you really want to min-max this (as in spend absurd amounts of time on hardly noticeable improvements, as I do) you will find plenty of resources that will recommend:
replacing any .animate() with .velocity()
never animating anything but transform or opacity, although Velocity claims they animate anything without a hit on performance (i find that debatable/arguable, at best) - but it's a net improvement over .animate()
sticking to CSS transitions, if possible (basically if you don't need chains)
using Web Animations API
Personal advice: never count on synced CSS animations, especially when you have many of them. If you change tabs or the system does something extremely resource heavy for a while, your animations will be way off. If you need chains, chain.
I'm looking for the best way to animate several divs onscreen. I tried jQuery, but it started getting skippy after I had > 5 elements on the screen. Raphael.js gave me the same problem. So, what is the best way to animate 5-6 divs on a screen at once? They're just moving horizontally across the screen.
Would CSS3's translate2d be good for this? I recall reading somewhere that you can severely optimize performance by using translate3d instead. Is that applicable in my case?
If your target browsers support CSS3, you can achieve much smoother animations using translate2d. If you need to animate all items together (i.e. the animation rules are the same for each one of them), you can just create a class
.animTarget{animation:translate3d(100, 0, 0)}
And then in your javascript code, say:
$("animation-target-selector").addClass('animTarget')
I have found that animating things like this is easier than doing something like:
$("animation-target-selector").css('animation', 'translate3d(100, 100, 0)');
Because it adds it to the style attribute of each and every dom element.
I'm creating a slider puzzle, I've got each section of the image in it's own ap div, each with the same z-index. I've restricted the drag movement to within the confines of the puzzle, but the ap divs are overlapping when I drag them. I was hoping the same z-index would prevent them from overlapping, but when I drag, they overlap. How can I prevent them from overlapping? I'm using HTML, CSS, and JavaScript. Any thoughts?
No, there is no way to prevent them from overlapping using the standard drag-and-drop facilities found in popular libraries like Dojo or jQuery. They're supposed to overlap; it's supposed to allow you to drop. At best, these libraries support borders you cannot cross, a bounding box for the drag operation. For your code, which sounds more complex, you will need to examine the bounding box code, write your own collision detection code for all the objects in your game's region, and incorporate that into the drag operation.
Setting the z-index has no effect on this. Browsers automagically adjust the z-index (often fractionally) to allow overlapping when needed.
Hello Heather body..
Please look at these websites,
<http://www.webreference.com/authoring/style/sheets/page_structuring2/>
<http://www.cs.txstate.edu/~rs01/1308/lectures/week5/5-1.htm>
I'm trying give users the option of selecting a different homepage by clicking left or right, and having an entirely new page appear. I'm aware of a few jQuery carousels that accomplish this in a purely x axis, or y axis manner, but not a rotation. Ideally the background images will sync up, and the overall effect would be like a globe spinning, with a different set of elements at a different portion of the globe. The elements at each section of the globe still need to be interactive and
Does anyone have any ideas on that?
using jQuery, you should be able to do this using the .slideDown and slideUp methods.
Essentially, when they perform the action that you want to trigger a switch, you add a slideUp() to the 'current' container and do a slideDown() on the next one. The animations will run concurrently.
http://jsfiddle.net/g19fanatic/stLvj/
Not many people here will write you a full solution, but they'll be happy to work through specific issues.
Are these homepages on different domains and/or are they under your control?
How globe-like do you mean? A kind of sphere distortion, or just seamlessly connected at the edges?
How important is the smoothness of the concept?
Off the top of my head, here's how I would (attempt to) do it:
Load the homepages in separate iframes
Stretch the iframe to the window's dimensions
Adapt a carousel script to animate iframes instead of images
Some sort of "prev/next" controls overlaying the iframe. Maybe with z-index.
Check out landing.js file on http://thetruth.com/ (or just let the page timer run to see the carousel)
What you want is basically that but with animations instead of fading the page in/out.
Just add CSS3 transforms to scale and slide instead of the fadein/out when a new page loads.
A polyfill will add the transform capability in JS (see jquery.transform.js, jquery.transition.js by https://github.com/louisremi and Modernizr)
I have seen a feature on a site I would like to emulate. I have intermediate php skill but am a novice javascript user. The feature is the site content displayed in divs which can be moved around on the screen and their position saved using cookies. This site: [url]www.nowgamer.com[/url] is where I saw it (latest podcasts, videos, reviews etc with filter)
How would I go about achieving this through javscript? I want to know how to connect javascript with the cookie so that the positions of the square divs are saved, as are the preferences of the content filter on each div. How can I achieve this?
Would this be a big job? Thank you for any help, I am working independently on this in my spare time so your contribution with advice is my lifeline.
As Zoidberg commented, its easy with JQuery or Yui, or any other javascript library that provides drag & drop functionality. They are almost easy to configure, checking at demo they give. They also expose certain events like beforeDrag, afterDrag, onDrop, etc. where you can fire a simple js function check the elements' dropped position store it in cookies. For setting cookies, there are world of code on internet.
Also, you might want to check floating absolute/relative positioning css, if your DOM divs are going to be floating around the page.
GoodLuck.
simplyharsh has the proper answer, but I'd like to expand on it a bit:
The basics of a draggable div aren't too complicated. You attach an onclick handler to initiate the dragging. Internally, that's accomplished by changing the div's CSS so it's position: absolute. Then you start monitoring mouse movements (basically onmousemove) and changing the div's top and left according to the movements you've captured.
Dropping is a bit more complicated. You can always just release the mouse and leave the div wherever you ended up moving it, but that leaves it absolutely positioned and therefore outside of normal document flow. But dropping it "inside" some other element means a lot of prep work.
Because of how mouseover/mouseout/mouseenter events work, they WON'T work while you're dragging an element - you've got your draggable div under the mouse at all times, so there's no mouseenter/leave events being fired on the rest of the page. jquery/mootools and the like work around it letting you specify drop zones. The locations/sizes of these zones are precalculated and as you're dragging. Then, as you're dragging, the dragged object's position is compared to these precalculated drop zone locations for every move event. If you "enter" one of those zones, then internally the libraries fire their mouseenter/mouseleave/mouseover events to simulate an actual mouseenter/leave/over event having occured.
If you drop inside a zone, the div gets attached as a child of that zone. If you drop outside, then it will usually "snap back" to where it was when you initiated the drag.
Resizing is somewhat similar, except you're adjusting height and width instead of top and left.