Home > Blockchain >  JavaScript not placing object in correct mouse position
JavaScript not placing object in correct mouse position

Time:08-04

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>

  • Related