I'm trying to get the style.left and style.top of a rectangular div, after it has been rotated using style.transform=rotate(90deg).
I understand how the div is being rotated, with it being rotated around a 'transform point'. And I also understand that a div could be rotated by 45 degrees, so giving the new top/left of that would be awkward (In effect giving the bounding box left/top).
But back to the original question, rotating the rectangular div by 90 degrees, is there a way to get the 'new' left/top?
The reason I need this, is for a project im working on to upload images, allow the user to zoom, rotate etc, but currently having to do it with PHP to keep all the dimensions correct for the final image (Which is obviously bad, because I'm having to keep loading a new image once PHP has done the rotating/zooming etc)
I've also made a little jsfiddle showing that the top/left position doesn't change when it 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.
Related
I have an image which as a "ruler" (made of basic divs positioned absolute on top of the image) that are use to measure the ends of the image. Now the idea is that if you long press one of the ruler ends (the dots at the end of the line which are draggable), the image in the background would zoom in that point, and follow the dot if the user moves it. I am able to detect the long press but I cannot get the image to zoom and follow the dot once detected. The code below is where I have done the detection and now I should apply the styling to move the image. I thought of using the transition property but couldn't get it to zoom on the dot. Any help is appreciated...
Here's a codesandbox with how the ruler works: Link
Meaningful code:
const x = get('x', varToUse); //This just gives the x coordinate of the ruler end
const y = get('y', varToUse); //This just gives the y coordinate of the ruler end
const image = ruler.current.parentElement.parentElement.childNodes[1].childNodes[1];
if (zoom) {
image.style.transform = `translate(${x * 2}px, ${y * 2}px) scale(2.0)`;
} else {
image.style.transform = `scale(1.0)`;
}
This is what the ruler looks like just to get an understanding:
You can make the image a div with background-image.
.image {
background-image: url({image_url});
}
so this way you can update the image size and position easily with this properties
.image {
background-size: x y;
background-position x y;
}
I think this way is easier to do the image resizing and zoom abilities.
another way is to use a canvas library that can help you a lot they have lots of built in functions.
I think trying it without library is better for now but as it grows try to move to a canvas library
The first reason is that in the code you provided, the DOM element that is being manipulated is a div id='root'. The image should be selected.
I've been working on this problem for days. I am trying to implement a "free transform" tool for svgs. Similar to that of Raphael.FreeTransform or how you would move/rotate/scale images in MS Word. (Yes, I am aware there are libraries) The following jSFiddle displays my problem: https://jsfiddle.net/hLjvrep7/12/
There are 5 functions in the jsFiddle: rotate-t. shrink-t, grow-t, shrink, grow. The functions suffixed with '-t' also apply the current rotation transformation. e.g.:
grow-t
rect.attr({height : height * 1.25, width : width * 1.25}).transform('r' + degree);
grow
rect.attr({height : height * 1.25, width : width * 1.25});
Once an svg is rotated, then scaled. If you try to rotate the svg again (after scale), the svg jumps. To see this, go top the fiddle:
Hit rotate-t twice. Svg should rotate a total of 30 degrees from the rectangles origin.
Hit grow (not grow-t) twice. Note the top left position of the svg stays the same.
Hit rotate-t once. Note the svg jumps to a different position, then rotates.
Note hitting rotate-t subsequent times will continue to rotate the image around the origin (which is what I want the first time rotate-t is clicked)
One solution I had was to apply the current rotation transformation whenever changing the height and width. This fixes my previous problem, but introduces another problem. To see an example of this, go to the fiddle, and:
Hit rotate-t twice.
Hit grow-t a couple times. Notice the svg grows, but the top left position of the rectangle moves. That's a problem for me. I want the svg to grow without the top left corner to move.
Notes on using the jsFiddle:
Any combination of rotate-t, grow-t, shrink-t will exhibit the ideal rotation behavior (about the origin, no jumping). But this also demonstrates the undesired growing and shrinking (top left position moved when svg is on angle).
Any combination pf rotate-t, grow, shrink will exhibit the ideal scaling behavior (top left corner of svg doesn't move). But this also demonstrates the undesired rotation property (will jump around after different rotations and scales).
Bottom line: I want to be able to the svg rotate around the origin. Then grow the image, while the top left position remains the same. Then rotate the svg again, around the origin without any jumping.
I am aware the how the transform function impacts the local coordinate system of the svg. I'm leaning towards using rotate-t, grow, shrink combo and simply apply some x-y offsets to remove the "jumping" effect. I would imagine there must be some sort of offset I could apply to avoid jumping or shifting during rotation or scaling, but its not clear to me how to calculate such offsets. Any help would be appreciated.
Please don't hesitate to ask anymore questions. Like I said, I've been digging into this for days. Clearly, I don't understand it all, but am somewhat intimate with what's happening and happy to explain anything in more detail.
My solutions for scale, rotate, move back and front etc:
$scope.back = function () {
if($scope.currentImage !==null) {
if($scope.currentImage.prev!=undefined) {
var bot = $scope.currentImage.prev;
$scope.currentImage.insertBefore(bot);
ft.apply();
}
}
};
//Function for moving front
$scope.front = function () {
if($scope.currentImage !==null) {
if($scope.currentImage.next!=undefined) {
var top = $scope.currentImage.next;
if($scope.currentImage.next.node.localName == "image")
$scope.currentImage.insertAfter(top);
ft.apply();
}
}
};
//ZOOM
$scope.zoomIn = function () {
if ($scope.currentImage!= null) {
var ft = paper.freeTransform($scope.currentImage);
if(ft.attrs.scale.y<4) {
$scope.currentImage.toFront();
ft.attrs.scale.y = ft.attrs.scale.y *(1.1);
ft.attrs.scale.x = ft.attrs.scale.x *(1.1);
ft.apply();
ft.updateHandles();
}
}
};
I use the $(window).resize(function()) to get changes in window size, and acoording to those I want to zoom in and zoom out. Why zooming?!, because I have a lot of dynamically appended divs with absolute coordinate and I want those divs to keep the allignment when window is changed.Basically what one would get, if pressed 'Ctrl' + '-'.
Let's say I have this image
If I use .css to add the following line, which zooms out '-moz-transform': 'scale(0.8)' I get an image like this
But if I use Ctrl + - instead I get
As you see the second image has some coordinates messed up(not changed). Has anyone any idea on why that is, or another function I could use to zoom out?
Here is a jsfiddle to play yourself http://jsfiddle.net/rnhev60f/8/
EDIT:: After the responses, I gave up on the idea. Instead I created a function to calculate the percentage of the changes (newSize / originalSize) and used the percentage to change the position and size of every object in order to avoid all backdoors and bugs. It's a bit more comlicated and ended up with a LOC-wise longer function, but works for me for now. Thanks for the responses tho!
You need to scale both the body and the span
Demo
http://jsfiddle.net/tdov936x/
Code
$('body,span').css({'transform': 'scale(' + currentZoom + ')'});
Result
Consider adding transform-origin: 0% 0%; as 2D transformations can change the x- and y-axis of an element
I'm trying to draw a grid on a <canvas> element with the ultimate goal of making a Go board.
For some reason the grid is looking stretched, with the lines being thicker than 1 pixel and the spacing being completely wrong. It doesn't even start in the (10,10) position..
It would be great if someone could take a look at tell me what I'm doing wrong.
http://jsfiddle.net/h2yJn/
I've found the problem. I was setting the dimensions of the <canvas> using CSS, when you actually have to set the width and height attributes. This was causing it to be stretched/skewed.
var canvas = $('<canvas/>').attr({width: cw, height: ch}).appendTo('body');
http://jsfiddle.net/h2yJn/66/
Please try it outside jsfiddle, maybe jsfiddle is applying some linear transformation.
Also please make sure that you add 0.5 everywhere to both x and y coordinates. Alternatively, you can apply translate(0.5, 0.5) to shift all coordinates by half a pixel.
I am trying to create a spot the ball game, so it will (eventually) be an image of a player kicking a ball but the ball has been removed and the player needs to click where the ball should be.
The first version went well and works.
http://enjoythespace.com/sites/game/test.html
But what I need to add is some sort of zooming so you can see more accurately where you are clicking. I been playing around and have come up with this
http://enjoythespace.com/sites/v2/demo.html
But once you click it looks great when zoomed in but when you go back to the image its way off.
I think its todo with how the image is setup, the #webpage is half the original size of the image and the #retina uses the full size of the image.
Any help?
The first problem is that you aren't setting the retina backgroundPosition correctly.
This code works (I added a zoom variable to make it clear how changing the zoom would change the calculation, but it would need other changes too):
/* Moving the retina div with the mouse
(and scrolling the background) */
zoom = 2.0;
retina.css({
left : left - sizes.retina.width/2,
top : top - sizes.retina.height/2,
backgroundPosition : ""+(-zoom*left+sizes.retina.width/2)+'px '+(-zoom*top+sizes.retina.height/2)+'px'
});
Test this by checking that all four corners are seen correctly in the retina, i.e. when you're over the corner of the main image, the corner should be in the center of the retina circle.
The second problem is if you resize the browser the position calculations are out because the offset variable isn't updated for the new size. A simple way to do this is to put this as the first line of webpage.mousemove() so the offsets are updated every time:
var offset = { left: webpage.offset().left, top: webpage.offset().top };
It looks like you are passing the top/left position click point of the zoomed image to highlight where you have clicked. What you will need to do is alter your top/left position based on whether the fisheye is over the image or not.
Does the un-zoomed image have to be part of the news page or can it be a standalone image?
If it can be standalone then the solution should be quite simple. If the zoomed in image is twice the size of the unzoomed one then you can just set the top/left values of the highlight to half the value of the zoomed, when looking at the unzoomed.
Jquery position will allow you to accurately get the position.
jQuery Position()