1

I want to make a random number of balls appear in the window, and for them to move in random directions at random speeds. I got just one ball to work, but in advancing to multiple balls, I tried to learn about ES6 classes, and I'm stuck. I tried a bunch of different ways to create the class Ball for each element of the array holding arrays of random coordinates, speeds, and directions, and I looked at the docs, and in Stackoverflow, and I'm still confused. I really want to understand what's happening with ES6 classes because all the new React stuff is written in ES6 syntax, and I didn't have to worry about this.myMethod.bind(this) before, but now I do, and it's all pretty overwhelming. If anyone wants to look at my code, I'll post it here, and if I'm being silly, I'm all ears as to the reason and in what direction I should head instead. Best wishes!

<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='utf-8'>
    <title>Bounce Test Multi!</title>
    <link rel='stylesheet' href='stylesheet.css'>
    <script src="script.js"></script>
  </head>
  <body>
    <button id="GO" onclick="goGoGadget(Ball, spaceTimeArr);">Balls
    </button>
  </body>
</html>

I also tried just onclick="goGoGadget();"

html, body {
    margin: 0;
    height: 100%;
    width: 100%;
}
button {
    text-decoration: none;
    text-align: center;
    font-size: 16px;
    color: white;
    background-color: navy;
    height: 50px;
    width: 80px;
    border-radius: 4px;
    position: absolute;
    top: 50%;
    left: 50%;
}
.ball {
    position = absolute;
    width = 40px;
    height = 40px;
    border-radius = 50%;
    background-color = crimson;
}

Aaand the Javascript:

var spaceTimeArr = [];

for (let i = 0; i < Math.ceil((Math.random() * 10)); i++) {
    let x = Math.random() * parseInt(window.innerWidth, 10);
    let y = Math.random() * parseInt(window.innerHeight, 10);
    if (x > (parseInt(window.innerWidth, 10) - 40)) {
            x -= 40;
    }
    if (y > (parseInt(window.innerHeight, 10) - 40)) {
            y -= 40;
    }
    let dx = Math.ceil(Math.random() * 5);
    let dy = Math.ceil(Math.random() * 5);
    let directions = ["upRight","upLeft","downRight","downLeft"];
    let dir = directions[Math.floor(Math.random() * 4)];
    spaceTimeArr.push([x, y, dx, dy, dir]);
}

class Ball {
    constructor(x, y, dx, dy, dir) {
        let ball = document.createElement("div");
        ball.setAttribute("class","ball");
        document.body.insertBefore(ball, document.getElementById('GO'));
        ball.style.left = `${x}px`;
        ball.style.top = `${y}px`;
        this.move = this.move.bind(this);
        var intervalThing;
    }
    move() {
        let xInM = ball.style.left;
        let yInM = ball.style.top;
        if (this.dir === "upRight") {
            intervalThing = setInterval(function() {
                xInM += dx;
                yInM -= dy;
                if (xInM > (window.innerWidth - parseInt(ball.style.width, 10))) {
                    this.dir = "upLeft";
                    clearInterval(intervalThing);
                    this.move();
                } else if (yInM < 0) {
                    this.dir = "downRight";
                    clearInterval(intervalThing);
                    this.move();
                } else {
                    ball.style.left = `${xInM}px`;
                    ball.style.top = `${yInM}px`;
                }
            });
        }
        if (this.dir === "upLeft") {
            intervalThing = setInterval(function() {
                xInM -= dx;
                yInM -= dy;
                if (xInM < 0) {
                    this.dir = "upRight";
                    clearInterval(intervalThing);
                    this.move();
                } else if (yInM < 0) {
                    this.dir = "downLeft";
                    clearInterval(intervalThing);
                    this.move();
                } else {
                    ball.style.left = `${xInM}px`;
                    ball.style.top = `${yInM}px`;
                }
            }, 16.6667);
        }
        if (this.direction === "downRight") {
            intervalThing = setInterval(function() {
                xInM += dx;
                yInM += dy;
                if (xInM > (window.innerWidth - parseInt(ball.style.width, 10))) {
                    this.direction = "downLeft";
                    clearInterval(intervalThing);
                    this.move();
                } else if (yInM > (window.innerHeight - parseInt(ball.style.height, 10))) {
                    this.direction = "upRight";
                    clearInterval(intervalThing);
                    this.move();
                } else {
                    ball.style.left = `${xInM}px`;
                    ball.style.top = `${yInM}px`;
                }
            }, 16.6667);
        }
        if (this.direction === "downLeft") {
            intervalThing = setInterval(function() {
                xInM -= dx;
                yInM += dy;
                if (xInM < 0) {
                    this.dir = "downRight";
                    clearInterval(intervalThing);
                    this.move();
                } else if (yInM > (window.innerHeight - parseInt(ball.style.height, 10))) {
                    this.dir = "upLeft";
                    clearInterval(intervalThing);
                    this.move();
                } else {
                    ball.style.left = `${xInM}px`;
                    ball.style.top = `${yInM}px`;
                }
            }, 16.6667);
        }
    }
}

function goGoGadget() {
    document.getElementById('GO').style.display = "none";
    return new Ball(...spaceTimeArr);
}

I also tried including parameters in the goGoGadget function definition, but I thought that Ball and spaceTimeArr would be defined globally. Maybe I'm making a mistake with how I'm handling arrays, or the parameter of Ball's constructor. As it stands, I'm getting one div class="ball" inserted into the DOM at top of 0px and left of ${the number of pixels in the window}.

  • 1
    `bind` is ES5, try using arrow functions in those `setInterval`. This seems more of a question about how `this` works in general... – elclanrs Jun 02 '16 at 15:13
  • Time to learn about `this`? https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this, http://stackoverflow.com/q/3127429/218196. http://stackoverflow.com/q/20279484/218196 – Felix Kling Jun 02 '16 at 15:20
  • @elclanrs Oh, right, like `intervalThing = setInterval(() => {` ? EDIT: SOMEONE JUST POSTED THIS RESOURCES, THANKS @Felix And I'm not sure it's about 'this', I thought I was having an issue with multiple instances of a class. If I am having an issue with the this, do you know of any good resources to learn about the this? – Gareth Field Jun 02 '16 at 15:22
  • You still have to [create properties using `this.` instead of `var`](http://stackoverflow.com/q/13418669/1048572). – Bergi Jun 02 '16 at 15:25
  • What is `this` // baby don't bind() me // don't bind() me // no moooore ... – Gareth Field Jun 02 '16 at 15:31
  • @Bergi so var intervalThing = this.intervalThing? Getting the same output – Gareth Field Jun 02 '16 at 15:34
  • @GarethField: No, the other way round. Also it's not only `.intervalThing`, but also `.ball` and basically most other variables you're using - constructor parameters don't automatically become properties, they're just local variables in the `constructor` method! This is not different than ES5 constructors+prototypes. – Bergi Jun 02 '16 at 15:40
  • @Bergi Ooooh, I thought ... well, I thought the thing that you say is totally wrong. I have errands to run, but I can't wait to get back to this. Thanks a bundle! – Gareth Field Jun 02 '16 at 15:52
  • OMG I've learned so much since then :O – Gareth Field Jun 05 '18 at 03:08

0 Answers0