I have this javascript code that make the div randomly move around web page,but i am not understanding how to make it that it does not flow continuously,its like if user click then it move and then stops there and whenever it clicks again it moves to another random position and after 5 time it shows a message and disappears.I am not getting how to make this animation not like a flow but like a leaf falling from a tree.
here is the jsfiddle : JSFIDDLE
below is the javascript code :
$(document).ready(function(){
animateDiv();
});
function makeNewPosition(){
// Get viewport dimensions (remove the dimension of the div)
var h = $(window).height() - 50;
var w = $(window).width() - 50;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
return [nh,nw];
}
function animateDiv(){
var newq = makeNewPosition();
var oldq = $('.a').offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
$('.a').animate({ top: newq[0], left: newq[1] }, speed, function(){
animateDiv();
});
};
function calcSpeed(prev, next) {
var x = Math.abs(prev[1] - next[1]);
var y = Math.abs(prev[0] - next[0]);
var greatest = x > y ? x : y;
var speedModifier = 0.1;
var speed = Math.ceil(greatest/speedModifier);
return speed;
}
I would use the CSS3 transitions, they hare hardware accelerated that mean smoother animations:
$(document).ready(function(){
var counter = 0;
$('.a').click( function () {
if ( ++counter < 5 ) {
var pos = makeNewPosition();
this.style.left = pos[1] +'px';
this.style.top = pos[0] +'px';
}
else if ( counter = 5 ) {
this.style.display = 'none';
alert( 'Your message' );
}
});
});
function makeNewPosition(){
// Get viewport dimensions (remove the dimension of the div)
var h = $(window).height() - 50;
var w = $(window).width() - 50;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
return [nh,nw];
}
div.a {
width : 50px;
height: 50px;
background-color: red;
position: fixed;
left : 0px;
top : 0px;
-webkit-transition: left 2s, top 2s;
-moz-transition: left 2s, top 2s;
-o-transition: left 2s, top 2s;
transition: left 2s, top 2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='a'></div>
The animateDiv function calls itself at the end, so as soon as it reaches its destination it picks a new destination and goes there. Here it is with the recursive callback removed:
function animateDiv(){
var newq = makeNewPosition();
var oldq = $('.a').offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
$('.a').animate({ top: newq[0], left: newq[1] }, speed);
};
And an updated fiddle, which now requires clicking the box to animate it: http://jsfiddle.net/Xw29r/3975/
Something like this ?
var isStart = true;
$(".a").click(function () {
animateDiv(isStart);
});
function makeNewPosition() {
// Get viewport dimensions (remove the dimension of the div)
var h = $(window).height() - 50;
var w = $(window).width() - 50;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
return [nh, nw];
}
function animateDiv() {
var newq = makeNewPosition();
var oldq = $('.a').offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
if (isStart) {
$('.a').animate({
top: newq[0],
left: newq[1]
}, speed, function () {
animateDiv();
});
isStart = false;
} else {
$('.a').stop();
isStart = true;
}
};
function calcSpeed(prev, next) {
var x = Math.abs(prev[1] - next[1]);
var y = Math.abs(prev[0] - next[0]);
var greatest = x > y ? x : y;
var speedModifier = 0.1;
var speed = Math.ceil(greatest / speedModifier);
return speed;
}
div.a {
width: 50px;
height:50px;
background-color:red;
position:fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div class='a'></div>
Related
To fire a console.log if a user scrolls on a webpage 25% and waits for 2 seconds or more. Similarly fire 50% scroll after a user scrolls a webpage 50% and waits for 2 seconds and similarly for 75% and 100%.
For example a user scrolls directly to 50% and waits there for 2 seconds then fire only 50% and not 25%. And also when the user scrolls to 100% quickly without 2 secs halt and then goes back to top do not fire any console.log as user has'nt waited for 2 secs. Pls help in adding this 2 seconds halt and then firing the console.log,
I did this using Javascript it is working but now how to add 2 seconds ?
var maxScrollHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var percentageObj = {};
var percentagesArr = [25,50,75,100];
window.addEventListener("scroll", function (event) {
var scrollVal = this.scrollY;
for(var i =0; i<percentagesArr.length;i++){
var currentPercentage = percentagesArr[i];
var scrollPercentage = parseInt((maxScrollHeight/100) * currentPercentage);
if(scrollVal >= scrollPercentage && !window.percentageObj[scrollPercentage.toString()]){
console.log("scrolled past - " + currentPercentage.toString() + "%");
window.percentageObj[scrollPercentage.toString()] = true;
}
}
});
Use setTimeout to delay logging and clearTimeout whenever page percentage changes:
var maxScrollHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var percentagesArr = [25,50,75,100];
const showed = {};
let timeout;
let previousPercentage;
window.addEventListener("scroll", function (event) {
var scrollVal = this.scrollY;
var scrollPercentage = Math.round(scrollVal / maxScrollHeight * 100);
let currentPercentage = 0;
let i = 0;
while(percentagesArr[i] <= scrollPercentage) {
currentPercentage = percentagesArr[i++];
}
if (previousPercentage !== currentPercentage) {
clearTimeout(timeout);
timeout = currentPercentage !== 0 && !showed[currentPercentage]
? setTimeout(() => {
console.log(currentPercentage);
showed[currentPercentage] = true;
}, 2000)
: null;
previousPercentage = currentPercentage;
}
});
window.addEventListener("resize", () => {
maxScrollHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
})
body {
height: 500vh;
position: relative;
margin: 0;
}
#container div {
height: 30px;
background-color: red;
position: absolute;
width: 100%;
font-family: sans-serif;
justify-content: center;
display: flex;
align-items: center;
}
#p25 {
top: calc(25% * 4/5);
}
#p50 {
top: calc(50% * 4/5);
}
#p75 {
top: calc(75% * 4/5);
}
<div id="container">
<div id="p25">25%</div>
<div id="p50">50%</div>
<div id="p75">75%</div>
</div>
var maxScrollHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var percentageObj = {};
var percentagesArr = [25,50,75,100];
window.addEventListener("scroll", function (event) {
var scrollVal = this.scrollY;
for(var i =0; i<percentagesArr.length;i++){
var currentPercentage = percentagesArr[i];
var scrollPercentage = parseInt((maxScrollHeight/100) * currentPercentage);
let currentTop = window.scrollY;
if(scrollVal >= scrollPercentage && !window.percentageObj[scrollPercentage.toString()]){
setTimeout((currentTop)=>{
if(currentTop === window.scrollY){
console.log("scrolled past - " + currentPercentage.toString() + "%");
window.percentageObj[scrollPercentage.toString()] = true;
}
},2000)
}
}
});
try this.
I have this function I'm using it in my AngularJS directive. This function scrolls to the top of the page, but this is not what I am aiming to do: I want to make it scroll up just 400px or 30%.
function scrollToTop() {
var scrollDuration = 500;
var scrollStep = -window.scrollY / (scrollDuration / 15);
console.log(scrollStep);
var scrollInterval = setInterval(function () {
if (window.scrollY != 0) {
window.scrollBy(0, scrollStep);
} else {
clearInterval(scrollInterval);
}
}, 15);
}
I tried changing the scrollStep variable to be 300 or any other number but I can't understand it actually.
The total distanceToScroll is either an arbitrary number of pixels (i.e 400) or the whole window-scroll distance if it is less than 400. For that you can use Math.min. scrollStep is calculated dependently from distanceToScroll. You need to keep a count of "how much I've scrolled so far" in the setInterval, lets call it distanceScrolled. Keep scrolling until you have covered the distanceToScroll.
function scrollToTop() {
var scrollDuration = 500;
var stepDuration = 15;
var distanceToScroll = Math.min(400, window.scrollY);
var scrollStep = distanceToScroll / (scrollDuration / stepDuration);
console.log(scrollStep);
var distanceScrolled = 0;
var scrollInterval = setInterval(function () {
if (distanceScrolled < distanceToScroll) {
window.scrollBy(0, -1 * scrollStep);
distanceScrolled += scrollStep
} else {
clearInterval(scrollInterval);
}
}, stepDuration);
}
document.getElementById('btn').addEventListener('click', scrollToTop);
#very-high {
height: 3000px;
}
#btn {
position: fixed;
right: 10px;
top: 10px;
}
<div id="very-high"></div>
<button id="btn">Scroll</button>
I'm trying to make my menu items move to random positions without overlapping on top of each other. I'm using animate with top left and obviously for those to work I set the position property to absolute.
Now the problem with this approach is that they will go across on top of each other when I just want them to bounce off on each other.
Is there a way to accomplish this?
function Menu($item) {
this.item = $item;
};
Menu.prototype.makeNewPosition = function ($container) {
var h = $container.height() - 50;
var w = $container.width() - 50;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
return [nh, nw];
};
Menu.prototype.move = function () {
var that = this;
$.each(this.item, function(index, value) {
var newq = that.makeNewPosition($(value).parent());
$(value).animate({
top: newq[0],
left: newq[1]
}, 2000, function() {
that.move();
});
});
};
var $menu = new Menu($('.nav li'));
$menu.move();
JSfiddle
I want this script not to change the sizes of the images but the same sizes anywhere they are during sliding. The issue is somewhere in this code but i don't know which one that is changing the size. I want an even size
/**
* Given the item and position, this function will calculate the new data
* for the item. One the calculations are done, it will store that data in
* the items data object
*/
function performCalculations($item, newPosition) {
var newDistanceFromCenter = Math.abs(newPosition);
// Distance to the center
if (newDistanceFromCenter < options.flankingItems + 1) {
var calculations = data.calculations[newDistanceFromCenter];
} else {
var calculations = data.calculations[options.flankingItems + 1];
}
var distanceFactor = Math.pow(options.sizeMultiplier, newDistanceFromCenter)
var newWidth = distanceFactor * $item.data('original_width');
var newHeight = distanceFactor * $item.data('original_height');
var widthDifference = Math.abs($item.width() - newWidth);
var heightDifference = Math.abs($item.height() - newHeight);
var newOffset = calculations.offset
var newDistance = calculations.distance;
if (newPosition < 0) {
newDistance *= -1;
}
if (options.orientation == 'horizontal') {
var center = data.containerWidth / 2;
var newLeft = center + newDistance - (newWidth / 2);
var newTop = options.horizon - newOffset - (newHeight / 2);
} else {
var center = data.containerHeight / 2;
var newLeft = options.horizon - newOffset - (newWidth / 2);
var newTop = center + newDistance - (newHeight / 2);
}
var newOpacity;
if (newPosition === 0) {
newOpacity = 1;
} else {
newOpacity = calculations.opacity;
}
// Depth will be reverse distance from center
var newDepth = options.flankingItems + 2 - newDistanceFromCenter;
$item.data('width',newWidth);
$item.data('height',newHeight);
$item.data('top',newTop);
$item.data('left',newLeft);
$item.data('oldPosition',$item.data('currentPosition'));
$item.data('depth',newDepth);
$item.data('opacity',newOpacity);
}
function moveItem($item, newPosition) {
// Only want to physically move the item if it is within the boundaries
// or in the first position just outside either boundary
if (Math.abs(newPosition) <= options.flankingItems + 1) {
performCalculations($item, newPosition);
data.itemsAnimating++;
$item
.css('z-index',$item.data().depth)
// Animate the items to their new position values
.animate({
left: $item.data().left,
width: $item.data().width,
height: $item.data().height,
top: $item.data().top,
opacity: $item.data().opacity
}, data.currentSpeed, options.animationEasing, function () {
// Animation for the item has completed, call method
itemAnimationComplete($item, newPosition);
});
} else {
$item.data('currentPosition', newPosition)
// Move the item to the 'hidden' position if hasn't been moved yet
// This is for the intitial setup
if ($item.data('oldPosition') === 0) {
$item.css({
'left': $item.data().left,
'width': $item.data().width,
'height': $item.data().height,
'top': $item.data().top,
'opacity': $item.data().opacity,
'z-index': $item.data().depth
});
}
}
}
Hi i found this animation, which i would like to use to give my navigation links a tiny, gentle random movement, but it just doesn't look very smooth. http://jsfiddle.net/2TUFF/
(Random Movement in a Fixed Container)
$(document).ready(function() {
animateDiv();
});
function makeNewPosition($container) {
// Get viewport dimensions (remove the dimension of the div)
$container = ($container || $(window))
var h = $container.height() - 50;
var w = $container.width() - 50;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
return [nh, nw];
}
function animateDiv() {
var $target = $('.a');
var newq = makeNewPosition($target.parent());
var oldq = $target.offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
$('.a').animate({
top: newq[0],
left: newq[1]
}, speed, function() {
animateDiv();
});
};
function calcSpeed(prev, next) {
var x = Math.abs(prev[1] - next[1]);
var y = Math.abs(prev[0] - next[0]);
var greatest = x > y ? x : y;
var speedModifier = 0.1;
var speed = Math.ceil(greatest / speedModifier);
return speed;
}
I've tried playing around with container size and speed but that doesn't help a lot, I also tried adding easing to the jquery myself but I have no knowledge of that mastery and failed.
Thanks!
I believe you need http://ijin.net/crSpline/demo.html for smooth "light breeze" animations.
Related answer: how to smooth jquery animations
Here is a full example in fiddle using jQuery.crSpline:
http://jsfiddle.net/2TUFF/295/