The Google card's "Flip and Grow" effect - javascript

I have been doing some research on how to create a flip and grow effect like Google card does (click on any card):
http://www.google.com/landing/now/#cards/restaurant-reservations
All resources I found is about flipping a card with front and back of same size but this is not what I'm looking for.
Any feedback will be hugely appreciated.

Both of the answers posted here are good generic css flippers but they don't address the core of the question which is "how does Google do it?". The problem is that google minifies and therefore obfuscates their code which makes it tough to tell exactly whats going on but using a DOM inspector you can get a pretty basic idea. This is the abstract:
Build a "clone" div that contains a front and a back child div but is hidden by default. Set it's css transition property to ~.5seconds so that any move it makes will be animated.
When a user clicks on a card in the grid, set the clone so it's the same position/dimensions as the clicked card, copy the contents of the clicked card into the front child element and set it as visible
Hide the original clicked card with visibility:hidden
At this point you now have a clone of the originally clicked card in the exact same place but no one can tell
Set css for top, left, height, width of the clone div to precalculated dimensions centering in the screen while also setting transform:rotateY() of the front/back children
At this point it appears as if the div is lifting up, flipping around, and moving/resizing to the center of the screen. An empty spot is left behind because the original card is still there, but visibility:hidden allows it to take up space without showing its contents
A click handler is set up so that when the user clicks outside of the clone card, the top,left,height,width,transform:rotateY() css is reset back to the original values which make it fly back in place.
Then the clone is hidden again and the original card is made visible
Demo: http://jsfiddle.net/jwhazel/AaU6v/11/
(Developed in Chrome, may need some vendor prefixes for other browsers)
HTML
<div class="cards">Generic Tile Card</div>
<div id="cardClone">
<div id="cloneFront">cardclone front</div>
<div id="cloneBack">cardclone back</div>
</div>
CSS
body {
position: relative;
font-family:Helvetica, Arial, Sans-serif;
text-align:center;
}
.cards {
margin:30px;
width:200px;
height:200px;
background-color:#59A3FF;
cursor:pointer;
display:inline-block;
overflow:hidden;
}
img {
display:block;
width:80%;
height:auto;
margin:0 auto
}
#cardClone {
position:fixed;
display:none;
margin:30px;
width:200px;
height:200px;
-webkit-transition:.6s;
transition:.6s;
-webkit-transform-style::preserve-3d;
transform-style:preserve-3d;
z-index:99;
perspective: 1000px;
-webkit-perspective: 1000px;
}
#cloneFront, #cloneBack {
backface-visibility: hidden;
width:100%;
height:100%;
position:absolute;
-webkit-transition:.6s;
transition:.6s;
overflow:hidden;
}
#cloneFront {
z-index:100;
background-color:#59A3FF;
transform: translatez(0);
}
#cloneBack {
transform:rotateY(-180deg);
z-index:101;
background-color:#aaa;
}
Javascript
//Cache the clone since we have to select it a couple of times
$clone = $('#cardClone');
//Set a global for the card we just clicked so we can track it
$lastelement = "";
//Set up an object for last clicked element so we know where to return to on collapse
lastelement = {
'top': 0,
'left': 0,
'width': 0,
'height': 0
};
//Set a flag to determine the current flip state of our clone
cloneflipped = false;
//Bind a handler to the clone so we can detect when the transition is done
$('#cardClone').on("transitionend", function (e) {
if (e.target === e.currentTarget) {
if (e.originalEvent.propertyName == 'top') {
//Toggle the clone state
cloneflipped = !cloneflipped;
//Detect if our clone has returned to the original position and then hide it
if (!cloneflipped) {
$($lastelement).css('opacity', 1);
$($clone).hide();
} else {
//Need to dynamically alter contents of the clone rear AFTER it animates? Do it here
//$('#cloneBack').html('hi');
}
}
}
});
$(".cards").click(function () {
if (!cloneflipped) {
//Cache clicked card
$lastelement = $(this);
//Store position of this element for the return trip
//[hack: subtract 30 due to the margin of .cards in this demo]
var offset = $lastelement.offset();
lastelement.top = offset.top - 30 - $(document).scrollTop();
lastelement.left = offset.left - 30;
lastelement.width = $lastelement.width();
lastelement.height = $lastelement.height();
//BONUS: lets check to see if the clicked card is further to the left or the right of the screen
//This way we can make the animation rotate inwards toward the center, google doesn't do this
var rotatefront = "rotateY(180deg)";
var rotateback = "rotateY(0deg)";
if ((lastelement.left + lastelement.width / 2) > $(window).width() / 2) {
rotatefront = "rotateY(-180deg)";
rotateback = "rotateY(-360deg)";
}
//Copy contents of the clicked card into the clones front card
$clone.find('#cloneFront').html($lastelement.html());
//Show the clone on top of the clicked card and hide the clicked card
//[hack: using opacity for hiding here, visibility:hidden has a weird lag in win chrome]
$clone.css({
'display': 'block',
'top': lastelement.top,
'left': lastelement.left
});
$lastelement.css('opacity', 0);
//Need to dynamically alter contents of the clone rear BEFORE it animates? Do it here
//$('#cloneBack').html('hi');
//Flip the card while centering it in the screen
//[hack: we have to wait for the clone to finish drawing before calling the transform so we put it in a 100 millisecond settimeout callback]
setTimeout(function () {
$clone.css({
'top': '40px',
'left': '40px',
'height': '400px',
'width': $(document).width() - 140 + 'px'
});
$clone.find('#cloneFront').css({
'transform': rotatefront
});
$clone.find('#cloneBack').css({
'transform': rotateback
});
}, 100);
} else {
$('body').click();
}
});
//If user clicks outside of the flipped card, return to default state
$('body').click(function (e) {
if (cloneflipped) {
if (e.target === e.currentTarget) {
//Reverse the animation
$clone.css({
'top': lastelement.top + 'px',
'left': lastelement.left + 'px',
'height': lastelement.height + 'px',
'width': lastelement.width + 'px'
});
$clone.find('#cloneFront').css({
'transform': 'rotateY(0deg)'
});
$clone.find('#cloneBack').css({
'transform': 'rotateY(-180deg)'
});
}
}
});

your code is here ! clickFLIPgrove
You can scale size of a div by css property called
transform:scale(2,2);
it will double the size of your element
refer this link for all css effects: cssAnimation
I have created flip effect on hover:
hoverFLIP
html
<div class="cards"></div>
css
body{
position: relative;
}
.cards{
margin:30px;
perspective: 500;
-webkit-perspective: 500;
-moz-perspective: 500;
-ms-perspective: 500;
-o-perspective: 500;
width:200px;
height:200px;
background-color:#59A3FF;
transform-style:preserve-3d;
-webkit-transform-style:preserve-3d;
-moz-transform-style:preserve-3d;
-o-transform-style:preserve-3d;
position:absolute;
cursor:pointer;
/* Animate the transitions */
-webkit-transition:0.8s; text-align:center;
-moz-transition:0.8s; text-align:center;
-ms-transition:0.8s; text-align:center;
-o-transition:0.8s; text-align:center;
transition:0.8s; text-align:center;
}
.flip{
transform:rotateY(180deg) scale(1.2,1.2);
-webkit-transform:rotateY(180deg) scale(1.2,1.2);
-moz-transform:rotateY(180deg);
-o-transform:rotateY(180deg);
-ms-transform:rotateY(180deg);
background-color:#FF5959;
}
javascript(add Jquery 2.1.0)
$(".cards").click(function(){
$(this).toggleClass("flip");
});

Try this jsFiddle
Base on this, make a 3d transform and left offset in transition,
-webkit-transform-style:preserve-3d;
-webkit-transform:rotateY(0deg);
-webkit-transition:-webkit-transform 0.25s , left 0.25s;
Use the css3 transform and transition.
Hope this can work for you.: )

maybe you like this one. check out my code using keyframes.
https://jsfiddle.net/jariesdev/y7Lz3mm0/
html:
<div id="logo">
<a>
<img src="http://fallbacks.carbonads.com/nosvn/fallbacks/2053cd7a29af8f37381467e04521a14e.png">
</a>
</div>
css:
#logo {
-moz-transform: perspective(1000px);
-moz-transform-style: preserve-3d;
}
#logo a {
display: inline-block;
}
#logo:hover a {
animation-name: rotateThis;
animation-duration: 1s;
animation-iteration-count: 1;
animation-timing-function:ease-in-out;
}
#keyframes rotateThis {
0% { transform:scale(0) rotateY(180deg) translateX(-100%);}
/*60% { transform:scale(.5) rotateY(90deg) translateX(-50%); }*/
100% { transform:scale(1) rotateY(360deg) translateX(0);}
}

Related

How to do animation on scroll in js on both ways (top/bottom)

I created a little aniamtion in JS by using bounding client. Once I scroll down until the text/content appears, I change its opacity to 1 by applying ".active" from CSS. And when I scroll up above the element again, opacity changes back to 0 (because ".active" gets taken away).
The problem is I want to make the same thing happen when I scroll up to the content element from below. Once the user goes below the content element, opacity should go to 0, then when they scroll back up (so the content element is again in view), opacity should go to 1. So it makes the animation work in both directions, something like on scrollrevealjs's front page.
document.addEventListener('scroll',()=>{
let content = document.querySelector('.text');
let contentPositiontop = content.getBoundingClientRect().top;
let screenPosition = window.innerHeight ;
if (contentPositiontop < screenPosition){
content.classList.add('active');
}
else{
content.classList.remove('active');
}
});
.text{
transform: translateX(700px) translateY(1000px);
font-family: Inter;
font-weight: 800;
font-size: 40px;
opacity: 0;
transition: all 2s ease;
position: absolute;
}
.active{
opacity: 1;
}
You just need to check the height of the bottom of the content element as well as the top.
(For the top, we needed to add in the screen height (window.innerHeight) because we were comparing its position to the bottom of the screen. We don't need this for the bottom because we are comparing its position to the top of the screen, which has a vertical position of 0.)
When both the bottom and the top are in range, we show the content element.
(If the content element's height were greater than the height of the screen for some reason, you would have to choose values between 0 and window.innerHeight to use to trigger the transition.)
document.addEventListener('scroll',() => {
const
content = document.querySelector('.text'),
top = content.getBoundingClientRect().top,
bottom = content.getBoundingClientRect().bottom;
if (top < innerHeight && bottom > 0){
content.classList.add('active');
}
else{
content.classList.remove('active');
}
});
.spacer{ height: 104vh; }
.text{ height: 100vh; background: blue; transform: translateX(20px); opacity: 0; transition: all 2s ease; }
.active{ opacity: 1; }
<div class="spacer"> </div>
<div class="text"></div>
<div class="spacer"> </div>
.

Creating Fade In / Fade Out effects in Javascript

I have grid class in javascript and when hover on some areas, an different image displays. I want this image to fade in/ fade out when displayed.
Hereby an exemple of the effect (could't figure out how it was made) : https://dustinthierry.com/
I am not sure how I should do it, as I am not directly using the CSS :hover .
Any leads ?
for (let i = 0; i < hovergrid.length; i++) {
if (hovergrid[i].hover(mouseX, mouseY)) {
console.log("hover on " + i)
hovergrid[i].display(i)
}
}
display(number) {
this.img = document.getElementById("displayedimage")
this.img.style.display = "block"
this.img.src = "images/" + number + ".jpg"
this.img.style.right = this.posx + "px"
this.img.style.bottom = this.posy + "px"
this.img.alt = picdes[number]
#displayedimage {
display: none;
position: absolute;
width: 30%;
}
You could use plain CSS for that effect. Using plain CSS will simplify your code, and also let you use CSS transitions.
Here's a rundown of what you could do:
Put your normal elements inside a Div (as in the OPULENCE text in the example)
Make your Div's position Relative. This will allow you to position certain elements inside of it, inside the dive
Create an overlay element that that is normally transparent
Put your images inside the overlay and make them invisible: opacity:0
Upon the hover of your overlay element, you can change the opacity of the image inside of it: div.overlay:hover > img {opacity: 1}.
.container{
width:500px;
height:500px;
background:black;
overflow:hidden;
position:relative;
}
h1{
text-align:center;
color:#ffffff;
margin-top:30px;
}
.overlay{
width:100%;
height:100%;
background:transparent;
position:absolute;
top:0;
left:0;
}
.overlay img{
width:200px;
position: absolute;
bottom:50px;
right:20px;
transition: all 0.5s;
opacity:0;
}
.overlay:hover > img{
opacity:1;
}
<div class="container">
<h1>Some text here</h1>
<div class="overlay">
<img src="https://images.unsplash.com/photo-1593642532842-98d0fd5ebc1a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80" />
</div>
</div>
Please note that because of the positionings, your overlay doesn't necessarily have to contain the whole element. It can be in a place, totally irrelevant to the image.
Also if you want to have more than one image, you can split your overlay into more inner elements that each have an image, and do the same thing for all of them.
This cleans up your Javascript and gives you all the CSS functionalities needed.

Start CSS animation after scrolling to particular section of page

I am trying to animate images using CSS on a webpage. The animation is working fine but I want to START the animation it only when user reaches at a particular section of the page. Here is my code:
<div class="sec1-right">
<img class="sec1-dmush1" src ="sec1-dmush1.png">
</div>
CSS
.sec1-right{
position: relative;
width: 50%;
float: right;
box-sizing: border-box;
min-height: 600px;
margin-top: 86px;
}
/* first section animation */
.sec1-dmush1 {
animation: fadeAndScale .9s cubic-bezier(.45,-0.22,.34,1.69);
transform-origin:center bottom;
max-width: 150px;
width: 100%;
position: absolute;
left: 180px;
top: 300px;
z-index: 0;
}
Animation
#keyframes fadeAndScale{
from{
opacity:0;
transform: scale3d(0,0,1);
}
to{
opacity: 1;
transform: scale3d(1,1,1);
}
}
How can I achieve
You need to write scroll event in javascript. element offsetTop minus window height. So as soon as element comes in viewport event starts.
Javascript:
var scrollpos = window.scrollY; // window scroll position
var wh = window.innerHeight-50; // as soon as element touches bottom with offset event starts
var element = document.querySelector(".sec1-dmush1"); //element
window.addEventListener('scroll', function(){
if(scrollpos > (element.offsetTop - wh)){
element.classList.add("onScroll");
}
});
JsFiddle
jQuery:
$(window).scroll(function(){
var wh = $(window).height()-50;
if($(window).scrollTop() > $('.sec1-dmush1').offset().top-wh){
$('.sec1-dmush1').addClass('onScroll');
}
});
jsFiddle
If you have multiple elements to animate. You can use waypoint js to reduce some efforts.
var wh = $(window).height();
var waypoints = $('.sec1-dmush1').waypoint(function(direction) {
$(this.element).addClass('onScroll');
console.log(11);
}, {
offset: wh-50
});
jsFiddle
using javascript you can find the scroll event . After the specific px(height). You can add a class to the existing class(jquery) for which you trying to animate.

Crossfade images with jQuery

Hi I'm trying to accomplish a crossfade effect for my banner images on my homepage. I'm doing this with jQuery and the fading effect is working fine.
This is my code:
<script>
function bannerImages(){
var $active = $('.banner-test .banner_one');
var $next = ($active.next().length > 0) ? $active.next() :
$('.banner-test img:first');
$next.css('z-index',2);//move the next image up the pile
$active.fadeOut(1500,function(){//fade out the top image
$active.css('z-index',1).show().removeClass('active');//reset the z-index and unhide the image
$next.css('z-index',3).addClass('active');//make the next image the top one
});
}
$(document).ready(function(){
// run every 7s
setInterval('cycleImages()', 7000);
})
</script>
As I said this is working fine however I've got one issue. In order for this to work I need to apply position:absolute to the .banner-test img class. Now I've also got another div within the .banner-test class to display some text on top of the banner image.
The code looks like this :
<div class="banner-test">
<img class="banner_one" src="../image.jpg" alt="" />
<img src="../image2.jpg" alt=""/>
<div id="text">
<p class="text1">Sample Text</p>
</div>
</div>
And the css for the #text :
#text {
position:absolute;
bottom:35px ;
left:10px;
width:70% ;
background-color:#104E8B;
font-size:1em;
color:white;
opacity:0.95;
filter:alpha(opacity=95); /* IE transparency */
}
.text1 {
padding:13px;
margin:0px;
}
.banner-test {
display: block;
position: relative;
}
So if I apply absolute positioning to the image it messes up the layout with the text (everything is pushed to the top of the page).
Can anybody think of a workaround for this?
EDIT
https://jsfiddle.net/ztrez888/1/embedded/result/ this is the fiddle - if position absolute is applied to the .banner-test img the text disappears
You said: (everything is pushed to the top of the page)
Its because your wrapper element .banner-test doesn't have a static height set. so when you apply a absolute position to the images in it .banner-test get shrink to height of the #text .text1.
Either set a height in the css:
.banner-test {
display: block;
position: relative;
height:200px; /* <--put the height of img */
}
or calculate it with jQuery:
$(document).ready(function(){
var arr = $('.banner-test img').map(function(){ // get the heights of imgs in array
return $(this).height();
}).get(),
h = Math.max.apply(Math, arr); // find out the greatest height in it.
$('.banner-test').css('height', h); // set the height here.
// run every 7s
setInterval('cycleImages()', 7000); // then cycle the images.
});
cycleImages() is been called in the setInterval and you have bannerImages() function on the page. I am assuming you have this cycleImages() function.
Updates:
#text {
position: absolute;
bottom: 30px;
left: 10px;
width: 100px;
background-color: #104E8B;
font-size: 1em;
color: white;
opacity: 0.95;
filter: alpha(opacity=95);
/* IE transparency */
z-index: 5; /* <----change these here*/
left: 10%;
top: 0;
}
Updated fiddle

jquery pan a large image within small div container using buttons

Hi there I need to an interactive element using a large image. This image sized 1000x1000 pixel with simple imagery will contain several questions with yes or no. What I want to do is place this image within a small div (say 500x300) with hidden overflow and add hotspots on the image for the yes/no option. What I want is when the user clicks yes, then the hotspot link pans to specific x/y coordinates of the same large image. Viewer will only see within the 500x300 window. So on and so forth. Is this possible? It seems so simple yet only option I can find is the pan by mouse option or iframe option with complicated divs and anchors. I'm not an expert in java/jquery but would love to find a script that is adaptable. Please help!
This sounded fun so I made a custom solution real quick. Demo here: jsBin
It's heavily reliant on the proper CSS, so check that in the bin, but here's the JS part:
var choice = document.querySelectorAll('.choice'),
image = document.getElementById('image')
for ( var i=0; i<choice.length; i++) {
choice[i].addEventListener('click', function (event) {
var x = this.dataset['x'],
y = this.dataset['y'];
image.style.top = '-'+y+'px';
image.style.left = '-'+x+'px';
})
}
Use css transitions for animation. Set up the positions you want the buttons to move the image around to in the image using a series of javascript objects. Then, set up your anchors, text, etc using absolute positioning on top of the image inside of a div container. Finally, add a click action in jQuery to assign your different positions to the top and left css of that container.
The end result, then, will be that you click an anchor, the left and top positions are assigned to the container via css in jQuery, and the transitions will slide the image around with the anchors.
I set up a fiddle here.
Here's the html from the fiddle:
<div id="window">
<div id="container">
<img src="http://upload.wikimedia.org/wikipedia/en/1/1f/Kill_The_Lights_1000x1000.jpg" id="image">
<ul>
<li><a id="city" href="#">City</a></li>
<li><a id="bottom" href="#">Bottom</a></li>
</ul>
</div>
</div>
And the CSS:
#window {
width:500px;
height:300px;
overflow:hidden;
position:relative;
}
#window a {
position: absolute;
z-index: 2;
display: block;
padding: 10px;
background: rgba(255,255,255,.5);
}
#city {
top: 20px;
left: 20px;
}
#bottom {
top: 220px;
left: 220px;
}
#container {
-webkit-transition:left 2s, top 2s, -webkit-transform 2s;
transition:left 2s, top 2s, transform 2s;
position: absolute;
z-index: 1;
top: 0px;
left: 0px;
}
Here's some javascript to give an example of setting up the positions as objects.
var city = {
top: -200,
left: -200
};
var bottom = {
top: -700,
left: -100
}
$('a').click(function() {
var t = this.id;
var c = $('#container');
if (typeof eval(t) !== 'undefined') {
c.css({
'top': eval(t).top,
'left': eval(t).left
});
}
});
I've just made a Fiddle with a demo image from where you could proceed.
HTML:
<div class="imgHolder">
<div class="hotspot one">Click</div>
<img src="image.jpg" />
</div>
CSS:
.imgHolder {
overflow:hidden;
width:300px;
height:300px;
position:relative;
}
.hotspot.one {
position:absolute;
top:10px;
padding:2px;
background-color:#fff;
left:10px;
}
.hotspot:hover {
cursor:pointer;
}
img {
position:relative;
z-index:-1;
}
jQuery:
$(".hotspot").on("click", function () {
$("img").animate({
"right": "+=100px"
});
});
For reference: http://api.jquery.com/animate/
You could e.g. fade hotspots in and out on specific positions and use animate() to move to the next hotspot.

Categories

Resources