Canvas

  1. Overview
    1. Introduced in HTML5
    2. Uses JavaScript to display 2D bitmapped graphics and animations in a rectangular region, something that traditionally has been done with Flash and Silverlight
    3. Currently supported by all modern browsers
  2. Rectangles
    1. <canvas> element used to provide rectangular drawing surface where the upper-left corner is (0,0)
      <canvas id="myCanvas" width="300" height="100" style="border: 1px solid black">
      
      Canvas
    2. Use canvas's context object to do drawing
    3. fillRect(leftX, topY, width, height) and strokeRect(leftX, topY, width, height)
      <script>
      var canvas = document.getElementById("myCanvas");
      var context = canvas.getContext("2d");
      
      // Draw filled orange rectangle
      context.fillStyle = "orange";
      context.fillRect(5, 10, 200, 75);
      
      // Draw outline of blue rectangle
      context.strokeStyle = "royalblue";
      context.lineWidth = 6;
      context.strokeRect(120, 30, 100, 40);
      </script>
      
  3. Paths
    1. Paths may contain lines, curves, and arcs
    2. Surround each path with beginPath() and closePath()
    3. Use moveTo() and lineTo() to move the pen and draw a line
    4. Use stroke() to draw the path, fill() to fill the interior of the path
      // Draw two single green lines
      context.beginPath();
      context.moveTo(200, 10);
      context.lineTo(200, 90);
      context.moveTo(210, 10);
      context.lineTo(210, 90);
      context.closePath();
      context.strokeStyle = "green";
      context.lineWidth = 5;
      context.stroke();
      
      // Draw a red shape
      context.beginPath();
      context.moveTo(5, 5);
      context.lineTo(100, 5);
      context.lineTo(50, 50);
      context.lineTo(5, 30);
      context.closePath();
      context.fillStyle = "yellow";
      context.fill();
      context.strokeStyle = "red";
      context.lineWidth = 10;
      context.stroke();
      
  4. Arcs and circles
    1. arc() function uses radians

      Radians
    2. arc(centerX, centerY, radius, startAngle, endAngle, optional counterclockwise = false)
      // Blue circle with radius of 30 pixels
      context.beginPath();
      context.arc(35, 50, 30, 0, Math.PI * 2);
      context.fillStyle = "blue";
      context.fill();
      
      // Outline semi-circle
      context.beginPath();
      context.arc(110, 50, 30, 0, Math.PI);
      context.stroke();
      
      // Outline semi-circle drawn counter-clockwise
      context.beginPath();
      context.arc(185, 50, 30, 0, Math.PI, true);
      context.stroke();
      
      // Red semi-circle
      context.beginPath();
      context.arc(260, 50, 30, 3 * Math.PI / 2, Math.PI / 2);
      context.fillStyle = "red";
      context.fill();
      
  5. Shadows
    1. Shadows can be added to any drawn shape
      // Blue circle with shadow
      context.beginPath();
      context.shadowBlur = 10;
      context.shadowOffsetX = 15;
      context.shadowOffsetY = 15;
      context.shadowColor = "black";
      context.arc(35, 50, 30, 0, Math.PI * 2);
      context.fillStyle = "blue";
      context.fill();
      
      // Red rectangle with shadow
      context.beginPath();
      context.shadowBlur = 20;
      context.shadowOffsetX = -15;
      context.shadowOffsetY = -15;
      context.shadowColor = "purple";
      context.fillStyle = "red";
      context.fillRect(150, 30, 100, 50);
      context.fill();
      
  6. Bezier Curves
    1. Bezier curves have a starting point, ending point, and two control points through which the curve passes
    2. bezierCurve(control1X, control1Y, control2X, control2Y, endX, endY)
      // Red bezier curve
      context.beginPath();
      context.moveTo(115, 20);
      context.bezierCurveTo(12, 37, 176, 77, 32, 100);
      context.lineWidth = 10;
      context.strokeStyle = "red";
      context.stroke();
      
  7. Linear and radial gradients
    1. createLinearGradient(startX, startY, endX, endY) and addColorStop(number, color)
      // Vertical gradient
      var gradient = context.createLinearGradient(0, 0, 0, 100);
      gradient.addColorStop(0, "white");
      gradient.addColorStop(0.5, "lightsteelblue");
      gradient.addColorStop(1, "navy");
      context.fillStyle = gradient;
      context.fillRect(0, 0, 100, 100);
      
      // Horizontal gradient
      gradient = context.createLinearGradient(100, 0, 200, 0);
      gradient.addColorStop(0, "white");
      gradient.addColorStop(0.5, "yellow");
      gradient.addColorStop(1, "orange");
      context.fillStyle = gradient;
      context.fillRect(100, 0, 100, 100);
      
      // Diagonal gradient
      gradient = context.createLinearGradient(200, 0, 300, 100);
      gradient.addColorStop(0, "white");
      gradient.addColorStop(1, "purple");
      context.fillStyle = gradient;
      context.fillRect(200, 0, 100, 100);
      
    2. createRadialGradient(startX, startY, startRadius, endX, endY, endRadius)
      // Radial gradient with concentric circles
      var gradient = context.createRadialGradient(50, 50, 10, 50, 50, 90);
      gradient.addColorStop(0, "white");
      gradient.addColorStop(1, "red");
      context.fillStyle = gradient;
      context.fillRect(0, 0, 100, 100);
      
      // Radial gradient with small outer circle
      gradient = context.createRadialGradient(150, 50, 10, 150, 50, 30);
      gradient.addColorStop(0, "white");
      gradient.addColorStop(1, "blue");
      context.fillStyle = gradient;
      context.fillRect(100, 0, 100, 100);
      
      // Radial gradient with non-concentric circles
      gradient = context.createRadialGradient(200, 50, 15, 200, 100, 100);
      gradient.addColorStop(0, "white");
      gradient.addColorStop(1, "purple");
      context.fillStyle = gradient;
      context.fillRect(200, 0, 100, 100);
      
  8. Images
    1. drawImage(leftX, topY) and drawImage(leftX, topY, width, height)
    2. Make sure drawImage is called after the image has downloaded by calling it after the load event has triggered
      var image = new Image();
      image.src = "images/harding_helmet.png";
      
      function draw()
      {
      	var canvas = document.getElementById("myCanvas8");
      	var context = canvas.getContext("2d");
      	
      	// Draw image at (10,10)
      	context.drawImage(image, 10, 10);
      	
      	// Stretch the width
      	context.drawImage(image, 110, 20, 150, 50);
      }
      
      window.addEventListener("load", draw, false);
      
  9. Text
    1. font attribute to specify font style, family, and size
    2. textAlign attribute to change horizontal alignment to center or right
    3. textBaseline attribute to specify vertical alignment
    4. fillText(string, x, y) and strokeText(string, x, y)
      // Red text 
      context.font = "italic 24pt Courier New";
      context.textBaseline = "top";
      context.fillStyle = "red";
      context.fillText("Red text", 0, 0);
      
      // Navy text
      context.font = "bold 30pt Arial";
      context.textAlign = "center";
      context.strokeStyle = "navy";
      context.lineWidth = 2;
      context.strokeText("Navy text", canvas.width / 2, 30);
      
  10. Transformations
    1. Four basic transformations: translate, scale, rotate, transform
    2. Translate
      1. Moves the location of canvas's entire contents
      2. translate(directionX, directionY)
        // Blue circle at the upper-left corner
        context.beginPath();
        context.arc(0, 0, 30, 0, 2 * Math.PI);
        context.fillStyle = "blue";
        context.fill();
        
        // Move (0,0) to the center of the canvas
        context.translate(canvas.width / 2, canvas.height / 2);
        
        // Red circle at (0,0) appears in the center
        context.beginPath();
        context.arc(0, 0, 30, 0, 2 * Math.PI);
        context.fillStyle = "red";
        context.fill();
        
    3. Scale
      1. Expands or shrinks the canvas' contents
      2. scale(scaleX, scaleY) where values < 1 shrink and > 1 expand
        // Move (0,0) to the center of the canvas
        context.translate(canvas.width / 2, canvas.height / 2);
        
        // Make 3 times wider, half as high
        context.scale(3, 0.5);
        
        context.beginPath();
        context.arc(0, 0, 30, 0, 2 * Math.PI);
        context.fillStyle = "forestgreen";
        context.fill();
        
    4. Rotate
      1. Rotates the canvas's contents clockwise or counter-clockwise
      2. rotate(radians) where negative values rotate counter-clockwise
        // Move (0,0) to the center of the canvas
        context.translate(canvas.width / 2, canvas.height / 2);
        
        // Rotate clockwise 18 degrees
        context.rotate(Math.PI / 10);
        
        context.fillStyle = "royalblue";
        context.fillRect(-50, -50, 100, 100);
        
        // Rotate clockwise another 18 degrees
        context.rotate(Math.PI / 10);
        
        context.fillStyle = "orange";
        context.fillRect(-50, -50, 100, 100);
        
    5. Transform
      1. transform() function can skew, scale, rotate, and translate
      2. transform(scaleX, skewY, skewX, scaleY, translateX, translateY)
        // Move (0,0) to the center of the canvas
        context.translate(canvas.width / 2, canvas.height / 2);
        
        // Green rectangle in the middle
        context.fillStyle = "green";
        context.fillRect(-50, -25, 100, 50);
        
        // Make the remaining content 40% transparent
        context.globalAlpha = 0.6;
        
        // Supply arguments for transform function
        var scaleX = 2;
        var skewY = 0;
        var skewX = 1;
        var scaleY = 1;
        var translateX = -10;
        var translateY = 30;
        context.transform(scaleX, skewY, skewX, scaleY, translateX, translateY);
        
        // Purple rectangle that is transformed
        context.fillStyle = "purple";
        context.fillRect(-50, -25, 100, 50);