How animate height of a div while image is still loading? - javascript

My code is showing pages by emptying an HTML tag and replacing the content.
The height of the parent div changes when different content is loaded, but I can't get the height change to transition smoothly. This probably has to do with the image still being loaded. What would be a good way to transition between these two states?
// first fade out
$(".page").animate({opacity:0}, 600, function() {
// then replace html
$(".page").html("new html here including an <img src='image.jpg'><br>and more text.");
// now calculate new height and then fade in again
var endHeight = $(".page").height();
$(".page").animate({opacity:1, height:endHeight});
});

Suppose you have a div element that acts as a container for you content. If you are loading content that may take some noticeable time to load (such as an image), you can wait for that new element to load, and then manually re-set the height of the container. Doing this, in conjunction with CSS3 transitions, will prevent the container from animating before the content can actually be displayed.
From the fiddle:
$(document).ready(function() {
var container = $('.container');
/* ... */
function replaceContent(container) {
var content = new Image();
content.onload = function(e) {
container.empty().append(content);
container.css({'height': content.height});
};
content.src = getRandomImageUrl();
};
setInterval(function() { replaceContent(container); }, 5000);
});
Working example on jsFiddle: http://jsfiddle.net/7Vn5a/1/

Did you try css transitions?
.YOUR_DIV{
-webkit-transition:all 0.5s ease-in-out;
-moz-transition:all 0.5s ease-in-out;
-o-transition:all 0.5s ease-in-out;
transition:all 0.5s ease-in-out;
}

Related

Css transition manifests only inside timeout function

I've created new div using JavaScript and set its width and height. Immediately after that I need to resize it to 100% width with transition effect. But it manifests only when the styles editing is inside of Timeout function. Without that it just jump to new width.
Css:
#project-detail {
#extend .project-detail-preview;
transition: width 0.25s ease-out, top 0.25s ease-out, left 0.25s ease-out, height 0.25s ease-out;
}
Script:
var detailContainer = document.createElement("div");
detailContainer.id = "project-detail";
detailContainer.innerHTML = previewContent.innerHTML;
detailContainer.style.width = previewWidth;
detailContainer.style.height = previewHeight;
blocksContainer.appendChild(detailContainer);
for (let project of source.projects) {
if(project.id == projectID) {
setTimeout(function () {
detailContainer.style.width = "100%";
}, 1);
}
}
JS is single threaded if you change width to 20 and then to 100, the change to 20 is like if didn't happen. so you need to use a setTimeout() so it first changes it to 20, and "later" it changes to 100
I believe this is because you append the div to the DOM, and immediately (next line of code), you resize it to 100% width.
The problem is that in the page's life cycle, the CSS doesn't have time to catch up and apply between these two lines of code. So, the transition duration is not yet applied, and you already resize the div, so it jumps immediately to 100%.
On the other hand, when you set a Timeout, being asynchronous, the function inside the Timeout is executed at the end of the execution stack, that is, after applying the CSS rules to the newly created elements. You can even set a 0 delay or no delay at all, it will work all the same.
I tried to do things like this with JS, even read bunch of articles about requestAnimationFrame and understood, that things like that better to do with CSS classes. Try to toggle class on action:
for (let project of source.projects) {
if(project.id == projectID) {
detailContainer.className += ' fullwidth-class';
}
}
And add same CSS class:
.fullwidth-class {
width: 100%!important;
}
#project-detail {
animation-duration: 1s;
}

Issue getting height of element when using jQuery .load()

I’m having an issue with my script that loads content to a page via jQuery .load(). The content loads properly, my animation of said content works (done with class "hidden"), but I’m setting the height of the wrapping container before loading, and then animating the height of said container to keep the page from jumping between the different content heights.
Essentially what’s happening, is the height is getting set to 0 for some reason, rather than the actual height of the element. Strangely, this seems to work on the initial click, but then on any others it breaks and sets the height to 0.
See the code below (I would create a jsFiddle but, .load() doesn't work with that):
HTML
<main id="content" class="content">
<div id="content-inner" class="content-inner">
<!-- Content -->
</div>
</main>
CSS
.content {
transition: .25s height;
}
.content-inner {
position: relative;
top: 0;
opacity: 1;
visibility: visible;
transition: .25s opacity, .25s top;
}
.hidden .content-inner {
top: -30px;
opacity: 0;
visibility: hidden;
transition: .25s opacity, .25s top, 0s visibility .25s;
}
JavaScript (jQuery)
var $mainContentOuter = $('#content'),
linkContent = '#content-inner',
$mainContentInner = $(linkContent);
function loadMainContent(link) {
// Assign height as current height to prevent jumping
$mainContentOuter.height( $mainContentInner.outerHeight() );
// Hide content
$mainContentOuter.addClass('hidden').delay(250).queue(function() {
// Load content
$mainContentOuter.load(link + ' ' + linkContent, function() {
// Animate the height difference when loaded
$mainContentOuter.height($mainContentInner.outerHeight());
});
// Dequeue for delay
$(this).dequeue();
}).delay(250).queue(function() {
// Reveal content and reset height
$mainContentOuter.removeClass('hidden').css('height','');
// Dequeue for delay
$(this).dequeue();
});
}
// Override behavior of navigational links
$('.nav-main > li > a').click(function(e){
var link = $(this).attr('href');
//Pass link
loadMainContent(link);
e.preventDefault();
});
Any help would be greatly appreciated.
Thanks in advance,
Rob
The problem is that you load the inner-content inside the outer content, so there is no inner-content after the load takes place. Try using:
$mainContentOuter.load(link + ' ' + '#content', function() {
// Animate the height difference when loaded
$mainContentOuter.height($mainContentInner.outerHeight());
});
Imagine it like you have 2 rectangles A and B, where B is inside A. If you load everything that B has and give it to A then there will be no B, but only A because B didn't have B in it, so A won't have B in it either. I recently encoutered a similar problem and it took me hours to understand and solve it. Please let me know if this solved your problem!
Thanks to #thanasis I realized what was going on here.
The variable $mainContentInner was storing a reference to the original object in the DOM. Once the page content was loaded, this object was removed and replaced with another one, albeit similar.
Even though they have the same ID, they're different objects. To get around this, I redefined the variable, so as to target the new object. See below:
// Load content
$mainContentOuter.load(link + ' ' + linkContent, function() {
// Redefine $mainContentInner to the new object
$mainContentInner = $(linkContent);
// Animate the height difference when loaded
$mainContentOuter.height($mainContentInner.outerHeight());
});

Dynamically set css transform before transition

I am trying to simulate a mouse animation. I would like to dynamically set the position, then move it with a css transition. So far I am able to get a program that moves the mouse. However, I am having trouble setting the initial position dynamically with javascript. My code looks like this:
Here is the CSS
.cursorDiv {
width: 30px;
height: 30px;
transform: translate(0px,0px);
transition: 2s ease;
}
.cursorDivMoved {
transform: translate(100px,200px);
}
Here is the javascript:
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.src="https://cdn2.iconfinder.com/data/icons/windows-8-metro- style/512/cursor.png";
document.body.appendChild(cursorDiv);
setTimeout(function() {
$(".cursorDiv").toggleClass("cursorDivMoved");
}, 1000);
//cursorDiv.style.transform="translate(100px,50px)";
When I run this it works fine. However, when I try to change the initial position with javascript (uncomment last line), then the transition doesn't occur anymore.
Here is a Demo:
https://jsfiddle.net/fmt1rbsy/5/
If you programmatically set the style.transform property directly on your element (which you need if you want to move it to an arbitrary position through JS), it will override any transform specified in classes. Hence adding "cursorDivMoved" class later on does not transform (translate / move) it.
You have to continue moving it by specifying its style.transform property, or simply remove it: cursorDiv.style.transform = null
Demo: https://jsfiddle.net/fmt1rbsy/9/
You may also want to have the very first translate being transitioned. In that case, you have to wait for the browser to make an initial layout with your element at its start position, otherwise it will see no transition (it will see it directly after the transform is applied, i.e. at its final position). You can either:
Use a small (but non zero) setTimeout to give some time for the browser to do its initial layout.
Force a browser layout by trying to access some property that require the browser to compute the page layout (e.g. document.body.offsetWidth).
Use 2 nested requestAnimationFrame's before applying your transform.
Demo: https://jsfiddle.net/fmt1rbsy/8/
Is this what you are looking for? Tell me if it can be improved. Open your console and change the class name to cursorDivMoved.
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.id = 'cursorDiv';
cursorDiv.src = "https://cdn2.iconfinder.com/data/icons/windows-8-metro-style/512/cursor.png";
document.body.appendChild(cursorDiv);
#cursorDiv {
width:30px;
height:30px;
-o-transition: 2s ease;
-moz-transition: 2s ease;
-webkit-transition: 2s ease;
-ms-transition: 2s ease;
transition: 2s ease;
}
.cursorDivMoved {
-o-transform:translate(100px, 200px);
-moz-transform:translate(100px, 200px);
-webkit-transform:translate(100px, 200px);
-ms-transform:translate(100px, 200px);
transform:translate(100px, 200px);
}
You can define initial postion (x,y), and then when user click the position will increase and set to the 'cursorDiv', such as:
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.src="https://cdn2.iconfinder.com/data/icons/windows-8-metro-style/512/cursor.png";
document.body.appendChild(cursorDiv);
var x = 100, y = 50;
setTimeout(function() {
cursorDiv.style.transform="translate(100px,50px)";
}, 1000);
$(document).click(function () {
x+= 20;
y += 50;
var str = "translate(" + x + "px," + y + "px)";
cursorDiv.style.transform=str;
});
Here is Demo

Smoothly change css

my situation is as follows:
I have the following function
var showHideMemberContent = function(){
if(isHidden === false){
$("#showHideMemberContent").text("Member Content");
$("#main").css("height","-=187");
$('#mainBottom').hide('slow', function() {
isHidden = true;
});
} else {
$("#showHideMemberContent").text("Verberg");
$("#main").css("height","+=187");
$('#mainBottom').show('slow', function() {
isHidden = false;
});
}
};
So when the function executes it hides the "mainBottom" div. The "main" div should decrease/increase its height.
It does so, but I need to know if there is a way to do this smoothly.
Thanks in regard.
You can use CSS to achieve this. Simply add this rule to your CSS declaration for #main:
#main {
-khtml-transition: height 0.3s ease;
-moz-transition: height 0.3s ease;
-ms-transition: height 0.3s ease;
-o-transition: height 0.3s ease;
-webkit-transition: height 0.3s ease;
transition: height 0.3s ease;
}
Here the height part defines the property to apply the transition to, the 0.3s defines the time it takes to transition from one state to another, and the ease property defines the function for the transition. Ease will slowly accelerate to 50% transition and then decelerate to 100%.
The advantage of using CSS over jQuery's animate function is that the CSS transform is hardware accelerated when supported, and will be smoother and more efficient. The disadvantage is that some antiquated browser versions will not support the effect, however it will simply fall back to a non-animated height change, rather than breaking.
To learn more about CSS transitions, follow the link below to Mozilla's article. They're a great reference for these sort of things and an excellent place to start learning, or even brush up on your knowledge. I've also included an example of this technique below.
MDN article on transitions.
Here is a jsfiddle example.
Yes, use jquerys animate() method, http://api.jquery.com/animate/.
Include jquery ui if you want to use easing types other than "linear" or "swing". Its passed as a second argument (string), to the animate method. https://jqueryui.com/easing/
Example (with jquery ui loaded):
$(selector).animate({ height: '200px' }, 'easeInOutCubic', function(){
/* animation comlete */
});
Also, work on your accept rate.
You can use animate for that:
var oldHeight = $("#main").height();
$("#main").animate({'height', oldHeight + 187}, { duration: 500, queue: false });
if you want to operate with css and classes, not the style attribute, you can use jquery-ui's switchClass() or toggleClass() methods http://docs.jquery.com/UI/Effects/switchClass http://jqueryui.com/demos/toggleClass/
Use animate()...
var showHideMemberContent = function(){
if(isHidden === false){
$("#showHideMemberContent").text("Member Content");
$("#main").animate({height:-=187}, 300);
$('#mainBottom').hide('slow', function() {
isHidden = true;
});
} else {
$("#showHideMemberContent").text("Verberg");
$("#main").animate({height:+=187}, 300);
$('#mainBottom').show('slow', function() {
isHidden = false;
});
}
};

Can we do fade in and fade out in iframes

Is it possible to make fade in and fade out transitions in iframes?
Fading in or out can be achieved by changing the opacity of an element over time, a very simple example:
var iframe = document.getElementById('iframe');
fadeOut(iframe, 1000);
function fadeOut(el, duration) {
/*
* #param el - The element to be faded out.
* #param duration - Animation duration in milliseconds.
*/
var step = 10 / duration,
opacity = 1;
function next() {
if (opacity <= 0) { return; }
el.style.opacity = ( opacity -= step );
setTimeout(next, 10);
}
next();
}
While jQuery is an incredible library your usage of it should be justified by more than just its ability to create fancy effects. A library should be adopted for its completeness and ease of use; not because it happens to offer just one thing you might want to use.
you can do it with jquery!
http://docs.jquery.com/Effects/fadeOut
http://docs.jquery.com/Effects/fadeIn
Or maybe, you can let CSS handle this for you. With a very little of javascript to trigger the effect.
CSS:
#iframe_selector {
/* initial values for iframe, we'll change them via javascript. */
opacity: 0;
/* Note: In out/2016 opacity is on 97.39% of browsers */
/* Just an extra property to show multiple transitions, not needed for fade effect. */
height: 0;
/* Here you can handle a couple of transitions as you wish */
transition: opacity 2s ease-in-out, height 3s ease-in-out;
/* Note: Add all prefixes */
}
Javascript
function toogleIframe(iframe) {
//Check if is show with opacity property,
if (iframe.style.opacity == 0) {
//and set to original values,
iframe.style.opacity = 1;
iframe.style.height = '500px';
} else {
//or hide it.
iframe.style.opacity = 0;
iframe.style.height = '0px';
}
}
//And now, just use it...
//Examples:
domReady(function() {
toogleIframe(document.getElementById('iframe_selector'));
});
var button = document.getElementById('my_button');
button.onclick = function() {
toogleIframe(document.getElementById('iframe_selector'));
};
//Just specify when your iframe needs to be show or not...
Just one thing, maybe you want load your iframe just when it is going to show, to do this just remove src from your iframe in HTML, and add in javascript with iframe.src. That was my case.
You can use the onload property and a css animation to make the iframe fade in once loaded
<iframe
src="..."
onload="this.style.opacity = '1';"
style="
opacity: 0;
transition-duration: 300ms;
transition-property: opacity;
transition-timing-function: ease-in-out;
"
></iframe>

Categories