Why does this not pauseFx before morph-ing? - javascript

This morphs just fine but I need it to pause first then morph.
var animate = (function(){
var div = document.getElement('div.es-transition');
if (div){
div.set('morph', {duration: 800, transition: 'quad:out'});
div.pauseFx(1000, 'morph');
div.addClass('hidden');
div.setStyles({'visibility': 'hidden', 'opacity': 0});
div.removeClass('hidden').fade('in');
}
});
window.addEvent('load', animate);
Banging head.
TIA

don't know about pauseFx? this is not standard mootools-core api. it has http://mootools.net/docs/core/Fx/Fx#Fx:pause - which needs to be applied to the instance.
in your case, it makes no sense anyway as you pause before you even run it. which means, use setTimeout or delay. pause is to stop and resume a morph/tween midway. please clarify what you are trying to achieve
also. .set('morph') does not work with .fade() - fade is based on tween options, not morph. the difference between tween and morph is single property vs multiple properties.
if I understand this correctly, you need to rewrite as:
var animate = (function(){
var div = document.getElement('div.es-transition');
if (div){
div.set('tween', {duration: 800, transition: 'quad:out'});
div.addClass('hidden');
div.setStyles({'visibility': 'hidden', 'opacity': 0});
(function(){
div.removeClass('hidden').fade(0, 1);
}).delay(1000);
}
});
window.addEvent('load', animate);

Related

How to replace margin-left animation with transform in Jquery animate() to fix laggy multislider

I'll preface this by saying my initial problem is difficult to reproduce.
Brief explanation of my problem following, question is at the bottom.
So I am using the Jquery multislider for a project.
Here is a link to it: Multislider
Now my issue is that the animation of the moving elements seems to lag... Sometimes.
It jumps instead of moving smoothly.
The way the element works is by applying the animate() method to the first item and applies an inline margin-left property to the first .item
With some research I have found that CSS animations often cause problems when margins are used for the animation(among some other properties like top/bottom/left/right, as well as height/width) and that using transform is preferable.
So far so good.
This is the snippet in the javascript that creates the animation:
function singleLeft(){
isItAnimating(function(){
reTargetSlides();
$imgFirst.animate(
{
marginLeft: -animateDistance /* This is the part that causes me problems */
}, {
duration: animateDuration,
easing: "swing",
complete: function(){
$imgFirst.detach().removeAttr('style').appendTo($msContent);
doneAnimating();
}
}
);
});
}
function singleRight(){
isItAnimating(function(){
reTargetSlides();
$imgLast.css('margin-left',-animateDistance).prependTo($msContent);
$imgLast.animate(
{
marginLeft: 0
}, {
duration: animateDuration,
easing: "swing",
complete: function(){
$imgLast.removeAttr("style");
doneAnimating();
}
}
);
});
}
Now if I understand it correctly, I have to replace the marginLeft: -animateDistance portion with a transformX property, is that correct?
But I am failing to make it work.
So my question is, how can I replace the marginLeft: -animateDistance portion with transform: translateX() and add the animateDistance variable between the parentheses?
I have tried something like transform: "translateX(-$(animateDistance))", but that just disables the animation entirely.
Am I missing something?
I'm open for other suggestions to solve the issue of the laggy animation as well, this just is the conclusion I came to.
You can use animate with $(this) and .css() if you use step()
let test = "100";
$('div h2').animate({ pxNumber: test }, {
step: function(pxNumber) {
$(this).css('transform','translateX(-' + pxNumber + 'px )');
},
duration:'slow',
easing: "swing",
complete: function(){
console.log('Animation done');
// doneAnimating();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div><h2>Move it</h2></div>

jQuery - Find CSS bottom of div at start, not during animation on hover

I'm finding the CSS value 'bottom' for each of these divs with the class of 'shelf-info-text'. Each of these divs are inside shelf-item.
The bottom value is automatically calculated using another function. On hover I wish bottom to be changed to 0px by way of animation, and then revert to the original bottom. Bottom will be different for every single div.
I have added a little code to find the bottom, however if you hover again mid-animation this finds the bottom before it has returned back to the original state, therefore breaking the animation.
Please advise where I'm going wrong. Thanks.
var $itemBottom = null;
$('.shelf-item').hover(function() {
$itemBottom = $(this).find('.shelf-info-text').css('bottom');
$(this).find('.shelf-info-text').stop().animate({ 'bottom': '0px'}, 300);
}, function() {
$(this).find('.shelf-info-text').stop().animate({ 'bottom': $itemBottom}, 300);
});
Edit :
After re-reading the question here's a solution that will get the bottom and save it in a data attribute.
// we loop through all the shelf items and set a data attribute to keep track of it.
$('.shelf-item').each(function(){
$item = $(this).find('.shelf-info-text');
$itemBottom = $item.css('bottom');
$item.data('bottom', $itemBottom);
});
$('.shelf-item').hover(function() {
$itemBottom = $(this).find('.shelf-info-text').data('bottom');
$(this).find('.shelf-info-text').stop().animate({ 'bottom': '0px'}, 300);
}, function() {
$(this).find('.shelf-info-text').stop().animate({ 'bottom': $itemBottom}, 300);
});
I'm too late to the party (because I got distracted making this fiddle). My approach is the same as #Patsy's but I avoid the .each() loop to set the data-bottom by simply setting it if it doesn't already exist:
var $el = null;
$('.shelf-item').hover(function() {
$el = $(this).find('.shelf-info-text');
$el.data('bottom',($el.data('bottom') || $el.css('bottom'))).stop().animate({ 'bottom': '0px'}, 300);
}, function() {
$el = $(this).find('.shelf-info-text');
$el.stop().animate({ 'bottom': $el.data('bottom')}, 300);
});
You could store the original bottom value using jQuery.data(). Then your function could check to see if that value had been stored, and never recalculate the bottom (avoiding the mid-animation issue).

Mootools wait with Fx.Morph start

I am trying to get var effect = new Fx.Morph(testMorph, { to wait/delay 2 seconds before starting.
(fiddle here)
But when I try .wait(2000) or .delay(2000), or even .wait(2000, effect) I get Uncaught TypeError: Object [object Object] has no method 'delay'
Any ideas how to get this working?
Code I'm using:
var testMorph = document.id('testMorph');
var effect = new Fx.Morph(testMorph, {
transition: 'back:out',
duration: 900,
link: 'chain'
}).start({
'top': 20,
'opacity': 1
}).start({
'border-color': '#A80025',
'color': '#A80025'
});
effect.delay(2000);
You can use a combination of chain() and delay() to achieve the desired effect.
new Fx.Morph(testMorph, {
transition: 'back:out',
duration: 900,
link: 'chain'
}).start().chain(function(){
this.start.delay(2000,effect,{
//first
});
}).chain(function(){
this.start({
//second
});
});
The chain() adds another effect at the end of the current one.
The first effect is simply start() with an empty effect, to provide context to our chain of events.
It is then chained to the delayed event, using the start.delay() method (delay() is a property of Function).
This, in turn, is chained to your other effect.
See here.

How to manage multiple elements in a mouseenter function in Mootools?

Hi! I really try to find a topic related to my issue here, but I had no luck...
Some simple code: I have two divs, placed in the same position -
<div id="fader1" style="display:inline-block;position:absolute;background-image:url(images/fader1.png);opacity:1;width:296px;height:435px;margin:-215px 50px -20px"></div>
<div id="fader2" style="display:inline-block;position:absolute;background-image:url(images/fader2.png);opacity:0;width:296px;height:425px;margin:-215px 50px -20px"></div>
The idea is when the mouse passes over the div "fader1", the opacity changes to 0, and the opacity of fader2 changes to 1. And turn back like the beginning if I put the cursor out of the div.
I've tried to achieve this with mootools but I'm now in a dead-end.
Mootools Demos have the example of Fx.Morph like this:
$('myElement').set('opacity', 0.5).addEvents({
mouseenter: function(){
// This morphes the opacity and backgroundColor
this.morph({
'opacity': 0.6,
'background-color': '#E79D35'
});
},
mouseleave: function(){
// Morphes back to the original style
this.morph({
opacity: 0.5,
backgroundColor: color
});
}
});
As you can see, I can only manage ONE element (this.morph). I try to put other element like: "('fader1').morph" with no results... But I think that I'm doing it wrong.
I really appreciate any help you can give me to achieve this in mootools. Regards!
you should read the manual and not copy/paste from examples.
$('myElement').set('opacity', 0.5).addEvents({
mouseenter: function(){
// This morphes the opacity and backgroundColor
this.morph({
'opacity': 0.6,
'background-color': '#E79D35'
});
}
});
in the above function, the scope this refers to myElement. if you need to reference a different element, then simply do so.
(function(){
var other = $('myOtherElement').set('moprh', {
link: 'cancel'
}); // save a reference and set link to cancel existing morphing
$('myElement').set('opacity', 0.5).addEvents({
mouseenter: function(){
// This morphes the opacity and backgroundColor
other.morph({
'opacity': 0.6,
'background-color': '#E79D35'
});
},
mouseleave: function(){
// Morphes back to the original style
other.morph({
opacity: 0.5,
backgroundColor: color
});
}
});
}());
read up on what $ (documentid) returns (an element), saving an element into a variable and referencing it later - this is standard javascript.

How to track element movement and trigger function at specific spot?

I have a #ball that when clicked uses jquery animate to move down 210px using this code:
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, 500);
setTimeout(crack, 400);
});​
currently Im using Timeout to trigger the next function which is "crack".
Instead I want to track the movement of #ball and when its css top = 210px I want to trigger the function crack(), how can I do this?
I saw in a somewhat similar post that the Step function might be what I'm looking for, but I am not sure how to approach that solution based on the info provided at http://api.jquery.com/animate/
Look at Demo: http://jsfiddle.net/EnigmaMaster/hbvev/4/
I am not sure why you want to use a tracker if you know that the ball will reach the box in 210px.
If you want to get rid of setTimeout, then use the .animate callback function which will be called when the ball reaches the box.
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, 500, crack); //<== crack will be called after ball animation
});​
DEMO
Incase if you want to call crack when the ball touches the box and still continue the movement of box then you can execute it 2 steps like below,
$('#ball').click(function() {
$(this).animate({
top: '+=180px'
}, 400, function() {
crack();
$(this).animate({
top: '+=30px'
}, 100);
});
});
Also check this version for fun in slow motion http://jsfiddle.net/skram/hbvev/8/
If you truly want to do something based on the position of the ball, then yes, step is probably the best way to go:
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function() {
if($(this).offset().top > 208) {
crack();
}
}
});
});
Demo: http://jsfiddle.net/qJjnN/1/
Now, there are a couple of caveats:
There will be a possible performance hit.
The position at each step will not necessarily be a whole number, and the object will not exist at every pixel between the start and stop location.
step is not called on the final position, so you cannot actually check for 210 if it is the final location.
Taking those into mind, you will not be able to check for the exact position of 210px. Instead, you will want to watch when it passes a certain position and only trigger crack at that point and not every point after:
$('#ball').click(function() {
var cracked = false;
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function() {
if($(this).offset().top > 208 && !cracked) {
cracked = true;
crack();
}
}
});
});
Demo: http://jsfiddle.net/qJjnN/2/
The step function also has parameters now and fx that can be used to see the current value of the css being animated. step is called for each step of each css attribute being animated. So, you have to be careful using those, because you need to look at fx to see what attribute value you are looking at (if you are animating more than one, i.e. top and left).
$('#ball').click(function() {
var cracked = false;
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function(now, fx) {
if(fx.prop != 'top') {
return;
}
if(now > 208 && !cracked) {
cracked = true;
crack();
}
}
});
});

Categories