Trying to loop a function.
It's a simple text animation - The text will
1.Fade in left letter by letter and then
2.Fade out up letter by letter.
3.This will repeat, but the text will appear again at another random location on the
page.
When I set the interval delay to 1000, the text appears 4 times in all with a gap of 1 sec each. The first time, the text appears with fade in left, the second & third the text just flashes as a whole and finally, the fade out happens letter by letter.
So, I set the delay to 4700. The animation works as desired, but it is not looping.
http://jsfiddle.net/y5C4G/3/
The callback function in textillate wasn't working too, so i chose setInterval.
HTML :
<span class="brand">
<h1>
<ul class="texts">
<li>E L Y S I U M</li>
<li></li>
</ul>
</h1>
</span>
JS :
$(window).bind("load", function () {
function ShowBrand() {
var docHeight = $(document).height();
var docWidth = $(document).width();
$newSpan = $(".brand");
spanHeight = $newSpan.height();
spanWidth = $newSpan.width();
maxHeight = docHeight - spanHeight;
maxWidth = docWidth - spanWidth;
$newSpan.show().css({
top: Math.floor(Math.random() * maxHeight),
left: Math.floor(Math.random() * maxWidth)
}).textillate({
in: {effect:'fadeInLeft'},
out: {effect:'fadeOutUp'}
});
}
setInterval(ShowBrand,4700);
});
I'm not so sure about what you want to achieve exactly on your animation, but I guess what you would like to do is something like this:
DEMO:http://jsfiddle.net/YKebf/9/
loadTextillate(jQuery);
$newSpan = $(".brand");
$newSpan.show().textillate({ in : {
effect: 'fadeInLeft'
},
out: {
effect: 'fadeOutUp',
callback: function () {
ShowBrand(); //set as a callback function
}
},
loop: true
});
function ShowBrand() {
var docHeight = $(document).height();
var docWidth = $(document).width();
var spanHeight = $newSpan.height();
var spanWidth = $newSpan.width();
var maxHeight = docHeight - spanHeight;
var maxWidth = docWidth - spanWidth;
var newPosTop = Math.floor(Math.random() * maxHeight);
var newPosLeft = Math.floor(Math.random() * maxWidth);
console.log("New Position",newPosTop,newPosLeft);
$newSpan.css({
top:newPosTop,
left:newPosLeft
});
}
CSS:
.brand{
position:absolute;
}
Hope this helps.
Edit: As mentioned by naota, you can set a callback. By doing this you will not be needing any setInterval and also you might not have to modify any code in plugin file in my case. See the updated demo : http://jsfiddle.net/lotusgodkk/y5C4G/6/
Instead of initializing textillate in each interval, why not just change the top and left value of span and rather add loop:true to the textillate.
JS:
$(window).bind("load", function () {
ShowBrand();
$('.brand').textillate({ in : {
effect: 'fadeInLeft'
},
out: {
effect: 'fadeOutUp',
callback: function () {
ShowBrand()
}
},
loop: true,
});
});
function ShowBrand() {
var docHeight = $(document).height();
var docWidth = $(document).width();
$newSpan = $(".brand");
spanHeight = $newSpan.height();
spanWidth = $newSpan.width();
maxHeight = docHeight - spanHeight;
maxWidth = docWidth - spanWidth;
$newSpan.show().css({
top: Math.floor(Math.random() * maxHeight),
left: Math.floor(Math.random() * maxWidth)
});
}
Also, make sure you have .brand positioned.
CSS:
.brand{position:absolute;}
Demo: http://jsfiddle.net/lotusgodkk/y5C4G/6/
Related
I have ~33 divs that I am setting the position of randomly and animating this places. These divs are originally positioned with the help of flex and then the positions are randomized by setting their positions to relative and changing the left and top values. This happens every click.
On every alternate click, I want to return the divs to their normal position. So far the only solution to this I've found is the .removeAttr('style') method. However, I want to be able to animate their return to original position. Is this possible?
Here is the code:
var position_checker = false;
$(document).click(function() {
if(position_checker == false) {
$('.poster05-text').each(function() {
var position = $(this).offset();
$(this).css({
position: 'relative',
}, position);
var docHeight = $(document).height(),
docWidth = $(document).width(),
divWidth = 500,
divHeight = 500,
heightMax = docHeight - divHeight,
widthMax = docWidth - divWidth;
var posLeft = Math.floor(Math.random() * widthMax);
var posTop = Math.floor(Math.random() * heightMax);
// console.log(docHeight, docWidth);
$(this).animate({
position: 'fixed',
left: posLeft,
top: posTop
}, 1000 , 'easeInQuint');
});
position_checker=true;
}
else if(position_checker==true) {
$('.poster05-text').each(function() {
$(this).removeAttr('style');
});
position_checker=false;
}
});
I don't know this a right way to do that or not .. but anyway .. you need to save the previous left and top positions for each div on array
var position_checker = false , T_L_Positions = [];
$(document).click(function() {
if(position_checker == false) {
$('.poster05-text').each(function(i) {
var position = $(this).offset();
$(this).css({
position: 'relative',
}, position);
T_L_Positions[i] = new Array(position.top ,position.left);
var docHeight = $(document).height(),
docWidth = $(document).width(),
divWidth = 500,
divHeight = 500,
heightMax = docHeight - divHeight,
widthMax = docWidth - divWidth;
var posLeft = Math.floor(Math.random() * widthMax);
var posTop = Math.floor(Math.random() * heightMax);
// console.log(docHeight, docWidth);
$(this).animate({
position: 'fixed',
left: posLeft,
top: posTop
}, 1000 , 'easeInQuint');
});
position_checker=true;
}
else if(position_checker==true) {
$('.poster05-text').each(function(i) {
$(this).animate({
position: 'relative',
left: T_L_Positions[i][1],
top: T_L_Positions[i][0]
}, 1000 , 'easeInQuint');
});
position_checker=false;
}
});
Note: This Code Not Tested .. but you can try it
maybe you'll need to wrap your code in $(document).ready(function(){ //code here })
If you're looking for a non-JS solution. You should be able to use CSS Transitions to do this.
transition: top 500ms, left 300ms;
That way you can just set and remove the position and let CSS deal with the animation.
For more information check out these examples:
https://www.w3schools.com/css/css3_transitions.asp
https://css-tricks.com/almanac/properties/t/transition/
I'm trying to animate a div on scroll. The point is that the div's width must grow until it reaches 80vw and stop. This does happen, but my variable keeps on growing (it's being logged to the console) even if the >=outerWidth*0.8 condition isn't met. Thanks to this, whenever I get to 80vw and scroll up and then down, the width becomes Xvw.
$(window).on('scroll',function(){
var scrollTop = $(this).scrollTop();
var outerHeight = $(this).outerHeight();
var outerWidth = $(this).outerWidth();
var scrollBottom = scrollTop + outerHeight;
var scrollTop = $(this).scrollTop();
console.log( growNaranja );
if (scrollTop > lastScrollTop){ // scroll down
if( naranjaWidth <= (outerWidth*0.8) ){
growNaranja = (naranja.outerWidth()*100) / outerWidth;
growNaranja = growNaranja+(scrollTop*0.05);
$('.grow.naranja').css( 'width', growNaranja + 'vw' );
}
} else { // scroll up
if( naranjaWidth >= (outerWidth*0.1) ){
growNaranja = (naranja.outerWidth()*100) / outerWidth;
$('.grow.naranja').css( 'width', growNaranja + 'vw' );
growNaranja = growNaranja - ((lastScrollTop-scrollTop)*0.05);
$('.grow.naranja').css( 'width', growNaranja + 'vw' );
}
}
lastScrollTop = scrollTop;
});
You can see a working example here.
Revisited this one, it was bugging me. First, the code was all spaghetti. Second, there was really function duplication. You had a function for scrolling up and one for scrolling down, and you were using the last scrollTop to calculate the next scroll step. Instead, I've made a single scale function that gets called regardless. The value of the percentage scrolled is multiplied by the step factor, and that is added to the ORIGINAL element width. By doing this, I'm not worried about where I was just prior to the scroll, only where I am now.
So I made the scaleWidthEl an object constructor, and simply wrapped the naranja div in that. The actual code to create it is the first three lines, and could be reduced to:
var scaleNaranja = new ScaleWidthEl($('.grow.naranja'), 0.8);
The rest is self-contained, allowing changes to be made without affecting anything else.
var maxElScale = 0.8;
var naranja = $('.grow.naranja');
var scaleNaranja = new ScaleWidthEl(naranja, maxElScale);
/***
* The rest of this is a black-box function, walled away from the main code
* It's a personal peeve of mine that code gets garbled otherwise.
***/
function ScaleWidthEl(el, maxScale) {
// I don't need a minScale, as I use the initial width for that
this.el = el;
this.vwConversion = (100 / document.documentElement.clientWidth);
this.startingWidth = el.outerWidth();
this.maxScale = maxScale;
this.max = $(window).outerWidth() * this.maxScale;
this.step = (this.max - this.startingWidth) / $(window).outerHeight();
// for the sake of clarity, store a reference to `this` for
// any nested functions.
var that = this;
/**
* function scaleEl
* handle the actual scaling of the element.
* Using a given step, we will simply add that
* to the element's current width, then update the CSS
* width property of the element.
**/
this.scaleEl = function() {
// First, calculate the percentage of vertical scroll
var winheight = $(window).height();
var docheight = $(document).height();
var scrollTop = $(window).scrollTop();
var trackLength = docheight - winheight;
// gets percentage scrolled (ie: 80 NaN if tracklength == 0)
var pctScrolled = Math.floor(scrollTop / trackLength * 100);
// console.log(pctScrolled + '% scrolled')
// Now, using the scrolled percentage, scale the div
var tempWidth = this.startingWidth * this.vwConversion;
tempWidth += pctScrolled * this.step;
// I want to fix the max of the scale
if (tempWidth > (this.maxScale * 100)) {
tempWidth = this.maxScale * 100;
}
this.el.css('width', tempWidth + 'vw');
};
$(window).on("scroll", function() {
that.scaleEl();
}).on("resize", function() {
/**
* In the case of a resize, we should
* recalculate min, max and step.
**/
that.min = $(window).outerWidth() * that.minScale;
that.max = $(window).outerWidth() * that.maxScale;
that.step = (that.max - that.min) / $(window).outerHeight();
})
}
body {
height: 10000px;
}
.grow {
position: fixed;
height: 100vh;
top: 0;
left: 0;
}
.grow.gris {
width: 35vw;
z-index: 2;
background: silver;
}
.grow.naranja {
width: 10vw;
z-index: 1;
background: orange;
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js" crossorigin="anonymous"></script>
<div class="grow naranja"></div>
<!-- .naranja -->
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'm creating a simple game and i am stuck currently at something i have a div called 'box' and an image inside it called 'Parachute' when the game start the parachute should move randomly inside the border of the div
my code :
<div id="box">
</div>
<script type="text/javascript">
var ToAppend = "<img src='Parachute.gif' width='25px' height='25px' class='Parachute' /> ";
setInterval(function () {
for (var i = 1; i <= 2; i++) {
$("#box").append(ToAppend);
MoveParticles();
}
}, 3000);
function MoveParticles() {
$(".Parachute").each(function () {
var x = Math.floor(Math.random() * 400);
var y = Math.floor(Math.random() * 400);
$(this).animate({ "left": x + "px" }, "slow");
$(this).animate({ "top": y + "px" }, "slow");
});
}
<script>
You seem to be animating #box, not .Parachute.
Here's a demo to get you in the right track.
//let's build the chutes
for (var i = 0; i < 50; ++i) {
$('<div/>', {
class: 'chute'
}).appendTo('#box');
}
//cache a few static values
var box = $('#box');
var width = box.width();
var height = box.height();
var chute = $('.chute');
//our main animation "loop"
chute.each(function foo() {
//generate random values
var top = (Math.random() * height) | 0;
var left = (Math.random() * width) | 0;
var time = Math.random() * (800 - 400) + 400 | 0;
//animate
//we introduce a random value so that they aren't moving together
//after the animation, we call foo for the current element
//to animate the current element again
$(this).animate({
left: left,
top: top
}, time, foo);
});
I´m working on this website
I´m doing the resize of vertical images using this script:
function Gallery(selector) {
this.add_module = function (type, image) {
var portrait_text = image.next('.portrait_text');
var container = $('<div />', {
'class': 'gallery_container'
}).append(image).append(portrait_text);
if (type == 'horizontal') {
var h_ar = image.attr('height') / image.attr('width');
var c_width = selector.width();
var c_height = selector.width() * h_ar
container.css({
'width': c_width,
'height': c_height
})
}
if (type == 'vertical') {
var c_width = v_width;
var c_height = v_height
container.css({
'width': Math.floor(v_width),
'height': v_height
})
}
container.css({
'float': 'left',
})
container.find('img').attr({
'width': '100%',
'height': '100%'
})
container.attr('ar', c_height / c_width)
container.appendTo(selector);
//container.children('img').fitToBox();
}
this.resized = function () {
//console.log(sel)
$('.gallery_container').each(function () {
if ($(this).attr('ar') >= 1) { // vertical
$(this).css({
'width': sel.width() / 2,
'height': sel.width() / 2 * $(this).attr('ar')
})
} else { // horizontal
$(this).css({
'width': sel.width(),
'height': sel.width() * $(this).attr('ar')
})
}
})
}
var _this = this;
var gutter = 0;
// start vars for counting on vertical images
var v_counter = 0;
var w_pxls = 0;
var h_pxls = 0;
var v_ar;
// iterates through images looking for verticals
selector.children('img').each(function () {
if (parseInt($(this).attr('width')) < parseInt($(this).attr('height'))) {
v_counter++;
h_pxls += $(this).attr('height');
w_pxls += $(this).attr('width');
v_ar = $(this).attr('height') / $(this).attr('width')
}
})
// calculates average ar for vertical images (anything outside from aspect ratio will be croped)
var h_avrg = Math.floor(h_pxls / v_counter);
var w_avrg = Math.floor(w_pxls / v_counter);
var v_width = Math.floor((selector.width()) / 2);
var v_height = v_width * v_ar;
var sel = selector;
selector.children('img').each(function () {
if (parseInt($(this).attr('width')) > parseInt($(this).attr('height'))) {
_this.add_module('horizontal', $(this));
} else {
_this.add_module('vertical', $(this));
}
})
$(window).bind('resize', _this.resized);
}
var gallery = new Gallery($('#gallery_images_inner'));
http://jsfiddle.net/mZ2Ks/
The problem I have is that the script makes all the container the same of height (depending on the last image on the page I think), so for example first images resizes in a bad way. If you look at the example, all 2 image rows have a height of 613px.
Is there any way how can I control each two images container to calculate it´s own height based on its images, it looks like right now it calculates the last image resize height and apply it to all other containers
Applying height: auto instead of 100% won´t work cause it will not make the images fit the height of the vertical container.
How can I fix the script?
yes, there is a easy way. but frist: your gallery-script calculates a average aspect ratio for all images inside. there is no simple way to change this behavior.
But you can do this simple workaround: put echt two images in their own gallery!
var gallery1 = new Gallery($('#gallery_images_inner1'));
var gallery2 = new Gallery($('#gallery_images_inner2'));
var gallery3 = new Gallery($('#gallery_images_inner3'));
See http://jsfiddle.net/mZ2Ks/2/ - i had to clean up your html code a little bit - you copied the "javascript affected" html code from (i assume) firebug, but you should have copied the plain html from source code direct (CTRL + U in firefox).