JavaScript not placing object in correct mouse position - javascript

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 class="deathStar" id="deathStar">
<div class="darthVader"></div>
</div>
<div class="hole"></div>
<script src="main.js"></script>
</body>
</html>

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 class="deathStar" id="deathStar">
<div class="darthVader"></div>
</div>
<div class="hole"></div>
<script src="main.js"></script>
</body>
</html>

Related

why I am getting nodelist empty when I am trying to get lines by let lines = document.querySelectorAll('.line');

'use strict';
const score = document.querySelector('.score');
const popup = document.querySelector('.popup');
const gameArea = document.querySelector('.gameArea');
const gameBoard = document.querySelector('.gameBoard');
let player = { speed: 5, start: false };
let keys = {
ArrowUp: false,
ArrowDown: false,
ArrowLeft: false,
ArrowRight: false,
};
gameBoard.addEventListener('click', start);
document.addEventListener('keydown', keyDown);
document.addEventListener('keyup', keyUp);
function keyDown(e) {
e.preventDefault();
keys[e.key] = true;
// console.log(keys);
}
function keyUp(e) {
e.preventDefault();
keys[e.key] = false;
// console.log(keys);
}
function gamePlay() {
console.log('game started');
let car = document.querySelector('.car');
let carD = car.getBoundingClientRect();
let road = gameArea.getBoundingClientRect();
if (player.start) {
if (keys.ArrowDown && player.y < road.height - carD.height)
player.y += player.speed;
if (keys.ArrowUp && player.y > road.height * 0.3) player.y -= player.speed;
if (keys.ArrowLeft && player.x > 0) player.x -= player.speed;
if (keys.ArrowRight && player.x < road.width - carD.width)
player.x += player.speed;
car.style.top = player.y + 'px';
car.style.left = player.x + 'px';
window.requestAnimationFrame(gamePlay);
}
}
function movesLines() {
let lines = document.querySelectorAll('.line');
console.log(lines);
lines.forEach(function (item) {
item.y += player.speed;
item.style.top = item.y + 'rem';
});
}
function start() {
if (player.start) return;
movesLines();
popup.classList.add('hide');
player.start = true;
window.requestAnimationFrame(gamePlay);
for (let i = 0; i < 6; i++) {
let roadLine = document.createElement('div');
roadLine.setAttribute('class', 'line');
roadLine.y = i * 15;
roadLine.style.top = roadLine.y + 'rem';
gameArea.appendChild(roadLine);
}
let car = document.createElement('div');
car.setAttribute('class', 'car');
gameArea.appendChild(car);
player.x = car.offsetLeft;
player.y = car.offsetTop;
// console.log('top position' + car.offsetTop);
// console.log('Left position' + car.offsetLeft);
}
/*
SPACING SYSTEM (px)
2 / 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 80 / 96 / 128
FONT SIZE SYSTEM (px)
10 / 12 / 14 / 16 / 18 / 20 / 24 / 30 / 36 / 44 / 52 / 62 / 74 / 86 / 98
*/
* {
margin:0;
padding:0;
box-sizing: border-box;
}
html{
font-size: 62.5%;
}
.gameBoard {
display: flex;
background-color: lightgreen;
overflow-x: hidden;
overflow-y: hidden;
}
.score {
position: absolute;
top: 1rem;
left: 1rem;
width: 10rem;
height: 5rem;
border: 2px solid green;
}
.popup {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%);
color: black;
font-weight: bold;
padding: 2rem;
border-radius: 11px;
background-color: #777;
z-index: 999;
}
.gameArea {
position: relative;
width: 40vw;
height: 100vh;
background-color: #333;
margin-left: auto;
margin-right: auto;
}
.car {
position: absolute;
bottom: 1rem;
width: 8rem;
height: 10rem;
background-color: red;
}
.enemy {
position: absolute;
bottom: 1rem;
width: 8rem;
height: 10rem;
background-color: blue;
}
.line {
position: absolute;
width: 1rem;
height: 10rem;
background-color: white;
left: 50%;
transform: translateX(-50%);
}
.hide {
display: none;
}
<!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>Game</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="gameBoard">
<div class="score"></div>
<div class="popup">
Click or Press any arrow to start!!
</div>
<div class="gameArea"></div>
</div>
<script src="./script.js"></script>
</body>
</html>
function movesLines() {
let lines = document.querySelectorAll('.line');
console.log(lines);
lines.forEach(function (item) {
item.y += player.speed;
item.style.top = item.y + 'rem';
});
};
here this lines is resulting into an empty nodelist, I am not able to rectify why this is happening actually this function is used to move road lines again and again so that it looks that like that car is going ahead...
here this lines is resulting into an empty nodelist, I am not able to rectify why this is happening actually this function is used to move road lines again and again so that it looks that like that car is going ahead...
here this lines is resulting into an empty nodelist, I am not able to rectify why this is happening actually this function is used to move road lines again and again so that it looks that like that car is going ahead...
Because the movesLines function is executed before you insert the .line elements in the DOM, in the start function.
movesLines();
popup.classList.add('hide');
player.start = true;
window.requestAnimationFrame(gamePlay);
for (let i = 0; i < 6; i++) {
let roadLine = document.createElement('div');
roadLine.setAttribute('class', 'line');
roadLine.y = i * 15;
roadLine.style.top = roadLine.y + 'rem';
gameArea.appendChild(roadLine);
}

i want to join these two vertical lines with my custom cursor starting and ending which is a line(horizontal)

<!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>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
perspective: 500px;
perspective-origin: top;
transform-style: preserve-3d;
width: 100%;
height: 100vh;
background: black;
position: relative;
}
.cursor {
position: absolute;
width: 8rem;
height: 3px;
border-radius: 10px;
background: white;
z-index: 11;
left: -50px;
top: 30px;
transform-style: preserve-3d;
transform: translateZ(100px) rotateX(-0deg);
}
.follow_cursor {
position: absolute;
background: white;
width: 2px;
height: 5rem;
z-index: 2;
top: 100%;
left: 0%;
right: 0;
transform-origin: top;
backdrop-filter: blur(20px);
}
.follow_cursor2 {
position: absolute;
background: white;
width: 2px;
height: 2rem;
z-index: 3;
top: 100%;
left: 100%;
right: 0px;
transform-origin: top;
backdrop-filter: blur(20px);
}
</style>
</head>
<body>
<!-- this div need to be fixed -->
<div class="follow_cursor"></div>
<div class="follow_cursor2"></div>
<div class="cursor"></div>
</body>
<script>
let cursor = document.querySelector(".cursor");
let main = document.querySelector(".main");
const follow = document.querySelector(".follow_cursor");
const follow_2 = document.querySelector(".follow_cursor2");
const origR = follow.getBoundingClientRect();
const origR_2 = follow_2.getBoundingClientRect();
document.onmousemove = (e) => {
let x = e.pageX;
let y = e.pageY;
cursor.style.transform = `translate3d(${x}px, ${y}px , 0)`;
// calculate distance and angle.
let xf = origR.left + origR.width / 2;
let x2f = origR_2.left + origR_2.width / 2;
let yf = origR.top;
let y2f = origR_2.top;
// // distance to cursor from follow
let dist = Math.sqrt((xf - x) * (xf - x) + (yf - y) * (yf - y));
let dist2 = Math.sqrt((x2f - x) * (x2f - x) + (y2f - y) * (y2f - y));
// console.log(dist)
var angle = 0;
var angle2 = 0;
// get the rotation angle
angle = 90 + (Math.atan2(yf - y, xf - x) * 180) / Math.PI;
angle2 = 90 + (Math.atan2(y2f - y, x2f - x) * 180) / Math.PI;
follow.style.transform =
"rotateZ(" + angle + "deg) scaleY(" + dist / origR.height + ")";
follow_2.style.transform =
"rotateZ(" + angle2 + "deg) scaleY(" + dist2 / origR_2.height + ")";
};
</script>
</html>
i am trying to join the vertical lines with my custom cursor but its not working.
i need to join these cursor ending with these vertical line endings.
the link of this image given below
you can run the snippets and check the image to take the refrence what i am trying to do.
i will be thankful if you will help me.
my communication skill are not good hope you will understand
i want this lines to look like this in the image
Your code was hard to read, but I think the transform: translateZ() in the initial css had to do with the error.
I've made you a working example containing 3 elements: the lines and the custom cursor.
I calculate the window height (win_H) and width (win_W) and the width of the custom cursor (myc_W).
The lines are fixed at the left and right bottom of the window, touching at the left and right corner of the custom pointer. From there it's simply maths: calculate the triangles (Pythagoras c2=a2+b2) and the angles (note the angles are in radials, not degrees!).
<!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>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
perspective: 500px;
perspective-origin: top;
transform-style: preserve-3d;
width: 100%;
height: 100vh;
background: black;
position: relative;
}
#my_cursor {
position: absolute;
width: 8rem;
height: 3px;
border-radius: 10px;
background: white;
left: 0px;
top: 0px;
}
#line_1{
position: absolute;
background: white;
width: 2px;
height: 100%;
bottom: 0;
left: 0;
transform-origin: bottom left;
backdrop-filter: blur(20px);
}
#line_2{
position: absolute;
background: white;
width: 2px;
height: 100%;
bottom: 0;
right: 0;
transform-origin: bottom right;
backdrop-filter: blur(20px);
}
</style>
</head>
<body>
<div id="line_1"></div>
<div id="line_2"></div>
<div id="my_cursor"></div>
</body>
<script>
let
my_cursor = document.getElementById("my_cursor"),
line_1 = document.getElementById("line_1"),
line_2 = document.getElementById("line_2"),
win_W=window.innerWidth,
win_H=window.innerHeight,
myc_W=(my_cursor.getBoundingClientRect().width)/2
;
//SET STARTING POSITION in middle of screen
_calculate( (win_W/2), (win_H/2));
document.onmousemove = (e) => {
_calculate( e.pageX, e.pageY);
}
function _calculate(mouseX,mouseY){
//CUSTOM CURSOR position:
let myc_XL = mouseX - myc_W,
myc_XR = mouseX + myc_W,
myc_Y = mouseY;
my_cursor.style.transform = `translate3d(${myc_XL}px, ${myc_Y}px , 0)`;
let a,b,c,angle;
//LINE 1
a = myc_XL;
b = win_H - mouseY;
c = Math.sqrt((a*a)+(b*b));
angle = Math.asin( a /c );
line_1.style.transform = "rotateZ(" + angle + "rad) scaleY(" + (c/win_H) + ")";
//LINE 2
a = win_W - myc_XR;
c = Math.sqrt((a*a)+(b*b));
angle = Math.asin( a / c );
line_2.style.transform = "rotateZ(" + (-angle) + "rad) scaleY(" + (c/win_H) + ")";
};
</script>
</html>

How to rotate a box div while dragging an element using jquery

I understand that we need to use transform: rotate(ndeg); in order to rotate a specific element in CSS. In this case, I want to do it dynamically. Using jQuery, I want to rotate the box/container div when the user drags the handle (the red background) on n degrees as the user wishes. Is it possible in jQuery?
body {
padding: 50px;
}
.box_element {
border: 1px solid black;
width: 200px;
height: 200px;
position: relative;
z-index: -1;
}
.handle {
position: absolute;
bottom: -10px;
right: -10px;
width: 10px;
height: 10px;
border: 1px solid;
background: red;
z-index: 10;
}
<body>
<div class="box_element">
THIS IS TEST
<div class="handle"></div>
</div>
</body>
Here you need to write few code to make it possible, try live code https://codepen.io/libin-prasanth/pen/xxxzbLg
var stop,
active = false,
angle = 0,
rotation = 0,
startAngle = 0,
center = {
x: 0,
y: 0
},
R2D = 180 / Math.PI;
function start(e) {
e.preventDefault();
var bb = this.getBoundingClientRect(),
t = bb.top,
l = bb.left,
h = bb.height,
w = bb.width,
x,
y;
center = {
x: l + w / 2,
y: t + h / 2
};
x = e.clientX - center.x;
y = e.clientY - center.y;
startAngle = R2D * Math.atan2(y, x);
return (active = true);
}
function rotate(e) {
e.preventDefault();
var x = e.clientX - center.x,
y = e.clientY - center.y,
d = R2D * Math.atan2(y, x);
rotation = d - startAngle;
return (rot.style.webkitTransform = "rotate(" + (angle + rotation) + "deg)");
}
function stop() {
angle += rotation;
return (active = false);
}
rot = document.getElementById("draggable");
rot.addEventListener("mousedown", start, false);
window.addEventListener("mousemove", function(event) {
if (active === true) {
event.preventDefault();
rotate(event);
}
});
window.addEventListener("mouseup", function(event) {
event.preventDefault();
stop(event);
});
#draggable {
left: 50px;
top: 50px;
width: 100px;
height: 100px;
position: relative;
border: 1px solid #000;
}
#draggable:before{
content: "";
position: absolute;
bottom: -5px;
right: -5px;
width: 10px;
height: 10px;
background: #f00;
}
<div id="draggable">
</div>
You can make use of a css-variable and then change the value of the variable when clicked.
const box_element = document.getElementById('box_element');
const handle = document.getElementById('handle');
handle.addEventListener('click', function() {
let currentVal = getComputedStyle(box_element).getPropertyValue('--rotate_deg');
box_element.style.setProperty(
'--rotate_deg', ((parseInt(currentVal.replace('deg', '')) + 90) % 360) + 'deg');
});
:root {
--rotate_deg: 0deg;
}
.box_element {
margin: 1em;
border: 1px solid black;
width: 100px;
height: 100px;
position: relative;
z-index: -1;
transform: rotate(var(--rotate_deg))
}
.handle {
position: absolute;
bottom: -10px;
right: -10px;
width: 10px;
height: 10px;
border: 1px solid;
background: red;
z-index: 10;
cursor: pointer;
}
<div class="box_element" id="box_element">
THIS IS TEST
<div class="handle" id="handle"></div>
</div>

Getting distance to be 0

I want this div to go from point A to point B and vice-versa. Problem is the dist variable (distance) never gets to 0, it is usually either 1 or -1 (or some other range of values), which results in the div getting stuck and not going anywhere. In my complete code, point A and B positions are randomized every time I open the page.
The example below is reproducing the problem. To see it working as intended set #pointA { top: 5px; left: 5px; } | #pointB { top: 5px; left: 105px; }
var score = 0, points = 0, boxMode = 0, speed, speedX, speedY, angleRadians,
distX, distY, dist;
var destinationX = $("#pointB").position().left;
var destinationY = $("#pointB").position().top;
var pointAPos = $("#pointA").position();
var pointAx = pointAPos.left;
var pointAy = pointAPos.top;
var pointBPos = $("#pointB").position();
var pointBx = pointBPos.left;
var pointBy = pointBPos.top;
var boxPos = $('#box').position();
var boxX = pointAx;
var boxY = pointAy;
function calculateDistance(x, y) {
distX = boxX - x;
distY = boxY - y;
dist = Math.sqrt((distX*distX)+(distY*distY));
}
function boxMove() {
angleRadians = Math.atan2(-distX, -distY);
speed = 2;
speedX = speed * Math.sin(angleRadians);
speedY = speed * Math.cos(angleRadians);
document.getElementById("box").style.left = boxX + "px";
document.getElementById("box").style.top = boxY + "px";
boxX += speedX;
boxY += speedY;
}
function boxAI() {
calculateDistance(destinationX, destinationY);
if (!dist == 0) {
boxMove();
} else {
if (boxMode == 0) {
points += 1;
if (points == 50) {
// change destination to point A
destinationX = pointAx;
destinationY = pointAy;
boxMode = 1;
}
} else {
// change destination to point B
destinationX = pointBx;
destinationY = pointBy;
score += points;
points = 0;
boxMode = 0;
}
}
}
function mainLoop() {
boxAI();
$("#debug").html(points + " " + score + " " + boxMode);
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
#levelWrapper {
position: relative;
width: 400px;
height: 150px;
top: 2px;
margin: auto;
border: 1px solid red;
}
#pointA {
position: absolute;
background: beige;
width: 45px;
height: 45px;
top: 3px;
left: 50px;
margin: auto;
}
#pointB {
position: absolute;
background: beige;
width: 45px;
height: 45px;
top: 45px;
left: 195px;
margin: auto;
}
#box {
position: absolute;
background: black;
height: 5px;
width: 5px;
}
#debug {
position: relative;
background: white;
width: 250px;
height: 120px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="debug"></div>
<div id="levelWrapper">
<div id="pointA">A</div>
<div id="pointB">B</div>
<div id="box"></div>
</div>
<script src="jquery-3.2.1.js"></script>
<script type="text/javascript" src="woods_2.js"></script>
</body>
In JavaScript the ! operator has precedence over the ==, so if (dist != 0) would already be an improvement.
But as you use a speed variable which determines the difference between two consecutive measurements of the distance, you should make your test accordingly, and see if the distance is one step removed from zero:
if (dist >= speed)
Here is your code with some changes:
var score = 0, points = 0, boxMode = 0, speed, speedX, speedY, angleRadians,
distX, distY, dist;
var destinationX = $("#pointB").position().left;
var destinationY = $("#pointB").position().top;
var pointAPos = $("#pointA").position();
var pointAx = pointAPos.left;
var pointAy = pointAPos.top;
var pointBPos = $("#pointB").position();
var pointBx = pointBPos.left;
var pointBy = pointBPos.top;
var boxPos = $('#box').position();
var boxX = pointAx;
var boxY = pointAy;
var speed = 2; // make speed visible to other functions
function calculateDistance(x, y) {
distX = boxX - x;
distY = boxY - y;
dist = Math.sqrt((distX*distX)+(distY*distY));
}
function boxMove() {
angleRadians = Math.atan2(-distX, -distY);
speedX = speed * Math.sin(angleRadians);
speedY = speed * Math.cos(angleRadians);
document.getElementById("box").style.left = boxX + "px";
document.getElementById("box").style.top = boxY + "px";
boxX += speedX;
boxY += speedY;
}
function boxAI() {
calculateDistance(destinationX, destinationY);
// As the distance makes jumps of <speed> units,
// check whether it is within one step of the target
if (dist >= speed) {
boxMove();
} else {
score++; // Not sure what score should be measuring
if (boxMode == 0) {
// Change destination to point A
destinationX = pointAx;
destinationY = pointAy;
boxMode = 1;
} else {
// Change destination to point B
destinationX = pointBx;
destinationY = pointBy;
boxMode = 0;
}
}
}
function mainLoop() {
boxAI();
$("#debug").html(points + " " + score + " " + boxMode);
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
#levelWrapper {
position: relative;
width: 400px;
height: 150px;
top: 2px;
margin: auto;
border: 1px solid red;
}
#pointA {
position: absolute;
background: beige;
width: 45px;
height: 45px;
top: 3px;
left: 50px;
margin: auto;
}
#pointB {
position: absolute;
background: beige;
width: 45px;
height: 45px;
top: 45px;
left: 195px;
margin: auto;
}
#box {
position: absolute;
background: black;
height: 5px;
width: 5px;
}
#debug {
position: relative;
background: white;
width: 250px;
height: 120px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="debug"></div>
<div id="levelWrapper">
<div id="pointA">A</div>
<div id="pointB">B</div>
<div id="box"></div>
</div>
I did not understand what you wanted to do with score and points, so you will need to modify the code in that respect. For now I removed the changes to the points variable, and only increased score with every bounce.

Show menus in upper half circle using javascript

I am using following link to show menus
http://codepen.io/anon/pen/dWdJbV
But I want to show them only in upper half circle. Even menu count changes it should use only upper half circle.
Js code
var items = document.querySelectorAll('.circle a');
for(var i = 0, l = items.length; i < l; i++) {
items[i].style.left = (50 - 35*Math.cos(-0.5 * Math.PI - 2*(2/l)*i*Math.PI)).toFixed(4) + "%";
items[i].style.top = (50 + 35*Math.sin(-0.5 * Math.PI - 2*(5/l)*i*Math.PI)).toFixed(4) + "%";
}
document.querySelector('.menu-button').onclick = function(e) {
e.preventDefault(); document.querySelector('.circle').classList.toggle('open');
}
I tried by changing values sin sin and cos but not getting required output
Here is the quick demo :
var isOn = false;
$('#menu-button').click(function() {
if(isOn) {
reset();
} else {
setPosition();
}
});
function setPosition() {
isOn = true;
var links = $('#menu-button a');
var radius = (links.length * links.width()) / 2;
var degree = Math.PI / links.length, angle = degree / 2;
links.each(function() {
var x = Math.round(radius * Math.cos(angle));
var y = Math.round(radius * Math.sin(angle));
$(this).css({
left: x + 'px',
top: -y + 'px'
});
angle += degree;
});
}
function reset() {
$('#menu-button a').css({
left: 0 + 'px',
top: 0 + 'px'
});
isOn = false;
}
body {
margin: 0;
background: #39D;
}
#menu-button:before {
position: absolute;
top: 0; left: 0;
width: 50px;
height: 50px;
background: #dde;
cursor: pointer;
text-align: center;
line-height: 50px;
color: #444;
border-radius:50%;
content:"\f0c9"; font: normal normal normal 14px/1 FontAwesome;
font-size:26px;
}
#menu-button {
position: absolute;
margin: auto;
top: 150px; left: 0; right: 0;
width: 50px;
height: 50px;
cursor: pointer;
text-align: center;
}
#menu-button > a {
position: absolute;
display: block;
width: 50px;
height: 50px;
-webkit-transition: top .5s, left .5s;
-moz-transition: top .5s, left .5s;
text-align: center;
text-decoration: none;
line-height: 50px;
color: #EBEAE8;
z-index: -1;
border-radius:50%;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Demo by http://creative-punch.net -->
<div id="menu-button" class="entypo-menu">
</div>
I made this changes in you example for displaying items only in top part of circle:
var items = document.querySelectorAll('.circle a');
var angle = 0;
var step = (Math.PI) / items.length;
for(var i = 0, l = items.length; i < l; i++) {
items[i].style.left = (50 - 35*Math.cos(angle).toFixed(4)) + "%";
items[i].style.top = (50 + 35* (-Math.abs(Math.sin(angle)))).toFixed(4) + "%";
angle += step;
}
So you need only angles from 0 to 180 degrees. That's why i use (-Math.abs(Math.sin(angle)))

Categories