How to change radius of circles but keep pattern? - javascript

I found some code online to draw circles around a center circle. How do I change the radius of the smaller circles without affecting the layout (currently all the circles shift and are not centered around the large circle anymore).
This happens when I change the radius(width & height) in the css file. Changing the large circle radius also causes the whole group of circles to shift right or left (although they maintain their symmetry).
Here is my code:
var div = 360 / 6;
var radius = 150;
var parentdiv = document.getElementById('parentdiv');
var offsetToParentCenter = parseInt(parentdiv.offsetWidth / 2); //assumes parent is square
var offsetToChildCenter = 20;
var totalOffset = offsetToParentCenter - offsetToChildCenter;
for (var i = 1; i <= 6; ++i) {
var childdiv = document.createElement('div');
childdiv.className = 'div2';
childdiv.style.position = 'absolute';
var y = Math.sin((div * i) * (Math.PI / 180)) * radius;
var x = Math.cos((div * i) * (Math.PI / 180)) * radius;
childdiv.style.top = (y + totalOffset).toString() + "px";
childdiv.style.left = (x + totalOffset).toString() + "px";
parentdiv.appendChild(childdiv);
}
#parentdiv {
position: relative;
width: 150px;
height: 150px;
background-color: red;
border-radius: 150px;
margin: 150px;
}
.div2 {
position: absolute;
width: 40px;
height: 40px;
background-color: red;
border-radius: 100px;
}
<div id="parentdiv"></div>
I would also like to move the circles to the center of the screen but I am not sure how.
I am very new to html/css/js and any help would be greatly appreciated!

To illustrate my comment. border-radius is a CSS rule to round boxe's corners.
https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius
The border-radius CSS property rounds the corners of an element's outer border edge. You can set a single radius to make circular corners, or two radii to make elliptical corners.
to modify the size , you can do it from the css file too, about the position , there is two vars to update : radius and offsetToChildCenter
Demo
var div = 360 / 6;
var radius = 180;
var parentdiv = document.getElementById('parentdiv');
var offsetToParentCenter = parseInt(parentdiv.offsetWidth / 2); //assumes parent is square
var offsetToChildCenter = 40;
var totalOffset = offsetToParentCenter - offsetToChildCenter;
for (var i = 1; i <= 6; ++i) {
var childdiv = document.createElement('div');
childdiv.className = 'div2';
childdiv.style.position = 'absolute';
var y = Math.sin((div * i) * (Math.PI / 180)) * radius;
var x = Math.cos((div * i) * (Math.PI / 180)) * radius;
childdiv.style.top = (y + totalOffset).toString() + "px";
childdiv.style.left = (x + totalOffset).toString() + "px";
parentdiv.appendChild(childdiv);
}
html {
display: flex;
height: 100%;
}
body {
margin: auto;
}
#parentdiv {
position: relative;
width: 150px;
height: 150px;
background-color: red;
border-radius: 150px;
margin: 150px;
}
.div2 {
position: absolute;
width: 80px;
height: 80px;
background-color: red;
border-radius: 10px;
}
<div id="parentdiv"></div>

You can center the circles by applying Flexbox to the parent circle's parent element. In my case, the parent element is <body>.
/* Apply Flexbox and use justify-content to
center parent circle horizontally. */
body {
width: 100vw;
display: flex;
justify-content: center;
}
To adjust the diameter of the smaller circles, you would have to remove the width and height properties in your .div2 selector and let Javascript calculate and set the width and height.
var parentdiv = document.getElementById('parentdiv');
var div = 360 / 6;
var radius = 150;
var offsetToChildCenter = 50; // Change me!
var offsetToParentCenter = parseInt(parentdiv.offsetWidth / 2); //assumes parent is square
var totalOffset = offsetToParentCenter - offsetToChildCenter;
for (var i = 1; i <= 6; ++i) {
var childdiv = document.createElement('div');
childdiv.className = 'div2';
childdiv.style.position = 'absolute';
var y = Math.sin((div * i) * (Math.PI / 180)) * radius;
var x = Math.cos((div * i) * (Math.PI / 180)) * radius;
childdiv.style.top = (y + totalOffset).toString() + "px";
childdiv.style.left = (x + totalOffset).toString() + "px";
// Let your JS code calculate the width and height
childdiv.style.width = `${offsetToChildCenter * 2}px`
childdiv.style.height = `${offsetToChildCenter * 2}px`
parentdiv.appendChild(childdiv);
}
body {
width: 100vw;
display: flex;
justify-content: center;
}
#parentdiv {
position: relative;
width: 150px;
height: 150px;
background-color: red;
margin: 150px;
/* Use 50% to ensure the element will always be a circle. */
border-radius: 50%;
}
.div2 {
position: absolute;
/* Remove width and height from CSS */
/* width: 40px; */
/* height: 40px; */
background-color: red;
/* Use 50% to ensure the element will always be a circle. */
border-radius: 50%;
}
<div id="parentdiv"></div>

Related

How to rotate point and place in the center?

I have tried to rotate point in case when parent container was rotated:
https://stackblitz.com/edit/js-qzfdbb?file=index.js
Code is:
var elParent = document.getElementById('parent');
var elCircle = document.getElementById('circle');
elCircle.addEventListener('click', function(e) {
const circleSvg = document.getElementById('circle');
const circleSvgRect = circleSvg.getBoundingClientRect();
const parentRect = document.getElementById('parent').getBoundingClientRect();
let leftTopX = circleSvgRect.left - parentRect.left;
let leftTopY = circleSvgRect.top - parentRect.top;
leftTopX = leftTopX + 15 - 5;
leftTopY = leftTopY + 15 - 5;
var degree = (20 * Math.PI) / 180;
var xc = 250;
var yc = 250;
leftTopX =
(leftTopX - xc) * Math.cos(degree) -
(leftTopY - yc) * Math.sin(degree) +
xc;
leftTopY =
(leftTopX - xc) * Math.sin(degree) +
(leftTopY - yc) * Math.cos(degree) +
yc;
let c = document.getElementById('c');
if (c) c.remove();
c = document.createElement('div');
c.setAttribute('id', 'c');
c.style.setProperty('left', leftTopX + 'px');
c.style.setProperty('top', leftTopY + 'px');
elParent.appendChild(c);
});
To see result make click inside red circle. Withour rotation a green circle is placed in the center of red circle. Otherwise has offset.
the maths should be something like this, but the solution needs some additional calculations for the rotation of the red circle itself within the outer rectangle.
Note 1: The margin of the body is removed for simplicity...
Note 2: Scrolls effect the script a lot. Therefore the solution also may not be very useful without taking it into consideration...
var elParent = document.getElementById('parent');
var elCircle = document.getElementById('circle');
elCircle.addEventListener('click', function(e) {
const circleSvg = document.getElementById('circle');
const circleSvgRect = circleSvg.getBoundingClientRect();
const parentRect = document.getElementById('parent').getBoundingClientRect();
const degree = getCurrentRotation(document.getElementById('parent'));
const xcenter = parentRect.width / 2 + parentRect.left;
const ycenter = parentRect.height / 2 + parentRect.top;
const dx = (circleSvgRect.left + 10) - xcenter;
const dy = ycenter - (circleSvgRect.top + 10);
console.log(dx + ' - ' + dy + '-' + Math.atan(dy / dx));
const r = Math.sqrt(dx * dx + dy * dy);
const curDegree = Math.atan(dy / dx) + degree;
xnew = xcenter + Math.sign(-dx) * Math.sin(curDegree) * r;
ynew = ycenter - Math.sign(-dx) * Math.cos(curDegree) * r;
let c = document.getElementById('c');
if (c) c.remove();
c = document.createElement('div');
c.setAttribute('id', 'c');
c.style.setProperty('left', xnew + 'px');
c.style.setProperty('top', ynew + 'px');
elParent.appendChild(c);
});
//https://stackoverflow.com/questions/19574171/how-to-get-css-transform-rotation-value-in-degrees-with-javascript
function getCurrentRotation(el) {
var st = window.getComputedStyle(el, null);
var tm =
st.getPropertyValue('-webkit-transform') ||
st.getPropertyValue('-moz-transform') ||
st.getPropertyValue('-ms-transform') ||
st.getPropertyValue('-o-transform') ||
st.getPropertyValue('transform') ||
'none';
if (tm != 'none') {
var values = tm
.split('(')[1]
.split(')')[0]
.split(',');
return (angle = Math.atan2(values[1], values[0]));
}
return 0;
}
<div id="parent">
<div id="circle" style="left: 100px; top: 100px"></div>
</div>
<style>
body {
margin:0px;
padding:0px;
}
#circle {
width: 30px;
height: 30px;
border-radius: 50%;
background: red;
position: relative;
}
#c {
position: absolute;
width: 10px;
height: 10px;
background: green;
border-radius: 50%;
}
#parent {
width: 500px;
position: relative;
height: 500px;
border: 1px solid #ccc;
transform: rotate(180deg);
}
</style>

sin and cos animations on a curved line with javascript and CSS

I am trying to use sin and cos to animate a CSS image to move on this shape. Can not make the CSS image to move on that curved bezier line.
Can someone assist on how to use sin or cos in so, if a CSS object added, it would move smoothly along such a line?
Here is the code that I tried to make the yellow circle to move on that line with sin and cos math in javascript.
Thanks
var field = document.getElementById("field");
var ball = document.getElementById("ball");
var ball2 = document.getElementById("ball2");
var maxX = field.clientWidth - ball.offsetWidth;
var maxY = field.clientHeight - ball.offsetHeight;
var duration = 5; // seconds
var gridSize = 50; // pixels
var start = null;
function step(timestamp) {
var progress, x, y, y2;
if (start === null)
start = timestamp;
progress = (timestamp - start) / duration / 1000; // percent
x = progress * maxX / gridSize; // x = ƒ(t)
y = 2 * Math.sin(x); // y = ƒ(x)
y2 = 2 * Math.cos(x);
ball.style.left = ball2.style.left = Math.min(maxX, gridSize * x)
+ "px";
ball.style.bottom = maxY / 2 + (gridSize * y) + "px";
ball2.style.bottom = maxY / 2 + (gridSize * y2) + "px";
if (progress >= 1)
start = null; // reset to start position
requestAnimationFrame(step);
}
requestAnimationFrame(step);
#field {
position: absolute;
height: 300px;
width: 300px;
z-index: 50;
top: 20px;
left: 20px;
}
#ball {
position: absolute;
left: 0;
bottom: 50%;
width: 40px;
background: yellow;
z-index: 5;
height: 40px;
border-radius: 200px;
}
#ball2 {
position: absolute;
left: 0;
bottom: 50%;
width: 20px;
height: 20px;
/*background: silver;*/
border-radius: 100px;
}
<div id="field">
<div id="ball"></div>
<div id="ball2"></div>
</div>
requestAnimationFrame calls the given function exactly ONCE
to animate, you need to call requestAnimationFrame within that given function, usually calling the function itself (though more complex animations may call something else, it doesn't matter)
The main point being, you need to call requestAnimationFrame for each frame you want to animate
var field = document.getElementById("field");
var ball = document.getElementById("ball");
var ball2 = document.getElementById("ball2");
var maxX = field.clientWidth - ball.offsetWidth;
var maxY = field.clientHeight - ball.offsetHeight;
var duration = 5; // seconds
var gridSize = 40; // pixels
var start = null;
function step(timestamp) {
var progress, x, y, y2;
if (start === null)
start = timestamp;
progress = (timestamp - start) / duration / 1000; // percent
x = progress * maxX / gridSize; // x = ƒ(t)
y = -2 * Math.cos(x); // y = ƒ(x)
y2 = 2 * Math.cos(x);
ball.style.left = ball2.style.left = Math.min(maxX, gridSize * x) +
"px";
ball.style.bottom = maxY / 2 + (gridSize * y) + "px";
ball2.style.bottom = maxY / 2 + (gridSize * y2) + "px";
if (progress >= 1)
start = null; // reset to start position
requestAnimationFrame(step);
}
requestAnimationFrame(step);
#field {
position: absolute;
height: 300px;
width: 300px;
z-index: 50;
top: 20px;
left: 20px;
}
#ball {
position: absolute;
left: 0;
bottom: 50%;
width: 40px;
background: yellow;
height: 40px;
border-radius: 200px;
}
#ball2 {
position: absolute;
left: 0;
bottom: 50%;
width: 20px;
height: 20px;
background: silver;
border-radius: 100px;
}
<div id="field">
<div id="ball"></div>
<div id="ball2"></div>
</div>

Detect circle overlap

I'm trying to trigger a hover function when ANY part of a fake cursor hovers over a circle.
I have played around with the X and Y positions of the fake cursor, but that only works well for one direction. Is there a smarter way to go about this?
Here's a pen showing what I'm trying to do: trigger a hover function when any part of the pink circle (fake cursor) touches the green circle.
https://codepen.io/Jessels/pen/LYPxmqx
$('.cursor')
.eq(0)
.css({
left: e.pageX - 20,
top: e.pageY - 5
});
You can add this to your mousemove event.
Here we are finding the intersections and if the "cursor" is within the circle.
Here is where I found this code: Fiddle
Here is my CodePen Demo
$(document).mousemove(function(e) {
$('.cursor').eq(0).css({
left: e.pageX - 25,
top: e.pageY - 20
});
// circles
var c1 = $('.cursor');
var c2 = $('.circle');
// radius
var d1 = c1.outerWidth(true) / 2;
var d2 = c2.outerWidth(true) / 2;
// center of first circle
var x1 = c1.offset().left + c1.width() / 2;
var y1 = c1.offset().top + c1.height() / 2;
// center of second circle
var x2 = c2.offset().left + c2.width() / 2;
var y2 = c2.offset().top + c2.height() / 2;
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
var d = (b * b + c * c - a * a) / (2 * c);
var h = Math.sqrt((b * b) - (d * d));
if (d < 0 || $.isNumeric(h)) {
c2.css('background', 'blue');
} else {
c2.css('background', 'green');
}
}
calc();
});
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
background: hotpink;
}
.circle {
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor"></div>
<div class="circle">
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
<div>

How to make a div follow the cursor, but shifted by Xpx towards the center of window?

Div should follow the cursor, but shifted 20px by X and Y axis toward the center of the screen, based on the quarter in which is the mouse cursor?
Like this: https://i.imgur.com/XaDk1hI.png
I used trigonometry to find vector from cursor to center of the window, so I have cursor coordinates, center coordinates, and third point C, but div moves in strange circles and I don't where I made mistake.
var lt = document.getElementById('lt')
var ltPosition = lt.getBoundingClientRect();
var element = document.getElementById('element');
var mousePosX = 0;
var mousePosY = 0;
document.onmousemove = function(e){
function angle(xCursor, yCursor, xCenter, yCenter){
var distanceA = xCursor - xCenter;
var distanceB = yCursor - yCenter;
var distanceC = Math.sqrt(distanceA*distanceA + distanceB*distanceB);
var theta = Math.atan2(distanceA, distanceB);
theta *= 180 / Math.PI;
var offsetX = distanceC * Math.sin(theta);
var offsetY = distanceC * Math.cos(theta);
function follow(x,y){
element.style.left = x + "px";
element.style.top = y +"px";
}
follow(e.clientX + offsetX, e.clientY + offsetY);
}
angle(e.clientX, e.clientY, ltPosition.right, ltPosition.bottom);
}
Here is fiddle: https://jsfiddle.net/sgvpvqhc/
What else should I do here in order to have this functionality?
What is that theta *= 180 / Math.PI; doing there? sin and cos take the angle in radians, just like atan returns it. If you want to display it, sure, convert it to degrees, but inside the Math API no conversion are needed.
(updated fiddle demo)
I though you might like this. I put it here too. https://jsfiddle.net/sgvpvqhc/5/
function mouseMover(element, offX, offY) {
var e = element,
bc = e.getBoundingClientRect();
var ox = offX,
oy = offY;
if (ox === undefined && oy === undefined) {
ox = -Math.round(bc.width / 2);
oy = -Math.round(bc.height / 2);
}
e.parentNode.onmousemove = function(eventObj) {
var ev = eventObj,
b = this.getBoundingClientRect();
var x = Math.round(ev.clientX - b.left);
var y = Math.round(ev.clientY - b.top);
e.style.left = x + (ox) + 'px';
e.style.top = y + (oy) + 'px';
}
}
mouseMover(document.getElementById('element'), 20, 20)
html, body {
margin: 0;
height: 100%;
}
.container {
width: 100%;
height: 100%;
}
#lt, #rt, #ld, #rd {
float: left;
width: 50%;
height: 50%;
display: inline-block;
}
#element {
background-color: red;
width: 50px;
height: 50px;
position: absolute;
}
#lt, #rd {
background-color: green;
}
#rt, #ld {
background-color: yellow;
}
<div id='container' class='container'>
<div id='element'></div>
<div id='lt'></div>
<div id='rt'></div>
<div id='ld'></div>
<div id='rd'></div>
</div>
<div class='box'></div>

Javascript Easing no working in Firefox

The below HTML and Javascript has an easing function applied to a background. It works fine in Chrome, Safari, and even IE, but not firefox?
anyone out there know why it wont work in FF?
var element = "ele";
var ease_against = true;
window.onload = function() {
var target = {
x: 0,
y: 0
};
var position = {
x: target.x,
y: target.y
},
ease = 0.2;
document.getElementById(element).addEventListener("mousemove", function(event) {
target.x = event.clientX / 5;
target.y = event.clientY / 5;
});
update();
function update() {
var vx = ease_against ? (((target.x - target.x - target.x) - position.x) * ease) : ((target.x - position.x) * ease);
var vy = ease_against ? (((target.y - target.y - target.y) - position.y) * ease) : ((target.y - position.y) * ease);
position.x += vx;
position.y += vy;
document.getElementById(element).style.backgroundPositionY = position.y + "px";
document.getElementById(element).style.backgroundPositionX = position.x + "px";
requestAnimationFrame(update);
}
};
html,
body {
margin: 0;
width: 100%;
height: 100%;
padding: 0;
}
#ele {
background: url('hex.jpg') repeat;
width: 400px;
height: 400px;
margin-left: auto;
margin-right: auto;
border-top: 1px solid black;
border-bottom: 1px solid black;
border-radius: 50%;
overflow: hidden;
}
<div id="ele">
</div>
It's not the easing that causes your problem.
Firefox doesn't support backgroundPositionX, but it does support background position
For example you can do:
myElement.style.backgroundPosition = position.x + "px "+position.y + "px";

Categories

Resources