I've been looking further into using maquette.js as a virtual DOM library.
Looking at the website the library has functionality to support animations when adding, removing, and updating DOM nodes.
But I cannot find any docs or API on what to do do achieve this.
To make it more concrete I have made a small sample below and here.
var isPopupShown = false;
var togglePopup = function(){
isPopupShown = !isPopupShown;
}
var renderMaquette = function () {
return h("div#container", [
h("button", {
onclick: togglePopup
}, ["Click me"]),
isPopupShown ? h("div#popup") : null
]);
}
In the example, clicking the button will open the popup.
What I would like is that the popup would animate a fade-in when the node is added to the DOM and a fade-out when the node is removed from the DOM.
The documentation how animations work is still in progress.
There are currently two ways to do the animation.
Velocity.js
The easiest way is to use a library like velocity.js. For this to work you need to:
Add the velocity.js script to the page
Change h("div#popup") to h("div#popup", {enterAnimation: fadeIn})
Add the following javascript function
Code:
var fadeIn = function(element) {
element.style.opacity = 0;
Velocity.animate(element, {opacity: 1}, 1500, "ease-out");
};
You can view the result here.
CSS Transitions
You can also use CSS transitions. They work the same as angularJS and react. You need to do the following:
Include the css-transitions.min.js script in your page. This
script is also provided by maquette.
Change h("div#popup") to h("div#popup", {enterAnimation: "fadeIn"})
Change the createProjector call to maquette.createProjector(document.body, renderMaquette, {transitions: cssTransitions});
Add the following style declarations to the stylesheet:
Stylesheet:
.fadeIn {
-webkit-transition: 0.5s ease-out opacity;
transition: 0.5s ease-out opacity;
opacity: 0;
}
.fadeIn.fadeIn-active {
opacity: 1;
}
You can view the result here
Related
I'm using the ScrollReveal library to animate in sections of my site.
I have a pretty complex vector which contains five groups. I'm trying to animate these five groups in separately using this library.
Here is my approach currently:
My SVG is a bit lengthy and Stack has a body count character limit, so I created a demo using JSFiddle here.
Each group has a class and as you can see from the demo, it initially loads, then disappears. None of the reveal effects are working? I have other divs with the same parameters which work, but it doesn't work with this SVG for some reason?
If we inspect the white space, I can see that the parts are not appearing because the opacity is 0. But, on scroll, this opacity isn't changing and I don't want to force opacity to 1 via CSS as this I want the part to fade in nicely, whereas setting it to 1 will just make it a static image.
I encountered this same issue. I could not figure out how to get the opacity to work using ScrollReveal directly, so I ended up using ScrollReveal to detect the scroll position and then trigger a callback function to toggle the class. It doesn't require much CSS, but it does require a little bit.
Here's a generic version of my code as an example:
#ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
svg {
.class-one {
opacity: 0;
transition: opacity 8000ms #ease-out-expo;
&.visible {
opacity: 1;
}
}
.class-two {
opacity: 0;
transition: opacity 8000ms #ease-out-expo;
&.visible {
opacity: 1;
}
}
.class-three {
opacity: 0;
transition: opacity 8000ms #ease-out-expo;
&.visible {
opacity: 1;
}
}
}
(function($) {
// Reveal the block
ScrollReveal().reveal(".container", {beforeReveal: showGraphic, viewFactor: 0.3});
// Define the showGraphic function
function showGraphic() {
$(".container svg .class-one").addClass( "visible" );
setTimeout(function() {
$(".container svg .class-two").addClass( "visible" );
}, 1800);
setTimeout(function() {
$(".container svg .class-three").addClass( "visible" );
}, 3600);
}
}(jQuery))
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;
}
Wanted to get insight and help advancing a plugin I am beginning to build!
Looking to build the same effect that AKQA.com has, were on page load certain elements transition into place (using translateY of course). However if the elements are in view within the browser window. As you scroll down, other elements have the same effect transitioning up into place and appearing from opacity 0 to 1.
What I am trying to accomplish is getting select elements to transition from opacity 0 to 1 effect translating upwards via scrollonly however when the element is not in-view. If however the elements are already in view (due to page loading right where the elements are) the effect will happen automatically until you scroll down to reveal more elements.
Currently in my JS code I am grabbing the data selector on the elements and applying to each of the elements a transition-delay and a CSS class which suppose to be the class that creates the effect. I have three variables docHeight, offSetter and scrolling that are suppose to help me create the logic behind the scrolling effect but I simply can not wrap my head around creating the effect.
Here is a live demo in my fiddle http://jsfiddle.net/coder101/hYS48/1/
The Hi link is simply for testing to toggle the in-view CSS class I have
Thank you for the help!
Javascript
var loop = function ScrollTransition( ) {
var core = function() {
var i = 100,
dataTheme = $('[data-show*="on-scroll"]').not('in-view'),
docHeight = $( document ).height(),
offSetter = parseInt(dataTheme.offset().top, 10),
scrolling = dataTheme.scrollTop();
// console.log(h);
dataTheme.each(function() {
_this = $( this ),
_this.css("transition-delay", i + "ms", i += 100);
});
},
initializer = function() {
if ( el.hasClass('js') && el.hasClass('no-touch') && el.hasClass('csstransitions') ) {
core();
}
};
return {
init:initializer()
}
};
loop();
// For testing
var divElements = $('article');
var doc = $( '#hit' );
doc.on("click", function() {
if( el.hasClass('js') && el.hasClass('no-touch') && el.hasClass('csstransitions') ) {
divElements.toggleClass('in-view');
}
});
CSS
.base {
width: 300px;
height:300px;
background:blue;
float:left;
}
article {
margin-right:45px;
margin-bottom: 40px;
}
/* starting phase */
.js.no-touch.csstransitions [data-show="on-scroll"] {
opacity:0;
-webkit-transform:translate(0,90px);
-ms-transform:translate(0,90px);
transform:translate(0,90px);
-webkit-transition:opacity .6s .1s, -webkit-transform .6s ease;
transition:opacity .6s .1s, transform .6s ease
}
/* finishing phase */
.js.no-touch.csstransitions .in-view {
opacity:1;
-webkit-transform:translate(0,0);
-ms-transform:translate(0,0);
transform:translate(0,0)
}
I'd like to add a slide & fade effect to a DIV, with purely Javascript, using "onclick".
The code is here: http://jsfiddle.net/TCUd5/
The DIV that has to slide has id="pulldown_contents_wrapper".
This DIV is contained in a SPAN, that also triggers it:
<span onclick="toggleUpdatesPulldown(event, this, '4');" style="display: inline-block;" class="updates_pulldown" >
<div class="pulldown_contents_wrapper" id="pulldown_contents_wrapper">
And I think the JS code that controls the SPAN onclick is:
var toggleUpdatesPulldown = function(event, element, user_id) {
if( element.className=='updates_pulldown' ) {
element.className= 'updates_pulldown_active';
showNotifications();
} else {
element.className='updates_pulldown';
}
}
If it is not possible to make it with pure JS, do you have an idea how could I do it with Mootools? (*I'd like to use only pure JS or the Mootols framework).
I have tried to implement the code from: why javascript onclick div slide not working? but with no results.
Thanks a lot.
I have managed to make it with Mootools, but I can't figure it out how to add a slide & fade effect, and a delay on mouseout
window.addEvent('domready', function() {
$('updates_pulldown').addEvents({
mouseenter: function(){
$('updates_pulldown').removeClass('updates_pulldown').addClass('updates_pulldown_active')
$('pulldown_contents_wrapper').set('tween', {
duration: 1000,
physics: 'pow:in:out',
transition: Fx.Transitions.Bounce.easeOut // This could have been also 'bounce:out'
}).show();
},
mouseleave: function(){
$('pulldown_contents_wrapper').set('tween', {
duration: 1000,
delay: 1000,
}).hide();
$('updates_pulldown').removeClass('updates_pulldown_active').addClass('updates_pulldown')
},
});
});
var toggleUpdatesPulldown = function(event, element, user_id) {
showNotifications();
}
Any idea?
jQuery is a lot easier, but with pure javascript you can do it.
In the CSS you'll need to use transitions
#thing { position:relative;
top: 0px;
opacity: 0.8;
-moz-transition: top 1s linear, opacity 1s linear;
-webkit-transition: top 1s linear, opacity 1s linear;
}
then in the javascript when you change the position of the element, it should change via the css transitions.
var toggleUpdatesPulldown = function(event, element, user_id) {
if( element.className=='updates_pulldown' ) {
element.style.top = someValue; //something like '100px' will slide it down 100px
element.style.opacity = '1.0'; //will fade the content in from 0.8 opacity to 1.0
element.className= 'updates_pulldown_active';
showNotifications();
EDIT - provided jQuery code
call the jQuery library, most easily done from the google hosting
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
make the hover function
$(document).ready(function() {
$('.updates_pulldown').hover( //first function is mouseon, second is mouseout
function() {
$(this).animate({top: '50px'}).animate({opacity: '1.0'});
},
function() { //delay 1000 milliseconds, animate both position and opacity
$(this).delay(1000).animate({top: '0px'}).animate({opacity: '0.5'});
}
)
})
the function timing will be the same as whatever you set it to in the css with transition tags. using 'this' instead of the class name again makes sure that the effect only occurs on the specific instance of the class that is hovered over. im not sure if this animation is exactly what you were asking for, but if i understand the question correctly then the main functionality will work for you. just change the numbers and such to fit your needs.
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;
});
}
};