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/
Related
I'm trying to write jQuery plugin for making accordion.
All items inside the container need to reduce their width so all items could be shown on one line.
On item hover, rest of the items should reduce width so it the hover item could be shown at its original width.
The error occurs when trying to initial set the items: the last item disappears.
the math is:
slider-width / all-items-width
and then:
each-item * (slider-width / all-items-width)
What am I calculating wrong?
jQuery(function($) {
$.fn.shadeAccordion = function(elmwrap, sliderH) {
var $this = $(this), //get the slider countiner
SlideR = $this,
SliderWidth = SlideR.width(), // slider should inherit parent witdth
thumbA = SlideR.find('a'), // images should wrap with a tag
thumbMOunt = thumbA.length, // count the number of images
thumbImg = thumbA.find('img'); // find acctual imgaes
var imgaesWidth = 0;
thumbImg.each(function(index, el) {
imgaesWidth += $(el).width();
});
console.log(imgaesWidth);
var margineach = SliderWidth / imgaesWidth;
console.log(margineach);
//some CSS Settigns
SlideR.find(elmwrap).css({
'transition': 'width .2s ease-in',
'height': sliderH,
'overflow': 'hidden',
'position': 'static'
}).find('img').css({
height: sliderH,
width: 'auto',
'position': 'relative',
'max-width': 'none'
});;
$.fn.HoverAnimation = function(SliderWidth) {
var $this = $(this), //get the specific hoverd container
imgWid = $this.data('orginalwidht'), //actual image width for this cont
sliderWidthAfterOpen = SliderWidth - imgWid,
thumbImgSibDiv = $this.siblings(elmwrap);
var sibImgaesWidth = 0;
thumbImgSibDiv.each(function(index, el) {
sibImgaesWidth += $(el).width();
});
var margineachOpend = sliderWidthAfterOpen / sibImgaesWidth;
$this.addClass('active').width(imgWid).css('opacity', '1');
thumbImgSibDiv.addClass('inactive').each(function() {
var thisW = $(this).width();
$(this).width(thisW * margineachOpend).css('opacity', '0.4');
});
}; //End of mouse over
$.fn.LeaveAnimation = function(SliderWidth) {
var $this = $(this),
imgWid = $this.data('editedwidth');
$this.removeClass('active').width(imgWid);
SlideR.find(elmwrap).css('opacity', '0.4').not('.active').removeClass('inactive').each(function() {
$(this).width($(this).data('editedwidth'));
}); //End of Each change Margin
}; //End of mouseleave
widhtS = 0;
// adjust new width and declare animation when hover
SlideR.find(elmwrap).each(function(idx, el) {
var imgW = $(el).find('img').width();
$(el).width(Math.round(imgW * margineach)); //change images width so they will super fit to the slider
$(el).attr('data-orginalwidht', imgW).attr('data-editedwidth', Math.round(imgW * margineach)).find('img').css({
margin: '0',
padding: '0'
});
$(el).css({
'margin': 0,
'clear': 'none',
'padding': 0
}); //change images width so they will super fit to the slider
widhtS += Math.round(imgW * margineach);
console.log(Math.round(widhtS));
})
.mouseover(function() {
$(this).HoverAnimation(SliderWidth)
})
.mouseleave(function() {
$(this).LeaveAnimation(SliderWidth)
});
}
});
heres a demo: https://jsfiddle.net/12345/8zd9nmvf/23/
the issue was CSS - i was calculating all images width before their width became auto.
so i moved css properties up before the calculation and it fixed:
//some CSS Settigns
SlideR.find(elmwrap).css({
'transition': 'width .2s ease-in',
'height': sliderH,
'overflow': 'hidden',
'position': 'static'
}).find('img').css({
height: sliderH,
width: 'auto',
'position': 'relative',
'max-width': 'none'
});
var imgaesWidth = 0;
thumbImg.each(function(index, el) {
imgaesWidth += $(el).width();
});
var margineach = SliderWidth / imgaesWidth;
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/
I have this markup:
<div class="container">
<figure></figure>
<figure></figure>
<figure></figure>
</div>
Now: I need to add for each of figures a symmetric element, but with different height and width value. For each item next I need to remove about 10% in width and height. So that the first has 90%, the second 80% and the third has 70% of initial size. I'm using the following code but it does not work, can anyone help?
var inside_element = $(figure);
var indx = 10;
inside_element.each(function(indx){
$(this).css({
width: '90%' - indx,
height: '90%' - indx
});
});
Thx.
You working on string '90%' and trying to complete math operation, which will fall. This should work:
var inside_element = $('figure');
var indx = 10;
inside_element.each(function(indx){
$(this).css({
width: (90 - (10*indx)) + '%' ,
height: (90 - (10*indx)) + '%'
});
});
Also declaration var indx = 10; is not necessary. This value will be overrided inside function.
EDIT: Also there can be more containers. Then code should look like this:
var inside_container = $('.inside_container');
inside_container.each( function(i) {
var inside_element = $(this).find('figure');
var step = 10;
inside_element.each(function(indx){
$(this).css({
width: (90 - (step*indx)) + '%' ,
height: (90 - (step*indx)) + '%'
});
});
});
You are calulating the next width and hight by substracting indx from a String.
try:
var width = 100;
var height = 100;
inside_element.each(function(indx){
width = width - 10;
height = height - 10;
$(this).css({
width: width + '%',
height: height + '%'
});
});
You are not selecting figure you need this $('figure');
var inside_element = $('figure');
inside_element.each(function(index){
$(this).css({
width: (90 - index * 10) +"%",
height:(90 - index * 10) +"%"
});
});
Try this:
var inside_element = $('figure');
var width = '90',
height = '90';
inside_element.each(function(indx){
$(this).css({
width: width + '%',
height: height + '%'
});
width = width - 10;
height = height - 10;
});
I have a vertically oriented vertical navigation bar, that I would like to make stop at the end of #contact. It will need to resume scrolling again if the user scrolls back up.
What is the best way to achieve this?
javascript being used:
$(function() {
$.fn.scrollBottom = function() {
return $(document).height() - this.scrollTop() - this.height();
};
var $el = $('#nav>div');
var $window = $(window);
var top = $el.parent().position().top;
$window.bind("scroll resize", function() {
var gap = $window.height() - $el.height() - 10;
var visibleFoot = 340 - $window.scrollBottom();
var scrollTop = $window.scrollTop()
if (scrollTop < top + 10) {
$el.css({
top: (top - scrollTop) + "px",
bottom: "auto"
});
} else if (visibleFoot > gap) {
$el.css({
top: "auto",
bottom: visibleFoot + "px"
});
} else {
$el.css({
top: 0,
bottom: "auto"
});
}
}).scroll();
});
jsfiddle
I believe this is the code you are looking for:
$(function() {
var $Nav = $('#Nav');
var $window = $(window);
var $contact = $('#contact');
var maxTop = $contact.offset().top + $contact.height() - $Nav.height();
window.navFixed = 1;
$window.bind("scroll resize", function() {
var currentTop = $window.scrollTop();
if (currentTop <= maxTop && window.navFixed == 0) {
$Nav.css({
position: 'fixed',
top: '5%'
});
window.navFixed = 1;
} else if (currentTop > maxTop && window.navFixed == 1) {
$Nav.css({
position: 'absolute',
top: maxTop
});
window.navFixed = 0;
}
}).scroll();
});
The #Nav element contains the CSS you had originally specified: position: fixed; top: (...). When the document is ready, the variable maxTop is calculated based on the #contact element's top and height.
On the scroll and resize event, the variable currentTop is calculated as the current scroll position. If this value is lower than maxTop, then #Nav is set to the original CSS; if the value is higher, new CSS styles are applied: position: absolute; top: maxTop;
window.navFixed is used to prevent the CSS to be constantly updated while scrolling. I'm sure that bit can be improved, however, it demonstrates its purpose.
Check out the JSFiddle for the full HTML..
PS. There's a minor bug in your code, where #Nav refers to the <ul> element, rather than the <nav> element. However, the moving element is the <ul>, when it should be <nav>.
Given a div "square"
and given I already have a touchmove function on that div and I can detect the position X in real time:
how can I implement the rubber band effect?
I mean: tap and drag to the left until the resistance reach the limit and if ou release the finger the square div goes back to its initial position with an easing animation
there is a simple math for that? or a plugin?
UPDATE
w/o jquery would be better if possible
Store its original position somewhere.
Then on the dragend event:
$(this).animate({
top: original_top,
left: original_left
}, 'slow');
Demo: http://jsfiddle.net/maniator/T8zYt/
Full code (with jQuery draggable):
(function($) {
$.fn.rubber = function(resist) {
var self = this,
position = $(this).position(),
selfPos = {
top: position.top,
left: position.left,
maxTop: resist + position.top,
maxLeft: resist + position.left,
minTop: resist - position.top,
minLeft: resist - position.left
};
self.draggable({
drag: function() {
var position = $(this).position(), width = $(this).width(), height = $(this).height();
if (position.left > selfPos.maxLeft || (position.left - width) < selfPos.minLeft || position.top > selfPos.maxTop || (position.top - height) < selfPos.minTop) {
return false;
}
},
stop: function() {
$(this).animate({
top: selfPos.top,
left: selfPos.left
}, 'slow');
}
})
};
})(jQuery)
$('selector').rubber(10);