LankyMoose LankyMoose - 6 months ago 15
HTML Question

Parallax-like tilting of elements in JS

First question here at SO so please be nice if my syntax or structure isn't great :P

Anyways, I'm building a full-page html/js app have a simple html structure with 4 divs that scale with the screen size, and are laid out in a 50/50 grid format.

I would like to have these divs tilt away from the mouse (with varying strength depending on x or y axis).

EDIT: I have constructed a small example that doesn't really happen to work too well:

https://jsfiddle.net/LankyMoose/a6wu587y/

var centerX = $( 'html' ).width() / 2;
var centerY = $( 'html' ).height() / 2;
var oppositeposX = event.pageX - centerX;
var oppositeposY = event.pageY - centerY;
var offset = "skew(" + oppositeposX * -.05 + "deg," + oppositeposY * .02 + "deg)";


^ this is the calculation I'm using to transform the content... I am sure there must be a better way to do this and achieve better results.I need it to skew the page in the opposite direction as if to focus on the mouse's direction.

EDIT #2: I've now got a nice looking tilt effect using the following!

$( "body" ).mousemove(function( event ) {
var centerX = $( "body" ).width() / 2;
var centerY = $( "body" ).height() / 2;
var oppositeposX = event.pageX - centerX;
var oppositeposY = event.pageY - centerY;
var offset = "rotateY(" + -oppositeposX * .2 + "deg) rotateX(" + (1 * oppositeposY * .1) + "deg)";
var rotate = {'transform' : offset};
$(".container").css(rotate);
});

Answer

I think the effect you are trying to achieve might be better suited to a css 3d rotation rather than a skew.

I've edited your fiddle with a few changes.

1) Setting a perspective on the body. This will allow the .container to be manipulated in 3d space.

2) Changed the transform rule to use rotate instead of skew.

3) I've altered the css to position the 4 items absolutely, rather than floating them. This means they will adapt to the size of whatever window they are in.

Anyway, hopefully that should give you a start towards getting the effect you want.

$( "#togglelogs" ).click(function() {
  $( "#logs" ).toggle( 100, function() {
    // Animation complete.
  });
});
$( "body" ).mousemove(function( event ) {
  var pos = "Mouse Position: ";
  var centerX = $( "body" ).width() / 2;
  var centerY = $( "body" ).height() / 2;
  var oppositeposX = event.pageX - centerX;
  var oppositeposY = event.pageY - centerY;
  var offset = "rotateY(" + oppositeposX * .2 + "deg) rotateX(" + (-1 * oppositeposY * .2) + "deg)";
  var skew = {'transform' : offset};
  var oppositeskew = {'transform' : offset};
  
  pos += "x = " + event.pageX + ", " + "y = " + event.pageY;
  $( "#mouselog" ).empty();
  $( "#mouselog" ).append(pos);
  $( "#center" ).empty();
  $( "#center" ).append("Center X = " + centerX + ", Center Y = " + centerY);
  $( "#offset" ).empty();
  $( "#offset" ).append("Offest X = " + oppositeposX + ", Offest Y = " + oppositeposY);
  $(".container").css(skew);
  $( "#css" ).empty();
  $( "#css" ).append(offset);
});
html , body {
  height: 100%;
  min-height:100%;
}

body {
  -webkit-perspective: 1000px;
  perspective: 1000px;
  overflow:hidden;
}
#togglelogs {
  display: block;
  font-size: 10px;
  position: absolute;
  top: 0;
  right: 0;
  background: rgba(0,0,0,0.6);
  color: #fff;
  padding: 4px;
  border-radius: 0 0 0 4px;
  cursor: pointer;
}
.container {
  position:absolute;
  height: 100%;
  top:0;
  bottom:0;
  left:0;
  right:0;

}
.grid-object {
  width: calc(50% - 2px - 4px);
  height: 50%;
  margin: 1px;
  text-align: center;
  background: #aaa;
  border: 1px solid #222;
  position: absolute;
  left:0;
  top:0;
}
.grid-object + .grid-object {
  left: 50%;
}

.grid-object + .grid-object + .grid-object{
  left: 0;
  top:50%;
}

.grid-object + .grid-object + .grid-object+ .grid-object {
  left: 50%;
  top:50%;
}
#logs {
  position: absolute;
  font-size: 10px;
  background: rgba(0,0,0,.6);
  color: #fff;
  display: block;
  width: 100%;
  top: 0;
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
   <div class="grid-object">
     <h3>1</h3>
   </div>
   <div class="grid-object">
     <h3>2</h3>
   </div>
   <div class="grid-object">
     <h3>3</h3>
   </div>
    <div class="grid-object">
     <h3>4</h3>
   </div>
</div>
<div id="logs">
  <div id="mouselog"></div>
  <div id="center"></div>
  <div id="offset"></div>
  <div id="css"></div>
</div>
<div id="togglelogs">Toggle Logs</div>