Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Transform Math - Calculate height of div caused by skew

I'm having difficulty figuring out how I could calculate the extra height of a div container caused by skewing it. I am masking an image inside the container and resizing it using a plugin.

The containers will not always have the same height and width so using fixed dimensions will not work.

Please see my demo. http://jsfiddle.net/RyU9W/6/

HTML

<div id="profiles" class="container">
        <div class="profile">
            <div class="image">
                <img src="http://placekitten.com/g/750/750" alt="">
            </div>
            <div class="detail">
            </div>
        </div>
        <div class="profile">
            <div class="image">
                <img src="http://placekitten.com/g/750/750" alt="">
            </div>          
            <div class="detail">
            </div>
        </div>        
        <div class="profile">
            <div class="image">
                <img src="http://placekitten.com/g/750/750" alt="">
            </div>          
            <div class="detail">
            </div>
        </div>
        <div class="profile">
            <div class="image">
                <img src="http://placekitten.com/g/750/750" alt="">
            </div>          
            <div class="detail">
            </div>
        </div>        
        <div class="profile">
            <div class="image">
                <img src="http://placekitten.com/g/750/750" alt="">
            </div>          
            <div class="detail">
            </div>
        </div>
        <div class="profile">
            <div class="image">
                <img src="http://placekitten.com/g/750/1200" alt="">
            </div>          
            <div class="detail">
            </div>
        </div>            
</div>

CSS

#profiles {
    margin-top: 300px;
    transform:skewY(-30deg);
    -ms-transform:skewY(-30deg); /* IE 9 */
    -webkit-transform:skewY(-30deg); /* Safari and Chrome */    
}
.profile {
    cursor: pointer;
    float: left;
    width: 32.25%;
    margin: 0.5%;
    position: relative;
}
.profile .image {
    position: relative;
    overflow: hidden;
    height: 400px;
    background: #000;
    backface-visibility:hidden;
    -webkit-backface-visibility:hidden; /* Chrome and Safari */
    -moz-backface-visibility:hidden; /* Firefox */
    -ms-backface-visibility:hidden; /* Internet Explorer */     
}
.profile .image * {
    position: relative;
    transform:skew(0deg,30deg);
    -ms-transform:skew(0deg,30deg); /* IE 9 */
    -webkit-transform:skew(0deg,30deg); /* Safari and Chrome */         
}
like image 465
hyperdrive Avatar asked Sep 06 '13 17:09

hyperdrive


People also ask

What does transform skew do in CSS?

CSS Demo: skew() This transformation is a shear mapping (transvection) that distorts each point within an element by a certain angle in the horizontal and vertical directions. The effect is as if you grabbed each corner of the element and pulled them along a certain angle.

What parameters does skew accept?

The skew() function accepts two arguments, indicating the angle of the skew for the x and y axes respectively. These are represented by angle values. If only one value is supplied, the second value has a zero value.


3 Answers

In skew we have a case of Right-angled triangle and the skew new width is equal to "Opposite" and we've the angle and the opposite so by this equation we can get the adjacent Opposite = Adjacent * tan(angle); Where opposite in case of skewX is the div height and in case of skewY will be the div width

Check this https://codepen.io/minaalfy/pen/exgvjb

function calculateSkew(){
  var el = document.getElementById('bluebox');
  var skewX = document.getElementById('skewX');
    skewX.value = skewX.value || 0;
  var skewY = document.getElementById('skewY');
    skewY.value = skewY.value || 0;
    
  var yRadians = skewY.value * Math.PI / 180;
  var newHeight = el.offsetWidth * Math.tan(yRadians);
  var calculatedHeight = el.offsetHeight + newHeight;
  
  var xRadians = skewX.value * Math.PI / 180;
  var newWidth = calculatedHeight * Math.tan(xRadians);
  var calculatedWidth = el.offsetWidth + newWidth;
  
  el.style.transform = ("skewX(" + skewX.value + "deg ) skewY(" + skewY.value  + "deg )");
  var output = document.getElementById('output');
  output.innerHTML = "skewY by "+skewY.value+ " and new height calculated is "+calculatedHeight+ "<br> skewX by "+skewX.value+ " and the new calculated width is "+ calculatedWidth;
}
body {text-align:center}
#bluebox {width:100px;height:100px;background:blue;margin: 20px auto;}
<h4>Enter any numeric value for skewX or skewY to calculate the new width&height for the box</h4>
<div id="bluebox"></div>
<input type="number" placeholder="skewX" id="skewX" onkeyup="calculateSkew()" />
<input type="number" placeholder="skewY" id="skewY" onkeyup="calculateSkew()" />
<h1 id="output"></h1>
like image 124
Mina paulis Avatar answered Oct 03 '22 09:10

Mina paulis


I got it using this solution.

var degrees = 30;
var radians= degrees*Math.PI/180;
var newHeight = parentWidth*Math.tan(radians);
var newOffset = newHeight / 2;
var parentHeight = parentHeight + newHeight;

Here is my updated fiddle with option to select degrees

http://jsfiddle.net/bhPcn/5/

like image 38
hyperdrive Avatar answered Oct 03 '22 10:10

hyperdrive


Two functions that could help you.

function matrixToArray(matrix) {
    return matrix.substr(7, matrix.length - 8).split(', ');
}

function getAdjustedHeight(skewedObj){
    var jqElement = $(skewedObj);
    var origWidth= jqElement.width();
    var origHeight= jqElement.height();
    var matrix = matrixToArray(jqElement.css('transform'))
    var alpha = matrix[2];
    var adjusted = Math.sin(alpha)*origWidth/Math.sin(Math.PI/2-alpha);
    return origHeight+Math.abs(adjusted);
}

function getAdjustedWidth(skewedObj){
    var jqElement = $(skewedObj);
    var origWidth= jqElement.width();
    var origHeight= jqElement.height();
    var matrix = matrixToArray(jqElement.css('transform'))
    var alpha = matrix[1];
    var adjusted = Math.sin(alpha)*origHeight/Math.sin(Math.PI/2-alpha);
    return origWidth+Math.abs(adjusted);
}

Usage (http://jsfiddle.net/x5her/18/):

 // if you use scewY
 console.log(getAdjustedWidth($(".image")[0]))


 // if you use scewX
 console.log(getAdjustedHeight($(".image")[0]))
like image 34
user854301 Avatar answered Oct 03 '22 10:10

user854301