janhartmann
janhartmann

Reputation: 15003

Animate the width/height from the far corners

I have a grid of 6 blocks. When clicking on each of the block, the block expand and cover the container holding the blocks.

The first box (top left) looks fine, but the others fail the illusion that the block grows to the container width and height, because it starts from their top left position.

Ideally box 2 and 5 should expand from their center and box 1, 3, 4 and 6 should expand from their far corners. Is that possible and how?

I've created a JSFiddle that shows my problem. But the code for reproduce is here:

JQuery

$(".service-block").on("click", "a", function (e) {
    e.preventDefault();

    var block = $(this);
    var blockOffset = block.offset();
    var blockBackgroundColor = block.css("backgroundColor");

    var container = $(".service-grid");
    var containerOffset = container.offset();

    // Create the popup and append it to the container
    var popout = $("<div class='service-block-popup'>Test</div>");
    popout.css({
        "backgroundColor": blockBackgroundColor,
        "position": "absolute",
        "top": blockOffset.top,
        "left": blockOffset.left
    }).appendTo(container)

    // Now animate the properties
    .animate({
        "height": container.height() + "px",
        "width": container.width() + "px",
        "top": containerOffset.top,
        "left": containerOffset.left
    }, 1500, function() {
        //alert("done");
    })

    .on("click", function () {
        popout.remove();
    });

});

Markup

<div class="service-grid">
    <div class="row">
        <div class="service-block">
            <a href="#" class="box1">
                <span class="title">Box 1</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box2">
                <span class="title">Box 2</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box3">
                <span class="title">Box 3</span>
            </a>
        </div>
    </div>
    <div class="row">
        <div class="service-block">
            <a href="#" class="box4">
                <span class="title">Box 4</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box5">
                <span class="title">Box 5</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box6">
                <span class="title">Box 6</span>
            </a>
        </div>
    </div>
</div>

CSS

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

.service-grid { width: 600px; }
.row { 
    overflow: hidden; 
}

.service-grid .service-block a {
    display: block;
    height: 200px;
    width: 200px;
    text-align: center;
    float: left;
}
.service-grid .service-block a > img {
    display: block;
    margin: 0 auto;
    transition: all 100ms linear 0s;
}
.service-grid .service-block a > .title {
    display: block;
    font-family: Arial,Helvetica,sans-serif;
    font-size: 2.2rem;
    font-weight: bold;
    line-height: 3.2rem;
    margin-top: 20px;
    text-transform: uppercase;
}

.box1 { background: red; }
.box2 { background: purple; }
.box3 { background: yellow; }
.box4 { background: orange; }
.box5 { background: green; }
.box6 { background: magenta; }

Upvotes: 6

Views: 236

Answers (5)

gav_aus_web
gav_aus_web

Reputation: 199

Understood that classes weren't your preference, but they are the most efficient approach, in regards to both memory and animation smoothness.

Applying the starting value(s) (Eg. width/height/etc.), animation-settings and scale(0) on the base-class (.message) is required.

HTML

<div class="trigger">trigger</div>
<div class="message">XXXXXXXXXhXXXXXX</div>

CSS

.message{
  background-color: blue;
  transform: scale(0);
  transform-origin: top left;
  height: 100px;
  transition: width 2s, height 2s, transform 2s;
}
        
.unreadMessage{   
  transform: scale(1);
}

jQuery

var msg = $('.message'),
    trigger = $('.trigger')

trigger.on('click',function(){
    msg.toggleClass('unreadMessage')
})

Codepen Example: https://codepen.io/gavAusMac/pen/zYKgWJN

Bonus Info: - Also, if applying dynamic style changes (eg. width/height) via Javascript, the use of requestAnimationFrame() & setTimeout() combined may be required, to ensure that dynamic height/etc. are applied before the animation class is set.

Code Example:

$(msg).css('width', dynamicWidth + 'px')
$(msg).css('height', dynamicHeight + 'px')
        
requestAnimationFrame(function() {
  setTimeout(function() {
    $(msg).toggleClass('unreadMessage')
  });
});

Upvotes: 0

Noopur Dabhi
Noopur Dabhi

Reputation: 1927

I've generated dynamic top and left based on width/height of container and width/height of box. Based on what size of container and box is, it will decide the position of box, whether it is in corner or in center and then decide top and left.

Here is js code :

$(".service-block").on("click", "a", function (e) {
  e.preventDefault();

  var block = $(this);
  var blockOffset = block.offset();
  var blockBackgroundColor = block.css("backgroundColor");

  var container = $(".service-grid");
  var containerOffset = container.offset();
  var top = 0;
  var left = 0;

  if (blockOffset.top - containerOffset.top == 0 &&  blockOffset.left - containerOffset.left == 0) {
      top = blockOffset.top;
      left = blockOffset.left;
  } else if (blockOffset.top - containerOffset.top == 0 && blockOffset.left - containerOffset.left + block.width() == container.width()) {
      top = blockOffset.top;
      left = container.width() - containerOffset.left;
  } else if (blockOffset.top - containerOffset.top + block.height() == container.height() && blockOffset.left - containerOffset.left == 0) {
      top = container.height() - containerOffset.top;
      left = containerOffset.left;
  } else if (blockOffset.top - containerOffset.top + block.height() == container.height() && blockOffset.left - containerOffset.left + block.width() == container.width()) {
      top = container.height() - containerOffset.top;
      left = container.width() - containerOffset.left;
  } else {
      top = blockOffset.top + (block.width() / 2);
      left = blockOffset.left + (block.height() / 2);
  }

  // Create the popup and append it to the container
  var popout = $("<div class='service-block-popup'>Test</div>");
  popout.css({
      "backgroundColor": blockBackgroundColor,
      "position": "absolute",
      "top": top,
      "left": left
  }).appendTo(container)

  // Now animate the properties
  .animate({
      "height": container.height() + "px",
      "width": container.width() + "px",
      "top": containerOffset.top,
      "left": containerOffset.left
  }, 1500, function() {
      //alert("done");
  })

  .on("click", function () {
      popout.remove();
  });

});

Here is fiddle.

It will work for more than 6 boxes.

Upvotes: 1

janhartmann
janhartmann

Reputation: 15003

I am going to answer my question myself. This was a simple mistake!

I did not set the width/height on the .service-block-popup. So it did not expand from its current state. This is how it should be constructed:

// Create the popup and append it to the container
var popout = $("<div class='service-block-popup'>Test</div>");
popout.css({
    "backgroundColor": blockBackgroundColor,
    "position": "absolute",
    "top": blockOffset.top,
    "left": blockOffset.left,
    "width": block.outerWidth(),
    "height": block.outerHeight()
}).appendTo(container)
/* .... */

Here in action: http://jsfiddle.net/hdq0x2s8/4/

Upvotes: 1

Lalji Tadhani
Lalji Tadhani

Reputation: 14149

Try This code I have Some change CSS & JS

$(".service-block").on("click", "a", function (e) {
        e.preventDefault();
        var block = $(this);
        var blockOffset = block.offset();
        var blockBackgroundColor = block.css("backgroundColor");

        var container = $(".service-grid");
        var containerOffset = container.offset();

        // Create the popup and append it to the container
        var popout = $("<div class='service-block-popup'>Test</div>");
        popout.css({

            "backgroundColor": blockBackgroundColor,
            "position": "absolute",
            "left": "50%",
            "top": "50%",
        }).appendTo(container)

        // Now animate the properties
        .animate({
            "height": container.height() + "px",
            "width": container.width() + "px",
            "top": containerOffset.top,
            "left": containerOffset.left
        }, 1500, function () {
            //alert("done");
        })

        .on("click", function () {
            popout.remove();
        });

    });

Demo Link http://jsfiddle.net/hdq0x2s8/3/

Upvotes: 0

Sachink
Sachink

Reputation: 1530

Hope this code will useful for you, I just added a few line of code. Find fiddle here

$(".service-block").on("click", "a", function (e) {
        e.preventDefault();

        var block = $(this);
        var blockOffset = block.offset();
        var blockBackgroundColor = block.css("backgroundColor");

        var container = $(".service-grid");
        var containerOffset = container.offset();

        // Create the popup and append it to the container
        var popout = $("<div class='service-block-popup'>Test</div>");
    
    	thisHeight = $(this).height();
        thisWidth = $(this).height();
    	var clsName = $(this).attr('class');
    
    	var topEle = ["box1", "box2", "box3"];
        if ($.inArray(clsName, topEle) > -1)
        {
            thisHeight = 0;
        }
    
    	var leftEle = ["box1", "box4"];
    	if ($.inArray(clsName, leftEle) > -1)
        {
            thisWidth = 0;
        }
        var midEle = ["box2", "box5"];
        if ($.inArray(clsName, midEle) > -1)
        {
            thisWidth = thisWidth/2;
        }
    
        popout.css({
            "backgroundColor": blockBackgroundColor,
            "position": "absolute",
            "top": blockOffset.top + thisHeight,
            "left": blockOffset.left + thisWidth
        }).appendTo(container)

        // Now animate the properties
        .animate({
            "height": container.height() + "px",
            "width": container.width() + "px",
            "top": containerOffset.top,
            "left": containerOffset.left
        }, 1500, function() {
            //alert("done");
        })

        .on("click", function () {
            popout.remove();
        });

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

.service-grid { width: 600px; }
.row { 
    overflow: hidden; 
}

.service-grid .service-block a {
    display: block;
    height: 200px;
    width: 200px;
    text-align: center;
    float: left;
}
.service-grid .service-block a > img {
    display: block;
    margin: 0 auto;
    transition: all 100ms linear 0s;
}
.service-grid .service-block a > .title {
    display: block;
    font-family: Arial,Helvetica,sans-serif;
    font-size: 2.2rem;
    font-weight: bold;
    line-height: 3.2rem;
    margin-top: 20px;
    text-transform: uppercase;
}

.box1 { background: red; }
.box2 { background: purple; }
.box3 { background: yellow; }
.box4 { background: orange; }
.box5 { background: green; }
.box6 { background: magenta; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="service-grid">
    <div class="row">
        <div class="service-block">
            <a href="#" class="box1">
                <span class="title">Box 1</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box2">
                <span class="title">Box 2</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box3">
                <span class="title">Box 3</span>
            </a>
        </div>
    </div>
    <div class="row">
        <div class="service-block">
            <a href="#" class="box4">
                <span class="title">Box 4</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box5">
                <span class="title">Box 5</span>
            </a>
        </div>
        <div class="service-block">
            <a href="#" class="box6">
                <span class="title">Box 6</span>
            </a>
        </div>
    </div>
</div>

Upvotes: 0

Related Questions