How do I animate things on scroll? - javascript

This theme demo on themeforest has neat animations including for example showing text when the users scrolls down, or making icons appear from the sides.
I'm guessing CSS3 and JavaScript, possibly with jQuery or a framework specialized in animations would be used for this, but I have no idea where to start learning how to accomplish these kinds of animations.
Where do I start?

Checkout WowJS.
And try going through their source code if you're curious about it works under the hood.
Otherwise its a pretty good library to get started with scroll animations.

Basically animations that are triggered by scrolling actions are Javascript / jQuery stuff (not CSS). There's a nice JS plugin which you can take a look at which helps to do all that: Scrollmagic, to be found here

If you are using Wordpress, chances are you can buy a theme that includes very nice animations ready for use with a few options (say how fast it should occur or such) - similarly there are many neat animations on codepen and similar sites so maybe if you search long enough you could find and copy what you want.
However, if you really want to learn how to do that yourself, there's no short cuts and you have to start with understanding JavaScript and the capabilities of CSS3 animations and deeply, so you know which can do what.
CSS Transitions, CSS Animations, Simple JS animations
These are all w3school tutorials but there are many other resources out there. Start with something simple and work your way up.
Since you mentioned the behavior on scroll, the relevant JavaScript is
object.addEventListener("scroll", myScript);
Here's a simple use case to start.

Well there are lots of ways to do it, but jQuery works nicely.
You may find this and this helpful.
$(window).scroll(function () {
if($('body').scrollTop() > 110) {
$('.box').css({
'width': '50px',
'height': '50px',
'background': 'coral'
});
} else {
$('.box').css({
'width': '100px',
'height': '100px',
'background': 'red'
});
}
});
body {
padding-top: 175px;
background: whitesmoke;
height: 600px;
}
.box {
margin-top: 150px;
background: red;
width: 100px;
height: 100px;
margin: 0 auto;
transition: all .6s ease;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
</div>

Related

removeClass is not working w/CSS transitions

I'm trying to make a blink effect on click (instantly set background and then fade out) but on second click removeClass is not removing it. Where is a mistake?
JS:
$('div').click(function() {
$(this).css({transition: '0s'}).addClass('qwe')
.delay(1).queue(function() {
$(this).css({transition: '2s'}).removeClass('qwe');
});
});
CSS:
div{
height: 100px;
width: 100px;
background: gray;
}
.qwe {
background: green;
}
Fiddle
The browsers are built to optimize consequent style changes by coalescing them. In case of CSS transitions they do it a bit over-zealously.
Currently there's no 'clean' way around it, the best you can do in current browsers is force restyle via window.getComputedStyle(document).color or similar before the applying the changes that would invoke transition (removeClass in your case).
See
Clean way to programmatically use CSS transitions from JS? for more information.
Solved it using jQuery UI
$('div').click(function() {
$(this).addClass('qwe').switchClass('qwe', '', 1000);
});

Get AngularJS to play nice with other javascript

I have started using AngularJS with some code that was already written and need to get it to play nice together.
So I have
<html ng-app="MainPage">
<head>
...Some JS includes
</head>
<body>
<div id="divDropDownMenu" class="DropDownMenu">
....AngularJS stuff in here
</div>
</body>
I'm using this code to append a button at the end of "divDropDownMenu" and when the button is clicked slide the up and down to reveal the menu items.
var divPanel = $("<div class='slide-panel'>");
var divContent = $("<div class='content'>");
(function ($, $scope) {
$.fn.slideBox = function(params){
var content = $(this).html();
var defaults = {
width: "100%",
height: "500px",
position: "top" // Possible values : "top", "bottom"
}
// extending the function
if(params) $.extend(defaults, params);
$(divContent).html(content);
$(divPanel).addClass(defaults.position);
$(divPanel).css("width", defaults.width);
// centering the slide panel
$(divPanel).css("left", (100 - parseInt(defaults.width))/2 + "%");
// if position is top we're adding
if(defaults.position == "top")
$(divPanel).append($(divContent));
// adding buttons
$(divPanel).append("<div class='slide-button'>Open Menu</div>");
$(divPanel).append("<div style='display: none' id='close-button' class='slide-button'>Close Menu</div>");
if(defaults.position == "bottom")
$(divPanel).append($(divContent));
//$(this).replaceWith($(divPanel));
// Buttons action
$(".slide-button").click(function(){
if($(this).attr("id") == "close-button")
$(divContent).animate({height: "0px"}, 1000);
else
$(divContent).animate({height: defaults.height}, 1000);
$(".slide-button").toggle();
});
};
})(jQuery);
function SlidePanelExpandCollapse(ExpandCollapse)
{
if (ExpandCollapse == "Expand") {
$(divContent).animate({ height: defaults.height }, 1000);
}
else {
$(divContent).animate({ height: "0px" }, 1000);
}
$(".slide-button").toggle();
}
The problem is that any angular inside the targeted div does not fire when using the above code.
this is the CSS that goes with the above JS menu slider
/* #override
http://samuelgarneau.com/slidebox.css
http://samuelgarneau.com/lab/validator/slidebox.css
http://samuelgarneau.com/lab/slidebox.css
http://samuelgarneau.com/lab/slidebox/style/slidebox.css
*/
body {
margin: 0;
padding: 75px 0 0;
}
.slide-panel {
z-index: 9999;
width: 5px;
position:absolute;
}
.bottom {
bottom: 0;
}
.right {
}
.left {
position: absolute;
left: 0;
}
.top {
top: 0;
}
.content {
margin-left: auto;
margin-right: auto;
z-index: 10;
overflow: hidden;
text-align: left;
background-color: #343434;
height: 0;
width: 100%;
color: #fff;
}
.slide-button {
background: none repeat scroll 0 0 gray;
margin-left: auto;
margin-right: auto;
position:relative;
width: 150px;
z-index: 20;
cursor: pointer;
height: 30px;
padding-top: 10px;
text-align: center;
}
.slide-button:hover {
color: #ffffff;
}
I don't see any actual use of AngularJS in your example at all. The only thing which reminded me of AngularJS was the mention of $scope in your function definition. Now while AngularJS appears to work magically in some areas this still won't do anything.
Also it might appear tempting to keep existing code and just add some AngularJS parts. However seeing your example I would recommend that you rewrite this functionality using the means of AngularJS. Showing and Hiding stuff can be easily done with ng:hide or ng:show. The animation stuff you do can be done with ng:animate. And if you need to dynamically show data, put it into a model (in your scope) and use that with functions like ng:repeat.
It appears that what you are doing in your example would boil down to only a couple of lines using the AngularJS functionality, so the result would be better and easier to read and maintain. Do yourself a favor and get familiar with what AngularJS can provide you with and stop bothering with direct DOM manipulation. It is a bad pattern. DOM manipulation is pesky, complicated and prone to break. It is also usually an unmaintable mess. And the best: If you are using AngularJS anyway, it is complete superflous because everything can be achieved much easier by having a model triggering conditional logic in your HTML.
Some impressive fact from the talk of the AngularJS creator at Google I/O 2013: He used AngularJS in its beginning to rewrite a internal project of Google. The result was that 14000 lines of code were reduced to 1500.
I recognize that this does not really count as an answer to your problem but I really believe that you would be better off stopping this approach right here and now and instead of wasting time to get this working rewrite it in AngularJS. This seriously should not take longer than half an hour even if you have to read up all the details still.
Edit/Addendum: The talk I mentioned is "Google I/O 2013 - Design Decisions in AngularJS" at http://www.youtube.com/watch?v=HCR7i5F5L8c I highly recommend watching this video even to people who have already experience with AngularJS. It gives good insight to the AngularJS way and its points come handy when trying to convince someone else in trying AngularJS :)
Edit/Addendum2: As Sprottenwels helpfully mentioned above, there is another question here on stackoverflow which gives a much more thorough explanation of what I boiled down above, so please give it a read: "Thinking in AngularJS" if I have a jQuery background?
Edit/Addendum3: As again Sprottenwels helpfully mentioned: The videos at http://www.egghead.io/lessons are a great resource. I personally found them sometime a little hard to understand (you might need to stop the video and read up in the documentation of AngularJS which thankfully is nowadays much better than it used to be).
Oh and on a personal note: While I did web development since about 1997, I was never a friend of doing application like stuff in JavaScript because all those frameworks are so complicated with lots of boilerplate and you are doing stuff which feels like a waste of time. AngularJS really did wonders to my motivation doing such stuff because it finally is totally logical and its magically like inner workings totally freed me from doing stuff I hated like synchronisation of data and view.
I am totally thankful to the AngularJS people and I absolutely believe that this is the only real future of doing web application programming. Right now AngularJS can be a problem performance-wise because of doing "bad" stuff like dirty-checking but this is going to change with new browser features like Object.observe. So I really think that choosing to use AngularJS to its full extent is a wise and future-safe move.

jQuery scrollTop() does not work in scrolling DIV on mobile browsers, alternatives?

I am trying to scroll to a specific location in a scrolling DIV. Right now I am using a pixel offset with the jQuery scrollTop() function which works great on desktop browsers but it does not work on android mobiles browsers with the exception of Google's Chrome Android browser (do not have an iOS device to test if that works). All the solutions I have found are for page (window) scrolling and not for scrolling in a DIV, anyone have any suggestions on what else I can use to accomplish the same task?
Here is a example:
http://jsfiddle.net/aQpPc/
http://jsfiddle.net/aQpPc/embedded/result/
Other things I have tried that work in desktop browsers:
document.getElementById('ID_of_element_in_a_DIV').scrollIntoView();
document.getElementById('ID_of_DIV').scrollTop = 200;
EDIT 3/11/13:
This is a know android browser issue: https://code.google.com/p/android/issues/detail?id=19625
One user in the bug report suggested a workaround:
because the issue only seems to appear when the overflow property is
set to scroll, you can first set it to 'hidden', set the scrollTop
property, then reset it back to 'scroll' (or auto). The scrollTop
property seems to be honored when the element is re-rendered with
scrollbars. It's not clear if this has any unexpected side-effects,
but "it works on my machine!"
This worked for me:
setTimeout( function() {
$(div).scrollTop(0)
}, 500 );
A workaound that worked for me: first, temporarily set the overflow property to 'hidden', then set the scrollTop property, then set the overflow property back to 'scroll' (or auto). The scrollTop value seems to be kept intact and honored when the overflow property is set back to 'scroll'. This was a pretty trivial workaround that worked on all browsers I tested on (desktop and mobile). I didn't test it exhaustively, and I didn't test with transitions in place, so there may be side-effects that I haven't encountered... Your mileage may vary - but it's an easy thing to try.
I found the answer here http://blog.jonathanargentiero.com/jquery-scrolltop-not-working-on-mobile-devices-iphone-ipad-android-phones/
Mobile phones doesn't understand $('html,body') so u can do the following for mobile
if(navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/)) {
window.scrollTo(0)
} else {
// default `$('html,body')` code for scrolling
}
OR
simply use $('body') instead of $('html, body').
rather than using the scroll, scrollTo, or scrollTop methods (which give me problems in mobile), I recommend setting an ID on your top DOM element (like #top), and just using:
document.getElementById("top").scrollIntoView();
that works the best for me so far across all devices and browsers.
I have a couple solutions for you to try. You will have to test them yourself, as I have not tried them in a mobile browser before, but here they are:
Use jQuery's .css() method (or .animate() depending on what your eventual goal us) to adjust the top margin (note: you would have to change the overflow to hidden and wrap the text in an inner div, which would be the element whose to margin you are adjusting)
Do the same thing as in the first solution, except set the embedded div's position to relative and adjust it's top attribute.
Let me know if you need help with any if this or have any more questions about this. Good luck! :)
Note that although I have not tested these in mobile before they are based on CSS standards, not jQuery functions, so they should work.
Temporarily setting the overflow property to 'hidden', as recommended in #Allan Nienhuis' answer, does not work on Android 4.0.3, for instance (which is, e.g., what the Kindle Fire 2s are running) - when you set overflow back to scroll, the element scrolls back to the top.
Alternatives:
Roll your own scrolling via a helper function, as demonstrated here - while this is simple to implement, it is bare-bones in that it doesn't give you inertial scrolling or overscrolling.
Use a library such as iScroll, which implements its own, sophisticated scrolling (inertial, overscrolling) based on CSS transformations.
Using iScroll requires a bit of setup, though: you need a wrapper div with fixed height and style overflow: hidden and the element to scroll should have no overflow style. This jsFiddle demo shows how it's done.
The only way i could achieve scrolling to the top of the page on a Galaxy Tab was hiding the page body for 100ms while scrolling. Using jQuery:
$("body").hide();
window.scrollTo(0, 0);
setTimeout(function(){ $("body").show() }, 100);
Try using jQuery's .animate method:
$('.div').animate({ scrollTo: x; });
Where x is equal to the position of the div you want to scroll to the top of.
Did you try this ?
$("html").scrollTop(0);
jQuery(document).ready(function($) {
$(".scroll").click(function(event){
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 1500);
});
});
Use the following code:
$("body").animate( { scrollTop: 50, }, 800, function(){
$("body").clearQueue();
} );
These solutions did not work for me. I know someone mentioned mobile detection but their approach did not work for me. It finally dawned on me to use mobile detection to deliver two different CSS styles for each case. Maybe not ideal but it for sure works. Temporarily changing the styles with js also suggested above did not work for me.
I had a two column layout with independently scrolling divs, each set to overflow:scroll and the body had to be set to overflow:hidden. I need to use scrollTop on one of the columns and no solutions worked.
I used wp_is_mobile() (Wordpress function) and if mobile true, overflow: hidden is removed from body and the divs with overflow:scroll have that css removed. Finally, scrollTop worked on mobile.
$(document).ready(function (){
$(window).scroll(function(){
if($(this).scrollTop() > 100){
$('.scrollup').fadeIn();
}
else{
$('.scrollup').fadeOut();
}
});
$('.scrollup').click(function(){
if (navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/)) {
window.scrollTo(0,0);
}
else{
$('html,body').animate({
scrollTop: 0
}, 500, function(){
$('html,body').clearQueue();
});
}
});
});
body{
height: 1500px;
}
.scrollup {
bottom: 135px;
height: 40px;
width: 40px;
display: none;
background: #000;
border: 2px solid #fff;
border-radius: 100%;
box-shadow: 1px 3px 5px #000;
text-align: center;
font-size: 25px;
color: #fff;
cursor: pointer;
position: fixed;
right: 12px;
line-height: 36px;
z-index: 25;
}
svg{
fill: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="scrollup">
<svg height="35" viewBox="0 0 512 512" width="30">
<polygon points="396.6,352 416,331.3 256,160 96,331.3 115.3,352 256,201.5 "/>
</svg>
</div>
I had the same problem and solved it by using jquery .offset() instead.
http://api.jquery.com/offset/
$('#yourFineElement').offset({ top: X, left Y)});

Spinning effect with only 2 images

We only have 2 images of a bottle (front and back), but would like to create some kind of spinning effect. I was trying to think of some way of doing this with jquery or just CSS - maybe with blurring. Couldn't think of a good way.
They want to press a button to see the other side of the bottle (spinning to get there).
Any ideas on how I could do this?
Have a look at the CSS Coke can example. That might help you get some quick results or at least serve as a base for new ideas. (English here, also it shows a little bit easier what's going on).
The only JS you'd need for this is to do the actual "scroll".
You could, for example, do that with the jQuery transit library http://ricostacruz.com/jquery.transit/
$('button').on('click', function(){
$('.bottle').transition({
perspective: '100px',
rotateY: '180deg'
});
});
Animate the width an margin left of the first image (front side) from width: 300px; margin-left: 0px to width: 0px; margin-left: 150px. Once the animation is complete, animate the second image from width: 0px; margin-left: 150px to width: 300px; margin-left: 0px.
You can use .animate() for this purpose: http://api.jquery.com/animate/
I hope this answered your question.
http://css3.bradshawenterprises.com/cfimg/
Check out demo 2 for the crossfade using a button. To get it to spin, add something like this:
transform:rotatey(180deg);
}

Change div height onclick with animation

I'm trying to make a gallery using divs that change their height when you click on them. Ideally, this would include animation to smoothly expand the div's height. There will be several of each div on each page, so it needs to just expand that section.
It's actually supposed to turn out something like the news section on this page: http://runescape.com/
I'd like to do it with JavaScript/jQuery if possible.
$('div').click(function(){
$(this).animate({height:'300'})
})
Check working example at http://jsfiddle.net/tJugd/
Here's the code I ended up using:
JS:
document.getElementById("box").addEventListener("click", function() {
this.classList.toggle("is-active");
});
CSS:
#box {
background: red;
height: 100px;
transition: height 300ms;
width: 100px;
}
#box.is-active {
height: 300px;
}
HTML:
<div id="box"></div>
Fiddle:
https://jsfiddle.net/cp7uf8fg/
try
$('div').toggle(function(){
$(this).animate({'height': '100px'}, 100);
}, function(){
$(this).animate({'height': '80px'}, 100);
});
DEMO
jQuery rules. Check this out.
http://api.jquery.com/resize/
The complete solution:
Both spacer DIV and Margin or Padding on content DIV works but best to still have a spacer DIV.
Responsive design can be then applied to it in your CSS file.
This is mutch better as with JAVA the screen would flicker!
If you use a grid system there will be a media query part there you need to include your settings.
I use a little spacer on HD screen while its increasing till mobile screen!
Still if you have breadcrumb in header multiple lines can be tricky, so best to have a java but deferred for speed resons.
Note that animation is for getting rid of flickering of screen.
This java then would only fire if breadcrumb is very long otherwise single CSS applied via the grid and no flickering at all.
Even if java fired its doing its work via an elegant animation
var header_height = $('#fixed_header_div').height();
var spacer_height = $('#header_spacer').height() + 5;
if (header_height > spacer_height) {
$('#header_spacer').animate({height:header_height});
};
Note that I have applied a 5px tolerance margin!
Ho this helps :-)
I know this is old, but if anyone seems to find their way here. #JacobTheDev answer is great and has no jQuery! I have added a little more for use cases where the event is not being assigned at the same point your toggling the css class.
HTML
<div id='item' onclick='handleToggle()'> </div>
JS
handleToggle(event){
document.getElementById(event.target.id).classList.toggle('active')
}
CSS
#item {
height: 20px;
transition: 1s;
}
.active {
height: 100px;
}

Categories