I'm trying to animate changes of the CSS "display" property with Dojo and dojo/_base/fx.
Here's my code :
function invert_display(id) {
var element = dom.byId(id),
currDisplay = style.get(element, 'display'),
nextDisplay = currDisplay === 'block' ? 'none' : 'block';
baseFx.animateProperty({
node: id,
properties: {
display: 'none',
backgroundColor: '#f00'
}
}).play();
}
Everything seems to work fine, modules are imported properly (AMD style), variable values are valid and the div background-color turns red but the div doesn't fade out ("display" property set to "none").
Thanks you in advance !
The display style cannot really be animated, as it doesn't have any intermediate values between none and the visible states (block, inline etc).
To make it fade in/out, you need to animate the opacity style (Dojo's base fx actually already has functions for this). Since you also want to animate the colour, you can for example you can change your function into something like:
function invert_display(id) {
var element = dom.byId(id),
opacity = style.get(element, 'opacity');
baseFx.animateProperty({
node: id,
properties: {
opacity: opacity<1 ? 1 : 0,
backgroundColor: opacity<1 ? '#00f' : '#f00'
}
}).play();
}
Now, setting the opacity to 0 doesn't remove the element, it just makes it transparent. If you want to elegantly remove it as well, you could perhaps add height: opacity<1 ? 42 : 0 to the animation as well, making it "minimize" while fading. Alternatively, you can use the onEnd and onBegin functions to set the display style when the animation is finished/beginning (this doesn't always look very elegant though).
Example here: http://jsbin.com/aqigoj/1/edit
Related
I know this is fairly easy in jQuery, but I want to do this in plain 'ol "will be around forever" javascript.
I have a dropdown select on my page. I choose one of 8 options. There is a default image showing on the page. When I select an option, the image changes to that pic. It all works fine.
But I want to make the image change a fade out, fade in switch over because I, like most of you, can't leave well alone. We have to keep fiddling.
The javascript that I have, which is triggered by an onchange="setPicture()" on the select dropdown is:
function setPicture(){
var img = document.getElementById("mySelectTag");
var value = img.options[img.selectedIndex].value;
document.getElementById("myImageDiv").src = value;
}
This works fine. The value of the selected index is a string with the path for each image. I just want a fade out then fade in stuck in there somewhere. I have fiddled about a bit, calling another function before changing the src but no luck.
Can someone point me in the right direction?
The easier way would be to use css keyframes alone.
But from javascript there is the web animation api made for that.
Here is a quick modif from the example, to match your case.
function setPicture(){
alice.animate(
[
{ opacity: 1 },
{ opacity: .1},
{ opacity: 1 }
], {
duration: 3000,
iterations: Infinity
}
)
}
<button onclick="setPicture()">
OPACITY ANIMATION
</button>
<img id="alice"
src="https://mdn.mozillademos.org/files/13843/tumbling-alice_optimized.gif"
>
</img>
How about setting the image default CSS with the opacity of 0 and with transition time
then in JavaScript just add a class that will make the opacity set to 1
HTML:
<img class="img1" src="sampleimg.jpg">
CSS:
.img1 {
opacity: 0;
transition: all .3s;
}
.img1.show {
opacity: 1;
}
JS:
function setPicture() {
var img = document.querySelector('.img1');
img.src = 'urlofnewimage';
img.classList.add('show');
}
Hope this helps.
Juste one function for all :
function fadeOutEffect(target) {
var fadeTarget = document.getElementById(target);
fadeTarget.style.opacity = 1;
fadeTarget.style.transition = "opacity 2s";
fadeTarget.style.opacity = 0;
setTimeout(function(){
fadeTarget.style.display = "none";
}, 2000);;
}
have a side menu on the left side of the website. I want the submenu to slide open to the right with a neat animation. I have made the script:
jQuery(document).ready(function($){
$(".main-navigation ul li").mouseenter(function() {
if ($(this).children().length > 0) {
$(this).children("ul").css ({
"display" : "block",
}).animate({
left: '250px',
opacity: 1,
}, 500)
}})
.mouseleave(function() {
setTimeout(function() {
$(this).children("ul").css({
"display" : "none",
"left" : "0px",
"opacity": 0,
})
}, 1000);
});
});
Sliding works just fine. The menu shows up nicely.
There's two problems though. One is, that the menu z-index doesn't work. The submenu's ul has a negative index set in css but when it slides it goes OVER the main ul. I want it to go UNDER the menu so it doesn't show.
Second one is, the SetTimeout function doesn't seem to work. Once the mouse leaves the area the ul just stays there forever. Without the Settimeout function it disappears just nicely (instantly though, I want it to stay there awhile).
I have made a jsfiddle example
http://jsfiddle.net/r8vx07ae/4/
Problem with z-index:
An element can not appear behind its parent. Since the submenu exists as a child element of the menu, it will not be able to appear behind the menu, z-index is really only applicable to two elements which share the same parent.
Problem with setTimeout:
The issue is most likely being caused because the this variable is out of scope by the time that the timeout occurs. This has an easy fix: create a global variable (say subMenu) and set subMenu = this before the timeout occurs and replace this with subMenu in your timeout function. You may use additional variables or a dictionary/array if you have multiple submenus to prevent the variable from being overwritten if two submenus get opened one right after the other
It is because $(this) is losing its scope on setTimeout function. To overcome this issue, you can assign your $(this) scope into a variable like $this and then use it in your setTimeout function. Here is the code changes:
.mouseleave(function() {
var $this=$(this);
setTimeout(function() {
$this.children("ul").css({
"display" : "none",
"left" : "0px",
"opacity": 0,
})
}, 1000);
});
And here is your updated fiddle:
http://jsfiddle.net/r8vx07ae/5/
The problem with the setTimeout is the scope of this
When it runs, it is the window, not the menu.
jQuery(document).ready(function($){
$(".main-navigation ul li").mouseenter(function() {
/* see if the timer has run yet, if it has not, cancel it */
var hideTimer = $(this).data("timer");
if (hideTimer) window.clearTimeout(hideTimer);
if ($(this).children().length > 0) {
$(this).children("ul").css ({
"display" : "block",
}).stop().animate({
left: '250px',
opacity: 1,
}, 500)
}})
.mouseleave(function() {
/* store the children here to get rid of the "this" scope issue */
var ul = $(this).children("ul");
/* Store a reference to the timer so we can cancel it if they mouseover again */
$(this).data("timer", setTimeout(function() {
ul.css({
"display" : "none",
"left" : "0px",
"opacity": 0,
})
}, 1000));
});
});
This will not fix the z-index issue.
I guess this is from the usage of "this" inside the callback of setTimeout sadly i do not have any computer to test out...
See section "the this problem": https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout#The_%27this%27_problem
To solve it, save a reference of this before the call of setTimeout, and use the saved reference inside your callback
this kind of emergency, so please, can someone help me...
I'm using movingboxes plugin for slideshow(this is the original plugin:http://css-tricks.com/moving-boxes/)
I need help with setting callback function add to the end of animation. I need to add fading effect, when currentSlidecomplete sliding,it should start fading into another view of the same image, for example,surrentSlide src is images/dr1.jpg and i need it to fade to images/dr1b.jpg and come back to images/dr1.jpg. looping through each current Slide
something like
completed :
function(e, slider, tar){
//fading for each currentSlide goes here;//
}
Something like you describe is already in the documentation
see the documentation here [1] and more specifically here [2].
EDIT: check jsfiddle here, i used a jquery add-on http://jsfiddle.net/r6yWC/157/
the add-on is here http://jqueryfordesigners.com/image-cross-fade-transition/
I also edited the code section below. I added the class "fade" to the img tag like this:
<img class="fade" src="http://chriscoyier.github.com/MovingBoxes/demo/4.jpg" alt="picture" style="background: url(http://chriscoyier.github.com/MovingBoxes/demo/2.jpg);"/>
In the 2nd link you will find a movingBoxes sample with a completed callback.
(function ($) {
$.fn.cross = function (options) {
return this.each(function (i) {
// cache the copy of jQuery(this) - the start image
var $$ = $(this);
// get the target from the backgroundImage + regexp
var target = $$.css('backgroundImage').replace(/^url|[\(\)'"]/g, '');
// nice long chain: wrap img element in span
$$.wrap('<span style="position: relative;"></span>')
// change selector to parent - i.e. newly created span
.parent()
// prepend a new image inside the span
.prepend('<img>')
// change the selector to the newly created image
.find(':first-child')
// set the image to the target
.attr('src', target);
// the CSS styling of the start image needs to be handled
// differently for different browsers
if ($.browser.msie || $.browser.mozilla) {
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : '',
'top' : this.offsetTop
});
} else if ($.browser.opera && $.browser.version < 9.5) {
// Browser sniffing is bad - however opera < 9.5 has a render bug
// so this is required to get around it we can't apply the 'top' : 0
// separately because Mozilla strips the style set originally somehow...
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : '',
'top' : "0"
});
} else { // Safari
$$.css({
'position' : 'absolute',
'left' : 0,
'background' : ''
});
}
// similar effect as single image technique, except using .animate
// which will handle the fading up from the right opacity for us
$$.hover(function () {
$$.stop().animate({
opacity: 0
}, 250);
}, function () {
$$.stop().animate({
opacity: 1
}, 250);
});
});
};
})(jQuery);
$('#slider').movingBoxes({
// **** Appearance ****
// start with this panel
...
...
//-----> here is your callback
// callback after animation completes
completed: function(e, slider, tar){
var img = slider.$panels.eq(tar).find('img');
img.cross();
img.stop().animate({opacity: 0}, 1250).delay(500).animate({opacity: 1}, 2550);
}
});
[1] https://github.com/chriscoyier/MovingBoxes/wiki
[2] http://jsfiddle.net/Mottie/r6yWC/2/
I am creating a coverflow plugin but I have a slight problem when it first loads.
The size/styles of the images is set based on their position in the coverflow. When the page first loads the images all resize properly but they do not reposition themselves. If I them use the left and right navigation they work correctly.
I am not sure what is causing this. I thought it might be something to do with the variable that sets the starting position of the coverflow...
Here's my code:
<script type="text/javascript" src="/scripts/jquery-ui.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var coverflowPos = Math.round($('#coverflow img').length / 2)
$('#coverflow img').each( function(i) {
$(this).css({'opacity' : 1-(Math.abs(coverflowPos-i)*0.4), 'z-index' : 100-(Math.abs(coverflowPos-i)) }).width(200-(Math.abs(coverflowPos-i)*50)).height(128-(Math.abs(coverflowPos-i)*50));
});
// If I run the testme() function here, it animates to the right place but I want it to start in this position rather than animate to it
$('#moveLeft').click( function() {
if(coverflowPos > 1) {
coverflowPos = coverflowPos-1
}
testme();
});
$('#moveRight').click( function() {
if(coverflowPos < $("#coverflow img").length -1) {
coverflowPos = coverflowPos+1
}
testme();
});
function testme() {
$('#coverflow img').each( function(i) {
$(this).animate({
opacity: 1-(Math.abs(coverflowPos-i)*0.4),
width: 200-(Math.abs(coverflowPos-i)*50),
height: 128-(Math.abs(coverflowPos-i)*50)
}, {
duration: 500,
easing: 'easeInOutSine'
}).css({ 'z-index' : 100-(Math.abs(coverflowPos-i)) });
});
};
});
</script>
And here's a link to a jsfiddle:
http://jsfiddle.net/r8NqP/4/
Calling testme() at the end of the ready() function moves them into place. It does ease them in though, which looks a bit odd, could get rid of the ease in testme() by adding a doease parameter.
Check you fist each :
'z-index' : 100-(Math.abs(coverflowPos-i)) }).width(200-(Math.abs(coverflowPos-i)*50)).height(128-(Math.abs(coverflowPos-i)*50));
I think U mean:
'z-index' : 100-(Math.abs(coverflowPos-i)),
'width' : 200-(Math.abs(coverflowPos-i)*50),
'height': 128-(Math.abs(coverflowPos-i)*50)
Linke In your testme() function ?!
After that, you can also add a "Hack", by executing testme(true); at the end of script.
And add, in your testme() function , a test parameter to set the duration at 0 or simply disable animate and replace by CSS().
But, it just a Hack.
200-(Math.abs(coverflowPos-i)*50) may be less than 0 -- e.g.,
200-(5-0)* 50= 200 - 250 = -50
And the negative width ends up not being applied, leaving the width at its original 200px value. The opacity gets set properly, so all you get is a huge blank space where the image is.
var width = 200-(Math.abs(coverflowPos-i)*50);
if ( width < 0 ) width = 0;
covers the init nicely.
I haven't bothered to check why it's okay once it's animated -- my guess is, that the images were already small, so it's not as noticeable.
The problem came from "Each index", that not correctly used to compute the Width and Height of the first image.
Try this :
$('#coverflow img').each( function(i) {
i++;
$(this).css({...
And remove the Blank.gif...
Here, you find my fork fiddle : http://jsfiddle.net/akarun/FQWQa/
I'm having some trouble with finding the visibility param for JQuery.
Basically... the code below does nothing.
$('ul.load_details').animate({
visibility: "visible"
},1000);
There's nothing wrong with the animate code (I replaced visibility with fontSize and it was fine. I just can't seem to find the correct param name equivalent for "visibility" in css.
You could set the opacity to 0.0 (i.e. "invisible") and visibility to visible (to make the opacity relevant), then animate the opacity from 0.0 to 1.0 (to fade it in):
$('ul.load_details').css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0});
Because you set the opacity to 0.0, it's invisible despite being set to "visible". The opacity animation should give you the fade-in you're looking for.
Or, of course, you could use the .show() or .fadeTo() animations.
EDIT: Volomike is correct. CSS of course specifies that opacity takes a value between 0.0 and 1.0, not between 0 and 100. Fixed.
Maybe you are just looking to show or hide an element:
$('ul.load_details').show();
$('ul.load_details').hide();
Or do you want to show/hide element using animation (this doesn't make sense of course as it will not fade):
$('ul.load_details').animate({opacity:"show"});
$('ul.load_details').animate({opacity:"hide"});
Or do you want to really fade-in the element like this:
$('ul.load_details').animate({opacity:1});
$('ul.load_details').animate({opacity:0});
Maybe a nice tutorial will help you get up to speed with jQuery:
http://www.webdesignerwall.com/tutorials/jquery-tutorials-for-designers/
You can't animate visibility. Either something is visible, or it's not (event 1% opaque items are 'visible'). It's much like half-existing - doesn't make sense. You're likely better off animating the opacity (via .fadeTo() etc).
This might help:
$(".pane .delete").click(function(){
$(this).parents(".pane").animate({ opacity: 'hide' }, "slow");
});
This is what worked for me (based on #Alan's answer)
var foo = $('ul.load_details'); // or whatever
var duration = "slow"; // or whatever
if (foo.css('visibility') == 'visible') {
foo.css({ opacity: 1 }).animate({ opacity: 0 }, duration, function () {
foo.css({ visibility: "hidden" });
});
} else {
foo.css({ opacity: 0 }).animate({ opacity: 1 }, duration).css({ visibility: "visible" });
}
When the foo element is visible, then slowly change the opacity to zero (via animate) and then wait until that's done before setting foo's visibility to be hidden. Otherwise, if set to hidden during the animate process then the fading out effect will not happen since it's hidden immediately.
Alternatively, you can use the simpler, cleaner fadeTo():
var foo = $('ul.load_details'); // or whatever
var duration = "slow"; // or whatever
if (foo.css('visibility') == 'visible') {
foo.fadeTo(duration, 0, function () {
foo.css({ visibility: "hidden" });
});
} else {
foo.fadeTo(duration, 1).css({ visibility: "visible" });
}