Geometry in web applications

Maths are present in our everyday life. As a popular TV show states: “We all use math every day”. In client-side web development we need to appeal –among other subjects– to geometry and trigonometry in the moment that we require to build applications with a high level of animations and interactivity.

In this post we are going to summarise the most basic and common maths problems that one faces in web development and the techniques that are commonly used to solve them.

Position elements in the viewport corners

If we use CSS to position elements we don‘t need to perform any calculation since we can use –among other– top, right, bottom and left properties for this. But if our application doesn‘t use styleheets for this task, we would need to use JavaScript calculations , and for that we need to take into account the width and height properties of the element to accurately position it. Supposing that the viewport has A width and B height, and the element has α width and β height, the calculations will be the next ones for each one of the positions.

Top left Top right Bottom right Bottom left

A JavaScript pseudo-code could be the next one:

// Variables
/**
 * element = HTML element to position
 * viewportW = viewport width
 * viewportH = viewport height
 * elementW = element width
 * elementH = element height
 */

// Puntos
const POINTS = [

	{ x: 0, y: 0 }, // top left
	{ x: viewportW - elementW, y: 0 }, // top right
	{ x: viewportW - elementW, y: viewportH - elementH }, // bottom right
	{ x: 0, y: viewportH - elementH } // bottom left

];

// Function to position the element
let index = 0;

const position = () => {

	index++;

	if(index === POINTS.length) index = 0;

	element.style.left = `${POINTS[index].x}px`;
	element.style.top = `${POINTS[index].y}px`;				

};

element.addEventListener('click', position);
Click on the orange element to observe its animation

Position elements at random viewport coordinates

The technique of position elements randomly in the viewport is pretty similar to the previous one. If we want to be sure that the element always keeps within the viewport area, the x and y coordinates must always be among the four points that we previously calculated. Therefore, to find a random point we should do it as descibed next:

Where ω is a random number between 0 and 1.

A JavaScript pseudo-code could be the next one (using the same variables as before):

// Function to position the element
const position = () => {

	const x = Math.random() * (viewportW - elementW);
	const y = Math.random() * (viewportH - elementH);

	element.style.left = `${x}px`;
	element.style.top = `${y}px`;				

};

element.addEventListener('click', position);
Click on the orange element to observe its animation

Position elements in the center of the viewport

If the reference point is located in the center of the element it wouldn‘t be necessary to appeal to any calculation to position it. In a viewport of A width and B height, the center will be at:

But if the reference point is located in the top left corner of the element (as it is by default in HTML elements) and the element has α width and β height, then we need to substract to the point the half of each side, to make the element visually located at the center of the viewport:
=

Click on the orange element to observe its animation

Rotate elements around a point

This process is relatively easy and it is based in a trigonometric relationship. If we have two points, we can calculate the θ angle that makes the vector between these points with the abscissa axis. The next example shows this trigonometric relationship:

Move the mouse around the scene to observe the animation

Having the coordinates of the two points we can calculate the angle represented by θ. The method to do so is to calculate the arctangent of the quotient of the difference in the y and the difference in the x coordinates. For example, if the coordinates of the first point are {x1, y1} and the ones of the second point are {x2, y2}, we can calculate the θ angle between these vectors in the next way:

This will calculate an angle between 0 y π when the second point is located below the first point and an angle between 0 and when it it located above. The next JavaScript pseudo-code makes the element to point to a dynamic point in the viewport, that in this case will be the mouse.

This code assumes that the element is an horizontal element pointing to the right, if the object is located in another position, it would be needed to add to the calculated angle, the angle that the element makes with the abscissa axis.

//  Element to position
const element = document.getElementById('element');

// Element coordinates
const bounds = element.getBoundingClientRect();
const elx = bounds.left + (bounds.right - bounds.left) / 2;
const ely = bounds.top + (bounds.bottom - bounds.top) / 2;

// Function to position the element
const position = (event) => {

	const mx = event.pageX;
	const my = event.pageY;

	const radian = Math.atan2(my - ely, mx - elx);
	const angle = radian * 180 / Math.PI;

	element.style.transform = `rotate(${angle}deg)`;			

};

document.addEventListener('mousemove', position);
Move the mouse around the scene to observe the animation

Position elements in the border of a circumference

To position elements in the border of a circumference or to animate them describing a circle, it is necessary to appeal, one more time, to trigonometry. First of all, we need to know that the relationship between a point of a circumference and its radius is the next one:

Where x and y correspond to the coordinates of a random point of the circumference and r corresponds to its radius. Let‘s take a look at the next example so we can understand better this relationship:

Move the mouse from one side to the other to observe the animation

We can realize that this relationship complies with the Pythagorean theorem as the conformed triangle is a right triangle, so if we have at least two variables from the aforementioned ones, we can calculate the third.

To apply the Pythagorean theorem in a practical example, let’s imagine that we need to generate random points on the edge of a circumference of a given radius. We could generate random numbers on the abscissa axis and then calculate the value on the ordinates, one of the possible methods would be the next one:

// Generate a random positive or negative number to select the quadrant
const ax = Math.round( Math.random() ) * 2 - 1;
const ay = Math.round( Math.random() ) * 2 - 1;

// Generate a random number between 0 and the value of the radius
const x = Math.random() * radius;

// Calculate the y coordinates from the random x coordinates using Pythagorean theorem 
const y = Math.sqrt( radius ** 2 - x ** 2 );

// Calculate the point adding the quadrant randomness
// and adding the value to the center of the circumference
const pointX = x * ax + centerX;
const pointY = y * ay + centerY;
Click on the scene to observe the animation

Having seen how to find points on a circumference using the Pythagorean theorem, let‘s see how how to find a series of equidistant points in a circumference, as well as animate them along the circumference perimeter using trigonometric relationships.

As we have seen before, the triangle conformed by x and y and the circumference radius is a right one. Therefore, it responds to trigonometric relationships that are fulfilled in this kind of triangles. For example, in a circumference of radius r, with an angle θ formed by a point {x, y} of the circumference, its center and the abscissa axis, the following relationships would be fulfilled:
     
Where θ is a value between 0 and . Therefore any point on the circumference could be described in the following way:

That is, knowing the angle and radius of the circumference we could easily calculate the point corresponding to these values. We can see this relationship in the following graph:

Move the mouse around the scene to observe the animation

Let’s make a practical example in which we can apply these calculations. We will place six equidistant elements on the edge of a circumference, and then we will calculate new positions to create an animation of these across the perimeter of the circumference. A JavaScript pseudo-code example could be the following (using Gsap for the animations):

// Variables
// centerX = point x of the circumference center
// centerY = point y of the circumference center
// radius = circumference radius

// Array of HTML elements
const elements = [elem0, elem1, elem2, ..., elem5];

// Separation angle among the elements
const sepAngle = (2 * Math.PI) / elements.length;

// Store the starting angle of each element
const positions = elements.map((element, index) => ({
  element,
  angle: index * sepAngle
}));

// Animate all the elements to the border of the circumference
positions.forEach((data, index) => {
	const { element, angle } = data;
	gsap.to(
		element,
		{
			x: centerX + Math.cos(angle) * radius,
			y: centerY + Math.sin(angle) * radius,
			duration: 1,
			onComplete: () => {
				if (index === 0) {
					animate();
				}
			}
		}
	);
});

// Increment angle of each step in the animation will be 2 radians
const inc = 2 * Math.PI / 180;

let currentAngle = inc;

// Recursive function to animate the elements through the circumference perimeter
const animate = () => {
	
	positions.forEach((data) => {
        const { element, angle } = data;
		gsap.to(
		    element,
			{
				x: centerX + Math.cos(angle + currentAngle) * radius,
				y: centerY + Math.sin(angle + currentAngle) * radius,
				duration: 0,
			}
		);
	});
	
	currentAngle += inc;
	
	setTimeout( animate, 10 );

};
Click on the scene to observe the animation

Position elements in the border of an ellipse

Working with an ellipse is pretty similar to working with a circumference, the biggest difference between these two shapes is that in the ellipse case there is no radius but two different semi axes. (if the semi axes were equal, then we would be talking about a circumference). The points of an ellipse with semi axes a and b comply with the next relationship:

Where x and y correspond to the coordinates of any point on the ellipse. Let’s look at the following example so that we can notice this relationship:

Move the mouse from one side to the other to observe the animation

Knowing this relationship we could easily generate points on an ellipse if we know at least three of the variables, the process would be the same as with the circumference so we will not explain it.

On the other hand, the relationship of a point on an ellipse with respect to an angle θ relative to the abscissa axis is much more complicated than that of a circumference:

So if we want to animate an element along the perimeter of an ellipse, it is much easier to work with a circumfernce and increase the calculated values in the x or reduce them in the y, so the result will be close to ellipsoidal.

We will take the same example of the circumference animation made previously and we are going to multiply the x values by 1.5, the result will be the following (a true ellipse with a semi-horizontal axis 1.5 times greather than the circumference radius has been placed behind, so that it can be compared with the path of the elements):

Click on the scene to observe the animation

And up to this point we have collected the main mathematical calculations that one faces daily in front-end web application projects. If you think there are others that are also commonly used, tell me about them so I can add them in future posts.

(4 votes, average: 5.00 Out Of 5)
Share this post:

It is possible to insert code fragments between <pre></pre> tags and HTML or XML code between <xmp></xmp> tags.

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.