modular multiplication around a circle

JavaScript project for beginners: modular multiplication around a circle with HTML canvas

Updated on 12/09/18
10 minute read

Disclosure

Webquestions.co is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for us to earn fees by linking to Amazon.com and affiliated sites. As an Amazon Associate I earn from qualifying purchases.

The goal of this JavaScript project for beginners is to achieve the functionality with HTML canvas and JavaScript.

This project is not very hard and can be completed in few hours. The result is amazing. So many wonderful shapes and patterns are created easily by changing values.

The challenge has almost no CSS involved except some basic stuff in order to align the page components.

No framework or library of any kind is involved in making this project. All you need to know is basic JavaScript, HTML canvas (or you will learn during the challenge) and some very basic HTML. In this challenge we will also cover the logic behind this times tables so you get the full picture.

At the end, I will share some of my favorite combination for creating unique patterns.

Here is a demo:

 

Subscribe:

 

 

Try this:

JavaScript rain effect - vanilla JS (ES6)

ES6 interview questions and answers.

Resources that will help you learn web development.

OK, let's start. 

The full HTML template

Here is the complete HTML template. 

<!-- The complete HTML file -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>Canvas tutorial</title>

  <script src="js/main.js"></script>   <!-- JavaScript file -->
  <link rel="stylesheet" type="text/css" href="styles/main.css">   <!-- CSS file -->                                

</head>
<body onload="draw();">
  <div id="container">
    <div id="inputFields">
      <div class="column-width-auto">
        <label for="multiplierInput" class="font-size">Multiplier:</label>
        <input type="number" name="multiplierInput" min="2" max="100" id="multiplierInput" value="2" class="width-100pc">
      </div>
      <div class="column-width-auto">
        <label for="pointNumber" class="font-size">Number of Points:</label>
        <input type="number" name="pointNumber" min="10" max="300" id="pointNumber" value="10" class="width-100pc">
      </div>
    </div>

    <canvas id="multiplier" width="600" height="600"></canvas>

  </div>
</body>
</html>

 

Few point regarding the HTML file:

In this stage, if you try to run the HTML file in the browser, you will probably get a few errors. We do not have the CSS and JavaScript files yet and the canvas is empty.

  • The canvas element will contain the circle.

  • The input elements are initialized with certain values, you can select your own minimum and maximum values.

  • Notice the link and script tags. Those add the required JavaScript and HTML to the project. You can create yours in any folder, just don't forget to link the files. You can also add everything in one file. It is up to you to decide. 

 

Adding styles to the project

Here is the complete styles file for the project.

/* The complete CSS file */

#container {
  width: 600px;
  margin: 0 auto;
}

#inputFields {
  padding: 25px 0 25px 0;
  column-count: 2;
}

.column-width-auto {
  column-width: auto;
}

.width-100pc {
  width: 100%;
}

.font-size {
  font-size: 20px;
}

canvas { 
  border: 1px solid black;
}

 

The result so far


Still an error. It is OK.

There are still few thing we need to do before we can see the result. 

 

Adding JavaScript to the project


This section holds the logic and the creation of elements in the canvas. 
We will go step by step and create this part of the project. 


Create a JavaScript file, and don't forget to update the link to the script tag in the HTML file.

 

Initialize the canvas


We start by adding the draw() function. It is called when onload event is fired. The event is added to the body element in the HTML file.

 

function draw() { 

    var canvas = document.getElementById('multiplier');
    var ctx = canvas.getContext('2d'); 
}

 

For now, we declared the canvas variable that will hold the circle element for us and ctx that will hold the context. All the canvas drawing are made using the ctx variable.

Let's move on to variables and functions declarations. Inside the draw() function, add the following variables:

 

var x = 300; // x coordinate
var y = 300; // y coordinate
var radius = 295; // Arc radius
var point_size = 2;
var number_of_points = 10;
var multiplier = 2;
var points = [];

  

The x and y represents the center of the circle on which lines will be added.

point_size will determine the point size. The point are those from which lines are drawn.

Finally, we initialize the number of points we would like to start with (number_of_points), the multiplier and the points array which later helps us performing calculations to create the patterns.

 

Drawing the circle

We need to add the following function to the JavaScript file, inside the draw() function.

 

//inside the draw() function

function drawCircle() {
    points = [];
    ctx.clearRect(0, 0, canvas.width, canvas.height);


    ctx.beginPath();
    
    var startAngle = 0; // Starting point on circle
    var endAngle = 2 * Math.PI; // End point on circle

    ctx.arc(x, y, radius, startAngle, endAngle);
    ctx.stroke();


    var i;
    var angleBetweenPoints = 360 / number_of_points;
    for (i = 0; i < number_of_points ; i++) {
        drawPoint(i * angleBetweenPoints, 1)
    }

    for (i = 1; i < points.length; i++ ) {
        ctx.beginPath();
        ctx.moveTo(points[i].x, points[i].y);

        if (i < points.length / multiplier ) {
            ctx.lineTo(points[i*multiplier].x, points[i*multiplier].y);

        } else {
            ctx.lineTo(points[i*multiplier % points.length].x, points[i*multiplier % points.length].y);
        }

        ctx.stroke();
    }
}

 

What is happening here? First we initialize the points array and then create the circle:

 

//inside drawCircle() function

points = [];
ctx.clearRect(0, 0, canvas.width, canvas.height);

ctx.beginPath();

var startAngle = 0; // Starting point on circle
var endAngle = 2 * Math.PI; // End point on circle

ctx.arc(x, y, radius, startAngle, endAngle);
ctx.stroke();

 

Then we create the points on the circle by dividing 360 degrees by the number of points to get the angle between each point.

The angle is used to draw a point in a function I will soon show:

 

//inside drawCircle() function

var i;
var angleBetweenPoints = 360 / number_of_points;
  
for (i = 0; i < number_of_points ; i++) {
    drawPoint(i * angleBetweenPoints, 1);  //the function will be added soon. 
}

 

Next step is creating the lines between each point.

We are using moveTo() in order to start a line from a desired point and not from the last drawing point which is the default behavior.

The method lineTo() is used to draw the line. lineTo() will draw a line from the last painting position which we moved by calling moveTo().

calling stroke() method will commit the actions and draw the line.

 

//inside drawCircle() function

for (i = 1; i < points.length; i++ ) {
   ctx.beginPath();
   ctx.moveTo(points[i].x, points[i].y);

   if (i < points.length / multiplier ) {
    ctx.lineTo(points[i*multiplier].x, points[i*multiplier].y);

   } else {
    ctx.lineTo(points[i*multiplier % points.length].x, points[i*multiplier % points.length].y);

   }

ctx.stroke();

}

 

Drawing a point


Points are arcs.

We are using the same above technique to create the points.

A point has an angle from the 0 angle and a distance from the center of the main circle which will always be 1 in our case.

  

function drawPoint(angle,distance) {
    var pointx = x + radius * Math.cos(-angle*Math.PI/180) * distance;
    var pointy = y + radius * Math.sin(-angle*Math.PI/180) * distance;

    ctx.beginPath();
    ctx.arc(pointx, pointy, point_size, 0, 2 * Math.PI);
    ctx.fill();

    points.push({x: pointx, y: pointy});
} 

 

Finally, let's add the first call to draw the circle and events listeners to recreate the circle when the user changes the multiplier or the number of dots.

 

if (canvas.getContext) {
    drawCircle();
}

// add event listener to point number selection
var pointNumElement = document.getElementById("pointNumber");
pointNumElement.addEventListener('input', function(e){
    number_of_points = this.value;
    drawCircle();
});

// add event listener to multiplier number selection
var pointNumElement = document.getElementById("multiplierInput");
pointNumElement.addEventListener('input', function(e){
    multiplier = this.value;
    drawCircle();
});

 

We are done.

Try and go through the complete JavaScript file, It will give you a better understanding of the moving parts.

 

Here is the complete JavaScript file:

 

//complete JavaScript file

function draw() {
 
    var canvas = document.getElementById('multiplier');
    var ctx = canvas.getContext('2d');
    var x = 300; // x coordinate
    var y = 300; // y coordinate
    var radius = 295; // Arc radius
    var point_size = 2;
    var number_of_points = 10;
    var multiplier = 2;
    var points = [];

    function drawCircle() {
        points = [];
        ctx.clearRect(0, 0, canvas.width, canvas.height);


        ctx.beginPath();
        var startAngle = 0; // Starting point on circle
        var endAngle = 2 * Math.PI; // End point on circle

        ctx.arc(x, y, radius, startAngle, endAngle);
        ctx.stroke();


        var i;
        var angleBetweenPoints = 360 / number_of_points;
        for (i = 0; i < number_of_points ; i++) {
            drawPoint(i * angleBetweenPoints, 1)
        }

        for (i = 1; i < points.length; i++ ) {
            ctx.beginPath();
            ctx.moveTo(points[i].x, points[i].y);

            if (i < points.length / multiplier ) {
                ctx.lineTo(points[i*multiplier].x, points[i*multiplier].y);

            } else {
                ctx.lineTo(points[i*multiplier % points.length].x, points[i*multiplier % points.length].y);

            }
            ctx.stroke();
        }
    }

    function drawPoint(angle,distance){
        var pointx = x + radius * Math.cos(-angle*Math.PI/180) * distance;
        var pointy = y + radius * Math.sin(-angle*Math.PI/180) * distance;

        ctx.beginPath();
        ctx.arc(pointx, pointy, point_size, 0, 2 * Math.PI);
        ctx.fill();

        points.push({x: pointx, y: pointy});
    }

    if (canvas.getContext) {
        drawCircle();
    }

    // add event listener to point number selection
    var pointNumElement = document.getElementById("pointNumber");
    pointNumElement.addEventListener('input', function(e){
        number_of_points = this.value;
        drawCircle();
    });

    // add event listener to multiplier number selection
    var pointNumElement = document.getElementById("multiplierInput");
    pointNumElement.addEventListener('input', function(e){
        multiplier = this.value;
        drawCircle();
    });
}

 

Try some combinations, here are some of my favorites (Multiplier / Number of points) :

  • 32 / 271
  • 97 / 278 - 288
  • 96 / 209
  • 150 / 200
  • 73 / 73

 

What is next?


Now that you have the basic functionality up and running, you can make some changes and further update the project.

Here are some ideas:

  • Change the input fields to sliders.
  • Make each line have a different color.
  • Make each point have a different color.
  • Add a slider that enables the rotation of the whole circle.
  • Have buttons with preset values to further demo the circle
  • Any thing you can think of.
     

To conclude


This JavaScript project for beginners will help you understand JavaScript events, DOM manipulation and few more basic topic in the subject.

modular multiplication around a circle's fun result is a good basis to further developing the project to your taste.

Hope you enjoyed the project.