Search code examples
javascripthtmljquerycanvashtml5-canvas

I want to change the shapes of object moving with number, For EXAMPLE rectangle,triangle,square. HOW TO DO THAT?


let canvas = document.getElementById("canvas");

let context = canvas.getContext("2d");
// for canvas size
var window_width = window.innerWidth;
var window_height = window.innerHeight;

canvas.width = window_width;
canvas.height = window_height;



let hit_counter=0;
let speedinc=2;




// object is created using class
class Circle {
    constructor(xpos, ypos, radius, speed, color, text) {

        this.position_x = xpos;
        this.position_y = ypos;

        this.radius = radius;

        this.speed = speed;

        this.dx = 1 * this.speed;
        this.dy = 1 * this.speed;

        this.text = text;

        this.color = color;
    }

// creating circle
    draw(context) {
        context.beginPath();
        context.strokeStyle = this.color;



        context.fillText(this.text, this.position_x, this.position_y);


        context.textAlign = "center";
        context.textBaseline = "middle"
        context.font = "20px Arial";
        context.lineWidth = 5;
        context.arc(this.position_x, this.position_y, this.radius, 0, Math.PI * 2);
        context.stroke();
        context.closePath();
    }


    update() {



        this.text=hit_counter;




        context.clearRect(0,0,window_width,window_height)

        this.draw(context);

        if ( (this.position_x + this.radius) > window_width ) {
            this.dx = -this.dx;  
            hit_counter++;  
        }

        if ( (this.position_x - this.radius) < 0 ) {
            this.dx = -this.dx;
            hit_counter++;  
        }

        if ( (this.position_y - this.radius) < 0 ) {
            this.dy = -this.dy;
            hit_counter++;  
        }

        if ( (this.position_y + this.radius) > window_height ) {
            this.dy = -this.dy;
            hit_counter++;  


        }

        this.position_x += this.dx;
        this.position_y += this.dy; 


    }
}







let my_circle = new Circle(100, 100, 50, speedinc , 'Black', hit_counter);




let updateCircle = function() {
  requestAnimationFrame(updateCircle);
 my_circle.update();

}

updateCircle();
<select name="shapes">
        <option value="square">SQUARE</option>
        <option value="rectangle">RECTANGLE</option>
        <option value="triangle">TRIANGLE</option>

        </select>
<canvas id="canvas"></canvas>

JS I want to change the shapes of object moving with number, For EXAMPLE rectangle,triangle,square. I Already created circle, I tried to create other shapes also IN THE SAME PAGE but it didn't work for me. HOW TO DO THAT?

let canvas = document.getElementById("canvas");

let context = canvas.getContext("2d");
// for canvas size
var window_width = window.innerWidth;
var window_height = window.innerHeight;

canvas.width = window_width;
canvas.height = window_height;



let hit_counter=0;
let speedinc=2;




// object is created using class
class Circle {
    constructor(xpos, ypos, radius, speed, color, text) {

        this.position_x = xpos;
        this.position_y = ypos;

        this.radius = radius;

        this.speed = speed;

        this.dx = 1 * this.speed;
        this.dy = 1 * this.speed;

        this.text = text;

        this.color = color;
    }
   
// creating circle
    draw(context) {
        context.beginPath();
        context.strokeStyle = this.color;
        
        
       
        context.fillText(this.text, this.position_x, this.position_y);
        
        
        context.textAlign = "center";
        context.textBaseline = "middle"
        context.font = "20px Arial";
        context.lineWidth = 5;
        context.arc(this.position_x, this.position_y, this.radius, 0, Math.PI * 2);
        context.stroke();
        context.closePath();
    }

    
    update() {
        

        
        this.text=hit_counter;

        
         
       
        context.clearRect(0,0,window_width,window_height)

        this.draw(context);

        if ( (this.position_x + this.radius) > window_width ) {
            this.dx = -this.dx;  
            hit_counter++;  
        }
        
        if ( (this.position_x - this.radius) < 0 ) {
            this.dx = -this.dx;
            hit_counter++;  
        }

        if ( (this.position_y - this.radius) < 0 ) {
            this.dy = -this.dy;
            hit_counter++;  
        }

        if ( (this.position_y + this.radius) > window_height ) {
            this.dy = -this.dy;
            hit_counter++;  
            
           
        }

        this.position_x += this.dx;
        this.position_y += this.dy; 
        
     
    }
}



  



let my_circle = new Circle(100, 100, 50, speedinc , 'Black', hit_counter);




let updateCircle = function() {
  requestAnimationFrame(updateCircle);
 my_circle.update();
 
}

updateCircle();




//for color

function changeColor(event)
{
    var coloor = event.value;
    canvas.style.background =coloor;
    
 }

HTML I want to change the shapes of object moving with number, For EXAMPLE rectangle,triangle,square. I Already created circle, I tried to create other shapes also IN THE SAME PAGE but it didn't work for me. HOW TO DO THAT?

<select name="shapes">
        <option value="square">SQUARE</option>
        <option value="rectangle">RECTANGLE</option>
        <option value="triangle">TRIANGLE</option>
       
        </select>
<canvas id="canvas"></canvas>

Solution

  • The best is to store "drawing commands" that are transformation agnostic, and then use the context's transformation to move these drawings where you want.

    At a very basic level this could be something like

    const canvas = document.querySelector("canvas");
    const ctx = canvas.getContext("2d");
    // we define all our "tracing" methods
    // they all are completely position agnostic
    // note how they have their "center" set to the coordinates (0, 0)
    const trace = [
      () => ctx.arc(0, 0, 50, 0, Math.PI * 2), // circle
      () => {
        [[0, -35], [35, 25], [-35, 25]]
          .forEach(([x, y]) => ctx.lineTo(x, y));
        ctx.closePath();
      }, // triangle
      () => ctx.rect(-25, -25, 50, 50) // rect
    ];
    let activeShape = Math.floor(Math.random() * trace.length);
    ctx.font = "30px sans-serif";
    ctx.textBaseline = "middle";
    ctx.textAlign = "center";
    
    setInterval(() => activeShape = Math.floor(Math.random() * trace.length), 1000);
    
    document.onmousemove = ({ clientX, clientY }) => {
      const { left, top } = canvas.getBoundingClientRect();
      draw(clientX - left, clientY - top);
    };
    
    function draw(x, y) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      // we move the drawing by changing the context's transform matrix
      ctx.translate(x, y);
      ctx.beginPath();
      // this is position agnostic
      trace[ activeShape ]();
      ctx.stroke();
      // this is also position agnostic
      ctx.fillText("A", 0, 0);
      // reset the transformation matrix for next frame
      ctx.setTransform(1, 0, 0, 1, 0, 0);
    }
    <canvas width="500" height="500"></canvas>

    Now, thanks to the Path2D API we can even just save the path object:

    const canvas = document.querySelector("canvas");
    const ctx = canvas.getContext("2d");
    // we define all our "tracing" methods
    // they all are completely position agnostic
    const circle = new Path2D();
    circle.arc(0, 0, 50, 0, Math.PI * 2);
    const triangle = new Path2D("M0,-35 35,25 -35,25Z");
    const rect = new Path2D();
    rect.rect(-25, -25, 50, 50)
    const shapes = [circle, triangle, rect];
    let activeShape = Math.floor(Math.random() * shapes.length);
    ctx.font = "30px sans-serif";
    ctx.textBaseline = "middle";
    ctx.textAlign = "center";
    
    setInterval(() => activeShape = Math.floor(Math.random() * shapes.length), 1000);
    
    document.onmousemove = ({ clientX, clientY }) => {
      const { left, top } = canvas.getBoundingClientRect();
      draw(clientX - left, clientY - top);
    };
    
    function draw(x, y) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      // we move the drawing by changing the context's transform matrix
      ctx.translate(x, y);
      ctx.beginPath();
      ctx.stroke(shapes[ activeShape ]);
      // this is also position agnostic
      ctx.fillText("A", 0, 0);
      // reset the transformation matrix for next frame
      ctx.setTransform(1, 0, 0, 1, 0, 0);
    }
    <canvas width="500" height="500"></canvas>

    With your code that could give something like:

    const canvas = document.getElementById("canvas");
    
    const context = canvas.getContext("2d");
    // for canvas size
    let window_width = window.innerWidth;
    let window_height = window.innerHeight;
    
    canvas.width = window_width;
    canvas.height = window_height;
    
    let hit_counter = 0;
    let speedinc = 2;
    
    // object is created using class
    class Shape {
      #shapes
      constructor(xpos, ypos, radius, speed, color, text) {
    
        this.position_x = xpos;
        this.position_y = ypos;
    
        this.radius = radius;
    
        this.speed = speed;
    
        this.dx = 1 * this.speed;
        this.dy = 1 * this.speed;
    
        this.text = text;
        this.color = color;
    
        // store all the drawable shapes
        const circle = new Path2D();
        circle.arc(0, 0, radius, 0, Math.PI * 2);
        const hypot = Math.hypot(radius, radius);
        const triangle = new Path2D();
        triangle.lineTo(0, -hypot);
        triangle.lineTo(hypot, radius);
        triangle.lineTo(-hypot, radius);
        triangle.closePath();
        const square = new Path2D();
        square.rect(-radius, -radius, radius * 2, radius * 2);
        this.#shapes = { circle, triangle, square };
        this.activeShape = "square";
      }
      draw(context) {
        context.beginPath();
        context.strokeStyle = this.color;
        context.translate(this.position_x, this.position_y);
        // remember to set all the context properties
        // before they're used
        context.textAlign = "center";
        context.textBaseline = "middle"
        context.font = "20px Arial";
        context.fillText(this.text, 0, 0);
        context.lineWidth = 5;
        context.stroke(this.#shapes[this.activeShape]);
        context.setTransform(1, 0, 0, 1, 0, 0);
      }
      update() {
        this.text = hit_counter;
        context.clearRect(0, 0, window_width, window_height)
        this.draw(context);
        // doing the update here means we're drawing one frame late
        if ((this.position_x + this.radius) > window_width) {
          this.dx = -this.dx;
          hit_counter++;
        }
    
        if ((this.position_x - this.radius) < 0) {
          this.dx = -this.dx;
          hit_counter++;
        }
    
        if ((this.position_y - this.radius) < 0) {
          this.dy = -this.dy;
          hit_counter++;
        }
    
        if ((this.position_y + this.radius) > window_height) {
          this.dy = -this.dy;
          hit_counter++;
        }
        
        this.position_x += this.dx;
        this.position_y += this.dy;
    
      }
    }
    const my_shape = new Shape(100, 100, 50, speedinc, 'Black', hit_counter);
    
    document.querySelector("select").addEventListener("change", (evt) => {
      my_shape.activeShape = evt.target.value;
    });
    
    const updateCircle = function() {
      requestAnimationFrame(updateCircle);
      my_shape.update();
    }
    
    updateCircle();
    <select name="shapes">
      <option value="square">SQUARE</option>
      <option value="circle">CIRCLE</option>
      <option value="triangle">TRIANGLE</option>
    
    </select>
    <canvas id="canvas"></canvas>

    But obviously there are many ways to write it differently.