arrange div elements in square using javascript and maths - javascript

I n number of divs which are arranged in a circle using JavaScript. Right now I set the dimension of each div to 40×40. Below is what I am able to achieve so far. This is how I find X & Y of each div.
x = 100 * Math.cos(angle) + hCenter;
y = 100 * Math.sin(angle) + vCenter;
where hCenter & vCenter are center point of the screen
When there are many circles they start overlapping each other. How
can I find the height & width of each div so that they fit in circle
with a little space between each other.
How can I arrange the same circles in the square. Means animate from
circle to square. How to find new X,Y position of each div.

How can I find the height & width of each div so that they fit in circle with a little space between each other.
The width and height of each circle are the same as its diameter, which (plus the little splace) is equivalent to the length of the sides of the polygon formed by their positions. You know the size ("diameter") of the large square/circle in which the are arranged, so you can easily compute the length of the sides from that and the number of items. Then subtract a small constant or factor, and you've got your result.
How to find new X,Y position of each div so that they are arranged in a square?
Compute from the angle on which side of the square they will sit. You've got your first coordinate. Then, use sin/cos to compute the position on that side.
var dir = Math.round(angle / Math.PI * 2) % 4,
dis = dir<2 ? 100 : -100;
if (dir % 2 == 0) {
x = hCenter + dis;
y = vCenter + dis * Math.tan(angle);
} else {
x = hCenter + dis / Math.tan(angle);
y = vCenter + dis;
}

Related

Generate Radial/Ellipse/Oval/Stadium Gradient Mask (Nested For Loop)

What I'm attempting to do
Loop through two axes and generating a shape with a width and height, either less or equal to the length of the nested for-loops, and calculate the distance from all positions to the center of that shape.
Main Issue(s)
How do I specify the width and height of an ellipse shape to draw using a nested for-loop with different dimensions to that ellipse?
For example a nested for-loop which goes for 0 to 45 in the X axis, and 0 to 100 in the Y axis but draws an ellipse with a width of 39 and a height of 90 - with the remaining difference used as padding (3 on either side, and 5 on top and bottom).
I have this half working using the EdgeOrInBounds function below, however I'm having trouble understanding why the values I'm using are giving the results they are.
Using a nested for-loop the same as above, but specifying an ellipse with a width of 30 and a height of 70 doesn't have the expected padding, it instead draws an ellipse with only one extra sprite surrounding all sides.
How do I calculate the distance from the center of the ellipse to the positions generated by the nested for-loop as a value between zero and one?
For example, any position outside the ellipse returns a value of zero and any position within the ellipse returns the distance scaled between zero and one from the center of the ellipse.
Similar to above, I have this half working as I can return a value of zero for all posiitons outside of the ellipse, but I do not understand how scale the distances for positions within the ellipse.
Bonus Issue(s)
I'm doing this on a platform where code isn't easily shareable and there are few built in functions, so I've had to create my own versions stolen from based on examples from the Nvidia developer site.
I have a basic understanding of some C# and JavaScript, but zero understanding of mathematical formulas.
Ellipse Function(s)
bool EdgeOrInBounds (Vector2 position) {
int x = ((int) Math.Pow (position.x - center.x, 2) / (int) Math.Pow (radius.x, 2));
int y = ((int) Math.Pow (position.y - center.y, 2) / (int) Math.Pow (radius.y, 2));
return (x + y <= 1);
}
Distance Function(s)
float distance (Vector2 position) {
return (sqrt (dot (centerPosition - position, centerPosition - position));
}
float dot (Vector2 a, Vector2 b) {
return (a.x * b.x + a.y * b.y);
}
float sqrt (float a) {
return (1.0 / pow (a, -0.5));
}
Variables
int mapWidth = 45;
int mapHeight = 100;
Vector2 radius = new Vector2 (mapWidth - 8, mapHeight - 4);
Vector2 center = new Vector2 (mapWidth / 2, mapHeight / 2);
Nested For Loops
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
// Store current position to reference in a minute
Vector2 position = new Vector2 (x, y);
// Check if position is within bounds or lies on the edge of the ellipse
if (EdgeOrInBounds (position)) {
// Calculate distance from center to current position
float dist = distance (position);
}
}
}
Example Image:
Closing Remarks
I know I haven't done a good job of explaining what I'm tring to achieve, so I'd like to apologize in advance, and I'd also like to thank anyone who reads this as any help would be very much appreciated.
Cheers.
To get color shade better under control, you could use an elliptic spiral, instead of a square grid traverse. Start out with the two radii, use X=R1 * Cos(angle) and Y=R2 * Sin(angle), where you gradually decrease R1 and R2 to zero. Your loop will use polar coordinates (angle,r), see below. You are then sure of the size of your "plot" and you won't need to test distances underways. It can probably do without any distance function for color scaling, but I'm not sure how to do that properly.. I have included a few options.
// The image is 440x240, I want ellipse in the center, margins 20 pix
// Parameters, dependent on size and shape of elllipse
Point pc = new Point(220,120); // pixel center
double r1=200; // radius 1 margin 2x20 on 440
double r2=100; // radius 2 margin 2x20 on 240
// Covering all pixels
int rmax = (int)Math.Max(r1,r2);
// scaling for color
var ravgmax = (r1+r2)/2.0;
// Find suitable loop counts
var nr = rmax; // number of radius steps in loop
var nh = 2*nr*Math.PI); // number of angles in loop
// Prepare initial loop displacements
var h=0.0;
var dr1 = r1/(nr*nh);
var dr2 = r2/(nr*nh);
var dh=(Math.PI*2.0)/nh;
// The loop
for (int i=0; i<nr; i++)
{
for (int j=0; j<(int)nh; j++)
{
var p = new PointF((float)(pc.X+r1*Math.Cos(h)),(float)(pc.Y+r2*Math.Sin(h)));
// vanilla shading
// int grayscale = 255 - (int)(255 * ((r1+r2)/2.0)/ravgmax );
// elliptical option without using distance, scale along axes
// grayscale = 255 - (int)(Math.Abs(p.X-pc.X)*255/200+Math.Abs((p.Y-pc.Y)*255/100)/2;
// "Distance grayscale" which is circular, not elliptical
int grayscale = (int)(255 * floatFDistance(p,pc)/rmax);
PlotF(p,grayscale); // you provide: plotpixel(PointF, int)
r1-=dr1; r2-=dr2;
h+=dh;
}
}
}
float floatFDistance(PointF p1, PointF p2)
{
double d1 = (p1.X - p2.X);
double d2 = (p1.Y - p2.Y);
return (float)(Math.Sqrt(d1 * d1 + d2 * d2));
}

Find the Points of Intersection of a Circle with a Line in Javascript

I'm trying to animate a given element to go around a pre-defined radius and I'm having trouble getting the position of the element at a Y point given.
I'm trying to find each point with the circle equation, but I can only get one point out of the two possible ones.
In Javascript, I use Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2) to get the point. assuming the center of the of the circle is 0,0.
but then I need to translate it to pixels on the screen since there are no negative pixels in positions on the browser.
All the sizing is relative to the window. so the radius, for example, is 80% of the height of the window in my tests.
Also, I'm trying to calculate what the distance of the element between each frame should be for the duration, but I'm not using it yet because I try to fix the issue above first.
This is what I have(a cleaned up version):
let height = window.innerHeight * 0.8,
radius = height / 2,
circumferance = (radius * 2) * Math.PI,
container = document.getElementById('container'),
rotating = document.querySelector('.rotating'),
centerX = radius - (rotating.offsetWidth / 2),
centerY = radius - (rotating.offsetHeight / 2),
duration = 10,
stepDistance = circumferance / 16;
// Setting the dimensions of the container element.
container.style.height = height + 'px';
container.style.width = height + 'px';
// return positive X of any given Y.
function getXOffset(y) {
return Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2);
}
// Setting the position of the rotating element to the start.
rotating.style.top = 0 + 'px';
rotating.style.left = centerX + 'px';
setInterval(() => {
let top = parseInt(rotating.style.top),
y = radius - top;
rotating.style.top = (top + 1) + 'px';
rotating.style.left = (centerX + getXOffset(y)) + 'px';
}, 16);
Here is a fiddle with a bit more code for trying to get the right amount of distance between points for a smoother animation(currently needs fixing, but it doesn't bother me yet.)
https://jsfiddle.net/shock/1qcfvr4y/
Last note: I know that there might be other ways to do this with CSS, but I chose to use javascript for learning purposes.
Math.sqrt would only return the positive root. You'll have to account for the negative value based on the application. In this case, you need the positive x value during the 1st half of the cycle and negative during the 2nd half.
To do that, you should implement a method to track the progress and reverse the sign accordingly.
Here is a sample. I modified upon yours.
edit:
Instead of Math.sqrt( Math.pow(radius, 2) - Math.pow(y, 2) , 2) You can use the full formula to get x if you do not want to assume origin as center, which in this case is Math.sqrt( Math.pow(radius, 2) - Math.pow((actualY - centerY), 2) , 2)
explanation:
The original equation (x-a)² + (y'-b)² = r²
becomes x = √(r² - (y'-b)²) + a
Assuming .rotating box have 0 width and height.
The variable equivalents in your code are centerX = a, centerY = b.
By assuming origin as center you're basically doing a pre-calculation so that your y value becomes the equivalent of (y'-b). Hence x = √(r² - y²) + a is valid.
At initial state top = 0
i.e (y'-b) => height - centerY.
In your code y = radius => height/2.
Now (height - centerY) being equal to (height/2) is a side effect of your circle being bound by a square container whose height determines the y value.
In other words, when you use origin as center, you are taking the center offsets outside of circle equation and handling it separately. You could do the same thing by using the whole formula, that is, x = √(r² - (y'-b)²) + a

Chart.js v2, remove padding/margin from radar chart

Has anyone run into the issue of removing padding (or margin?) from a chartjs chart?
Below is my code (in jsFiddle)...and image (notice the bottom? UGLY sauce).
Here's a JSFiddle that highlights the issue. Notice the padding at the bottom of the white box. https://jsfiddle.net/mre1p46x/
You can wrap a bit of logic around the fit method using the beforeFit and afterFit handlers to correct this padding when the number of labels is 3 (the fit function starts off by assuming a maximum radius of half the chart height. For a triangle, we actually have a bit more space)
All we do is scale the height property to compensate for this assumption, like so
...
options: {
scale: {
beforeFit: function (scale) {
if (scale.chart.config.data.labels.length === 3) {
var pointLabelFontSize = Chart.helpers.getValueOrDefault(scale.options.pointLabels.fontSize, Chart.defaults.global.defaultFontSize);
scale.height *= (2 / 1.5)
scale.height -= pointLabelFontSize;
}
},
afterFit: function (scale) {
if (scale.chart.config.data.labels.length === 3) {
var pointLabelFontSize = Chart.helpers.getValueOrDefault(scale.options.pointLabels.fontSize, Chart.defaults.global.defaultFontSize);
scale.height += pointLabelFontSize;
scale.height /= (2 / 1.5);
}
},
...
The scaling factor 2 / 1.5 is pretty easy to figure out
With h = distance from center of triangle to a corner
Total height of the triangle = h + distance from center of triangle to a side
= h + h * sin 30
= 1.5 h
h currently = chart height / 2
We want to scale this by r, such that
1.5 * chart height / 2 * r = chart height
This gives us
r = 2 / 1.5
Fiddle - https://jsfiddle.net/zqp525gf/

How to measure distance between two circles, and then check for collision?

i'm making a game in jquery/javascript. And the game is to hit one moving object by using your mouse to click on the screen. I have problem with the detection bit. Is there a jQuery/javascript function that can mesure the distance between the center of the two objects at all time? Becasue then i can easily make a control check the distance of the two centers. and se if the collide. They are both two circles.
<div id="box">
<div id="prepend">
<div id="hero"></div>
</div>
<div id="enemy"></div>
</div>
Where "box" is the area where the game takes place, "hero" the bullet that you are going to hit the "enemy".
To get the distance use the formula
function getDistance(obj1,obj2){
Obj1Center=[obj1.offset().left+obj1.width()/2,obj1.offset().top+obj1.height()/2];
Obj2Center=[obj2.offset().left+obj2.width()/2,obj2.offset().top+obj2.height()/2];
var distance=Math.sqrt( Math.pow( Obj2Center[0]-Obj1Center[0], 2) + Math.pow( Obj2Center[1]-Obj1Center[1], 2) )
return distance;
}
Call using
getDistance($("#obj1"),$("#obj2"));
To check for collision:
function hasCollision(obj1,obj2){
return getDistance(obj1,obj2)<obj1.width()/2+obj2.width()/2;
}
Here's a jsfiddle example demonstrating both
You can use the following:
var $this = $(this);
var offset = $this.offset();
var width = $this.width();
var height = $this.height();
var centerX = offset.left + width / 2;
var centerY = offset.top + height / 2;
Do this for both and then calculate the difference between those values.
There isn't one, but its pretty simple actually:
Get the absolute coords of the current item as well as width and height
Calculate center point (x + width/2, y + height/2)
Do that for both circles
use trigonometric functions to calculate distance between those two points: difference of x in square plus difference of y in square, take the square root of that = distance
if the distance minus the radius of both circles is greater than 0, no collision. If 0: they touch, if smaller than 0, they collided.

Finding point n% away from the centre of a semicircle in Javascript?

I'm sorry to say that Math really isn't my strong suit. Normally I can get by, but this has got me totally stumped.
I'm trying to code up a quiz results screen in HTML/CSS/Javascript.
On my interface, I have a semicircle (the right hemisphere of a target).
I have a range of 'scores' (integers out of 100 - so 50, 80, 90 etc.).
I need to plot these points on the semicircle to be n% away from the centre, where n is the value of each score - the higher the score, the closer to the centre of the target the point will appear.
I know how wide my semicircle is, and have already handled the conversion of the % values so that the higher ones appear closer to the centre while the lower ones appear further out.
What I can't wrap my head around is plotting these points on a line that travels out from the centre point (x = 0, y = target height/2) of the target at a random angle (so the points don't overlap).
Any suggestions are gratefully received!
Do you have an example of what you want this to look like? It sounds like you want to divide up the circle into N slices where N is the number of points you need to display, then plot the points along each of those radii. So you might have something like:
Edit: code was rotating about the origin, not the circle specified
var scores = [];
//...
//assume scores is an array of distances from the center of the circle
var points = [];
var interval = 2 * Math.PI / N;
var angle;
for (var i = 0; i < N; i++) {
angle = interval * i;
//assume (cx, cy) are the coordinates of the center of your circle
points.push({
x: scores[i] * Math.cos(angle) + cx,
y: scores[i] * Math.sin(angle) + cy
});
}
Then you can plot points however you see fit.
After much headscratching, I managed to arrive at this solution (with the help of a colleague who's much, much better at this kind of thing than me):
(arr_result is an array containing IDs and scores - scores are percentages of 100)
for (var i = 0; i < arr_result.length; i++){
var angle = angleArray[i]; // this is an array of angles (randomised) - points around the edge of the semicircle
var radius = 150; // width of the semicircle
var deadZone = 25 // to make matters complicated, the circle has a 'dead zone' in the centre which we want to discount
var maxScore = 100
var score = parseInt(arr_result[i]['score'], 10)
var alpha = angle * Math.PI
var distance = (maxScore-score)/maxScore*(radius-deadZone) + deadZone
var x = distance * Math.sin(alpha)
var y = radius + distance * Math.cos(alpha)
$('#marker_' + arr_result[i]['id'], templateCode).css({ // target a specific marker and move it using jQuery
'left' : pointX,
'top': pointY
});
}
I've omitted the code for generating the array of angles and randomising that array - that's only needed for presentational purposes so the markers don't overlap.
I also do some weird things with the co-ordinates before I move the markers (again, this has been omitted) as I want the point to be at the bottom-centre of the marker rather than the top-left.

Categories