Jump to content
Search Community

"Pinching" top corners of a div box

benderhune test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

What I'm trying to do is create an effect similar to the iOS-like window minimization effect, only it will as a hover function. I have most of it put together so far, but what I came to GSAP originally for, I'm finding to be very difficult (yup, I converted from previously using CSS3 for animations.) I thought the skew command would work but it's not doing what I'd like. Basically what I want is for the top 2 corners of a box to pinch inward, then tween into a full square. The point of this is to make it appear that it's coming flying at you from far away, much like the text from our favorite Star Wars movies. I tried combining skews but that didn't work, neither did applying both positive and negative skews within one tween. Does anyone know of a way to do this (with GSAP or otherwise)? I could very easily create the animation in Flash, but I'd like to avoid Flash at all cost.

 

I've seen some somewhat similarities to what I'm looking to do. On this website (http://fff.cmiscm.com/#!/section/sheeps) the title card animates one corner at a time, which is very similar to what I'm trying to do.

 

For reference, the object that's being animated is a simple rectangular div with a solid background (for now, but I will use an image in the future once testing is complete).

Link to comment
Share on other sites

Hello and Welcome to the GreenSock Forum!

 

If you can provide a limited

See the Pen by pen (@pen) on CodePen

or jsfiddle of your code we can better help see whats going on!

 

when you say..  you thought the skew command would work

  • were you using the transform: skew() property ?

if so..  you have to use skewX() or skewY() due to the skew() shorthand method not being supported since early drafts of the spec:

 

https://developer.mozilla.org/en-US/docs/Web/CSS/transform

 

Note: The skew() function was present in early drafts. It has been removed but is still present in some implementations. Do not use it.

To achieve the same effect, use skewX() if you were using skew() with one parameter or matrix(1, tan(ay), tan(ax), 1, 0, 0) for the general way. Note that tan() isn't a CSS function and you have to precalculate it yourself.

 

Browsers that do have the skew() property will eventually have it removed in the future due to it being experimental in early drafts of the CSS Transforms Level 1 spec.

 

thx :)

Link to comment
Share on other sites

Right, of course it would help to have the code to see... :blink:

Here is my JSFiddle: http://jsfiddle.net/K6mxC/2/

 

I have changed the method in which I try to achieve "pinching." Instead of using the skewX() command, I realized that by adding transform perspective and 3D rotation along the X axis that I could achieve almost exactly what I was planning on doing. The pinch does in fact work, however, I have found that I have a whole slew of new problems.

 

When I was originally setting up the code I had everything centered. It took me a rather long time to figure out how to get the child div (the #box element that shows up) to move in relative position to its parent (which is necessary because this animation will be used in a navigation menu.)

 

So my current problems are these two:

1) For some reason the div #box will animate to its proper location, but the animation sequence is making the #box div originate far from the left. It originally originated from the center and flipped forward, but now it's inexplicably way out in left field and I have been unable to figure out how to make it start in the center. It seems that the div is being created from the top-left corner, though that makes no sense because the transformOrigin point is (50% 50%).

 

2)This is probably more of a jQuery selector issue (bare with me, I just started learning JS, jQuery, and GSAP a week ago) but for some reason, when I try to convert the animated div from being selected by an ID to a class, the animation no longer works. The div appears invisible or doesn't display at all. I would assume this has something to do with the fact that the final function has 2 elements called. It seems to work just fine when .hover me is a class and #box is an ID, but as soon as I convert everything to .box, it completely fails.

 

Thank you for your help!!!!

Link to comment
Share on other sites

Hi,

 

The first issue has to do with the fact that you're tweening the element's width and height, and in that case the transform point is always the top-left corner, is just how the box model works. You could try by scaling the element down instead of using width and height, like that it should go to the center point instead of the top left corner.

 

The second issue is a bit odd, I tweaked your fiddle and using class selectors works fine, perhaps just a syntax issue, take a look:

 

http://jsfiddle.net/K6mxC/3/

 

Also a couple of suggestions, for this cases is far better to store the tween in a variable and use the play() and reverse() methods on mouseenter and mouseout, it save's you writting some code and you get more familiar with the engine's methods.

 

You can use a from() instance to create the animation. The from instance starts with the end values of the tween, so for example you created your element with a certain width and you want that element to appear from a smaller size and opacity zero; you create a from instance and once the instance is created the element's size and opacity are changed.

 

Also is always a good choice to use a set instance to establish the perspective of an element before creating the tweens to animate it, like this:

TweenLite.set("#box", {transformPerspective:400});

With this suggestions you're code will look like this:

TweenLite.set("#box", {transformPerspective:400});

var tn = TweenLite.from("#box", 3, 
{
  rotationX:90,
  opacity:0,
  borderRadius:0,
  display:'none',
  scale:0.001,
  ease:Bounce.easeOut,
  paused:true
});

$('.hoverme, .box').mouseover(function()
{
  tn.play();
});

$('.hoverme, .box').mouseout(function()
{
  tn.reverse();
});

And the CSS will be like this:

body {
	text-align:center;
}
.hoverme {
	width:100px;
	border:thin solid #000;
	margin-left:200px;
	text-align:center;
}
#box {
	position:absolute;
	width:350px;
	height:200px;
	float:left;
	margin-top:-16px;
	;
	background-color:#F00;
	border: solid thin #F00;
        border-radius:10px;
}
p {
	font-family:Arial, Helvetica, sans-serif;
	font-size:12pt;
}

I've forked your fiddle:

http://jsfiddle.net/K6mxC/5/

 

Best,

Rodrigo.

Link to comment
Share on other sites

Awesome! Thank you so much for helping me, you guys rock. I attempted to use a tweenLite timeline but I wasn't having a whole lot of luck with it, I didn't realize the information had to be stored in a var.

 

Edit:

Two final questions though.

-I'd like the easing animations to be different on when the mouseOut event occurs. With the last Fiddle you sent me, when you reverse the animation, the easeOut animation displays first, then the element disappears. I've tried using the overwrite:"all" and "auto" method and redefining the ease method on the mouseOut event, but that seems to screw up the whole animation. Is there a way to make that happen or will I have to write a separate tween to do that?

-As I said before, I want to use this animation for a navigation menu. The only problem is that when one link is hovered, the box is displayed under all of them. Is there a simple way to make the box only appear under the hovered element? Or will I have to tough it out and just write a script for each individual navigation item? Here's a forked Fiddle to demonstrate: http://jsfiddle.net/K6mxC/11/

 

Carl, thanks a lot for digging that out for me! Ohhh the world of Javascript is very exciting.

Edited by benderhune
Link to comment
Share on other sites

Hi,

 

First thanks a lot for bringing the tweet and repository up Carl, that effect was really baking my noodle  :wacko:

 

As for eliminating the easing, what you can do is determinate how much the mouseover animation has progressed, stop the mouseover animation and create a new animation with that amount of time. The other tween gets overwritten and send for GC and the new one executes. Somtehing like this:

TweenLite.set("#box",
{
    transformPerspective:400,
    width:350,
    height:200,
    opacity:0,
    rotationX:90,
    scale:0.001,
    display:'none',
    borderRadius:0
});

$('.hoverme, .box').mouseover(function()
{
  TweenLite.to("#box", 2,
  {
      rotationX:0,
      opacity:1,
      borderRadius:10,
      display:'block',
      scale:1,
      ease:Back.easeOut
  });
});

$('.hoverme, .box').mouseout(function()
{
    var tnTime;
    
    if(TweenLite.getTweensOf("#box")[0] == null)
    {
        tnTime = 2;
    }
    else
    {
        tnTime = TweenLite.getTweensOf("#box")[0].time();
    }
    
    TweenLite.to("#box", tnTime,
    {
        rotationX:90,
        opacity:0,
        borderRadius:0,
        display:'none',
        scale:0.001
    });
});

You can see it here:

http://jsfiddle.net/K6mxC/10/

 

Best,

Rodrigo.

Link to comment
Share on other sites

Rodrigo, I was looking at the Fiddle you supplied but I'm noticing that even after I speed up the animation, it's a little buggy finishing up the animation when you hover over the animating div. It's either really not smooth or the div just runs away lol.

 

I feel as if I can live with the ease animation issue, more importantly though, do you have any thoughts on how I can take care of my other problem? It's really the only thing preventing me from actually implementing it to my website. Not sure if you saw my edit from my previous post but this is what I wrote:

 

As I mentioned before, I want to use this animation for a navigation menu. The only problem is that when one link is hovered, the box is displayed under every link. Is there a simple way to make the box only appear under the hovered element? Or will I have to tough it out and just write a script for each individual navigation item? Here's a forked Fiddle to demonstrate: http://jsfiddle.net/K6mxC/11/

Thanks!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...