Compute screen location based on initial coords and angle of movement - javascript

Given initial coordinates (the left and top css properties) of an absolutely positioned element on screen, and an angle of movement, how can I find out the values I should feed to transform: translate to animate the element? (The element would eventually fall off-screen, so one of the final coords will be 0 or window.innerWidth or window.innerHeight.)
For example, starting from left: 0 and top: 0, and given an angle of 90°, the destination point would be at left equal to window.innerWidth and top equal to 0. If the angle is 135°, the element would end up in the bottom right corner, etc. How can I calculate this for any angle?
(transform: translate takes deltas as parameters, not absolute positions; either is fine)

It is actually fairly simple trig. Based on the example you have given:
Your known quantities are initial coords { x: 0, y: 0 } and { angle: 90 /* in degrees*/ }
Find x-distance between initial x-coord and { window.innerWidth if angle is between 90-270 or 0 if angle between 0-90 & 270-360 }
Find the cosine of angle and multiply it with x-distance
Find y-distance between initial y-coord and { window.innerHeight if angle between 180-360 or 0 if angle between 0-180 }
Find the sine of angle and multiply it with y-distance
Add the initial x-coord with result of cosine * x-distance. This gives new x-coordinate
Add the initial y-coord with result of sine * y-distance. This gives new y-coordinate
Add some buffer to xnew and ynew so they fall off screen
For moving the element, you no longer require transform. You can simply add a transition CSS property and define new coords with new class added to that element. JSFiddle Demo
HTH

Related

Css Transform Effect in MongoDB site

I am new to css and learning different type of css styles. I want to learn how the effect used in official MongoDb website. The effect which tracks the mouse position and transforms the boxes. I know how to do the transform in css. But, how can it be done with the mouse position. Thanks for the help.
General overview of how to do it:
Register a mousemove-handler and track your mouse-screen location (see link)
translate mouse screenlocation, to mouse location relative to rectangle:
e.target in mousemove event gives you the rectangle (or some descendent which allows you to get to the rectangle.
given the target element get it's position (top + left using getBoundingClientRect) as well as width and height. These should be easy to lookup
Notice that the mouse at the center of the rectangle doesn't rotate the rectangle. Only when moving to the edges, the rotation starts to get going. This rotational rate-of-change seems to be linear. So:
determine the max rotation that seems nice to have in degrees. Simply test with different numbers in the chrome dev tools or similar: transform: rotateY(0.01deg) rotateX(0.01deg); Say you want to have a max rotation of 25 degrees.
say the rectangle is 100px in width. It's clear to see that each pixel movement from the center to the edge (50 px in total) adds 0.5 degree to the rotation due to the linear rate of change: 25 deg / 50px. So for example moving 20px to the left of the center translates to rotateY(10deg);. Moving 20px to the right results in the mirror rotation (rotateY(-10deg);). NOTE: the positive and negative may need to be flipped.
similarly, moving along the Y-axis changes the rotateX-property.
Once calculated, set the css-property and you're done
I believe this must be done with Javascript. The general idea is when the mouse enter/move on the element, you compare it's coordinate with the position and width/height of the element to decide the rotation values. When the mouse leave the element, you reset the values of the rotation back to normal.
You can get the coordinate of the mouse from event by using:
const mouseX = event.clientX; // Get the horizontal coordinate
const mouseY = event.clientY; // Get the vertical coordinate
And the position of the element:
const eleLoc = event.target.getBoundingClientRect();
From there you calculate the center and the width/height of the element:
const centerX = (eleLoc.right + eleLoc.left) / 2
const centerY = (eleLoc.bottom + eleLoc.top) / 2
const halfWidth = (eleLoc.right - eleLoc.left) / 2
const halfHeight = (eleLoc.bottom- eleLoc.top) / 2
Then you calculate the distance between the mouse and the center in percent. In the center, the distance is 0, at the border, it's 1 (or -1).
const percentX = (mouseX - centerX) / halfWidth
const percentY = (mouseY - centerY) / halfHeight
Now you only need to rotate X/Y based on the distance percent:
const degX = percentX * maxDegX
const defY = percentY * maxDegY
event.target.style.transform = `perspective(${yourPerspective}px) rotateX(${degX}deg) rotateY(${degY}deg)`
Remember to reset the transform when your mouse move out.
There are some libraries for this, ie: tilt.js

CreateJs - distance from left

Here is the graphics:
http://snag.gy/aVFGA.jpg
the big rectangle is canvas element, the small rectangle is the image object in the canvas. I want to find what is the real distance from the left.
values are such from what I see in console:
regX: 564.256
regY: 41.4
scaleX: 0.4491319444444445
scaleY: 0.4491319444444445
x: 363.3333333333333
y: 409.77777777777777
So as I see x is not real. It somehow relates with regX and scaleX. But I am not finding how it relates. From the image I think the x should be about 100 - 150 px.
THe bigger the x - the more it is to the right.
But the bigger regX - the more it makes rectangle go to the left.
So if I would just take the difference 564.256 - 363.333 = ~200 - left corner of the rectangle should be in them middle of canvas because canvas is 400px widh. But it is not, so substraction does not help. So how do I get how many pixels are in real from the left?
You can do this by using the localToGlobal method (see here).
It depends to which object the given attributes belong.
If they belong to the shape and your rectangle inside the image / shape starts at (0,0):
var point = shape.localToGlobal(0, 0);
// this will calculate the global point of the shape's local point (0,0)
If they belong to the stage:
var point = stage.localToGlobal(yourRectObject.x, yourRectObject.y);
// point.x should contain the position on the canvas
You should use these methods in general because your method might work for the current situation but will probably break as soon as you scale the stage itself or put the shape in a scaled / positioned container.
I guess I found what by experimenting with values:
distanceFromLeft = x - scaleX * regX;
so getting 109.90793888888885 px
If someone has worked more with this library, they could confirm that its not accidental.

Resizing Handles on a Rotated Element

I'm trying to put resizing handles on the four corners of a rectangle, which can be dragged to resize the rectangle. What I'm having trouble with is calculating the new width, new height, and new points of the rectangle after I've dragged one of the rectangle's points.
If the rectangle were not rotated, this would obviously be very easy because the width and height would change by the same amout as the mouse's offsetX and offsetY. However, this rectangle CAN be rotated, so offsetX and offsetY don't match up to the changes in width/height.
In the image above, I've represented information that I already have in solid black, and information I want to find in light grey. I've tried to show how the rectangle should change if I dragged the a1 corner up and to the right.
Could anyone help me figure out how to calculate the missing information?
Thanks for any help! It's much appreciated.
--
EDIT: I've got drag start, drag move, and drag end callbacks on each handle. My current code simply gets the new point (in this example, a2). Unfortunately this simply moves the handle we're currently dragging into its new position, but obviously has no effect on the width/height of the rectangle, and the position of its other points. What I'm hoping for help figuring out is how do I calculate the new width and height, and the new position of the other points, based on this drag.
Handle Coordinates (before drag)
handles: {
a: { x: 11, y: 31 },
b: { x: 44, y: 12 },
c: { x: 39, y: 2 },
d: { x: 6, y: 21 }
};
Callbacks:
// Save the original x and original y coordinates
// of the handle, before dragging
onDragStart: function(x, y, handle) {
handle.data({
ox: x,
oy: y
});
}
// While dragging the handle, update it's coordinates to
// reflect its new position
onDragMove: function(dx, dy, handle) {
handle.attr({
x: handle.data('ox') + dx,
y: handle.data('oy') + dy
});
}
// Not currently using the drag end callback
onDragEnd: function(x,y,handle) {}
http://en.wikipedia.org/wiki/Cartesian_coordinate_system#Distance_between_two_points gives you the method for finding the length of a1 to a2
var len=Math.sqrt(Math.pow(a2x-a1x,2)+Math.pow(a2y-a1y,2));
Then looking at the triangle formed by the intersection of the grey and black lines (Lets call that point H) and a1 and a2. You can use trigonometry to solve. So the angle formed by the line d1 to c1 with the bottom lets call that the angle of rotation(R). That means the R is equal to angle at a2 and the angle at a1 is equal to 90-R. To find the sides then you go
//line from a2 to H
var hDif=Math.sin(R)*len;
//line from a1 to H
var wDif=Math.cos(R)*len;
You can then use these to find the new length and height. There will a few more calculations to see if you are adding or subtracting to the old width and height.
I have another idea:
Consider that your rectangle is rotated by 30 degress anticlockwise with respect to the origin.
When the user clicks on one of the edges or corners, do the following:
1) Let StartPt = the point where the mouse starts.
2) Get the point where the mouse moves to. Let it be EndPt.
3) Rotate each of the vertex of the Rectangle by -30 so that now it becomes an unrotated rectangle. (Do not draw the unrotated rectangle, it is for calculcation purpose only)
4) Rotate the StartPt and EndPt by -30 degrees. Calculate the change in the width and height of the rectangle when the point.
5) Add the change to the rotated vertices of the rectangle.
6) Rotate the vertices of the Rectangle by +30 degrees. Now draw the Rectangle.
https://www.experts-exchange.com/questions/24244758/How-can-let-a-user-drag-to-resize-a-rotated-rectangle.html#answer23964155

Three.js - Width of view

Is there a way to find out the width of a rendered portion of the scene?
For example, if we have a mesh of width 100, but rendered with a certain level of zoom...how can I calculate the width of the portion of the mesh that is being rendered in the screen?
You have to be precise here.
You can calculate the visible rectangular region given the camera's field-of-view, camera.fov, and a given distance, dist, from the camera.
Since the object presumably has depth, you have to pick one plane through the mesh, and do the calculation at that distance.
Here is how to calculate the visible height and width for a given distance dist from the camera.
var vFOV = THREE.MathUtils.degToRad( camera.fov ); // convert vertical fov to radians
var height = 2 * Math.tan( vFOV / 2 ) * dist; // visible height
var width = height * camera.aspect; // visible width
three.js r.117
For a (perfect) spherical object, it will cover more of the view close up as you need to take the tangent into account i.e. you can't see the 'poles'.
Use the following for a spherical object:
// we're using the following triangle: camera - tangent point on sphere - centre of sphere
var targetAngle = 2 * Math.asin(objectRadius / distanceToCamera);
var vFOV = THREE.Math.degToRad(this.fov);
var normalizedHeight = targetAngle / vFOV;
Multiply this with your viewport width to get screen height. For width you need to apply hFOV - see: 90 degree field of view without distortion in THREE.PerspectiveCamera

How does one rotate a HTML canvas object around a fixed point using mouse action?

For example it may be used in the application of manually adjusting the hands of the clock. I guess it probably involves translating the needle (to make the end point of the needle the centre of rotation) then rotating it, then translating the needle again.
But since the needle listens to the mouse event all the time, the 1st mouse event will be captured. The result is that the needle ends up being translated and not rotated at all. Mouse event is impossible to debug too...
Any idea or code snippets that I can refer to? Using Javascript or CSS to rotate both fine.
In your example, you will want to calculate the angle between the centre of the clock face (black dot), and the current mouse position (red dot), relative to the Y axis (cardinal north if you imagine a compass).
If I remember my trig correctly, you can calculate this by using the following:
var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
// alter the angle to be relative to Y axis instead of X
angle += 90;
if(angle < 0) { angle = 360 + angle; }
In the formula, x and y are the coordinates of the two points, one of which you will know (it is the centre of the clock face), and the other you can get from the mouse move event.
Once you have the angle, you can simply translate to the the centre of the circle, rotate the canvas by the calculated amount, and draw the hand.
Update: I created a jsfiddle to illustrate the angle calculation:
http://jsfiddle.net/DAEpy/1/

Categories

Resources