Плавное увеличение части картинки на чистом JS

Есть картинка, на которой есть несколько объектов. При клике на объект должно происходить плавное увеличение, как эффект наезжания камеры, до того момента пока объект не будет на весь экран. Я сделал вариант с разделением картинки на несколько более мелких, соединением их и при клике увеличивать на весь экран блок с объектом, но пока это слабо походит на "наезжание камеры". Вопросы: Как сделать плавный сдвиг всех остальных блоков (или уменьшение этих блоков) при клике на один из блоков (в моем примере блоки заменяют кусочки картинки), чтобы создался эффект наезда камеры?

console.clear();

var root  = document.documentElement;
var body  = document.body;
var pages = document.querySelectorAll(".page");
var tiles = document.querySelectorAll(".tile");

for (var i = 0; i < tiles.length; i++) {  
  addListeners(tiles[i], pages[i]);
}

function addListeners(tile, page) {
  
  tile.addEventListener("click", function() {
    animateHero(tile, page);
  });
  
  page.addEventListener("click", function() {
    animateHero(page, tile);
  });  
}

function animateHero(fromHero, toHero) {
    
  var clone = fromHero.cloneNode(true);
      
  var from = calculatePosition(fromHero);
  var to = calculatePosition(toHero);
  
  TweenLite.set([fromHero, toHero], { visibility: "hidden" });
  TweenLite.set(clone, { position: "absolute", margin: 0 });
  
  body.appendChild(clone);  
      
  var style = {
    x: to.left - from.left,
    y: to.top - from.top,
    width: to.width,
    height: to.height,
    autoRound: false,
    ease: Power1.easeOut,
    onComplete: onComplete
  };
   
  TweenLite.set(clone, from);  
  TweenLite.to(clone, 2, style)
    
  function onComplete() {
    
    TweenLite.set(toHero, { visibility: "visible" });
    body.removeChild(clone);
  }
}

function calculatePosition(element) {
    
  var rect = element.getBoundingClientRect();
  
  var scrollTop  = window.pageYOffset || root.scrollTop  || body.scrollTop  || 0;
  var scrollLeft = window.pageXOffset || root.scrollLeft || body.scrollLeft || 0;
  
  var clientTop  = root.clientTop  || body.clientTop  || 0;
  var clientLeft = root.clientLeft || body.clientLeft || 0;
    
  return {
    top: Math.round(rect.top + scrollTop - clientTop),
    left: Math.round(rect.left + scrollLeft - clientLeft),
    height: rect.height,
    width: rect.width,
  };
}
  
  .tile {
    width: 49vw;
    height: 50vh;
    cursor: pointer;  
    display: inline-block;
  }
  
  .page-container {
    visibility: hidden;
  }
  
  .page {
    cursor: pointer;
    position: absolute;
    height: 100vh;
    width: 100vw;
    top: 0;
    left: 0;
    position: fixed;
  }
  
  .hero-1 {
    background: red;
  }
  
  .hero-2 {
    background: #000;
  }
  
  .hero-3 {
    background: #7DD6FE;
  }
  
  .hero-4 {
    background: #DC3C84;
  }
          <div class="tile hero-1"></div>
          <div class="tile hero-2"></div>
          <div class="tile hero-3"></div>
          <div class="tile hero-4"></div>
      
      <div class="page-container">
        <div class="page hero-1"></div>
        <div class="page hero-2"></div>
        <div class="page hero-3"></div>
        <div class="page hero-4"></div>
      </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.3/TweenMax.min.js"></script>


Ответы (1 шт):

Автор решения: DiD

Как-то так чтоли?

var Boxlayout = (function() {

  var $el = $('#bl-main'),
    $sections = $el.children('section'),
    // works section
    $sectionWork = $('#bl-work-section'),
    // work items
    $workItems = $('#bl-work-items > li'),

    // navigating the work panels
    // if currently navigating the work items
    isAnimating = false,
    // close work panel trigger
    transEndEventNames = {
      'WebkitTransition': 'webkitTransitionEnd',
      'MozTransition': 'transitionend',
      'OTransition': 'oTransitionEnd',
      'msTransition': 'MSTransitionEnd',
      'transition': 'transitionend'
    },
    // transition end event name
    transEndEventName = transEndEventNames[Modernizr.prefixed('transition')],
    // support css transitions
    supportTransitions = Modernizr.csstransitions;

  function init() {
    initEvents();
  }

  function initEvents() {

    $sections.each(function() {

      var $section = $(this);

      // expand the clicked section and scale down the others
      $section.on('click', function() {

        if (!$section.data('open')) {
          $section.data('open', true).addClass('bl-expand bl-expand-top');
          $el.addClass('bl-expand-item');
        }

      }).find('span.bl-icon-close').on('click', function() {

        // close the expanded section and scale up the others
        $section.data('open', false).removeClass('bl-expand').on(transEndEventName, function(event) {
          if (!$(event.target).is('section')) return false;
          $(this).off(transEndEventName).removeClass('bl-expand-top');
        });

        if (!supportTransitions) {
          $section.removeClass('bl-expand-top');
        }

        $el.removeClass('bl-expand-item');

        return false;

      });

    });


  }

  return {
    init: init
  };

})();

$(function() {
  Boxlayout.init();
});
body,
html {
  font-size: 100%;
  padding: 0;
  margin: 0;
  height: 100%;
}

*,
*:after,
*:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

body {
  font-family: 'Lato', Calibri, Arial, sans-serif;
  color: #f2ede3;
  background: #333;
  font-size: 0.9em;
  font-weight: 300;
}

a {
  color: #f0f0f0;
  text-decoration: none;
  font-weight: 700;
  letter-spacing: 2px;
  padding: 0 5px;
  text-transform: uppercase;
  font-size: 80%;
}

a:hover {
  color: #fff;
}

.container {
  height: 100%;
}

.bl-main {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.bl-main>section {
  position: absolute;
  width: 50%;
  height: 50%;
}

.bl-main>section:first-child {
  top: 0;
  left: 0;
  background: #F06060;
}

.bl-main>section:nth-child(2) {
  top: 0;
  left: 50%;
  background: #FA987D;
}

.bl-main>section:nth-child(3) {
  top: 50%;
  left: 0;
  background: #72CCA7;
}

.bl-main>section:nth-child(4) {
  top: 50%;
  left: 50%;
  background: #10A296;
}

.bl-box {
  position: relative;
  width: 100%;
  height: 100%;
  cursor: pointer;
  opacity: 1;
  /* Centering with flexbox */
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
  -webkit-flex-wrap: wrap;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
  -webkit-box-pack: center;
  -moz-box-pack: center;
  -webkit-justify-content: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-align: center;
  -moz-box-align: center;
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;
}

.bl-box h2 {
  text-align: center;
  margin: 0;
  padding: 20px;
  width: 100%;
  font-size: 1.8em;
  letter-spacing: 2px;
  font-weight: 700;
  text-transform: uppercase;
}

.bl-icon {
  speak: none;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  cursor: pointer;
  -webkit-font-smoothing: antialiased;
}

.bl-icon:before {
  display: block;
  font-size: 2em;
  margin-bottom: 10px;
}

.bl-icon-about:before {
  content: "⌬";
}

.bl-icon-works:before {
  content: "⎈";
}

.bl-icon-blog:before {
  content: "〠";
}

.bl-icon-contact:before {
  content: "⚠";
}

.bl-main>section .bl-icon-close {
  position: absolute;
  top: 20px;
  right: 20px;
  cursor: pointer;
  z-index: 100;
  opacity: 0;
  pointer-events: none;
}

.bl-icon-close:before {
  content: "⊗";
}

.bl-content,
div.bl-panel-items>div>div {
  opacity: 0;
  pointer-events: none;
  position: absolute;
  top: 60px;
  left: 30px;
  right: 30px;
  bottom: 30px;
  padding: 0 20px;
  overflow: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}




/* Transition classes and properties */


/* Separated for a better overview and control */

.bl-main>section {
  -webkit-transition: all 0.5s ease-in-out;
  -moz-transition: all 0.5s ease-in-out;
  transition: all 0.5s ease-in-out;
}

.bl-main>section.bl-expand {
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}

.bl-main>section.bl-expand-top {
  z-index: 100;
}

.bl-main>section:first-child.bl-expand {
  background: #EE4444;
}

.bl-main>section:nth-child(2).bl-expand {
  background: #F98262;
}

.bl-main>section:nth-child(3).bl-expand {
  background: #4BBE8E;
}

.bl-main>section:nth-child(4).bl-expand {
  background: #0D8278;
}

.bl-main.bl-expand-item>section:not(.bl-expand),
.bl-main.bl-expand-item>section.bl-scale-down {
  -webkit-transform: scale(0.5);
  -moz-transform: scale(0.5);
  -ms-transform: scale(0.5);
  transform: scale(0.5);
  opacity: 0;
}

.bl-box {
  -webkit-transition: opacity 0.2s linear 0.5s;
  -moz-transition: opacity 0.2s linear 0.5s;
  transition: opacity 0.2s linear 0.5s;
}

section.bl-expand .bl-box {
  opacity: 0;
  -webkit-transition: opacity 0s linear;
  -moz-transition: opacity 0s linear;
  transition: opacity 0s linear;
}

.bl-box h2 {
  -webkit-transition: all 0.2s ease-in-out;
  -moz-transition: all 0.2s ease-in-out;
  transition: all 0.2s ease-in-out;
}

.no-touch section:not(.bl-expand) .bl-box:hover h2 {
  -webkit-transform: translateY(-15px);
  -moz-transform: translateY(-15px);
  -ms-transform: translateY(-15px);
  transform: translateY(-15px);
}

.bl-content,
.bl-icon-close {
  -webkit-transition: opacity 0.1s linear 0s;
  -moz-transition: opacity 0.1s linear 0s;
  transition: opacity 0.1s linear 0s;
}

section.bl-expand .bl-content,
section.bl-expand .bl-icon-close {
  pointer-events: auto;
  opacity: 1;
  -webkit-transition: opacity 0.3s linear 0.5s;
  -moz-transition: opacity 0.3s linear 0.5s;
  transition: opacity 0.3s linear 0.5s;
}

@media screen and (max-width: 46.5em) {
  .bl-content,
  .bl-box {
    font-size: 75%;
  }
  .bl-expand .bl-box {
    height: 130px;
  }
  .bl-content>ul li {
    width: 40%;
  }
}
<script src="https://tympanus.net/Development/FullscreenLayoutPageTransitions/js/modernizr.custom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div id="bl-main" class="bl-main">
    <section>
      <div class="bl-box">
        <h2 class="bl-icon bl-icon-about">About</h2>
      </div>
      <div class="bl-content">
      </div>
      <span class="bl-icon bl-icon-close"></span>
    </section>
    <section id="bl-work-section">
      <div class="bl-box">
        <h2 class="bl-icon bl-icon-works">Works</h2>
      </div>
      <div class="bl-content">
      </div>
      <span class="bl-icon bl-icon-close"></span>
    </section>
    <section>
      <div class="bl-box">
        <h2 class="bl-icon bl-icon-blog">Blog</h2>
      </div>
      <div class="bl-content">
      </div>
      <span class="bl-icon bl-icon-close"></span>
    </section>
    <section>
      <div class="bl-box">
        <h2 class="bl-icon bl-icon-contact">Contact</h2>
      </div>
      <div class="bl-content">
      </div>
      <span class="bl-icon bl-icon-close"></span>
    </section>
  </div>
</div>

Источник

→ Ссылка