Jump to content
Search Community

Add an Animation / Transform on a Cloned jQuery Element

emilychews test
Moderator Tag

Go to solution Solved by emilychews,

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

Hi
 
I'm going to be adding an image gallery to a site and I basically have it so that when you click on an image, the image is cloned and reappears in the centre of the window.
 
The codepen is here: 
 
I would like it so that the cloned image goes through a transformation to arrive in its new position.  At the moment when you click on the image, the clone just appears in the middle of the window. I can't seem to get my head around how to have it so wherever the image is on the screen, it smoothly transitions to the central position. I tried swapping out the CSS object in my JS with some tweens, but this was a bit of a non-starter.
 
I'm quite up on the functionality of Greensock tweens and timelines now, however, I'm at a bit of a loss how to approach this.
 
Any help or pointers would be amazing.

Emily.
 
For quick reference I've also cut and pasted the JS / HTML and CSS code below: 
 
JS
$(function() {

// ===== vars to evaluate the left positioning after the element is cloned.
  var $windowWidthMiddle = $(window).width()/2;
  var $holderWidthMiddle = $('.holder').width() * 1.5 / 2;  
  var $left = $windowWidthMiddle - $holderWidthMiddle;
  
// ===== vars to evaluate the top positioning after the element is cloned.  
  var $windowHeightMiddle = $(window).height()/2;
  var $holderHeightMiddle = $('.holder').height() * 1.5 / 2;
  var $top = $windowHeightMiddle - $holderHeightMiddle;
  
// ====== Clone each image when clicked - these all have the default class '.holder'
  $('.holder').on("click",function() {
    if ($( this ).find(".cloned").length == 0) { // if not cloned already
      var $myClone = $(this).clone()
        .insertAfter(this)
        .addClass('cloned')
        .css({
          position: 'absolute',
          left: $left,
          top: $top,
          transition: 'all 1s'
        });

// ===== This adds the small 'x' to the cloned image to close it     
      $myClone.prepend('<div class="closeX">X</div>');
    
    }

  });
  
// ====== This is what causes the cloned image to be closed / removed
  $(".wrapper").on("click", ".closeX", function(e) {
    e.stopPropagation(); // this stops the click on the holder
    $(this).closest("div.cloned").remove();
  });
});
CSS
.wrapper {width: 100%; height: 100%;}

/* This is each image before cloning */

.holder {
width: 20vw;
height: 100px;
background: red;
position: relative;
margin-bottom: 5px;
display: inline-block;
z-index:0;
transform-origin: top left;
color: white;
}


/* The positioning 'top' and 'left' values after cloning are added in the javascript */

.holder.cloned {
  background: blue;
  z-index: 20;
  transform: scale(1.5);
} 


/*CSS for the prepended 'x' that shows on the cloned element*/

.closeX {
  position: absolute;
  background: yellow;
  top: 5px;
  right: 5px;
  width: 25px;
  height: 25px;
  line-height: 25px;
  text-align: center;
  cursor: pointer;
  color: black;
}

HTML
<div class="wrapper">
<!--   five images -->
  <div class="holder image1">Image 1</div>
  <div class="holder image2">Image 2</div>
  <div class="holder image3">Image 3</div>
  <div class="holder image4">Image 4</div>
  <div class="holder image5">Image 5</div>
</div>
 

 

See the Pen YZGxWZ by emilychews (@emilychews) on CodePen

Link to comment
Share on other sites

Hi Shaun,

 

Thanks for that, that's really useful to know.  The effect I wanted was when the transformation moves the image from where it is on the page to the center.  

In doing some further research for this I came across a JS script that does this called photoswipe.js  and looking at the complexity involved at what I want to achieve, I think the best thing is going to be to just use that script / plugin.

 

What you showed though was incredibly helpful for another less complex problem I was trying to resolve, and the whole concept of using TweenMax on click handlers was a lot simpler than I imagined.

Thanks

Emily.
 

Link to comment
Share on other sites

  • Solution

Sorry Blake, I didn't even see your answer.  A thousand apologies!

 

That looks very good, and thinking about it, I could probably have a play around with that pen and see how near I can get it.  I wouldn't want it full screen because it's going to be for an image library with downloadable images, so the image clicked on will be a smaller version of the downloadable hi-res image, which could look blurry at 100vh, but I'm thinking getting it to centre in the viewport at 50vh with that foundation of code may not be as daunting as first thought.

 

I loved your business card animation on that page as well btw.

 

Thanks again.

Emily.

Link to comment
Share on other sites

In doing some further research for this I came across a JS script that does this called photoswipe.js  and looking at the complexity involved at what I want to achieve, I think the best thing is going to be to just use that script / plugin.

 

 

 

I use photoswipe in a lot of projects (here for an example) ... it really is perfect for gallery setups and handles all the touch/swipe/click-drag/keyboard interactions & animations along with a host of other considerations. It's a solid choice.

Link to comment
Share on other sites

Hi Blake / Shaun,

 

I'm almost there. I've managed to get the effect I was after to work, but I've really hit a wall for the last few hours in terms of removing the cloned element in the context of GSAP.  

The new codepen is here 

See the Pen LWbxpX by emilychews (@emilychews) on CodePen



When the cloned element goes back into position I can't seem to be able to remove the clone after the reversed animation.  In the pen I've commented out the original code that was causing the clone to be removed, but when I try and integrate it into the animation, at the end it either just makes the cloned div just disappear (without animating) when I close the element or, as is the case at the moment, the timeline reverses but the cloned div stays.

Also I can't get it so when the cloned div is enlarged the other images are not unclickable, which used to be the case as well.

Any help would be awesome.

 

Emily.

Link to comment
Share on other sites

A few things I would do to make it a bit more straight forward ...

 

1. I would change the classes of `image1`, `image2`, etc to ids. Then I would put a data-clone-of attribute on the clones themselves (this helps tie them to their clone source)

 

2. I would then use the position of the original item as the x/y properties of a new tween and put an 'onComplete' property in that tween whose function removes the clone.

 

I think this would be simpler than reversing the timeline and then setting some sort of ticker/conditions on 1) the timeline being reversed and 2) its position being polled in order to know when to remove the object from the DOM.

 

You can see here what I'm suggesting

 

See the Pen bqBrpa by sgorneau (@sgorneau) on CodePen

 

 

The changes I'm proposing are in your  click handlers

$('.holder').on("click",function() { ...
$('.wrapper').on('click', '.closeX', function(e) { ...

All new lines marked with `// New code`

Link to comment
Share on other sites

Thanks for this.  I'll look at it properly tomorrow on my computer (as in, not on my phone), but that looks great.

 

It's taken me days to get it to where I am now...I can only dream of being able to use JS like you guys in the future. 

Can i ask? I've been using JS for about 9 months now.  How long did it take you to be able to use it like you do? JS is my first programming language and some of the stuff on this forum and what GSAP do is incredible.  I kind of wonder if it's going to be beyond what I'll ever be able to do / understand in terms of problem solving.

  • Like 1
Link to comment
Share on other sites

It takes years to get good. Definitely, not something that happens overnight. I've been doing JS since 2012, but it isn't my first language. I got better by doing stuff that was outside my area of expertise. After a while, stuff starts clicking, and you can focus on problem solving instead of the language.

  • Like 3
Link to comment
Share on other sites

 I kind of wonder if it's going to be beyond what I'll ever be able to do / understand in terms of problem solving.

I think you can accomplish anything if you stay with it. Hanging out in the GreenSock forum has taught me so much. I can't thank everyone around here enough. As Blake mentioned, things will start clicking after a while. I started having a lot of 'aha moments' after about 9-12 months. I'm certainly not an expert, but I'm much more comfortable than I was 18 months ago. I just strive to learn one or two new things each day.

 

I know all too well how daunting it can seem at times, but you can do it. Happy tweening.

:)

  • Like 4
Link to comment
Share on other sites

Can i ask? I've been using JS for about 9 months now.  How long did it take you to be able to use it like you do? JS is my first programming language and some of the stuff on this forum and what GSAP do is incredible.  I kind of wonder if it's going to be beyond what I'll ever be able to do / understand in terms of problem solving.

 

I've been working with JS for about 10 years now ... but I'm not going to even try to fake it ... OSUBlake is the JS rockstar here!

 

One of the things I've tried to do over the past few years is write JS (and HTML & CSS too, for that matter) as generically as possible and allowing data-attributes to be the value containers for ever-changing environments. This helps (me) keep the JS clean and lean and also gives me a nice place to inject initial values from the server. I work with CMSs a lot and I really like to give control to content teams to create dynamic, configurable elements, and for me the cleanest way to translate their "settings" to a template file is to pass those initial values into data-attributes that the JS can then hook into rather than injecting <script> blocks to pass those values. When watching a live DOM, it's also nice to see those attributes updating right on the elements, especially when addressing an issue.

 

But, more importantly, to OSUBlake's and PointC's points ... it's all about identifying and addressing the problem/challenge (the "what") and much less about JS (or any language). Once you get comfortable breaking it down into logical/modular chunks, even written in plain English, the "how" part starts with poking around in API documentation (vanilla JS, jQuery, GSAP, etc.) and eventually you do that enough to not have to make too many trips back into the docs (side note: I still make trips to the docs ;) )

 

Once you separate the logic from the language(s) in terms of a mindset, it becomes much more clear which steps you need to take ... and then you determine what markup, functions, methods, and syntax will get you there.

  • Like 5
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...