How to get the position of element transformed with css rotate
Per your current Question and your requested confirmation of:
var x = termin.top + Math.cos(angle) * div.height;
var y = div.left + Math.sin(angle) * div.height;
The solution can be found in this other SO Answer for a different question, enhanced here:
// return an object with full width/height (including borders), top/bottom coordinates
var getPositionData = function(el) {
return $.extend({
width: el.outerWidth(false),
height: el.outerHeight(false)
}, el.offset());
};
// get rotated dimensions
var transformedDimensions = function(el, angle) {
var dimensions = getPositionData(el);
return {
width: dimensions.width + Math.ceil(dimensions.width * Math.cos(angle)),
height: dimensions.height + Math.ceil(dimensions.height * Math.cos(angle))
};
};
Here's an interactive jsFiddle that provides real-time updates for getPositionData();
function.
You'll be able to see the top
and left
values at the end of the CSS3 Rotation process you control.
Reference: jsFiddle
Status Update: The above jsFiddle works great for 0-90deg and can be approved upon for all angles and different units such as rad, grad, and turn.
CSS use transform-origin to position a rotated element
One method to achieve the expected output would be to do the following:
- Put the
button
withindiv2
and position it at the right edge. - Absolutely position the
div2
at the bottom of the parent container. - Rotate the
div2
in counter clockwise direction (-90deg) with the transform origin at left bottom. - After rotation, the
div2
would entirely go outside of the container and hence we need to add an extratranslateY(100%)
to the transform stack. - The text is aligned to the right and an extra
padding-right
(greater than the width of the button) is added to keep the text away from the button. - The button would also get rotated by -90 degree because it is a child of
div2
and to counter that (that is to make the button text get displayed properly), we need to apply counter rotation.
Now, in this approach the only drawback is that if the text length increases beyond what can be fit in a single line then it would wrap around to the next line (have a look at the second sample in snippet).
.div1 { position: relative; height: 120px; width: 120px; float: left; margin: 20px; border: solid 1px #000; overflow: hidden;}button { position: absolute; display: inline-block; bottom: 0; right: 0; width: 48px; height: 48px; border: 0; margin: 0; padding: 0; transform: rotate(90deg);}.div2 { position: absolute; box-sizing: border-box; bottom: 0px; height: 48px; width: 100%; padding-right: 60px; line-height: 48px; background-color: #999; text-align: right; transform: rotate(-90deg) translateY(100%); transform-origin: left bottom;}
<div class="div1"> <div class="div2">HELLO <button>></button> </div></div>
<div class="div1"> <div class="div2">HELLO WORLD!!!!! <button>></button> </div></div>
How to position rotated element to the right edge
getBoundingClientRect is a good approach, the problem is that when you set css left, it positions it without the rotation calculated. The order in which you set it doesn't change the fact the the rotation is applied in relation to the css, not in relation to the current position of the rotated div. So when you calculate dimensions using getBoundingClientRect you're taking into account the rotation, then you use it on a css that doesn't take it into account.
One easy way to get proper coordinates, would be to calculate the x difference between before rotation and after and adjust you left accordingly. You'll have prevDimension.x - dimension.x
giving you the difference in x that the rotation is creating, which allows you to adjust newLeft.
Like this:
$('#rotate-align').click(function () {
var prevDimensions = $('.element')[0].getBoundingClientRect();
$('.element').css('transform', 'rotate(0.99923rad)');
var dimensions = $('.element')[0].getBoundingClientRect();
var newLeft = $('#bounds').width() - dimensions.width - dimensions.x + prevDimensions.x;
$('.element').css('left', newLeft);
});
http://jsfiddle.net/jgcynwmp/3/
Another approach would be to calculate the x difference based on the width difference between the non rotated element and the rotated element. This can be done using offsetWidth (which doesn't take the rotation into account) and the getBoundingClientRect. The difference between the 2 will tell you how much width is lost with the rotation. Note that for this calculation, the transform origin is important. For example, with a centered rotation, you'll need to divide by 2 the width difference to get the x difference, but with another origin it would be something else.
Like this:
$('#rotate-align').click(function () {
$('.element').css('transform', 'rotate(0.99923rad)');
var dimensions = $('.element')[0].getBoundingClientRect();
var newLeft = $('#bounds').width() - $('.element')[0].offsetWidth + (($('.element')[0].offsetWidth - dimensions.width) / 2);
$('.element').css('left', newLeft);
});
http://jsfiddle.net/jgcynwmp/4/
Getting CSS left and top when div is rotated
Okay, thanks to the comment left above, I managed to throw together an answer.
Basically using:
newleft = parseInt(div.style.top) + Math.cos(90) * parseInt(div.style.height);
newtop = parseInt(div.style.left) + Math.sin(90) * parseInt(div.style.height);
after the div had been rotated.
I've updated my jsfiddle aswell, because the one in the comment above uses jQuery, but this way uses only javascript.
How to transform: translate more elements to same position?
for simplest answer, use CSS variables with a calc()
function.
one time all the elements!! easy and fast
I commented on the code if you want...
the first element has a
--i
var with 0, so it will be 0 position xthe second element has a
--i
var with 1, so it will be -100 position xthe third element has a
--i
var with 2, so it will be -200 position x
the amazing part about this, is if you want to add more images, it will be easy for you, because the formula is calculated by CSS (not you)
here the fixed code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
/* here the trick */
--end-position: calc(-100px * var(--i));
}
img {
width: 100px;
height: 100px;
}
.container {
background-color: red;
height: 400px;
width: 100%;
display: flex;
justify-content: center;
}
/* use the DRY method (Dont Repeat Yourself) */
.container img:hover {
transition: 3s;
/* one time for all, that's easy! and fast*/
transform: translate(var(--end-position), 200px);
}
<div class="container">
<img style="--i: 0;" class="img-test1" src="https://avatars.githubusercontent.com/u/87947051?v=4" alt="Sample Image">
<img style="--i: 1;" class="img-test2" src="https://avatars.githubusercontent.com/u/87947051?v=4" alt="Sample Image">
<img style="--i: 2;" class="img-test3" src="https://avatars.githubusercontent.com/u/87947051?v=4" alt="Sample Image">
</div>
Related Topics
How to Disable the Save Password Bubble in Chrome Using JavaScript
How to Separate Web Components to Individual Files and Load Them
How to Change the Background Image of Div Using JavaScript
Set Height of <Div> = to Height of Another <Div> Through .Css
React Inline Style - Style Prop Expects a Mapping from Style Properties to Values, Not a String
Jquery Mobile Prevent Scroll-To-Top Before Page Transition
Detect Inside Android Browser or Webview
Angularjs- Login and Authentication in Each Route and Controller
Difference Between (Function(){})(); and Function(){}();
Class VS. Static Method in JavaScript
When Using Jquery On(), Why Use (Document) VS. the Element Itself
How Does Github Change the Url But Not the Reload
How to Limit Options Selected in a HTML Select Box
Convert CSS Width String to Regular Number
Transitionend Event Fires Twice
How to Use Materialize-CSS with Angular
Disabling the Context Menu on Long Taps on Android
How to Make a Function Wait Until a Callback Has Been Called Using Node.Js