how can i add an easing/animation/slowly moving to this function?
At the moment it just jumps.
Now it should move to the "anchor" with an animation.
<script type='text/javascript'>
setTimeout("window.scrollBy(0,270);",3000);
</script>
also possible with plain javascript using request animation frame..
// first add raf shim
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
// main function
function scrollToY(scrollTargetY, speed, easing) {
// scrollTargetY: the target scrollY property of the window
// speed: time in pixels per second
// easing: easing equation to use
var scrollY = window.scrollY,
scrollTargetY = scrollTargetY || 0,
speed = speed || 2000,
easing = easing || 'easeOutSine',
currentTime = 0;
// min time .1, max time .8 seconds
var time = Math.max(.1, Math.min(Math.abs(scrollY - scrollTargetY) / speed, .8));
// easing equations from https://github.com/danro/easing-js/blob/master/easing.js
var PI_D2 = Math.PI / 2,
easingEquations = {
easeOutSine: function (pos) {
return Math.sin(pos * (Math.PI / 2));
},
easeInOutSine: function (pos) {
return (-0.5 * (Math.cos(Math.PI * pos) - 1));
},
easeInOutQuint: function (pos) {
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(pos, 5);
}
return 0.5 * (Math.pow((pos - 2), 5) + 2);
}
};
// add animation loop
function tick() {
currentTime += 1 / 60;
var p = currentTime / time;
var t = easingEquations[easing](p);
if (p < 1) {
requestAnimFrame(tick);
window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t));
} else {
console.log('scroll done');
window.scrollTo(0, scrollTargetY);
}
}
// call it once to get started
tick();
}
// scroll it!
scrollToY(0, 1500, 'easeInOutQuint');
For anyone viewing this question in 2019: this can now be done natively by using
window.scrollBy({
top: 0,
left: 270,
behavior: 'smooth'
});
This works in all major browsers except edge and safari. See https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy#Examples
Adapted from this answer:
function scrollBy(distance, duration) {
var initialY = document.body.scrollTop;
var y = initialY + distance;
var baseY = (initialY + y) * 0.5;
var difference = initialY - baseY;
var startTime = performance.now();
function step() {
var normalizedTime = (performance.now() - startTime) / duration;
if (normalizedTime > 1) normalizedTime = 1;
window.scrollTo(0, baseY + difference * Math.cos(normalizedTime * Math.PI));
if (normalizedTime < 1) window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
}
This should allow you to smoothly scroll by the specified distance.
This will Work, Assume you need to Smooth-scrolls to the top of the page.
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
};
Another example with jQuery, uses the easing plugin for some nice effects:
http://tympanus.net/codrops/2010/06/02/smooth-vertical-or-horizontal-page-scrolling-with-jquery/
got it myself. because of wordpress and the jquery.noConflict Mode i hade to modify the code:
<script type="text/javascript">
(function($){
$(document).ready(function(){
setTimeout(function() {
$('body').scrollTo( '300px', 2500 );
}, 3000);
});
}(jQuery));
</script>
thanks for everybody!!!
When using jQuery, you could easily use the .animate function.
Here's an example on how it should work.
Using jQuery makes this much easier, perhaps with the scrollto plugin. http://flesler.blogspot.se/2007/10/jqueryscrollto.html
Consider a solution such:
<script type='text/javascript' src='js/jquery.1.7.2.min.js'></script>
<script type='text/javascript' src='js/jquery.scrollTo-min.js'></script>
<script type='text/javascript' src='js/jquery.easing.1.3.js'></script><!-- only for other easings than swing or linear -->
<script type='text/javascript'>
$(document).ready(function(){
setTimeout(function() {
$('html,body').scrollTo( {top:'30%', left:'0px'}, 800, {easing:'easeInBounce'} );
}, 3000);
});
</script>
Of course you need to dl the scripts.
See http://jsfiddle.net/7bFAF/2/ for a working example
We can make it simpler by using the css property scroll-behavior
html {
scroll-behavior: smooth;
}
Related
I have a page "link.html" which has an anchor pointing to index.html page <a href = "index.html?#myInnerLink"
I want smoothscroll to the div on another page(index.html) which has an Id of "myInnerLink" in jquery .. it is working fine but the problem is that it is scrolling from bottom to top instead of top to bottom to that particular div
"myInnerLink" div is internal in "myDiv" div... Thanks
link.html
<a id="mylink" href="index.html?#myInnerLink">Go To MY InnerLink</a>
index.html
<div id="myDiv" class="mydiv">
SomeText here...
<div id="myInnerLink">
ScrollTo This Div...
</div>
</div>
jquery
$(document).ready(function() {
if (window.location.hash) {
var hash = window.location.hash;
$('#myDiv').animate({
scrollTop : $(hash).offset().top
}, 500);
};
});
I'm currently using this script below, which is modified and originally came from https://jsfiddle.net/s61x7c4e/
function doScrolling(element, duration) {
let bodyRect = document.body.getBoundingClientRect(),
elementRect = element.getBoundingClientRect(),
offset = ((elementRect.top - bodyRect.top) - 40);
let startingY = window.pageYOffset,
elementY = offset,
targetY,
diff,
easeInOutCubic,
start;
duration = duration || 500;
// if element is close to page's bottom then window will scroll only to some position above the element...
targetY = document.body.scrollHeight - elementY < window.innerHeight ? document.body.scrollHeight - window.innerHeight : elementY;
diff = targetY - startingY;
easeInOutCubic = function (t) {
return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
};
if (!diff) return;
// bootstrap our animation,
// it will get called right before next frame shall be rendered...
window.requestAnimationFrame(function step(timestamp) {
if (!start) start = timestamp;
let time = timestamp - start, // elapsed milliseconds since start of scrolling...
percent = Math.min(time / duration, 1); // get percent of completion in range [0, 1]
// apply the easing, it can cause bad-looking
// slow frames in browser performance tool, so be careful...
percent = easeInOutCubic(percent);
window.scrollTo(0, startingY + diff * percent);
// proceed with animation as long as we wanted it to.
if (time < duration) {
window.requestAnimationFrame(step)
}
})
}
document.getElementById('scrollMid').addEventListener('click', function(){
var element = document.getElementById('middle');
doScrolling(element, 1000);
});
I need to clear interval of function in this example
$.fn.bounce = function(options) {
var settings = $.extend({
speed: 10
}, options);
return $(this).each(function() {
var $this = $(this),
$parent = $this.parent(),
height = $parent.height(),
width = $parent.width(),
top = Math.floor(Math.random() * (height / 2)) + height / 4,
left = Math.floor(Math.random() * (width / 2)) + width / 4,
vectorX = settings.speed * (Math.random() > 0.5 ? 1 : -1),
vectorY = settings.speed * (Math.random() > 0.5 ? 1 : -1);
// place initialy in a random location
$this.css({
'top': top,
'left': left
}).data('vector', {
'x': vectorX,
'y': vectorY
});
var move = function($e) {
var offset = $e.offset(),
width = $e.width(),
height = $e.height(),
vector = $e.data('vector'),
$parent = $e.parent();
if (offset.left <= 0 && vector.x < 0) {
vector.x = -1 * vector.x;
}
if ((offset.left + width) >= $parent.width()) {
vector.x = -1 * vector.x;
}
if (offset.top <= 0 && vector.y < 0) {
vector.y = -1 * vector.y;
}
if ((offset.top + height) >= $parent.height()) {
vector.y = -1 * vector.y;
}
$e.css({
'top': offset.top + vector.y + 'px',
'left': offset.left + vector.x + 'px'
}).data('vector', {
'x': vector.x,
'y': vector.y
});
setTimeout(function() {
move($e);
}, 50);
};
move($this);
});
};
$(function() {
$('#wrapper li').bounce({
'speed': 7
});
});
So whenever I need I start the animating circle and when I don't want I can stop. So in the above code you can see move($this); is getting called in interval what I need to stop or clear the interval so the circle stop animating. and when again I need I can just click the button and it again start animation.
I divided your code in bounce function into three section:
One for initialization where the element took their start positions.
Another for the logic of animation (with the start and stop added)
The last one is for the movement (the same function move but insetead of define it inside each (not good because it will get redifined for every element), I defined it outside the each).
The code contain tons of comments. If something is still unclear post a comment bellow.
$.fn.bounce = function(options) {
var settings = $.extend({
speed: 10
}, options);
// Keep a reference to this to use when we are inside bounded functions (where this is something different)
var that = this;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// LOGIC FOR INITIALIZATION ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// function init to initialize the elements.
function init(){
$(that).each(function() {
var $this = $(this),
$parent = $this.parent(),
height = $parent.height(),
width = $parent.width(),
top = Math.floor(Math.random() * (height / 2)) + height / 4,
left = Math.floor(Math.random() * (width / 2)) + width / 4,
vectorX = settings.speed * (Math.random() > 0.5 ? 1 : -1),
vectorY = settings.speed * (Math.random() > 0.5 ? 1 : -1);
// place initialy in a random location
$this.css({
'top': top,
'left': left
}).data('vector', {
'x': vectorX,
'y': vectorY
});
});
}
// call it right away (initialize) before starting anything else
init();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// LOGIC FOR ANIMATION ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the boolean that will stop the animation
var keepGoing = false;
// If the selector for the start button is specified
if(settings.start){
// attach animate to its click event listener
$(settings.start).on("click", animate);
}
else // no button is provided then start automatically
animate();
// If the selector for the stop button is specified
if(settings.stop){
// attach stop to its click event listener
$(settings.stop).on("click", stop);
}
// the function that will start the animation
function animate(){
// If we are not already animating
if(!keepGoing){
keepGoing = true;
// call move on all the elements to start the magic.
// we use 'that' instead of 'this' here because 'this' is the button that have been clicked (see the event listener above=.
$(that).each(function() {
move($(this));
});
}
}
// the function that will stop the animation ...
function stop(){
// ... by simply set keepGoing to false
keepGoing = false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// LOGIC FOR MOVEMENT ///////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the move function responsible for moving the elements
function move($e) {
var offset = $e.offset(),
width = $e.width(),
height = $e.height(),
vector = $e.data('vector'),
$parent = $e.parent();
if (offset.left <= 0 && vector.x < 0) {
vector.x = -1 * vector.x;
}
if ((offset.left + width) >= $parent.width()) {
vector.x = -1 * vector.x;
}
if (offset.top <= 0 && vector.y < 0) {
vector.y = -1 * vector.y;
}
if ((offset.top + height) >= $parent.height()) {
vector.y = -1 * vector.y;
}
$e.css({
'top': offset.top + vector.y + 'px',
'left': offset.left + vector.x + 'px'
}).data('vector', {
'x': vector.x,
'y': vector.y
});
// if keep going, ... you know, keep going.
if(keepGoing){
setTimeout(function() {
move($e);
}, 50);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
// the options can have the 'start' and 'stop' selector optionally.
$(function() {
$('#wrapper li').bounce({
'speed': 7,
'start': '#startAnimation', // selector of the element that when clicked the animation will start. If not provided the animation will start automatically
'stop' : '#stopAnimation' // selector of the element that when clicked the animation will stop (pause). If not provided the animation will go for ever
});
});
body, * {
padding: 0 !important; margin: 0: }
#wrapper {
width:500px;
height: 500px;
border:
1px solid red; }
li {
position: absolute;
width: 60px;
height: 60px;
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
border-radius: 30px;
background-color:#0FF;
line-height: 60px;
text-align:center;
cursor:pointer; }
button{
width: 100px;
height: 30px;
}
<script src='http://code.jquery.com/jquery-3.1.1.min.js'></script>
<ul id="wrapper">
<button id="startAnimation">Start</button>
<button id="stopAnimation">Stop</button>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
I think you want to be using setInterval for this problem. You can use clearInterval on the instance of setInterval you created to make it stop.
Why I think you should be using setInterval instead of setTimeout? Well because setInterval is meant for running functions in a certain time interval (which is what you want to do). Where as setTimeout is meant to delay a function call.
// sample code
var counter = 0;
var example = setInterval(function(){
console.log(counter);
if (counter == 10) {
console.log("I'm out");
clearInterval(example);
}
counter++;
}, 300);
You can assign timeout function to a variable and use clearTimeout method. Like below:
var timer = setTimeout(function() {
move($e);
}, 50);
clearTimeout(timer);
Please, play with teh fiddle below. ONE bug goes as it should - turns its "head" and crawls in proper direction. But several bugs (starting with two and up) destroy it all. Jquery "each" returns coordinates twice so instead of two sets of coordinates for two bugs FOUR are generated.
$(document).ready(function () {
function bug() {
$('.bug').each(function () {
//var bugs = $('.bug').length;
var h = $(window).height() / 2;
var w = $(window).width() / 2;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
//$this = $(this);
//var newCoordinates = makeNewPosition();
var p = $(this).offset();
var OldY = p.top;
var NewY = nh;
var OldX = p.left;
var NewX = nw;
var y = OldY - NewY;
var x = OldX - NewX;
angle = Math.atan2(y, x);
angle *= 180 / Math.PI
angle = Math.ceil(angle);
console.log(p);
$(this).delay(1000).rotate({
animateTo: angle
});
$(this).animate({
top: nh,
left: nw
}, 5000, "linear", function () {
bug();
});
});
};
bug();
});
http://jsfiddle.net/p400uhy2/
http://jsfiddle.net/p400uhy2/4/
As mentioned by #Noah B, the problem is that each "bug" is setting the loop for all "bugs".
I'd make bug() function per element, so that each "bug" can be set individually.
EDIT (#Roko C. Buljan comment)
function bug() {
// ... your code ...
// calculate animation time, so that each of bugs runs same fast in long and short distance:
var top_diff = Math.abs(OldY - nh),
left_diff = Math.abs(OldX - nw),
speed = Math.floor(Math.sqrt((top_diff * top_diff) + (left_diff * left_diff))) * 15;
$(this).animate({
top: nh,
left: nw
}, speed, "linear", function () {
// rerun bug() function only for that single element:
bug.call(this);
});
};
$('.bug').each(bug);
DEMO
The problem is that you had .each() calling a function with .each() in it...so each bug had the bug() callback. You just have to move the bug() call outside of the .each(){}. See fiddle: http://jsfiddle.net/p400uhy2/2/
I am trying to animate a video on scroll like the landing page for the new iPhone 6. I have the video animating on scroll, but I am trying to some how ease the the video once the mousewheel has been released. I'm not sure how I should approach this challenge. Should I be trying to use an actual easeOut function? Or should I do it some other way?
Here is a snippet of the JS I currently have. And a live example here.
function easeOut(t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
};
var $win = $(window),
$video = $('video'),
frameRate = 29.97,
target = 0,
scroll = 0,
isTicking, scrollTimeout, delta, target;
var ScrollVideo = function() {
this.scrollY = 0;
$win.on('mousewheel DOMMouseScroll', this.onScroll.bind(this));
};
ScrollVideo.prototype = {
/**
* Callback for our scroll event
* keeps track of the last scroll value
*/
onScroll: function(event) {
var e = event.originalEvent ? event.originalEvent : event; // get original event if available
target += (e.wheelDelta > 0) ? -70 : 70;
if (target < 0) target = 0;
delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
this.requestScrollTick();
},
/**
* Calls rAF if it hasn't already
* been done
*/
requestScrollTick: function() {
if( !isTicking ) {
window.requestAnimationFrame(this.scrollHandler);
}
isTicking = true;
},
/**
* Animate stuff on scroll
*/
scrollHandler: function() {
scroll += (target - scroll) * 0.1;
console.log(scroll);
if(delta < 0) {
$video[0].currentTime += (1 / frameRate);
}
else {
$video[0].currentTime -= (1 / frameRate);
}
// stop ticking
isTicking = false;
}
};
var scrollVideo = new ScrollVideo();
I'd love to be able to tackle this, any help/direction is greatly appreciated.
I'm searching for a good vertical bubble marquee plugin.
Not simple vertical marquee, I'm looking for a good "flash like" effects plugin, something smooth with element marquee from bottom to top of a div content.
Could be really nice but I think it's only in my dreams this plugin
Well, it's not terribly efficient, but this is a good start I think:
jQuery.fn.verticalMarquee = function(vertSpeed, horiSpeed) {
this.css('float', 'left');
vertSpeed = vertSpeed || 1;
horiSpeed = 1/horiSpeed || 1;
var windowH = this.parent().height(),
thisH = this.height(),
parentW = (this.parent().width() - this.width()) / 2,
rand = Math.random() * 1000,
current = this;
this.css('margin-top', windowH + thisH);
this.parent().css('overflow', 'hidden');
setInterval(function() {
current.css({
marginTop: function(n, v) {
return parseFloat(v) - vertSpeed;
},
marginLeft: function(n, v) {
return (Math.sin(new Date().getTime() / (horiSpeed * 1000) + rand) + 1) * parentW;
}
});
}, 15);
setInterval(function() {
if (parseFloat(current.css('margin-top')) < -thisH) {
current.css('margin-top', windowH + thisH);
}
}, 250);
};
$('.message').verticalMarquee(0.5, 1);
It uses Math.sin to move the element horizontally. The function verticalMarquee accepts two arguments, one for vertical speed and the other for horizontal speed. The function can only be called on jQuery objects that contains only one element - during testing anything more than one element been animated at once caused terrible amount of lagging.
See a simple demo here: http://jsfiddle.net/CcccQ/2/
Do you mean something like The Silky Smooth Marquee plugin?