Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toggle an animation over an element of a grid and fadein/out the other elements

I am experimenting with a tile-like layout for my site with which the user can interact. Each box is a button used to select a product, and upon selection of a product, the other boxes fade out and are hidden. This effect is toggle-able.

I have slightly modified the following fiddle that I found online, and it comes very close the desired result.

$('.box').click(function() {
  $('.box').not(this).fadeToggle(250);
});
div.box {
  width: 100px;
  height: 63px;
  background-color: #52c6ec;
  margin: 5px;
  padding-top: 37px;
  float: left;
  text-align: center;
  color: #fff;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="box" id="box1">Box 1</div>
<div class="box" id="box2">Box 2</div>
<div class="box" id="box3">Box 3</div>
<div class="box" id="box4">Box 4</div>
<div class="box" id="box5">Box 5</div>
<div class="box" id="box6">Box 6</div>
<div class="box" id="box7">Box 7</div>
<div class="box" id="box8">Box 8</div>
<div class="box" id="box9">Box 9</div>
<div class="box" id="box10">Box 10</div>
<div class="box" id="box11">Box 11</div>
<div class="box" id="box12">Box 12</div>
<div class="box" id="box13">Box 13</div>
<div class="box" id="box14">Box 14</div>
<div class="box" id="box15">Box 15</div>
<div class="box" id="box16">Box 16</div>
<div class="box" id="box17">Box 17</div>
<div class="box" id="box18">Box 18</div>
<div class="box" id="box19">Box 19</div>
<div class="box" id="box20">Box 20</div>

The only thing I want to do is to have the selected item transition (via animation) to the top-left, rather than just appearing there. Preferably also during the fading of the other boxes.

Because I'm using floats here, I cannot figure out how to animate these, since they don't have any numeric properties.

Ideas for a jQuery solution? Thanks.

like image 437
Chris Avatar asked Mar 18 '16 10:03

Chris


2 Answers

Is this what you want?

var t, l, loctop, locleft;

$('.box').click(function() {
  
  var e = $(this);
  
  if( $('.box').not(this).is(':visible') )
  {
    t = e.position().top + 'px';
    l = e.position().left + 'px';
    loctop = locleft = 0;
    $(this).css( {position: 'fixed', top:t, left:l} );
    $('.box').not(this).fadeToggle(550, function(){
      $(e).animate({ 
          top: loctop,
          left: locleft
        }, 800, function(){
        $(this).stop(true, true);
      });
    });
  }
  else
  {
    loctop = parseInt(t);
    locleft = parseInt(l);
    $(e).animate({ 
          top: loctop,
          left: locleft
        }, 800, function(){
      $('.box').not(this).fadeIn(550, function(){
        $(e).css( {position: 'relative', top:'', left:''} );
      });
    });
  }
  
});
div.box {
  width: 100px;
  height: 63px;
  background-color: #52c6ec;
  margin: 5px;
  padding-top: 37px;
  float: left;
  text-align: center;
  color: #fff;
  font-weight: bold;
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="box" id="box1">Box 1</div>
<div class="box" id="box2">Box 2</div>
<div class="box" id="box3">Box 3</div>
<div class="box" id="box4">Box 4</div>
<div class="box" id="box5">Box 5</div>
<div class="box" id="box6">Box 6</div>
<div class="box" id="box7">Box 7</div>
<div class="box" id="box8">Box 8</div>
<div class="box" id="box9">Box 9</div>
<div class="box" id="box10">Box 10</div>
<div class="box" id="box11">Box 11</div>
<div class="box" id="box12">Box 12</div>
<div class="box" id="box13">Box 13</div>
<div class="box" id="box14">Box 14</div>
<div class="box" id="box15">Box 15</div>
<div class="box" id="box16">Box 16</div>
<div class="box" id="box17">Box 17</div>
<div class="box" id="box18">Box 18</div>
<div class="box" id="box19">Box 19</div>
<div class="box" id="box20">Box 20</div>
like image 60
rmondesilva Avatar answered Oct 19 '22 23:10

rmondesilva


Here's my attempt in vanilla JS (tested on Chrome and Firefox)
Basically it works only with CSS transitions over the transform property for the selected element and over the opacity for all the other elements. The fadeOut/In runs while the selected element is moving as you specified.

CodePen Demo


CSS

main {
  display: flex;
  flex-wrap: wrap;
  border: 1px solid #ccc;
}

div {
   background: #a0c6df;
   width: 100px;
   height: 100px;
   border: 2px #8fa0c6 dashed;
   margin: 10px;
   opacity: 1;
   cursor: pointer;
   transition: all 1s;
}

main.fadeout div:not(.current) {
   opacity: 0;
   cursor: default;
}

JS

var main = document.querySelector('main');
var boxes = document.querySelectorAll('main div');
var animationIsRunning = false;

var getBoxPosition = function() {
  [].forEach.call(boxes, function(b) {
     var gBCR = b.getBoundingClientRect();
     b.dataset.top = gBCR.top;
     b.dataset.left = gBCR.left;
  }); 
}

window.addEventListener('resize', function() {
    var dc;
    getBoxPosition();
    if (dc = main.querySelector('div.current')) {
       main.classList.remove('fadeout');
       dc.classList.remove('current');
       dc.style.transform = 'translate(0,0)';
    }
});

main.addEventListener('click', function(evt) {
   var b    = evt.target,
       left = 0, 
       top  = 0;

   /* listen to the div click event only */
   if (b.nodeName.toLowerCase() !== 'div') { return false; }

   /* don't listen if there's a current element and user clicked 
      over a hidden div */
   if (
       main.querySelector('.current') &&
       !b.classList.contains('current')
   ) { return false; }

   /* only if another animation is not running... */
   if (!animationIsRunning) {
       animationIsRunning = true;

       b.classList.toggle('current');
       main.classList.toggle('fadeout');

       if (b.classList.contains('current')) {
          left = b.dataset.left;
          top  = b.dataset.top;
       }

       b.style.transform = 'translate(-'+ left +'px, -'+ top +'px)';
   }
});

main.addEventListener('transitionend', function() {
  animationIsRunning = false;
});


getBoxPosition();
like image 44
Fabrizio Calderan Avatar answered Oct 20 '22 01:10

Fabrizio Calderan