HTML5 Game - Canvas Animation Pendulum

Swinging a pendulum

The following code shows how to create a pendulum whose angle oscillates as a function of time.

Demo

ResultView the demo in separate window

<!DOCTYPE HTML>
<html>
    <head>
        <script>
class MyObject{/* ww w . jav a 2 s  .  c  o  m*/
   draw(animationController){
      let canvas = animationController.getCanvas();
      let context = animationController.getContext();
      this.rotationPointX = canvas.width / 2;
      // update
      this.theta = (this.amplitude * Math.sin((2 * Math.PI * animationController.getTime()) / this.period)) + Math.PI / 2;
      
      // clear
      animationController.clear();
      
      // draw top circle
      context.beginPath();
      context.arc(this.rotationPointX, this.rotationPointY, 15, 0, 2 * Math.PI, false);
      context.fillStyle = "red";
      context.fill();
      
      // draw top inner circle
      context.beginPath();
      context.arc(this.rotationPointX, this.rotationPointY, 10, 0, 2 * Math.PI, false);
      context.fillStyle = "blue";
      context.fill();
      
      // draw shaft
      context.beginPath();
      let endPointX = this.rotationPointX + (this.pendulumLength * Math.cos(this.theta));
      let endPointY = this.rotationPointY + (this.pendulumLength * Math.sin(this.theta));
      context.beginPath();
      context.moveTo(this.rotationPointX, this.rotationPointY);
      context.lineTo(endPointX, endPointY);
      context.lineWidth = this.pendulumWidth;
      context.lineCap = "round";
      context.strokeStyle = "#555";
      context.stroke();
      
      // draw bottom circle
      context.beginPath();
      context.arc(endPointX, endPointY, 40, 0, 2 * Math.PI, false);
      let grd = context.createLinearGradient(endPointX - 50, endPointY - 50, endPointX + 50, endPointY + 50);
      
      grd.addColorStop(0, "#444");
      grd.addColorStop(0.5, "white");
      grd.addColorStop(1, "#444");
      context.fillStyle = grd;
      context.fill();
   }
   constructor(){
      this.x = 0;
      this.y = 20;
      this.width = 10;
      this.height = 10;

      this.vx = 0;
      this.vy = 0;

      this.amplitude = Math.PI / 4; // 45 degrees
      this.period = 4000; // ms
      this.theta = 0;
      this.pendulumLength = 250;
      this.pendulumWidth = 10;
      this.rotationPointX = 0;
      this.rotationPointY = 20;
   }
}    
class MyAnimation {
   constructor(canvasId){
        this.canvas = document.getElementById(canvasId);
        this.context = this.canvas.getContext("2d");
        this.t = 0;
        this.timeInterval = 0;
        this.startTime = 0;
        this.lastTime = 0;
        this.frame = 0;
        this.animating = false;
        

        window.requestAnimFrame = (function(callback){
            return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(callback){
                window.setTimeout(callback, 1000 / 60);
            };
        })();
   }
   getContext(){
      return this.context;
   };

   getCanvas(){
      return this.canvas;
   };

   clear(){
       this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
   };

   setDrawStage(func){
       this.drawStage = func;
   };

   isAnimating = function(){
       return this.animating;
   };

   getFrame(){
      return this.frame;
   };

   start(){
        this.animating = true; 
        let date = new Date();
        this.startTime = date.getTime();
        this.lastTime = this.startTime;
        
        if (this.drawStage !== undefined) {
            this.drawStage();
        }
        
        this.animationLoop();
   };

   stop(){
       this.animating = false;
   };

   getTimeInterval(){
       return this.timeInterval;
   };

   getTime(){
    return this.t;
   };

   getFps(){
      return this.timeInterval > 0 ? 1000 / this.timeInterval : 0;
   };

   animationLoop(){
        let that = this;
        
        this.frame++;
        let date = new Date();
        let thisTime = date.getTime();
        this.timeInterval = thisTime - this.lastTime;
        this.t += this.timeInterval;
        this.lastTime = thisTime;
        
        if (this.drawStage !== undefined) {
            this.drawStage();
        }
        
        if (this.animating) {
            requestAnimFrame(function(){
                that.animationLoop();
            });
        }
    }   
} 
            window.onload = function(){
                let myAnimation = new MyAnimation("myCanvas");
                let canvas = myAnimation.getCanvas();
                let context = myAnimation.getContext();
                let myObject = new MyObject();
                myAnimation.setDrawStage(function(){
                    myObject.draw(myAnimation);
                });
                
                myAnimation.start();
            };
        </script>
    </head>
    <body>
        <canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
        </canvas>
    </body>
</html>