I'm trying to do very basic, custom animation with JavaScript. I'm using a library called Modernizr to detect HTML5 support, and if a browser doesn't support CSS3 Transitions, I'd like to have my own custom (non jQuery) script that recreates the same effect of CSS3 Transitions.
My idea for this code is this:
JS:
function slide() {
var cur = 0;
while (cur <= 50) {
setInterval("document.getElementById('slider').style.marginLeft=cur + 'px'",100);
cur = cur++;
}
}
HTML (for hovering):
<div id="slider" onmouseover="slide()">
This should slide left.
</div>
This doesn't work (I know it doesn't loop, that's one of the issues that I can't figure out). I'm pretty new with JS so I don't know some pretty basic stuff.
The main reason that I don't want to use jQuery is for educational purposese. I want to know basic JS before I learn jQuery, just so I know how to do the things I want to do.
I'd like this to work for two different cases, one being automatically, one being only on hover (and the hover version doesn't have to loop). I had something kind of working on hover, but the more you hovered over it, the faster it would move.
Thanks!
function slide() {
var cur = 0;
while (cur >= 50) {
setInterval("document.getElementById('slider').style.marginLeft=cur + 'px'",100);
cur = cur++;
}
}
Your code sets cur to 0, and then the while condition is cur >= 50 (*while cur variable is larger or equal to 50) which will never be true because it is 0.
Also, animating with a loop is not a good idea, as the browser likely won't render the results in a manner that is pleasant to look at (or at all). Use setInterval() without the loop.
If I was tasked with writing this, it may look like...
function slide(element, newHeight) {
var currentHeight = element.offsetHeight;
var increaseHeight = function() {
currentHeight += 10;
element.style.height = currentHeight + 'px';
}
var interval = setInterval(function() {
if (currentHeight >= newHeight) {
clearInterval(interval);
}
increaseHeight();
}, 100);
}
jsFiddle.
There are many examples of doing sliding in javascript.
Here is one of them.
http://www.harrymaugans.com/2007/03/06/how-to-create-an-animated-sliding-collapsible-div-with-javascript-and-css/
In your example, if you use setInterval you will also want to call clearInterval. For a description of both you can look at: https://developer.mozilla.org/en/window.setInterval
Hopefully you aren't actually using the onmouseover function in the element, as shown, but are instead checking if you need this, then setting it after the page has loaded.
You may want to look at unobtrusive javascript to get an idea how this can be done well.
There are various articles on this, but you could start with:
http://labs.adobe.com/technologies/spry/articles/best_practices/separating_behavior.html
Related
For a parallax-effect, I created a simple script in native Javascript, but it seems to fail somewhere I can't see. That's why I already added the requestAnimationFrame-functionality, but it doesn't seem to really help.
My relevant code is as follows:
var $parallax, vh;
$(document).ready(function() {
$parallax = $('.parallax');
vh = $(window).height();
$parallax.parallaxInit();
});
$(window).resize(function() {
vh = $(window).height();
$parallax.parallaxInit();
});
$.fn.parallaxInit = function() {
var _ = this;
_.find('.parallax-bg')
.css('height', vh + (vh * .8) );
}
//call function on scroll
$(window).scroll(function() {
window.requestAnimationFrame(parallax);
});
var parallaxElements = document.getElementsByClassName('parallax'),
parallaxLength = parallaxElements.length;
var el, scrollTop, elOffset, i;
function parallax(){
for( i = 0; i < parallaxLength; i++ ) {
el = parallaxElements[i];
elOffset = el.getBoundingClientRect().top;
// only change if the element is in viewport - save resources
if( elOffset < vh && elOffset + el.offsetHeight > 0) {
el.getElementsByClassName('parallax-bg')[0].style.top = -(elOffset * .8) + 'px';
}
}
}
I think it's weird that this script by Hendry Sadrak runs better than my script (on my phone) while that is not really optimised, as far as I can tell.
Update: I checked if getBoundingClientRect might be slower in some freak of Javascript, but it's about 78% faster: https://jsperf.com/parallax-test
So here is the downlow on JS animations on mobile devices. Dont rely on them.
The reason is that mobile devices have a battery and the software is designed to minimize battery load. One of the tricks that manufacturers use (Apple does this on all their mobile devices) is temporarily pause script execution while scrolling. This is particularly noticeable with doing something like parallax. What you are seeing is the code execution - then you scroll, it pauses execution, you stop scrolling and the animation unpauses and catches up. But that is not all. iOS uses realtime prioritization of the UI thread - which means, your scrolling takes priority over all other actions while scrolling - which will amplify this lag.
Use CSS animation whenever possible if you need smooth animation on mobile devices. The impact is seen less on Android as the prioritization is handled differently, but some lag will likely be noticeable.
Red more here: https://plus.google.com/100838276097451809262/posts/VDkV9XaJRGS
I fixed it! I used transform: translate3d instead, which works with the GPU instead of the CPU. Which makes it much smoother, even on mobile.
http://codepen.io/AartdenBraber/pen/WpaxZg?editors=0010
Creating new jQuery objects is pretty expensive, so ideally you want to store them in a variable if they are used more than once by your script. (A new jQuery object is created every time you call $(window)).
So adding var $window = $(window); at the top of your script and using that instead of calling $(window) again should help a lot.
I was wondering if you would mind taking a look at the following code and tell me where I'm going wrong. I know close to nothing about javascript but I was able to some code that is supposed to do what I want. I've got a div ID makes a fullscreen image background. I want to change out what image is used every 5000 milliseconds. Here's the javascript:
<script type="text/javascript">
$(window).load(function() {
var i =0;
var images = ['cover1.jpg','cover2.jpg'];
var image = $('.cover_image');
image.css('background-image', 'url(/img/cover1.jpg)');
setInterval(function(){
image.fadeOut(1000, function () {
image.css('background-image', 'url(' + images [i++] +')');
image.fadeIn(1000);
});
if(i == images.length)
i = 0;
}, 5000);
});
</script>
Here's the CSS being used:
.cover_image {
background-repeat: no-repeat;
background-image: url("/img/cover1.jpg");
background-position: bottom center;
background-size: cover;
z-index: -3;
position: relative;
}
And here's the HTML:
<div class="slide cover_image"></div>
You have 2 problems here, when you use JQuery, and your "loop"
JQuery Loading
JQuery isn't always loaded at the same time as Javascript. So trying to detect when Javascript is loaded to use JQuery might let you use Javascript code, as soon as you run some JQuery selectors, it'll crash. And burn. So don't do that.
Why?
Most modern browsers excuse many Javascript files at once. This means JQuery starts when the document is ready, and your code tries to use the uninitialized JQuery library. This means you use something that's not there. It's like trying to read the end of th
If your only objective was to read the end of that sentence, you would crash, too.
Zero-Indexed Arrays
Also, I made a change to the way your loop works, because it was somewhat broken. Javascript has 0-indexed arrays, so trying to get the .length of an array with 2 elements will return 2, but the elements are at [0] and [1].
Why?
It was mainly because computers could started counting at zero, so in the old days, it made no sense to waste a bit (literally), and it was also much more processor intensive to do arithmetic, so starting at zero made sense. We could switch to 1-indexed arrays, like Lua does, but it's still a bit friendlier on computers to start at zero, plus many programmers were used to it, and changing an aspect like that will break older programs.
Code/TL;DR;
$(function(){
var i =0;
var images = ['cover1.jpg','cover2.jpg'];
var image = $('.cover_image');
image.css('background-image', 'url(/img/cover1.jpg)');
setInterval(function(){
image.fadeOut(1000, function () {
image.css('background-image', 'url(' + images[i] +')');
image.fadeIn(1000);
});
if(i == (images.length - 1)){
i = 0;
} else {
i++;
}
}, 5000);
})
Bootstrap has a "carousel" class that looks great and works without the need for extensive JS. If you don't know what Bootstrap is, I would advise looking it up because I use it on almost all of my webpages. Here's a link to a carousel example: http://www.w3schools.com/bootstrap/bootstrap_carousel.asp
I am trying to make the elements on my site fly-in and fly-out on scroll.
This is the effect I am looking for.
http://nizoapp.com/
The effect in the nizo site is done with jquery, I think
I have tried many different ways to get this effect working, with Skrollr, scrollorama, and jquery animate and with css transitions etc etc etc
I decided to use css transitions as mad by the "css animation cheat sheet" (google it)
After a lot of effort and some borrowed code, I have got it half working, as in, I can get the elements to fly-in on down scroll, but not to fly back out on up scroll.
This is a jsfiddle with it half working
http://jsfiddle.net/mrcharis/Hjx3Z/4/
The code is......
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
$(window).scroll(function () {
$('.box').each(function (i) {
if (isScrolledIntoView(this)) {
$(this).addClass("slideRight");
}
});
});
// this is the function to check if is scroll down or up, but I cannot get it to trigger the fly in effect,
(function () {
var previousScroll = 0;
$(window).scroll(function () {
var currentScroll = $(this).scrollTop();
if (currentScroll > previousScroll){
// i figure to put the fly-in code here
}
else {
// and the fly-out code here
}
previousScroll = currentScroll;
});
}());
I have tried using another function (code chunk) to check if the scrolling is down or up, but i can't get it working with the existing code.
Any help to get this working would be awesome
Have a nice day
I will post the solution one day, if I can figure it out, sure someone else would like to know
The trick to knowing whether you're scrolling up or down is not to ask. Make it relational by using the top offset of the elements in question. Then it's as easy as > or <, for the most part.
Though if you do want to get the current direction you could always record the last scroll position and compare it with the current one.
var before = 0;
$(window).scroll(function(event){
var now = $(this).scrollTop();
if (now > before){
//on down code
} else {
//on up code
}
before = now;
});
Like the answer here suggests.
I like to trigger the events based on the screen size and the element position in the screen, so it doesn't matter whether it's up or down, it follows the same rules forwards and backwards. That way instead of asking up or down, it just asks if it's scrolling and executes it accordingly.
If you need me to make changes to my fiddle for you, just let me know what you want to happen. I only made the fiddle because of the horrible job they did on the tympanus.net example. You don't make a tutorial to accomplish a simple task 2 pages of js, that's unnecessary and it doesn't provide any instruction other than "hey, you want to do this? Then copy and paste these things I put together that have no clear course of action, and way too much code to digest quickly". Which doesn't help anyone learn.
After some code borrowing from tympanus.net and using the modernizer library I came up with this.
I tried different approaches as well but all of them turned out to have some flaws in them so I find best approach to be using the sample code and the already provided modernizer JS library.
Is there easier way to make something to appear slowly on webpage? I tried to incrementally increase opacity of the CSS, but it (opacity) tag is different for each browser. Is there well know Javascript function that everyone uses? Or is there any css tag?
[edit] Thanks for Jquery suggestion. Is there other option? My page is very small and don't want to add Jquery. (I know about Google hosting it)
Aargh! Every JS developer here seems to have contracted the jqueryitis!
If you're not yet infected or still want to escape from it, here's a small function that do the job cross browser :)
function appear(elm, i, step, speed){
var t_o;
//initial opacity
i = i || 0;
//opacity increment
step = step || 5;
//time waited between two opacity increments in msec
speed = speed || 50;
t_o = setInterval(function(){
//get opacity in decimals
var opacity = i / 100;
//set the next opacity step
i = i + step;
if(opacity > 1 || opacity < 0){
clearInterval(t_o);
//if 1-opaque or 0-transparent, stop
return;
}
//modern browsers
elm.style.opacity = opacity;
//older IE
elm.style.filter = 'alpha(opacity=' + opacity*100 + ')';
}, speed);
}
To appear
appear(document.getElementsByTagName('DIV')[0], 0, 5, 40);
To disappear
appear(document.getElementsByTagName('DIV')[0], 100, -5, 40);
Easy with Jquery:
$("#myElementID").fadeIn("slow");
Dear Lord! Yes, I think most of us do know about jQuery, thanks.
Opacity isn't so complicated to set, today; it's now only IE that needs special help. See this answer for some simple plain-JavaScript time-independent fading code.
If you can use jQuery then animate() function will hep you.
$('your_selector').animate({opacity: 0.25}, 5000, function() {
// Animation complete.
});
See .animate()
or you can use fadeIn
$('your_selector').fadeIn('slow', function() {
// Animation complete
});
YUI Also has animate functionality and allows you to only include required modules which will reduce your load times.
YUI Animation
You fadein and fadeout of jQuery. For example, jQuery('#ID').fadeout() will make an element with 'ID' as its id to fade out (slowly disappear),
I recommend using jQuery. You will have to use the fadeIn() function. Detailed explanation here: http://api.jquery.com/fadeIn/. I rarely use pure Javascript after having started with the jQuery library.
You can use slideDown as well.
$("#YourID").slideDown("slow");
I would like to learn how to do fade, and similar effects on JavaScript. I often get answers, like why not use jQuery, Mootools, etc ? Well, I want to learn how stuff works, then I won't mind using any of these frameworks.
I'm currently learning about making changes on the DOM, so, I've read a lot of stuff on this theme. Also, I've read about Reflow, still, I didn't find any cool stuff on Repaint, but, I'll keep searching.
From seeing source files etc, I see a few methods, that I don't know if they've created or are Core methods of JS.
My question is, is there any resource where I can learn all this neat stuff like smooth position change, fading elements trough opacity or whatever, etc?
Take a look at emile.js. It's brand-spanking new. Great way to learn how to do your own.
Introduced at the recent jsconf conference. Written by Thomas Fuchs (script.aculo.us).
http://github.com/madrobby/emile
Émile Stand-alone CSS animation
JavaScript mini-framework
Doesn't need
a JavaScript framework
Full set of CSS
properties for animation (length-based
and colors)
Easing and callbacks
Less
than 50 lines of code
Get updates on
Twitter: http://twitter.com/emilejs
here's an example that works in firefox and chrome. ie doesn't respect the opacity style.
var ELEMENT;
var STEPS;
var INTERVAL;
var COUNT;
var TIMERID;
// 5 * 200ms = 1 second
STEPS = 5;
INTERVAL = 200;
function Button1_onclick() {
ELEMENT = document.getElementById("foo");
COUNT = STEPS - 1;
TIMERID = setInterval(Fade, INTERVAL);
}
function Fade() {
ELEMENT.style.opacity = String(COUNT / STEPS);
COUNT--;
if (COUNT < 0) {
clearInterval(TIMERID);
TIMERID = 0;
}
}
setInterval and clearInterval are standard js functions. they will execute the given function every x milliseconds. in our case we kill it when we've hit 0 opacity.
sliding a window is a similar process. you'd set the left/right/top/bottom style instead of opacity.
Fading using javascript is basically modifying opacity of an element programmatically. The "smoothness" is done by using timers. Same for position/size changes. You need to read up on css to understand what style properties of an element you have to control using javascript for the effect you want.
If you are really curious, you can dive into the source of yui in github: http://github.com/yui