Is there an issue with this code? HTML5 canvas

I am attempting to create a mesmerizing animation of a black hole simulation using the canvas element. My goal is to make objects exit the black hole if their distance from its center is greater than the black hole's radius, and to do so at variable speeds.

HTML


<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Black Hole Test</title>
        <script>
            var canvas, ctx;
            var blackhole;
            var circle;
            var circles = new Array();
            var G = 6.67e-11, 
                c = 3e8, 
                M = 12e31, 
                Rs = (2 * G * M) / 9e16, 
                pixel_Rs = Rs / 1e3; 

            function update() {
                for (var i = 0; i < 200; i++) {
                    var vec2D = new Vector2D(Math.floor(Math.random() * 1400), Math.floor(Math.random() * 800));
                    circle = new Ball(5, vec2D.x, vec2D.y, "grey");
                    circle.draw(ctx)
                    circles.push(circle);
                    var distance = Math.sqrt(((vec2D.x - 700) * (vec2D.x - 700)) + ((vec2D.y - 400) * (vec2D.y - 400)));

                    if (distance > pixel_Rs) {
                        var delta = new Vector2D(1, 1);
                        var forceDirection = Math.atan2(vec2D.y - 700, vec2D.x - 400);
                        delta.x += Math.cos(forceDirection) * 3;
                        delta.y += Math.sin(forceDirection) * 3;
                        vec2D.x += delta.x;
                        vec2D.y += delta.y;
                        requestAnimationFrame(update);

                    }
                }
            };

            function init() {
                var G = 6.67e-11, 
                    c = 3e8, 
                    M = 12e31, 
                    Rs = (2 * G * M) / 9e16, 
                    pixel_Rs = Rs / 1e3; 

                    canvas = document.getElementById("space");
                ctx = canvas.getContext('2d');

                blackhole = new Ball(pixel_Rs, 700, 400, "black");

                blackhole.draw(ctx);

                requestAnimationFrame(update);
            };

            function Ball(radius, posx, posy, color) {
                this.radius = radius;
                this.posy = posy;
                this.posx = posx;
                this.color = color;
            };
            Ball.prototype.draw = function(ctx) {
                ctx.fillStyle = this.color;
                ctx.beginPath();
                ctx.arc(this.posx, this.posy, this.radius, 0, 2 * Math.PI);
                ctx.closePath();
                ctx.fill();
            };

            function drawCircle(ctx) {
                for (var i = 0; i < 200; i++) {
                    var vec2D = new Vector2D(Math.floor(Math.random() * 1400), Math.floor(Math.random() * 800));
                    circle = new Ball(5, vec2D.x, vec2D.y, "grey");
                    circle.draw(ctx)
                    circles.push(circle);
                }
            };

            function Vector2D(x, y) {
                this.x = x;
                this.y = y;
            }

            Vector2D.prototype = {
                length: function() {
                    return this.x * this.x + this.y * this.y;
                },
                add: function(vec) {
                    return new Vector2D(this.x + vec.x, this.y + vec.y);
                },

                subtract: function(vec) {
                    return new Vector2D(this.x - vec.x, this.y - vec.y);
                },
                decrementBy: function(vec) {
                    this.x -= vec.x;
                    this.y -= vec.y;
                }
            };

            window.onload = init;

        </script>
        <style>
            body {
                background-color: #021c36;
                margin: 0px;
            }
        </style>
    </head>
    <body>
        <canvas id="space" , width="1400" , height="800">
        </canvas>
    </body>
</html>

Why isn't it working or displaying anything?

Answer №1

To bring this animation to life, you will need to put in more effort. Your update function should:

  1. iterate through all the circles in each animation frame.
  2. check the distance between the circles and the black hole.
  3. adjust their positions if needed.
  4. redraw the entire canvas if any of the circles have moved.

In your current code, the update function only draws more circles. Simply calling requestAnimationFrame won't handle circle animations automatically. Additionally, you have a drawCircle function that is never utilized.

I have integrated these changes into this jsfiddle. Another minor correction is in your

Math.atan2(vec2D.y - 700, vec2D.x - 400)
, which should be
Math.atan2(vec2D.y - 400, vec2D.x - 700)
; and the delta should be initialized as (0, 0) instead of (1, 1).

var canvas, ctx;
var blackhole;
var circle;
var circles = new Array();
var G = 6.67e-11, //gravitational constant 
    c = 3e8, //speed of light (m/s)
    M = 12e31, // masseof the blackhole in kg (60 solar masses)  
    Rs = (2 * G * M) / 9e16, //Schwarzchild radius 
    pixel_Rs = Rs / 1e3; // scaled radius 

function update() {
    var pos, i, distance, somethingMoved = false;
    for (i = 0; i < circles.length; i++) {
        pos = circles[i].position;
        distance = Math.sqrt(((pos.x - 700) * (pos.x - 700)) + ((pos.y - 400) * (pos.y - 400)));
        if (distance > pixel_Rs && visible(circles[i])) {
            var delta = new Vector2D(0, 0);
            var forceDirection = Math.atan2(pos.y - 700, pos.x - 400);
            delta.x += Math.cos(forceDirection) * 3;
            delta.y += Math.sin(forceDirection) * 3;
            pos.x += delta.x;
            pos.y += delta.y;
            somethingMoved = true;
        }
    }
    if (somethingMoved) {
        drawEverything();
        requestAnimationFrame(update);
    }
}

function visible(ball) {
    // --- Test whether ball is visible
    return ball.position.x > ball.radius && ball.position.x < canvas.width - ball.radius &&
        ball.position.y > ball.radius && ball.position.y < canvas.height - ball.radius;
}

function drawEverything() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    blackhole.draw(ctx);
    for (var i = 0; i < circles.length; i++) {
        if (visible(circles[i])) {
            circles[i].draw(ctx);
        }
    }
}

function init() {
    canvas = document.getElementById("space");
    ctx = canvas.getContext('2d');
    blackhole = new Ball(pixel_Rs, {
        x: 700,
        y: 400
    }, "black");
    for (var i = 0; i < 200; i++) {
        var vec2D = new Vector2D(Math.floor(Math.random() * 1400), Math.floor(Math.random() * 800));
        circle = new Ball(5, vec2D, "grey");
        circles.push(circle);
    }
    drawEverything();
    requestAnimationFrame(update);
}

function Ball(radius, position, color) {
    this.radius = radius;
    this.position = position;
    this.color = color;
}
Ball.prototype.draw = function(ctx) {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.fill();
};

function Vector2D(x, y) {
    this.x = x;
    this.y = y;
}

Vector2D.prototype = {
    length: function() {
        return this.x * this.x + this.y * this.y;
    },
    add: function(vec) {
        return new Vector2D(this.x + vec.x, this.y + vec.y);

    },

    subtract: function(vec) {
        return new Vector2D(this.x - vec.x, this.y - vec.y);
    },
    decrementBy: function(vec) {
        this.x -= vec.x;
        this.y -= vec.y;
    }

};

window.onload = init;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to exchange the chosen selection within 2 select elements?

I have been trying to swap the cities in my select fields using two select elements, but for some reason, it is not working when the button is clicked: https://i.sstatic.net/mHg4Y.jpg <div class="select-wrapper"> <select class="airport-selec ...

Angular animations: triggered by user interaction

I'm encountering some difficulties with animating elements in my Angular application. The issue involves a grid made up of cells (created using ng-repeat). What I'm aiming to achieve is a simple animation: when a cell is clicked, it should disapp ...

Top Strategies for PHP - Managing Directs and Header Content

PHP is a versatile language frequently used for generating 'templates' like headers to maintain a consistent look across websites and simplify updates via require or include commands. Another common task involves managing log-ins and redirecting ...

Transfer information(text) to the clipboard using Vue (Nuxt js)

When the vs-button is clicked, I want the value of single_download_link.pdfId to be copied to the clipboard. I attempted it like this, but it did not work. I do not want to use the v-clipboard node module. Can someone please assist me with this? Thank you. ...

Experiencing an issue with Jest - Error: unable to access property 'forEach' of null

After watching some tutorials, I decided to create a sample project in Jest for writing tests. In a TypeScript file, I included a basic calculation function like this: Calc.cs export class Calc { public add(num1: number, num2: number): number { ...

The process of merging these two functions involves ensuring that one function does not start until the other has successfully completed its task

A closer look at the two functions in question: const handleSubmit = async (e) => { e.preventDefault(); console.log(songLink) const newSong = { songName, songLink, userId }; const song = await dispatch(pos ...

Exploring the transparency of material lab autocomplete drop-down text for enabling multiple selections

Check out this demo for checkboxes and tags in Material UI The code below demonstrates an autocomplete component that functions correctly. However, the drop-down text appears transparent. Is there a way to fix this issue without modifying any libraries? ...

The Bootstrap navbar stubbornly refuses to hide after being clicked on

Is there a way to adjust the data-offset-top for mobile view? Additionally, I am having trouble hiding the menu when clicking on a link. I have tried some code from stackoverflow without success. Can someone please assist with this issue: <nav class= ...

Difficulty with info window within a for loop

I am currently working on implementing multiple info windows for markers. I found an example on Stack Overflow that I am trying to follow. Despite not encountering any errors in the console, the info windows do not appear as expected when clicking on the m ...

Is it time to execute a mocha test?

Good day, I am currently exploring the world of software testing and recently installed Mocha. However, I seem to be encountering an issue with running a basic test that involves comparing two numbers. Can someone please guide me on why this is happening a ...

Troubleshooting issue: AngularJS not receiving NodeJS GET requests

I recently developed a web application for sharing photos. Currently, I am working on a route that is designed to fetch and display the photos of all users from an array. The code for the route is as follows: router.get('/getphotos',function(re ...

Utilize AJAX to dynamically refresh the page without having to reload it, enabling the use of both POST and GET methods

In order to avoid reloading the page when refreshing, I am utilizing Ajax for this particular 3-sided content along with JavaScript. Here is the code: Content: <ul id="nav"> <li><a href="ajax_adat.php?id=8&epul=0">Data</a>< ...

Swapping the icon in the panel heading of Bootstrap 3 Collapse based on its collapse status

Despite many attempts, I haven't been able to make any of the provided answers work in my code. My setup involves using Bootstrap 3 panels and collapse functionality to display advertisements. In the default view, only the advertisement heading is vi ...

Is there a way to stop TD from going to the next line?

I am using Javascript to dynamically generate a table and I want it to extend beyond the boundaries of the page. When I manually create the table, it works fine and extends off the page, but once I put it into a loop, the <td> elements wrap onto a se ...

Issue encountered: Unable to load resource - ajax file upload failed due to net::ERR_SSL_BAD_RECORD_MAC_ALERT error

I've implemented an AJAX form file upload using jQuery. After testing my code across multiple computers and browsers, I've encountered an issue on one Windows 8 machine running Chrome where the upload functionality fails with the following error ...

Selecting properties from a GeoJSON object on the fly with Leaflet

I am currently attempting to dynamically modify the displayed property on my leaflet map. Below is the code I have been working with: $("#button_thermal").click(function(){ $.getJSON("physicalProperties.geojson", function(data) { var geojson2 = L.geoJson( ...

Node.js server experiencing delays due to V8 processing constraints

REVISED I am currently running a nodeJS http server designed to handle uploads from multiple clients and process them separately. However, I have encountered an issue where the first request seems to block any subsequent requests until the first one is co ...

Continuously running React useEffect even with an empty dependency array

In my React application, I have implemented a hook system. Each sub-hook that is generated within this main hook is assigned a unique ID automatically. This ID is incremented by 1 every time a new sub-hook is created, ensuring uniqueness. const App = ...

How to use a string condition to filter a list of objects in Javascript?

Below is the structure of the object: var objList = [ { "age": 19, "valueField": 34, "booleanField": false }, { "age": 15, "valueField": 5, "booleanField": false }, { "age": 22, "valueField": 17, "booleanField": true } ]; Given the condition ...

Using jQuery to verify the presence of an element, especially one that may have been dynamically inserted via AJAX

I have a good understanding of how to verify elements that are present when the document is loaded: jQuery.fn.exists = function () { return jQuery(this).length > 0; } However, this approach does not detect elements that are dynamically added via A ...