I'm building an AngularJS app and am looking to do something a little tricky with animations that I'm not quite sure how to do. One aspect of the app entails animation between views in a panning manner, but the appearance of a single view needs to be maintained. For example, if there is a scene with a square in the center, on view-change that square would appear to leave the screen as if we were panning across (while other elements enter in), all without it feeling like the view has really changed.
I know that ng-animate provides a lot of powerful animation functionality, but I'm stumped on what the best way to maintain the appearance of a single view while transitioning between them is.
Does anyone have experience trying to do this or know of an animation library that would make this possible?
I'll update this question with possible solutions as I find them.
When a view is added, the following classes are added:
.ng-enter
.ng-enter.ng-enter-active
When a view is removed, the following classes are added:
.ng-leave
.ng-leave.ng-leave-active
You can attach CSS 3 transition styles to the classes to achieve the animation effect you want.
If I understand correctly, the 'leaving' animation should pan left to right, and fade-out, starting from a 0px offset. The 'entering' animation should also pan left to right, but fade-in, starting from a negative offset.
Here is an example:
Plunker Demo
JS FIddle Demo
Related
I am trying to create a side panel similar to that of codepen editor in react, where you can drag to adjust the size of the different editors.
If I drag an editor header towards the bottom low enough, the editor below it will follow, almost as if I have appended that component to the drag, likewise if i try ti drag the header upwards. I have built the layout to my liking with a similar concept to the accordion from material UI:
https://mui.com/material-ui/react-accordion/
I was also able to mimic the on click behaviors of the header from codepen, for example, double click would open the editor to full size and triple click will open all evenly by keeping track of the heights of all the 'containers' in a useState hook. However, I am having trouble with the dragging part. I am looking for some suggestions for good libraries/ideas to use to help me achieve this.
Currently I am using framer motion to make the expanding of the container more 'smooth'.
https://www.framer.com/docs/transition/
I noticed that they also have dragging capabilities which I am also exploring. My idea is to have an onDrag for each of the headers. Depending on which header I am dragging, if I drag down until my container size is 0, I start shrinking the container below it and then the one below it and so on and so forth. I am able to get the Y property from the onDrag function but I am a bit hesitant to do my calculations in x/y coordinates. Does anyone have any suggestions or any libraries that might make this easier?
I don’t know any libraries. I think if you got this far you can probably do it yourself in plain js, using listeners and selectors, etc, or whatever react can provide. Is there something specific that makes you ‘hesitant’? I recently found these which made things easier for me, they might not be 100% relevant but still good to know: getBoundingClientRect
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
That will tell the position relative to the viewport, it was useful for me dragging dividers between panels.
And if you need the position relative to the container:
https://stackoverflow.com/a/11634823/5350539
And if you’re not already, I guess you could look at setting the panel CSS positions using ‘bottom’ (with position absolute or relative), then animating the height to e.g. 30px less than the bottom edge of the upper panel. Tip: while dragging, add a body class to disable user select: user-select: none;
I am making a basic webpage on React with two Parallax Layers with images, the first layer image is a drawing of a room, and the second layer image is a drawing of a doorway, with a transparent cutout where the door is. I plan on doing a bunch of parallax scrolling in the future for this site, and want to use the react-spring package since it has many features I'm keen on using.
As the user scrolls down, I want to zoom and increase the width of the doorway image (yellow box) from the center point, till it is no longer visible and gives way to the room illustration, instead of it scrolling up and disappearing. Essentially, an illusion of entering a room through a door.
Here is the jist of my code on codesandbox, if you scroll you can see some of the react-spring Parallax in effect. I have spent about 12 hours looking for an answer on how to increase the width of the doorframe image (yellow box) as I scroll, and have had no working results. I'm running out of things to Google - I've tried methods with Javascript, where I give the CSS style a variable, Jquery that tracks scroll distance, using Spring native to, and pure CSS and still can't seem to find a solution compatible for the react-spring package.
https://codesandbox.io/embed/practical-sea-2tecb?fontsize=14&hidenavigation=1&theme=dark
Since I am trying to use React and the react-spring library, I think I've made this issue complicated. But, as I develop more of the site, I want to be able to use the features on react-spring. Any guidance would be so, so helpful.
Thanks
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 found this page http://www.wanderworld.io/ when you scrolling its start animation on scrolling and scenes are changing. how to create something like this? Please help me, any example on jsffidle or codepen?
To point you in the right direction, this is called parallax scrolling and can be accomplished using CSS, but is most commonly done in Javascript / jQuery.
This library is great for parallax animation and would probably accomplish most, if not all, of what the example site does: http://prinzhorn.github.io/skrollr/
Basically the idea is to have a page scroll listener that tracks the window.scroll position. At certain ranges, elements move in and out of the screen. The concept behind it is relatively simple, but it can be difficult to implement and can be as complicated as you choose to make it.
I have a grid of div boxes that I will be animating. They will be moving across the screen after a user drags one of the boxes (to re-align into a grid).
Currently I am using JQuery to change the css left and top positions of all of the divs and running this on an interval.
It is laggy if there are more than 50 boxes. How do I make this less laggy? Is there an animation library that is better for this, or do I just need to limit it to 50 boxes?
Image of layout:
You have a few options to optimize the performance.
Newer browsers have requestAnimationFrame that lets the browser take care of the animation timing in order to optimize Javascript animations. Rather than using times to perform the animation, which is what jQuery framework uses, you repeatedly a callback to requestAnimationFrame. The browser will call your function with a progress variable for the animation, and you render the current stage of your animation based on the progress variable. requestAnimationFrame for smarting animating talks about this in depth. Google Closure is the only framework I am aware of that uses requestAnimationFrame however, and it's rather heavyweight.
CSS animations. jQuery offers CSS animation, so do many other frameworks. CSS animations give you hardware acceleration, so the animation is much faster. Unfortunately, CSS animations are relatively new and not yet well supported, so you'll probably end up falling back to Javascript animation on older browsers, depending on the library you use.
Optimize your Javascript. Instead of animation each and every box in the grid, encapsulate each row in a div and animate the entire div instead. That should speed the animation up by a bit. I'm sure there are other ways you can optimize based on your current implementation.
Honestly, I don't know of any library that will make this work more efficiently for you, though there are many libraries out there that are faster than jQuery. The issue isn't just the jQuery, its the fact that you have 50 elements that are all moving/draggable, thus requiring a lot of the browser's resources.
If you can post your code there may be a few things that we could suggest to speed it up slightly.
The two biggest things problems that I can think of are if you added those boxes programmatically and added the handler for each as you added the element to the page, and if you don't store your selectors in variables. Aside from that I would have to see the code.
Have a look at:
jQuery isotope
It has options to allow you to use css3 animations if available or use jQuery / JS animations.
Handy for grid like animation and arrangements.
Some brave soul has managed to add drag and drop to isotope too. http://tyler-designs.com/masonry-ui/ (a bit clunky but works)
There are several ways of increasing the performance. One would be to reduce the amount of DOM elements required for each box. Another is to not animate (and render) boxes outside of the current viewport. Give all boxes that are outside of the viewable area "display: none;" and exclude them before starting a new animation. If you want to go even further you can start to recycle boxes instead of showing and hiding them when the user is scrolling through the page.
This way you will always get the same performance no matter how many boxes you have (above the amount that you can fit in the viewport).
This technique is called UI virtualization. There are several projects that use it like: http://github.com/mleibman/SlickGrid/wiki. It's really useful when you need to render a lot of elements (hundreds, thousands, millions). But it takes quite some work to get it right. And I don't know about any generic working components that are easy to plug in. I tried to find an article that explains it. This is the only thing I could come up with for now, it's for Silverlight though: http://www.silverlightshow.net/items/Virtualization-in-Silverlight-4-RC.aspx
Also try this this plugin for jQuery. Use the regular 'animate' method and it will try to use (hardware accelerated) CSS animations where possible: http://playground.benbarnett.net/jquery-animate-enhanced/