Show menus in upper half circle using javascript - 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)))

Related

JavaScript not placing object in correct mouse position

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>

Optimized solution for filling entire page with DIVs

I want to have a webpage whose entire viewable area is filled with divs. I am currently using the following code:
var wh= window.innerHeight;
var ww= window.innerWidth;
var area= wh * ww;
i= 1;
while(area > 0) {
document.getElementById("map").innerHTML+= "<div class='map-box' id='box" + i + "'></div>";
area-= 20 * 20;
i+=1;
}
.map-box {width: 20px; height: 20px; border-color: grey; border-width: 1px; border-style: solid; display: inline-block; margin: 0; padding: 0;}
<body>
<div id='map'></div>
</body>
If you try to use this code is your browser, you will see that there are two flaws in this:
First, it creates too many extra divs which go outside the viewable screen.
Second, this code is also somewhat slow.
Can someone here help me address both of these flaws and also optimize this code for faster performance?
1.) That <div> is not 20x20, because of the border:
let d = document.getElementById("test");
console.log(d.offsetWidth, d.offsetHeight);
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
<div id="test" class="map-box"></div>
2.) There's still the default border around the entire thing, and also some spacing between the lines:
var wh = window.innerHeight;
var ww = window.innerWidth;
var area = wh * ww;
i = 1;
while (area > 0) {
document.getElementById("map").innerHTML += "<div class='map-box' id='box" + i + "'></div>";
area -= 22 * 22; // hardcoding is not that nice
i += 1;
}
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
#map {
background: blue;
}
body {
background: red;
}
<div id='map'></div>
3.) Half cells are evil, so the width/height should be rounded downwards to a multiple of 22. Suddenly the grid is becoming an actual rectangle, at least in Chrome/Edge. The between-spacing is still a problem:
var wh = Math.floor(window.innerHeight / 22) * 22; // <--!!
var ww = Math.floor(window.innerWidth / 22) * 22; // <--!!
var area = wh * ww;
i = 1;
while (area > 0) {
document.getElementById("map").innerHTML += "<div class='map-box' id='box" + i + "'></div>";
area -= 22 * 22;
i += 1;
}
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
#map {
background: blue;
}
body {
background: red;
margin: 0; // <--!!
padding: 0; // <--!!
}
<div id='map'></div>
I don't actually know how to use line-height properly, this one works on my machine with my scaling/DPI, in Chrome/Edge, but that's all I can say about it. The 22-s are cut back, area now simply stores the number of <div>s to generate.
var wh = Math.floor(window.innerHeight / 22);
var ww = Math.floor(window.innerWidth / 22);
var area = wh * ww;
i = 1;
while (area > 0) {
document.getElementById("map").innerHTML += "<div class='map-box' id='box" + i + "'></div>";
area--;
i += 1;
}
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
#map {
line-height: 0.6;
}
body {
margin: 0;
padding: 0;
}
<div id='map'></div>
Instead of accessing dom element's inner html on each loop iteration - do it once after the loop with "prepared" data to set there
const wh = window.innerHeight;
const ww = window.innerWidth;
let area = wh * ww;
i = 1;
const ms = Date.now();
const divs = [];
while (area > 0) {
divs.push("<div class='map-box' id='box" + i + "'></div>");
area -= 20 * 20;
i += 1;
}
document.getElementById("map").innerHTML = divs.join("");
console.log("done fast", Date.now() - ms);
js fiddle with comparison https://jsfiddle.net/aL7zqwy9/
The final solution, not ideal but
<html>
<body>
<div id='map'></div>
</body>
<style>
body {
margin: 0;
padding: 0;
/* Overflow appears when last row is added and shrinks the "width" */
overflow-y: hidden;
}
#map {
/* To exclude space between rows */
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.map-box {
width: 20px;
height: 20px;
border: 1px solid grey;
display: block;
margin: 0;
padding: 0;
/* So border thickness will not affect element size */
box-sizing: border-box;
}
</style>
<script>
const cellSize = 20; // px
const wh = window.innerHeight;
const ww = window.innerWidth;
// not always divisible by cell size without a remainder
const columnsCount = Math.floor(ww / cellSize);
const rowsCount = Math.floor(wh / cellSize);
const cellsCount = columnsCount * rowsCount;
console.log(`wh: ${wh}, ww: ${ww}, cols: ${columnsCount}, rows: ${rowsCount}`);
const divs = [];
for (let i = 0; i < cellsCount; i++) {
divs.push(`<div class='map-box' id='box${i}'></div>`);
}
document.getElementById("map").innerHTML = divs.join("");
</script>
</html>

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.

My auto-generated "dots" stick to the bottom of the screen after a few seconds

So I have this site (http://mc.wordquest.nl/green/dots.html) and I want to make dots floating from the bottom of the page into the air. In the first few seconds, it works fine. But after a second or 5, the dots stay in their place.
Click here for the picture (of the problem)
The dots are supposed to float to 100px above the bottom of the page. I do this by using a CSS animation (maybe not the best way of doing things, but I can work with it...).
The code I use for the page:
window.setInterval(function() {
randomSquare();
}, 100);
var i = 0;
function randomSquare() {
//Set window height
var w = window.innerWidth;
var h = window.innerHeight;
//Set dot x-position
var x = Math.floor((Math.random() * w) + 1);
var y = Math.floor((Math.random() * h) + 1);
// Add a dot to follow the cursor
dot = document.createElement('div');
dot.className = "dot";
dot.style.left = x + "px";
dot.style.bottom = 10 + "px";
i++;
//Random color
var COLOURS = ['#69D2E7', '#A7DBD8', '#E0E4CC', '#F38630', '#FA6900', '#FF4E50', '#F9D423'];
// var color = "blue";
var color = COLOURS[Math.floor(Math.random() * COLOURS.length)];
dot.style.backgroundColor = color;
if (y < h * 0.97 && x < w * 0.97) {
document.body.appendChild(dot);
}
};
body {
height: 80%;
width: 90%;
font-family: Arial;
font-weight: Bold;
}
.dot {
width: 20px;
height: 20px;
background-color: green;
position: absolute;
color: white;
z-index: 1px;
border-radius: 50%;
animation: dots 2s linear;
}
#keyframes dots {
0% {
width: 20px;
height: 20px;
opacity: 1;
bottom: 0px;
}
100% {
/* opacity: 0; */
width: 0px;
height: 0px;
bottom: 100px;
}
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<style>
</style>
</head>
<body>
</body>
</html>
The problem is that after reaching 100% the properties you defined in your keyframes won't stay applied to your animation. In order to do that, you need to set animation-fill-mode: forwards;. What is more, it is important to notice that you infinitely adding elements to your DOM. That is a memory leak. Instead, after some time (animation completed) you should remove the element. (Or possibly have fixed number of dots, and re-use them) Consider following snippet, note that there is
setTimeout(function(){
dot.remove();
}, 2000)
Additionally, you forgot to add var keyword to dot variable, making it global.
window.setInterval(function() {
randomSquare();
}, 100);
var i = 0;
function randomSquare() {
//Set window height
var w = window.innerWidth;
var h = window.innerHeight;
//Set dot x-position
var x = Math.floor((Math.random() * w) + 1);
var y = Math.floor((Math.random() * h) + 1);
// Add a dot to follow the cursor
var dot = document.createElement('div');
dot.className = "dot";
dot.style.left = x + "px";
dot.style.bottom = 10 + "px";
i++;
//Random color
var COLOURS = ['#69D2E7', '#A7DBD8', '#E0E4CC', '#F38630', '#FA6900', '#FF4E50', '#F9D423'];
// var color = "blue";
var color = COLOURS[Math.floor(Math.random() * COLOURS.length)];
dot.style.backgroundColor = color;
if (y < h * 0.97 && x < w * 0.97) {
document.body.appendChild(dot);
}
setTimeout(function(){
dot.remove();
}, 2000)
};
body {
height: 80%;
width: 90%;
font-family: Arial;
font-weight: Bold;
}
.dot {
width: 20px;
height: 20px;
background-color: green;
position: absolute;
color: white;
z-index: 1px;
border-radius: 50%;
animation: dots 2s linear;
-webkit-animation-iteration-count: 1;
animation-fill-mode: forwards;
}
#keyframes dots {
0% {
width: 20px;
height: 20px;
opacity: 1;
bottom: 0px;
}
100% {
width: 0px;
height: 0px;
bottom: 100px;
}
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</body>
</html>
To let the elements maintain their style at the end of the animation, add:
.dot {
animation-fill-mode: forwards;
}

Html5 resizing object by dragging

I need to resize notes in my little application, but I don't know how. They have to be resized by dragging their bottom right corner and it must be done in pure java script.
Div with "+" adds new note and empty div is something like counter of all notes.
Code:
document.addEventListener("onload", Load());
var index = 0;
var cnt = 0;
var x = 0;
var y = 0;
var xx = 0;
var yy = 0;
var clicked = false;
var dragged = false;
var counter = 0;
var numberOfPapers = 0;
var state = 0;
function Load(){
var adder = document.querySelector("#add");
adder.setAttribute("onclick", "addClick()");
}
function addClick(){
cnt++;
numberOfPapers++;
document.querySelector("#counter").innerHTML = "Przebieg = " + cnt + "<br>" + "Liczba kartek = " + numberOfPapers;
var paper = document.createElement("div");
var paperX = document.createElement("div");
var paperR = document.createElement("div");
var paperS = document.createElement("div");
//papierek xD
paper.setAttribute("class", "paper");
paper.setAttribute("onmousedown", "movePaper(this,event)");
paper.setAttribute("onmouseup", "stop(this)");
paper.setAttribute("onmouseleave", "stop(this)");
paper.setAttribute("id", "id_" + cnt);
paper.style.top = "100px";
paper.style.left = "100px";
paper.style.zIndex = cnt;
//niszczyciel papierków
paperX.setAttribute("class", "deleter");
paperX.setAttribute("onclick", "deletePaper(this)");
//zmieniacz rozmiarów
paperR.setAttribute("class", "resizer");
paperR.ondragstart = function(e){
e.preventDefault();
};
paperR.setAttribute("onmousedown", "resize(this,event)");
//edytor tekstu tini emce
paperS.setAttribute("class", "txtEditor");
paperS.setAttribute("onclick", "editTxt()");
paper.appendChild(paperX);
paper.appendChild(paperR);
paper.appendChild(paperS);
document.body.appendChild(paper);
}
function stop(e){
e.setAttribute("onmousemove", null);
state = 1;
}
function resize(e,event){
state = 2;
}
function deletePaper(e){
e.parentElement.id = "del";
var del = document.querySelector("#del");
del.parentNode.removeChild(del);
numberOfPapers--;
document.querySelector("#counter").innerHTML = "Przebieg = " + cnt + "<br>" + "Liczba kartek = " + numberOfPapers;
}
function movePaper(e, event){
index++;
e.style.zIndex = index;
x = event.clientX;
y = event.clientY;
xx = e.style.left;
yy = e.style.top;
xx = xx.slice(0,xx.search("px"));
yy = yy.slice(0,yy.search("px"));
x = x - xx;
y = y - yy;
e.setAttribute("onmousemove","moreMove(this,event)");
}
function moreMove(e,event){
e.style.top = event.clientY - y + "px";
e.style.left = event.clientX - x + "px";
}
body{
margin: 0;
padding: 0;
}
#add{
position: absolute;
width: 45px;
height: 35px;
top: 25px;
right: 25px;
background-color: #F5574E;
text-align:center;
padding-top:10px;
border: solid black 1px;
}
#counter{
position: absolute;
width: 200px;
height: 45px;
top: 25px;
right: 80px;
background-color: #F5574E;
text-align:center;
border: solid black 1px;
}
.paper{
position: absolute;
width: 100px;
height: 100px;
top: 25px;
left: 25px;
background-color: #E3D67F;
border: solid black 1px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.deleter{
position: absolute;
width: 10px;
height: 10px;
top: 0px;
right: 0px;
background-color: red;
}
.resizer{
position: absolute;
width: 10px;
height: 10px;
bottom: 0px;
right: 0px;
background-color: green;
}
.txtEditor{
position: absolute;
width: 10px;
height: 10px;
top: 10px;
right: 0px;
background-color: yellow;
}
<body>
<div id="add">+
</div>
<div id="counter">
</div>
</body>
You can simply take replicate your move functions and instead of targeting top and left you target width and height of the parent node. Like this:
function resize(e, event) {
event.stopPropagation();//this to prevent move behavior to be triggered when clicking resize handle
state = 2;
index++;
e.style.zIndex = index;
x = event.clientX;
y = event.clientY;
xx = e.parentNode.style.width;
yy = e.parentNode.style.height;
xx = xx.slice(0, xx.search("px"));
yy = yy.slice(0, yy.search("px"));
x = x - xx;
y = y - yy;
e.setAttribute("onmousemove", "resizeMove(this,event)");
}
function resizeMove(e, event) {
console.log('resixe')
e.parentNode.style.height = event.clientY - y + "px";
e.parentNode.style.width = event.clientX - x + "px";
}
You'll have to declare width and height of your parentNode for it to work, you can add it to your paper section.
paper.style.width = "100px";
paper.style.height = "100px";

Categories