Skip to content

Rotating Motor


Rotating Motor

Rotating Motor Demo

We want to animate a rotating motor as a circle. The motor must have circular arrows on it that show the direction of the rotation of the motor. The arrows must point clockwise when we are going forward and counter-clockwise when we are going in reverse. Drawing arrows with a triangle at the end is easy. But circular arrows that scale well up or down is a lot more challenging.

In this lesson we will use "decomposition" to break this task down into steps:

  1. Draw the outline of a circle
  2. Draw arcs within the circle using the arc() function
  3. Draw arrows at the tips of the arcs

We will use the translate(), scale(), and rotate() functions to perform this animation.

Draw Rotating Motor

Draw Motor

The key here is to be able to make the motor scale to any size. We do this by doing the following three functions:

  1. translate() to the center of the motor
  2. scale the motor to the correct size
  3. rotate the motor so it appears to spin in the right direction
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function drawMotor(x, y, scaleVal, angle, direction) {
  angleMode(DEGREES);  // Change the mode to 

  // get ready to jump into a new reference frame
  push();

      // order is key
      translate(x, y);
      scale(scaleVal);
      rotate(angle);

      // gray
      fill(180);
      strokeWeight(2);
      circle(0,0, 220)
      strokeWeight(10);
      stroke('black')
      noFill();
      // top circle x,y  w,h  start-ang, end-angle
      arc(0, 0, 180, 180, 180, 310, OPEN);
      // bottom circle
      arc(0, 0, 180, 180,   0, 130, OPEN);

      // forward
      if (direction == 1) {
        // up right
        drawArrowTip(50,-75, 140)
        // lower left
        drawArrowTip(-60, 70, -30)
      }
      // reverse
      if (direction == -1) {
        // up right x,y, ang
        drawArrowTip(90, 0, -20)
        // lower left
        drawArrowTip(-90, 0, 164)
      }
  pop();
}

Draw Arrow Tip

We use the translate() and rotate() functions to first get into position. Then we use the triangle() function to draw the triangle at the front of the arch.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function drawArrowTip(x, y, rotationAngle) {
  push();  // Save the current drawing style and transformations
     translate(x, y);  // Move the origin to the given location
     rotate(rotationAngle);  // Rotate by the given angle
     fill(0);  // Set the fill color to black
     noStroke();  // Disable drawing an outline
     // set the size
     let sz = 20;
     // lower right, top, lower left
     triangle(sz, 0,  0,-3*sz,   -sz,0);  // Draw the arrow tip
  pop();  // Restore the previous drawing style and transformations
}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// scale motor test
// Goal: add a size to the motor drawing to not require only a fixed size hard coded in the draw.

let direction = 1;
let radiusSlider;
let angle = 0;
let circleRadius = 100; // default value
let myFrameRate = 24;

function setup() {
    const canvas = createCanvas(400, 400);
    canvas.parent('canvas-container');
    // this changes the entire layout


    let forwardButton = createButton('Fwd');
    forwardButton.position(10, height-20);
    forwardButton.mousePressed(forward);

    let stopButton = createButton('Stop');
    stopButton.position(55, height-20);
    stopButton.mousePressed(stop);

    let reverseButton = createButton('Rev');
    reverseButton.position(105, height-20);
    reverseButton.mousePressed(turnReverse);

    // radiusSlider = createSlider(0, 200, circleRadius);
    scaleSlider = createSlider(.1, 2, 1, .1);
    scaleSlider.position(215, height - 35);
    scaleSlider.style('width', '180px');

        // radiusSlider = createSlider(0, 200, circleRadius);
    speedSlider = createSlider(0, 20, 5, .1);
    speedSlider.position(215, height - 16);
    speedSlider.style('width', '180px');
    frameRate(myFrameRate);
}

function stop() {
    direction = 0;
  }

  function forward() {
    direction = 1;
  }

  function turnReverse() {
    direction = -1;
  }

function draw() {
     background(240);
     // center axis
     stroke(0);
     line(0, height / 2, width, height / 2)
     line(width / 2, 0, width/2, height)

    // Update the circle radius based on slider value
    scaleVal = scaleSlider.value();
    motorSpeed = speedSlider.value();

    // Center the motor on the canvas
    angle += direction * motorSpeed;
    // x,y, scale,  angle, dir, speed
    drawMotor(width / 2, height / 2, scaleVal, angle, direction)

    // Draw the label and the current radius value
    stroke(0);
    strokeWeight(0);
    fill(0); // black color for the text
    text("Scale: " + scaleVal, 140, height - 30);
    text("Speed: " + motorSpeed, 140, height - 10);
}

function drawMotor(x, y, scaleVal, angle, direction) {
  angleMode(DEGREES);  // Change the mode to 
  push();

      // order is key
      translate(x, y);
      scale(scaleVal);
      rotate(angle);

      // gray
      fill(180);
      strokeWeight(2);
      circle(0,0, 220)
      strokeWeight(10);
      stroke('black')
      noFill();
      // top circle x,y  w,h  start-ang, end-angle
      arc(0, 0, 180, 180, 180, 310, OPEN);
      // bottom circle
      arc(0, 0, 180, 180,   0, 130, OPEN);

      // forward
      if (direction == 1) {
        // up right
        drawArrowTip(50,-75, 140)
        // lower left
        drawArrowTip(-60, 70, -30)
      }
      // reverse
      if (direction == -1) {
        // up right x,y, ang
        drawArrowTip(90, 0, -20)
        // lower left
        drawArrowTip(-90, 0, 164)
      }
  pop();
}

// draw a triangle with a base at (x,y) in the direction of rotationAngle
function drawArrowTip(x, y, rotationAngle) {
  push();  // Save the current drawing style and transformations
    translate(x, y);  // Move the origin to the given location
    rotate(rotationAngle);  // Rotate by the given angle
    fill(0);  // Set the fill color to black
    noStroke();  // Disable drawing an outline
    // set the size of the triangle
    let sz = 10;
    // lower right, top, lower left
    triangle(sz, 0,  0,-3*sz,   -sz,0);  // Draw the arrow tip
  pop();  // Restore the previous drawing style and transformations
}