I am looking for a scaling function in JavaScript. In my canvas there are moving points which connects with each other through a line in the form of a triangle (Please look at the code snippet below for better understanding.)
What I am looking for is, whenever two moving points are getting closer, their corresponding line should be thicker.
Two connected points far away = thin line,
two connected points close = thick line
I would prefer using pure JavaScript then using libraries or anything like, that I wouldn't probably understand.
There are quite few comments for documentation. It should help explain my code better
body {
background-color: #000000;
}
canvas {
padding: 0;
margin: auto;
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #111416;
/*background-color: white; */
border: 10px solid #37c7f7;
border-style: double;
box-shadow: 0 0 20px 5px #37c7f7;
}
<!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>
</head>
<body>
<link rel="stylesheet" href="canvas.css">
<canvas id="myCanvas" width="700" height="700"></canvas>
<script>
// Get id from the canvas element
var canvas = document.getElementById("myCanvas");
// Provide 2D rendering context for the drawing surface of canvas
var context = canvas.getContext("2d");
// Get width and height of the canvas element
var canvW = document.getElementById("myCanvas").width;
var canvH = document.getElementById("myCanvas").height;
// Create a random range of numbers
const randomRange = (min, max) => {
return Math.random () * (max - min) min;
}
// Create empty array called
const agents = [];
// Class = Create multiple objects with the same properties
class Point {
// Build the new object and pass parameters
constructor(x, y){
// Define properties
// "this" refers to the scope of the class
// class point contains propertie x and y
this.x = x;
this.y = y;
}
// "v" stands for vector
//Connecting the moving points into a triangle
getDistance(v){
const dx = this.x - v.x;
const dy = this.y - v.y;
// Phytagorean Theorem
return Math.sqrt(dx*dx dy*dy);
}
}
// Separate point from canvas
// Make dot a new entity
// Create another class
class Agent {
constructor(x, y){
// First property is position using x and y parameters
this.pos = new Point(x, y);
// Define velocity of point.
this.vel = new Point(randomRange(-0.75, 0.75), randomRange(-0.75, 0.75));
// Create points with random radius
this.radius = randomRange(4, 12);
}
// Generated points are bouncing off from the edge of the canvas
bounce(canvW, canvH) {
if (this.pos.x <= 0 || this.pos.x >= canvW) this.vel.x *= -1;
if (this.pos.y <= 0 || this.pos.y >= canvH) this.vel.y *= -1;
}
update() {
this.pos.x = this.vel.x;
this.pos.y = this.vel.y;
}
// Create new method called draw
// Pass paramter as reference to the context
draw (context) {
// Draw the points
context.save();
context.translate(this.pos.x, this.pos.y);
context.beginPath();
context.arc(0, 0, this.radius, 0, Math.PI * 2);
context.lineWidth = 2;
context.fillStyle = "#37c7f7";
context.fill();
context.stroke();
context.restore();
for (let i = 0; i < agents.length; i ){
const agent = agents[i];
for(let j = i 1; j < agents.length; j ){
const other = agents[j];
//Get distance between the moving points
const dist = agent.pos.getDistance(other.pos);
// If distance greater than the number, do not connect the lines
if (dist > 200) continue;
// Connecting the moving points with lines
context.beginPath();
context.moveTo(agent.pos.x, agent.pos.y);
context.lineTo(other.pos.x, other.pos.y);
context.stroke();
context.strokeStyle = "#37c7f7";
}
}
}
}
// Create random number of points using a for loop
for (let i =0; i<40; i ){
const x = randomRange(0, canvW);
const y = randomRange(0, canvH);
// push adds new items to the end of an array
// push changes the length of an array
// push returns the new length
agents.push(new Agent (x, y));
}
// Drawing and updating the animation process
const animate = () => {
context.save();
context.fillStyle = "#111416";
context.fillRect(0, 0, canvW, canvH);
context.restore();
agents.forEach(agent => {
agent.draw(context);
agent.update();
agent.bounce(canvW, canvH);
});
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>
CodePudding user response:
One way you can approach this is by using the dist
between the agents to determine the lineWidth. Here I made sure the width would atleast be 1 and played with the 100 variable.
...
if (dist > 200) continue;
...
context.stroke();
context.lineWidth = dist / 100 1;
context.strokeStyle = "#37c7f7";
CodePudding user response:
This can be done by normalizing distance between two connected points to some fixed range, in this case 0..radius
looks fine:
body {
background-color: #000000;
}
canvas {
padding: 0;
margin: auto;
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #111416;
/*background-color: white; */
border: 10px solid #37c7f7;
border-style: double;
box-shadow: 0 0 20px 5px #37c7f7;
}
<!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>
</head>
<body>
<link rel="stylesheet" href="canvas.css">
<canvas id="myCanvas" width="700" height="700"></canvas>
<script>
// Get id from the canvas element
var canvas = document.getElementById("myCanvas");
// Provide 2D rendering context for the drawing surface of canvas
var context = canvas.getContext("2d");
// Get width and height of the canvas element
var canvW = document.getElementById("myCanvas").width;
var canvH = document.getElementById("myCanvas").height;
// Create a random range of numbers
const randomRange = (min, max) => {
return Math.random () * (max - min) min;
}
// Create empty array called
const agents = [];
// Class = Create multiple objects with the same properties
class Point {
// Build the new object and pass parameters
constructor(x, y){
// Define properties
// "this" refers to the scope of the class
// class point contains propertie x and y
this.x = x;
this.y = y;
}
// "v" stands for vector
//Connecting the moving points into a triangle
getDistance(v){
const dx = this.x - v.x;
const dy = this.y - v.y;
// Phytagorean Theorem
return Math.sqrt(dx*dx dy*dy);
}
}
// Separate point from canvas
// Make dot a new entity
// Create another class
class Agent {
constructor(x, y){
// First property is position using x and y parameters
this.pos = new Point(x, y);
// Define velocity of point.
this.vel = new Point(randomRange(-0.75, 0.75), randomRange(-0.75, 0.75));
// Create points with random radius
this.radius = randomRange(4, 12);
}
// Generated points are bouncing off from the edge of the canvas
bounce(canvW, canvH) {
if (this.pos.x <= 0 || this.pos.x >= canvW) this.vel.x *= -1;
if (this.pos.y <= 0 || this.pos.y >= canvH) this.vel.y *= -1;
}
update() {
this.pos.x = this.vel.x;
this.pos.y = this.vel.y;
}
// Create new method called draw
// Pass paramter as reference to the context
draw (context) {
// Draw the points
context.save();
context.translate(this.pos.x, this.pos.y);
context.beginPath();
context.arc(0, 0, this.radius, 0, Math.PI * 2);
context.lineWidth = 2;
context.fillStyle = "#37c7f7";
context.fill();
context.stroke();
context.restore();
for (let i = 0; i < agents.length; i ){
const agent = agents[i];
for(let j = i 1; j < agents.length; j ){
const other = agents[j];
//Get distance between the moving points
const dist = agent.pos.getDistance(other.pos);
// If distance greater than the number, do not connect the lines
if (dist > 200) continue;
const r = this.radius;
// Connecting the moving points with lines
context.beginPath();
context.moveTo(agent.pos.x, agent.pos.y);
context.lineTo(other.pos.x, other.pos.y);
context.strokeStyle = "#37c7f7";
context.lineWidth = r * (1 - (dist - r) / (200 - r));
context.stroke();
}
}
}
}
// Create random number of points using a for loop
for (let i =0; i<40; i ){
const x = randomRange(0, canvW);
const y = randomRange(0, canvH);
// push adds new items to the end of an array
// push changes the length of an array
// push returns the new length
agents.push(new Agent (x, y));
}
// Drawing and updating the animation process
const animate = () => {
context.save();
context.fillStyle = "#111416";
context.fillRect(0, 0, canvW, canvH);
context.restore();
agents.forEach(agent => {
agent.draw(context);
agent.update();
agent.bounce(canvW, canvH);
});
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>