Last active
November 29, 2024 10:24
-
-
Save andreiglingeanu/aa3aef6c8dffb2105736148b2cab3617 to your computer and use it in GitHub Desktop.
A nice way to nullify CSS transforms and get original positions of the un-modified rect
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Nullify the transforms of the element | |
// | |
// This is all behaving just like getBoundingClientRect() but it nullifies all the transforms | |
// and kinds _reverts_ the element onto its original position. | |
// This will work even with complex translations, rotations. | |
// The beauty is in the way it applies matrix inverse onto the transformation | |
// matrix and mutates the getboundingclientrect along the way. | |
// | |
// Usage: | |
// let { top, left } = nullifyTransforms(el); | |
// | |
// TODO: | |
// can probably be extended to be having width/height support too but | |
// that is not mandatory, I only needed top/left for my use case | |
// | |
// Props to that awesome answer on StackOverflow | |
// https://stackoverflow.com/questions/27745438/how-to-compute-getboundingclientrect-without-considering-transforms | |
function nullifyTransforms(el) { | |
//add sanity checks and default values | |
let {top, left, width, height} = el.getBoundingClientRect() | |
let transformArr = parseTransform(el) | |
if (transformArr.length == 6) { | |
// 2D matrix | |
// need some math to apply inverse of matrix | |
// That is the matrix of the transformation of the element | |
// a scale x | |
// b shear y | |
// c shear x | |
// d scale y | |
// e translate x | |
// f translate y | |
var t = transformArr | |
let det = t[0] * t[3] - t[1] * t[2] | |
return { | |
width: width / t[0], | |
height: height / t[3], | |
left: | |
(left * t[3] - top * t[2] + t[2] * t[5] - t[4] * t[3]) / | |
det, | |
top: | |
(-left * t[1] + top * t[0] + t[4] * t[1] - t[0] * t[5]) / | |
det, | |
} | |
} else { | |
/*if (transformArr.length > 6)*/ | |
//3D matrix | |
//haven't done the calculation to apply inverse of 4x4 matrix | |
return {top, left, width, height} | |
} | |
function parseTransform(el) { | |
let transform = window.getComputedStyle(el).transform | |
//add sanity check | |
return transform | |
.split(/\(|,|\)/) | |
.slice(1, -1) | |
.map(function(v) { | |
return parseFloat(v) | |
}) | |
} | |
} |
.split(/[(,)]/)
@Tofandel got any specific case that needs to be covered? Feel free to send an executable case and I'll fix the initial gist. Thanks!
It's the same regex, just one that is more readable
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Never mind, just found out about
.offsetLeft
and.offsetTop
;)