There is a circle and some object around it.the objects number may vary from 1 to n (dynamic).
How can i place all this objects around the circle automatically ??
Tnx in advance.
Here is a way of doing it. I've added comments in the code to explain the steps. I've taken the liberty to use just colored divs instead of images, but the effect is the same.
// Editor to change the number of persons dynamically
var nr = document.getElementById('nr');
nr.addEventListener('keyup', function(){updatePersons();});
// The globe
var globe = document.getElementById('globe');
// A function to reinitialize the persons
function updatePersons() {
var personCount = parseInt(nr.value);
globe.innerHTML = ''; // A bit dirty way to remove all previous peeps
// Just add them in a loop, and apply a transformation.
for (var i = 0; i < personCount; i++) {
var person = document.createElement('div');
person.className = 'mens';
var rotation = i * (360 / personCount);
console.log(rotation);
person.style.transform = 'translate(125px, -100px) rotate(' + rotation + 'deg)';
globe.appendChild(person);
}
}
// Initial positioning of persons.
updatePersons();
#nr {
position: relative;
z-index: 1;
}
.corea {
background-color: blue;
border-radius: 50%;
width: 300px;
height: 300px;
position: relative;
}
.mens {
position: absolute; /* Needed, otherwise they influence each other */
width: 50px;
height: 100px;
background-color: red;
transform-origin: 25px 250px;
/* Transform is set in Javascript */
x-transform: translate(125px, -100px) rotate(180deg);
}
<input id="nr" value="5">
<div id="globe" class="corea">
</div>
Related
hello everyone hope you guys are having a great day!
so, i am building a simple game where I use a custom-made cursor as the aim for shooting div elements moving around the screen as the enemies and when i apply the "pointerdown" event i want the enemy to change its color. however, every time i hover over the enemy the cursor falls behind witch i don't understand why, and when i use the z-index property it will prevent the "pointerdown" event from firing. if some cool OG programmer can help me, it would mean a lot to me.
style
* {
margin: 0;
padding: 0;
cursor: none;
}
.aim {
position: absolute;
background: black;
width: 10px;
height: 10px;
border-radius: 50%;
transform: translate(-50%, -50%);
}
.enemy {
position: absolute;
border: 3px solid black;
background-color: blue;
width: 50px;
height: 50px;
}
javascript
const body = document.body;
const aim = document.createElement("div");
const enemy = document.createElement("div");
body.appendChild(aim);
body.appendChild(enemy);
aim.classList.add("aim");
enemy.classList.add("enemy");
let enemy_X_position = 0;
let enemy_Y_position = 0;
let enemy_X_distance = 1;
let enemy_Y_distance = 1;
function Flight()
{
enemy.style.left = enemy_X_position + "px";
enemy.style.top = enemy_Y_position + "px";
}
setInterval(function()
{
enemy_X_position += enemy_X_distance;
enemy_Y_position += enemy_Y_distance;
if ((enemy_X_position + enemy.offsetWidth) >= window.innerWidth || enemy_X_position <= 0)
enemy_X_distance = -enemy_X_distance;
if ((enemy_Y_position + enemy.offsetHeight) >= window.innerHeight || enemy_Y_position <= 0)
enemy_Y_distance = -enemy_Y_distance;
Flight();
},1000/60)
window.onmousemove = function()
{
aim.style.left = event.pageX + "px";
aim.style.top = event.pageY + "px";
}
enemy.onpointerdown = function()
{
event.target.style.background = "red";
}
enemy.onpointerup = function()
{
event.target.style.background = null;
}
Update
The event is not triggering because pointerdown was received by aim when it sits on top of enemy.
To solve this, add pointer-events: none on aim class to prevent it from being the target of a pointer event.
More about pointer-events
Hope this will help!
.aim {
position: absolute;
background: black;
width: 10px;
height: 10px;
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
Original
Perhaps an over simplified solution, but it seems that if you reverse the order of appendChild, the aim should be stacked over enemy without additional styling.
Example:
body.appendChild(enemy);
body.appendChild(aim);
Because both elements are child of body, Unless there is other styling that override this stacking, the later one should be on top.
I have a red container which initially is at bottom right of black container. I have a scale function that gradually scales the container. I want to make the bottom right position of red container to be fixed and scale it towards top left. How can I do that?
const box = document.getElementById("box")
const initHeight = 200
const initWidth = 200
const centerX = initWidth / 2
const centerY = initHeight / 2
function transform(scale, translate) {
if (translate) {
translate[0] = -centerX + translate[0]
translate[1] = -centerY + translate[1]
}
box.style.transform = `scale(${scale})${
translate ? ` translate(${translate.map((x) => x + "px").toString()})` : ""
}`
}
let initX = initWidth
let initY = initHeight
let scaleVal = 0.5
transform(scaleVal, [initX, initY])
function scale() {
scaleVal = scaleVal + 0.01
transform(scaleVal, [
initX - scaleVal * initWidth,
initY - scaleVal * initHeight
])
if (scaleVal <= 1) {
setTimeout(() => {
requestAnimationFrame(scale)
}, 50)
}
}
scale()
* {
box-sizing: border-box;
}
.box {
height: 200px;
width: 200px;
background-color: black;
position: absolute;
}
.box:nth-child(2) {
background-color: red;
}
<div id="app">
<div class="box"></div>
<div class="box" id="box"></div>
</div>
To lock the bottom right corner of the red box to the bottom right of the black box this snippet does two things: positions red box right bottom relative to the parent app container and sets the transform-origin to that spot too (normally transform origin is at the center of an element). It then uses a CSS animation to expand the red box and contract it again using scale.
This method does not need JS as it is a simple scaling transform, but of course some of the subtleties of the original transformations are lost because of tying the corner down.
* {
box-sizing: border-box;
}
body {
position: relative;
width: 100vw;
height: 100vh;
}
#app {
position: absolute;
height: 200px;
width: 200px;
}
.box:nth-child(1) {
height: 200px;
width: 200px;
background-color: black;
position: absolute;
top: 0;
left: 0;
}
#box {
background-color: red;
width: 100px;
height: 100px;
position: absolute;
bottom: 0;
right: 0;
transform-origin: right bottom;
animation: scale 5s 1 ease-in-out;
}
#keyframes scale {
0% {
transform: scale(1);
}
50% {
transform: scale(2);
}
100% {
transform: scale(1);
}
}
<div id="app">
<div class="box"></div>
<div class="box" id="box"></div>
</div>
Okay so I finally figured it out,
const box = document.getElementById("box")
let scale = 0
const initWidth = 50
const initHeight = 50
function fixed(num, fix = 1) {
return Number(parseFloat(num).toFixed(fix))
}
function scaleBox() {
const [x, y] = [
fixed((initWidth - scale * initWidth) / 2),
fixed((initHeight - scale * initHeight) / 2)
]
box.style.transform = `translate(${x}px, ${y}px) scale(${scale})`
scale = scale + 0.1
if (scale < 1) {
setTimeout(() => {
requestAnimationFrame(scaleBox)
}, 500)
}
}
scaleBox()
* {
box-sizing: border-box;
}
.box {
height: 50px;
width: 50px;
background-color: black;
position: absolute;
}
.box:nth-child(2) {
background-color: red;
transform: translate(0, 0) scale(0);
}
<div id="app">
<div class="box"></div>
<div class="box" id="box"></div>
</div>
Explanation
The trick is to translate the container in such a way that when its scaled after the translation, it always places itself in the bottom right of purple container.
To figure out the translation amount, let's first scale the container to 0.5 without any translation. It looks like this,
As you can see the container's width is 25 as 0.5(scale) * 50(init_width)=25 and position from container from all sides(top left, bottom left, top right, bottom right) will be (25/2, 25/2)=(12.5,12.5) since the container is scaled equally from all sides.
Since the position from bottom right is (12.5,12.5), we need to translate the container to (+12.5,+12.5) and then scale it to exactly place it at bottom right.
You can achieve many things using display:flex, it's great!
This is how I would approach your problem:
const handleClick = () => {
const blackDiv = document.getElementById("black-div");
const redDiv = document.getElementById("red-div");
let widthRatio = 0;
let heightRatio = 0;
const scaleUpTimer = setInterval(() => {
if (widthRatio === 1 || heightRatio === 1) clearInterval(scaleUpTimer);
widthRatio = redDiv.offsetWidth / blackDiv.offsetWidth;
heightRatio = redDiv.offsetHeight / blackDiv.offsetHeight;
redDiv.style.width = widthRatio * 100 + 2 + "%";
redDiv.style.height = heightRatio * 100 + 2 + "%";
}, 10);
};
#black-div {
width: 200px;
height: 200px;
background-color: rgb(0, 0, 0);
display: flex;
align-items: flex-end;
justify-content: flex-end;
}
#red-div {
background-color: red;
width: 50%;
height: 50%;
}
<div id='black-div'>
<div id='red-div' onclick={handleClick()}></div>
</div>
EDIT: I used onclick here but obviously you would have to handle the situations where someone clicks the red square and its already scaled up to avoid setting unnecessary timers. Or you could just call the function directly, without having to click anything.
I'm trying to create elements in random locations on the screen but I have run into some trouble. Creating the elements works but when I try to make them have random locations, nothing happens. Thanks for the help in advance.
Here's my code:
var newObject = document.createElement("DIV");
newObject.setAttribute("class", "object");
newObject.setAttribute("id", "powerup");
document.body.appendChild(newObject);
var powerup = document.getElementById("powerup");
var object = document.getElementsByClassName("object");
for (i = 0; i < object.length; i++) {
object[i].style.top = Math.floor(Math.random() * window.innerHeight) + 50 + "px";
object[i].style.left = Math.floor(Math.random() * window.innerWidth) + 50 + "px";
}
function createObject() {
var newObject = document.createElement("DIV");
newObject.setAttribute("class", "object");
newObject.setAttribute("id", "powerup");
document.body.appendChild(newObject);
for (i = 0; i < object.length; i++) {
object[i].style.top = Math.floor(Math.random() * window.innerHeight) + 50 + "px";
object[i].style.left = Math.floor(Math.random() * window.innerWidth) + 50 + "px";
}
}
html, body {
height: 100%;
width: 100%;
margin: 0;
}
#powerup {
background: red;
height: 10px;
width: 10px;
}
<body>
<button onclick="createObject()">Create a Block</button>
</body>
Your code is working correctly. Its able to set top and left of each #powerup element. The only problem is that the position of #powerup is static by default. So you just need to change css of #powerup element to
#powerup {
background: red;
height: 10px;
width: 10px;
position: relative;
}
position: absolute can also be used. Choose the one that fits your requirements.
I made a CodePen with your code.
For those elements to have their top and left properties have an effect, you need to add position: absolute; to the #powerup elements.
#powerup {
background: red;
height: 10px;
width: 10px;
position: absolute;
}
Also, I'm not sure if this is what you intended, but your JavaScript code is selecting a new random location for each pre-existing #powerup element whenever you click the button.
I'm trying to write a facebook like chatbox, but i've encountered a small problem.
I'm using the following code (it's only test code, so it's not really clean):
css code:
#messenger {
position: fixed;
bottom: 0px;
right: 10px;
width: 200px;
height: 300px;
z-index: 4;
background-color: #ECECEC;
border: 1px solid #000;
}
#messenger.p {
text-align: right;
}
#contacts {
margin: 5px 5px 5px 5px;
}
#chatspace {
position: fixed;
bottom: 0px;
right: 240px;
height: 20px;
left: 20px;
background-color: #ECECEC;
border: 1px solid #000;
z-index: 4;
}
.chatbox {
position: absolute;
bottom: 0px;
width: 200px;
height: 200px;
z-index: 4;
background-color: #ECECEC;
border: 1px solid #000;
}
html/javascript code:
<script type="text/javascript">
var i = 0;
function oc_chatbox() {
if (i == 0) {
document.getElementById('contacts').style.visibility = 'hidden';
document.getElementById('messenger').style.height = '20px';
i = 1;
}
else {
document.getElementById('contacts').style.visibility = 'visible';
document.getElementById('messenger').style.height = '300px';
i = 0;
}
}
function new_chat(userid) {
var new_right;
new_right = document.getElementById('messenger').style.right;
//alert('old value: '+ new_right);
new_right += 20;
//alert('New value of right: '+ new_right);
document.getElementById('chatspace').innerHTML = '<div id="'+userid+'" class="chatbox" style="right: '+new_right+'px;"></div>';
//document.write('<div id="'+userid+'" class="chatbox" style="right: '+new_right+'px;"></div>');
}
</script>
<div id="chatspace"></div>
<div id="messenger">
<p>Collapse</p>
<div id="contacts">
<ul>
<li>contact A</li>
</ul>
</div>
</div>
the problem is, that when I try to add new chats to the chatbar, i can't seem the place them next to each other.
anyone who can help ?
EDIT:
so i changed to javascript code to:
var last = null;
function new_chat(userid) {
if(userid==null)
userid = "user666";
var new_right;
var margin = 10;
var messenger = window.last==null?document.getElementById('messenger'):window.last; //Take the messenger or the last added chat
new_right = document.body.clientWidth-messenger.offsetLeft; //Compute the window size
console.log(new_right); //Log the number
new_right += margin; //keep spaces between divs
var newChat = document.createElement("div"); //DOM create DIV
newChat.id = userid;
newChat.className = "chatbox shadow";
newChat.style.right = new_right+"px";
newChat.innerHTML = '<p>'+userid+'</p><p><textarea></textarea></p>';
window.last = newChat; //Remember whichever is last
document.body.appendChild(newChat);
}
and now it works, thanks !
You cannot get an element right offset using its style, unlest the style is set and valid. Instead you must get element.offsetLeft and size of window area and do this:
new_right = windowSize()[0]-messenger.offsetLeft;
Where window size is this function.
Here is my, working, version of your function:
var last = null;
function new_chat(userid) {
if(userid==null)
userid = "user666";
var new_right;
var margin = 20;
var messenger = window.last==null?document.getElementById('messenger'):window.last; //Take the messenger or the last added chat
new_right = windowSize()[0]-messenger.offsetLeft; //Compute the window size
console.log(new_right); //Log the number
new_right += margin; //keep spaces between divs
var newChat = document.createElement("div"); //DOM create DIV
newChat.id = userid;
newChat.className = "chatbox";
newChat.style.right = new_right+"px";
window.last = newChat; //Remember whichever is last
document.body.appendChild(newChat);
}
You may get errors if console is not defined in your brouwser. But in such case you should take a better browser. Normally, the if(console!=null) is put in code.
And here is the link.
You should try adding a float style.
.chatbox {
float: right;
}
Add that to your chatbox styles. You may need to mess around a bit to make sure the float doesn't mess with your other elements. You may need a better container for them.
If you want to get really fun, you can add .draggable() from jQuery, and you can have them snap to your chat bar. You can then change the order of your chats.
I am trying to make a webpage where when you click a link, the link moves diagonally every 100 milliseconds.
So I have my Javascript, but right now when I click the link nothing happens
Also, does anyone know of a Javascript IDE I can use to make sure I have no errors in my code?
PS: Does anyone know why my elements dont stretch to fit the whole 200px by 200px of the div element? The links are only small when they should be the same width as their parent div element.
Edited with new advice, although still wont move.
<script LANGUAGE="JavaScript" type = "text/javascript">
<!--
var block = null;
var clockStep = null;
var index = 0;
var maxIndex = 6;
var x = 0;
var y = 0;
var timerInterval = 100; // milliseconds
var xPos = null;
var yPos = null;
function moveBlock()
{
if ( index < 0 || index >= maxIndex || block == null || clockStep == null )
{
clearInterval( clockStep );
return;
}
block.style.left = xPos[index] + "px";
block.style.top = yPos[index] + "px";
index++;
}
function onBlockClick( blockID )
{
if ( clockStep != null )
{
return;
}
block = document.getElementById( blockID );
index = 0;
x = parseInt( block.style.left, 10 );
y = parseInt( block.style.top, 10 );
xPos = new Array( x+10, x+20, x+30, x+40, x+50, x+60 );
yPos = new Array( y-10, y-20, y-30, y-40, y-50, y-60 );
clockStep = self.SetInterval( moveBlock(), timerInterval );
}
-->
</script>
<style type="text/css" media="all">
<!--
#import url("styles.css");
#blockMenu { z-index: 0; width: 650px; height: 600px; background-color: blue; padding: 0; }
#block1 { z-index: 30; position: relative; top: 10px; left: 10px; background-color: red; width: 200px; height: 200px;
margin: 0; padding: 0; /* background-image: url("images/block1.png"); */ }
#block2 { z-index: 30; position: relative; top: 50px; left: 220px; background-color: red; width: 200px; height: 200px;
margin: 0; padding: 0; /* background-image: url("images/block1.png"); */ }
#block3 { z-index: 30; position: relative; top: 50px; left: 440px; background-color: red; width: 200px; height: 200px;
margin: 0; padding: 0; /* background-image: url("images/block1.png"); */ }
#block4 { z-index: 30; position: relative; top: 0px; left: 600px; background-color: red; width: 200px; height: 200px;
margin: 0; padding: 0; /* background-image: url("images/block1.png"); */ }
#block1 a { display: block; width: 100%; height: 100%; }
#block2 a { display: block; width: 100%; height: 100%; }
#block3 a { display: block; width: 100%; height: 100%; }
#block4 a { display: block; width: 100%; height: 100%; }
#block1 a:hover { background-color: green; }
#block2 a:hover { background-color: green; }
#block3 a:hover { background-color: green; }
#block4 a:hover { background-color: green; }
#block1 a:active { background-color: yellow; }
#block2 a:active { background-color: yellow; }
#block3 a:active { background-color: yellow; }
#block4 a:active { background-color: yellow; }
-->
</style>
Errors needed to fix
To fill the width of the div elements, the a elements need to be display: block; not their default display: inline;.
Knowing runtime errors is more important in my opinion, and IDEs don't catch DOM errors or anything more complex than syntax; use the error logging in your browser (Firefox's is called Error Console). That'll also catch in-development errors like syntax errors.
This is the most important point to stress: block.style.left and block.style.top are not just numbers with implicit pixel values in them. Setting it to a number without a unit suffix will do absolutely nothing. You need to add % or px or whatever unit when setting left and top.
When getting the current value, as in var x = ... and var y = ..., you need to Number() manually to get the numeric portion of the string.
Also, I believe you meant || block == null, not =, which would set block to null.
Tips
You can use moveBlock instead of "moveBlock();" as an argument to setTimeout. This avoids parsing the string into code, and avoids scope problems (though not in this example as moveBlock is global).
I know that you have an array of values, where both x and y move 10 each time. I assume you want to move at a 45 degree angle. If so, this won't work as you expect even after fixing all the errors as x is percentage and y is in pixels.
You should declare your x and y above like your other variables. It may work but its confusing.
in your setTimeout, use moveBlock, not "moveBlock()" - it will save the step of evaluating your string into code.
block.style.left will return a string that includes "px" - it won't be a number. You can do:
x = Number(x);
//or
x = parseInt(x, 10);
When you set the position, remember to add the "px":
block.style.left = xPos[index] + "px";
EDIT:
Ok, the key problem is 'style.left' is not reading because it was set with CSS and not the style object. I use my library to get the style which runs through a few scenarios and catches that automatically. So change these lines to (this may not be exactly correct but will get things moving):
x = parseInt( node.style.left, 10 ) || 0;
y = parseInt( node.style.top, 10 ) || 0;
Also, this is wrong (you never declared 'self', and you don't need it here anyway; JS is case sensitive, SetInterval is not capped; pass the function, not the function result):
clockStep = self.SetInterval( moveBlock(), timerInterval ); // <-- result of moveBlock
// change to:
clockStep = setInterval( moveBlock, timerInterval ); // <-- the function moveBlock
During dev, you should remove the if() statements that could have been blocking the code and just put a simple count--; in there. It's really hard to debug code when you have literally 20 things wrong. Write a line, test. Write a line, test.
You have HTML comments in the script and style blocks. This is from 1998. While they don't hurt anything intact, in the past I've accidentally edited my code and removed one of them, and this will throw everything out of whack - your IDE, the browser - because they won't know what's wrong and you won't get a good error message.
LANGUAGE="JavaScript" is no longer used and is a waste of bytes.
To help speed development add this line:
window.onloadfunction(){
onBlockClick('block1')
}
That will execute your code right away for testing and you don't have to click every time.
Finally, I highly recommend you use Firefox and Firebug. Developing without it is like trying to build a ship in a bottle with boxing gloves. Using console.log(block.style.left) would have shown you it was not set. The error messages would have told you SetInterval and moveBlock() was incorrect. You do need to remember to remove the console.logs before production though. or... (shameless plug)... use my JavaScript Console Fix library which will do that for you: http://clubajax.org/javascript-console-fix-v2-now-with-ios/