I'm very new to HTML, CSS, and JavaScript. My darthVader character keeps on teleporting to the side of the screen any time I try to do any movement. I think this might be a problem with my CSS. Also I am open to any and all suggestions for changes for this project. Whether it is efficiency, layout, or any math involved in this project. Right now I'm just learning as I go instead of watching a hand holding tutorial.
//Global variables
let deathStar = document.querySelector(".deathStar")
let counter = 0;
let darthVader = document.querySelector(".darthVader");
let vaderX = window.scrollX darthVader.getBoundingClientRect().left;
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
//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 midPointX = (x2 x1) / 2;
let midPointY = (y2 y1) / 2;
let radius = x2 - midPointX - 10;
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();
}
//Storm Trooper Removal
document.addEventListener('click', (e) => {
//variable to check if type stormtrooper
let typeTrooper = e.target.className.split(" ")[0];
if(typeTrooper == "trooper"){
let stormTrooperChecker = document.querySelector("." e.target.className.split(" ")[1]);
stormTrooperChecker.remove();
}
alert(e.x);
console.log("Y: " e.y);
});
//Character Movement
document.addEventListener("keydown", function(e) {
if(e.key =='d'){
vaderX = 2;
darthVader.style.left = vaderX "px";
}
if(e.key =='a'){
vaderX -= 2;
darthVader.style.left = vaderX "px";
}
});
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: relative;
height: 7px;
width: 9px;
transform: translate(-5px, 1px);
background-color: black;
}
.gun{
position: relative;
display: flex;
height: 2px;
width: 10px;
background-color: black;
transform: translate(-5px, 10px)
}
.legSplit{
position: relative;
display: flex;
width: 1px;
height: 8px;
background-color: black;
transform: translate(-5px, 22px);
}
.darthVader{
display: flex;
position: absolute;
height: 30px;
width: 10px;
z-index: 3;
background-color: black;
}
<!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:
Because the initial values of vaderX
aren't the same as the X coordinate (or style.left
) of the darthVader
initial position.
getBoundingClientRect
returns the position relative to the viewport. The darthVader
element is inside an element with position: relative
. The value darthVader.style.left
is relative to the parent with a position
that is not static
.
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
The Element.getBoundingClientRect() method returns a DOMRect object providing information about the size of an element and its position relative to the viewport. (...) Properties other than width and height are relative to the top-left of the viewport.
https://developer.mozilla.org/en-US/docs/Web/CSS/position
absolute (...) It is positioned relative to its closest positioned ancestor, if any; otherwise, it is placed relative to the initial containing block. Its final position is determined by the values of top, right, bottom, and left.
https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block
The size and position of an element are often impacted by its containing block. Most often, the containing block is the content area of an element's nearest block-level ancestor, but this is not always the case. (...) The process for identifying the containing block depends entirely on the value of the element's position property (...)
You fix the issue if you replace:
let vaderX = window.scrollX darthVader.getBoundingClientRect().left;
with:
let vaderX = darthVader.offsetLeft;
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft
The HTMLElement.offsetLeft read-only property returns the number of pixels that the upper left corner of the current element is offset to the left within the HTMLElement.offsetParent node.