I have a stormTrooper characters randomly placed around my circle called deathStar. I am trying to make my stormTroopers place in the location that my mouse clicks once they have already been clicked. But instead they are placing in random locations. I'm still having problems grasping the concept of getBoundingClientRect() and offset. I thought adding them together and subtracting from mouseClick would be the solution. I'm also open to any other advice for this project. The area I'm having problems with is the mouseDown event listener.
//Global variables
let deathStar = document.querySelector(".deathStar")
let counter = 0;
let darthVader = document.querySelector(".darthVader");
let vaderX = darthVader.offsetLeft;
let vaderY = darthVader.offsetTop;
//Death Star information
const x1 = window.scrollX deathStar.getBoundingClientRect().left; // top left X
const y1 = window.scrollY deathStar.getBoundingClientRect().top; // top left Y
const x2 = window.scrollY deathStar.getBoundingClientRect().right; // bottom right X
const y2 = window.scrollY deathStar.getBoundingClientRect().bottom; // top right Y
let midPointX = (x2 x1) / 2;
let midPointY = (y2 y1) / 2;
let radius = x2 - midPointX - 10;
//Create a storm trooper
function createStormTrooper(){
colorArray = ['blue', 'green', 'orange', 'yellow', 'white', 'red','purple', 'pink'];
counter ;
//create each div
let stormTrooper = document.createElement('div');
let body = document.createElement('div');
let gun = document.createElement('div');
let head = document.createElement('div');
let legSplit = document.createElement('div');
//append div to proper div
deathStar.append(stormTrooper);
stormTrooper.append(body);
body.append(gun);
body.append(head);
body.append(legSplit);
//add classes
stormTrooper.classList.add("trooper",'stormTrooperPart' counter, "stormTrooper");
body.classList.add("trooper", 'stormTrooperPart' counter, "body");
gun.classList.add("trooper", 'stormTrooperPart' counter, "gun");
head.classList.add("trooper", 'stormTrooperPart' counter, 'head');
legSplit.classList.add("trooper", 'stormTrooperPart' counter, "legSplit");
let randomColor = Math.floor(Math.random()*8);
body.style.backgroundColor = colorArray[randomColor];
placeInsideDeathStar(stormTrooper);
}
//Places a trooper in a random spot inside the death star
function placeInsideDeathStar(stormTrooper){
let theta = Math.random() * Math.PI * 2;
let r = (Math.sqrt(Math.random()) * radius);
let yRandom = r * Math.sin(theta);
let xRandom = r * Math.cos(theta);
stormTrooper.style.transform = "translate(" (xRandom) "px," (yRandom) "px)";
}
//Create Troopers
for(let i = 0; i < 10;i ){
createStormTrooper();
}
let targetFound = false;
let stormTrooper;
//Storm Trooper placing and removing
document.addEventListener('mousedown', (e) => {
//variable to check if type stormtrooper
let typeTrooper = e.target.className.split(" ")[0];
//If type storm trooper of already have a target
if(typeTrooper == "trooper" || targetFound == true){
//if no stormTrooper found yet
if(targetFound == false){
stormTrooperChecker = document.querySelector("." e.target.className.split(" ")[1]);
targetFound = true;
}
//if stormTrooper found
else{
//Distance to move stormTrooper
var xposition = (e.clientX - stormTrooperChecker.getBoundingClientRect().left stormTrooperChecker.offsetLeft);
var yposition = (e.clientY - stormTrooperChecker.getBoundingClientRect().top stormTrooperChecker.offsetTop);
//Move Storm Trooper
stormTrooperChecker.style.transform = "translate(" (xposition) "px," yposition "px)";
//Check if outside of death star
if(pTheoremAB(stormTrooperChecker.offsetTop, stormTrooperChecker.offsetLeft) > pTheoremC(radius) || pTheoremAB(stormTrooperChecker.offsetTop, stormTrooperChecker.offsetLeft) < -pTheoremC(radius)){
stormTrooperChecker.classList.add("explosion")
stormTrooperChecker.innerHTML = "";
setTimeout(() => stormTrooperChecker.remove(), 1000);
}
//reset targetFound
targetFound = false;
}
//stormTrooperChecker.remove();
}
});
//P theorem
function pTheoremAB(a,b){
return ((a * a) (b * b));
}
function pTheoremC(c){
return c * c;
}
function wDown(){
vaderY -= 2;
darthVader.style.top = vaderY "px";
if(-pTheoremAB((vaderX - 345),(vaderY - 335)) <= -pTheoremC(radius)){
vaderY =2
}
}
function sDown(){
vaderY = 2;
darthVader.style.top = vaderY "px";
if(pTheoremAB((vaderX - 345),(vaderY - 335)) >= pTheoremC(radius)){
vaderY -= 2;
}
}
function aDown(){
vaderX -= 2;
darthVader.style.left = vaderX "px";
if(-pTheoremAB((vaderX - 345),(vaderY - 335)) <= -pTheoremC(radius)){
vaderX = 2;
}
}
function dDown(){
vaderX = 2;
darthVader.style.left = vaderX "px";
if(pTheoremAB((vaderX - 345),(vaderY - 335)) >= pTheoremC(radius)){
vaderX -= 2;
}
}
const controller = {
'w': {pressed: false},
'a': {pressed: false},
's': {pressed: false},
'd': {pressed: false},
}
document.addEventListener("keydown", (e) => {
if(controller[e.key]){
controller[e.key].pressed = true
}
if(controller['w'].pressed){
wDown();
}
if(controller['a'].pressed){
aDown();
}
if(controller['s'].pressed){
sDown();
}
if(controller['d'].pressed){
dDown();
}
})
document.addEventListener("keyup", (e) => {
if(controller[e.key]){
controller[e.key].pressed = false
}
})
body{
border: 0;
background: black;
display: flex;
align-items: center;
justify-content: center;
}
.deathStar {
position: relative;
display:flex;
height: 700px;
width: 700px;
border-radius: 50%;
background-color: darkgrey;
top: 50%;
align-items: center;
justify-content: center;
}
.hole{
display: flex;
height: 100px;
width: 50px;
border-radius: 50%;
background-color: gray;
top: 50%;
transform: translateX(-60PX);
}
.stormTrooper{
display: flex;
position: absolute;
z-index: 2;
}
.body{
display: flex;
position: relative;
height: 30px;
width: 10px;
z-index: 2;
}
.head{
display: flex;
position: absolute;
height: 7px;
width: 7px;
transform: translate(0, 1px);
background-color: black;
}
.gun{
position: absolute;
display: flex;
height: 2px;
width: 10px;
background-color: black;
transform: translate(-9px, 10px)
}
.legSplit{
position: absolute;
display: flex;
width: 1px;
height: 8px;
background-color: black;
transform: translate(4px, 22px);
}
.darthVader{
display: flex;
position: absolute;
height: 30px;
width: 10px;
z-index: 3;
background-color: black;
}
.explosion{
position: absolute;
display: flex;
height: 0px;
width: 0px;
border-radius: 50%;
background-color: red;
transform: translate(80px, 80px);
animation-duration: 1s;
animation-name: move;
}
@keyframes move {
25% {
width: 10px;
height: 10px;
}
50% {
width: 20px;
height: 20px;
}
75% {
width: 30px;
height: 30px;
}
100% {
width: 40px;
height: 40px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div id="deathStar">
<div ></div>
</div>
<div ></div>
<script src="main.js"></script>
</body>
</html>
CodePudding user response:
The translate
positioning is relative to the Death Star element's center, so I updated that.
translate
does not affect offsetTop/Left
, so your "in Death Star" logic was failing. I fixed that.
Also, you do not need to adjust for the scroll position (comes into effect only when scrolled). I fixed that.
Lastly, I had to put in some code in the handler to calculate the new midpoint of the Death Star element, as you only calculated it on initialization (it should be recalcuated on every use).
//Global variables
let deathStar = document.querySelector(".deathStar")
let counter = 0;
let darthVader = document.querySelector(".darthVader");
let vaderX = darthVader.offsetLeft;
let vaderY = darthVader.offsetTop;
//Death Star information
const x1 = deathStar.getBoundingClientRect().left; // top left X
const y1 = deathStar.getBoundingClientRect().top; // top left Y
const x2 = deathStar.getBoundingClientRect().right; // bottom right X
const y2 = deathStar.getBoundingClientRect().bottom; // top right Y
let midPointX = (x2 x1) / 2;
let midPointY = (y2 y1) / 2;
let radius = x2 - midPointX - 10;
//Create a storm trooper
function createStormTrooper(){
colorArray = ['blue', 'green', 'orange', 'yellow', 'white', 'red','purple', 'pink'];
counter ;
//create each div
let stormTrooper = document.createElement('div');
let body = document.createElement('div');
let gun = document.createElement('div');
let head = document.createElement('div');
let legSplit = document.createElement('div');
//append div to proper div
deathStar.append(stormTrooper);
stormTrooper.append(body);
body.append(gun);
body.append(head);
body.append(legSplit);
//add classes
stormTrooper.classList.add("trooper",'stormTrooperPart' counter, "stormTrooper");
body.classList.add("trooper", 'stormTrooperPart' counter, "body");
gun.classList.add("trooper", 'stormTrooperPart' counter, "gun");
head.classList.add("trooper", 'stormTrooperPart' counter, 'head');
legSplit.classList.add("trooper", 'stormTrooperPart' counter, "legSplit");
let randomColor = Math.floor(Math.random()*8);
body.style.backgroundColor = colorArray[randomColor];
placeInsideDeathStar(stormTrooper);
}
//Places a trooper in a random spot inside the death star
function placeInsideDeathStar(stormTrooper){
let theta = Math.random() * Math.PI * 2;
let r = (Math.sqrt(Math.random()) * radius);
let yRandom = r * Math.sin(theta);
let xRandom = r * Math.cos(theta);
stormTrooper.style.transform = "translate(" (xRandom) "px," (yRandom) "px)";
}
//Create Troopers
for(let i = 0; i < 10;i ){
createStormTrooper();
}
let targetFound = false;
let stormTrooper;
//Storm Trooper placing and removing
document.addEventListener('mousedown', (e) => {
//variable to check if type stormtrooper
let typeTrooper = e.target.className.split(" ")[0];
//If type storm trooper of already have a target
if(typeTrooper == "trooper" || targetFound == true){
//if no stormTrooper found yet
if(targetFound == false){
stormTrooperChecker = document.querySelector("." e.target.className.split(" ")[1]);
targetFound = true;
}
//if stormTrooper found
else{
//Distance to move stormTrooper
const x1 = deathStar.getBoundingClientRect().left; // top left X
const y1 = deathStar.getBoundingClientRect().top; // top left Y
const x2 = deathStar.getBoundingClientRect().right; // bottom right X
const y2 = deathStar.getBoundingClientRect().bottom; // top right Y
let midPointX = (x2 x1) / 2;
let midPointY = (y2 y1) / 2;
var xposition = (e.clientX - midPointX);
var yposition = (e.clientY - midPointY);
//Move Storm Trooper
stormTrooperChecker.style.transform = "translate(" (xposition) "px," yposition "px)";
//Check if outside of death star
if(pTheoremAB(yposition, xposition) > pTheoremC(radius) || pTheoremAB(yposition, xposition) < -pTheoremC(radius)){
stormTrooperChecker.classList.add("explosion")
stormTrooperChecker.innerHTML = "";
setTimeout(() => stormTrooperChecker.remove(), 1000);
}
//reset targetFound
targetFound = false;
}
//stormTrooperChecker.remove();
}
});
//P theorem
function pTheoremAB(a,b){
return ((a * a) (b * b));
}
function pTheoremC(c){
return c * c;
}
function wDown(){
vaderY -= 2;
darthVader.style.top = vaderY "px";
if(-pTheoremAB((vaderX - 345),(vaderY - 335)) <= -pTheoremC(radius)){
vaderY =2
}
}
function sDown(){
vaderY = 2;
darthVader.style.top = vaderY "px";
if(pTheoremAB((vaderX - 345),(vaderY - 335)) >= pTheoremC(radius)){
vaderY -= 2;
}
}
function aDown(){
vaderX -= 2;
darthVader.style.left = vaderX "px";
if(-pTheoremAB((vaderX - 345),(vaderY - 335)) <= -pTheoremC(radius)){
vaderX = 2;
}
}
function dDown(){
vaderX = 2;
darthVader.style.left = vaderX "px";
if(pTheoremAB((vaderX - 345),(vaderY - 335)) >= pTheoremC(radius)){
vaderX -= 2;
}
}
const controller = {
'w': {pressed: false},
'a': {pressed: false},
's': {pressed: false},
'd': {pressed: false},
}
document.addEventListener("keydown", (e) => {
if(controller[e.key]){
controller[e.key].pressed = true
}
if(controller['w'].pressed){
wDown();
}
if(controller['a'].pressed){
aDown();
}
if(controller['s'].pressed){
sDown();
}
if(controller['d'].pressed){
dDown();
}
})
document.addEventListener("keyup", (e) => {
if(controller[e.key]){
controller[e.key].pressed = false
}
})
body{
border: 0;
background: black;
display: flex;
align-items: center;
justify-content: center;
}
.deathStar {
position: relative;
display:flex;
height: 700px;
width: 700px;
border-radius: 50%;
background-color: darkgrey;
top: 50%;
align-items: center;
justify-content: center;
}
.hole{
display: flex;
height: 100px;
width: 50px;
border-radius: 50%;
background-color: gray;
top: 50%;
transform: translateX(-60PX);
}
.stormTrooper{
display: flex;
position: absolute;
z-index: 2;
}
.body{
display: flex;
position: relative;
height: 30px;
width: 10px;
z-index: 2;
}
.head{
display: flex;
position: absolute;
height: 7px;
width: 7px;
transform: translate(0, 1px);
background-color: black;
}
.gun{
position: absolute;
display: flex;
height: 2px;
width: 10px;
background-color: black;
transform: translate(-9px, 10px)
}
.legSplit{
position: absolute;
display: flex;
width: 1px;
height: 8px;
background-color: black;
transform: translate(4px, 22px);
}
.darthVader{
display: flex;
position: absolute;
height: 30px;
width: 10px;
z-index: 3;
background-color: black;
}
.explosion{
position: absolute;
display: flex;
height: 0px;
width: 0px;
border-radius: 50%;
background-color: red;
transform: translate(80px, 80px);
animation-duration: 1s;
animation-name: move;
}
@keyframes move {
25% {
width: 10px;
height: 10px;
}
50% {
width: 20px;
height: 20px;
}
75% {
width: 30px;
height: 30px;
}
100% {
width: 40px;
height: 40px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div id="deathStar">
<div ></div>
</div>
<div ></div>
<script src="main.js"></script>
</body>
</html>