UNPKG

codehs-graphics

Version:

Helpers used to run graphics problems in the CodeHS editor.

195 lines (178 loc) 7.07 kB
'use strict'; var Thing = require('./thing.js'); /** * @class Rectangle * @augments Thing * @param {number} width - Desired width of resulting rectangle. * @param {number} height - Desired height of resulting rectangle. */ function Rectangle(width, height) { if (arguments.length !== 2) { throw new Error( 'You should pass exactly 2 arguments to <span ' + 'class="code">new Rectangle(width, height)</span>' ); } if (typeof width !== 'number' || !isFinite(width)) { throw new TypeError( 'Invalid value for <span class="code">width' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">new Rectangle(width, height)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?' ); } if (typeof height !== 'number' || !isFinite(height)) { throw new TypeError( 'Invalid value for <span class="code">height' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">new Rectangle(width, height)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?' ); } Thing.call(this); this.width = Math.max(0, width); this.height = Math.max(0, height); this.type = 'Rectangle'; } Rectangle.prototype = new Thing(); Rectangle.prototype.constructor = Rectangle; /** * Draws the rectangle in the canvas. * * @param {CodeHSGraphics} __graphics__ - Instance of the __graphics__ module. */ Rectangle.prototype.draw = function(__graphics__) { var context = __graphics__.getContext(); // http://stackoverflow.com/questions/17125632/html5-canvas-rotate-object-without-moving-coordinates context.save(); context.fillStyle = this.color.toString(); if (this.hasBorder) { context.lineWidth = this.lineWidth; context.strokeStyle = this.stroke.toString(); } context.beginPath(); context.translate(this.x + this.width / 2, this.y + this.height / 2); context.rotate(this.rotation); // Note: after transforming [0,0] is visually [x,y] // so the rect needs to be offset accordingly when drawn context.rect(-this.width / 2, -this.height / 2, this.width, this.height); context.closePath(); if (this.hasBorder) { context.stroke(); } context.fill(); context.restore(); }; /** * Sets the size of the Rectangle. * * @param {number} width - The desired width of the resulting Rectangle. * @param {number} height - The desired height of the resulting Rectangle. */ Rectangle.prototype.setSize = function(width, height) { if (arguments.length !== 2) { throw new Error( 'You should pass exactly 2 arguments to <span ' + 'class="code">setSize(width, height)</span>' ); } if (typeof width !== 'number' || !isFinite(width)) { throw new TypeError( 'Invalid value for <span class="code">width' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">setSize(width, height)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?' ); } if (typeof height !== 'number' || !isFinite(height)) { throw new TypeError( 'Invalid value for <span class="code">height' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">setSize(width, height)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?' ); } this.width = Math.max(0, width); this.height = Math.max(0, height); }; /** * Sets the width of the Rectangle. * * @param {number} width - The desired width of the resulting Rectangle. */ Rectangle.prototype.setWidth = function(width) { if (arguments.length !== 1) { throw new Error( 'You should pass exactly 1 argument to <span class="code">setWidth(width)</span>' ); } if (typeof width !== 'number' || !isFinite(width)) { throw new TypeError( 'Invalid value for <span class="code">width' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">setWidth(width)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?' ); } this.width = Math.max(0, width); }; /** * Sets the height of the Rectangle. * * @param {number} height - The desired height of the resulting Rectangle. */ Rectangle.prototype.setHeight = function(height) { if (arguments.length !== 1) { throw new Error( 'You should pass exactly 1 argument to <span class="code">setHeight(height)</span>' ); } if (typeof height !== 'number' || !isFinite(height)) { throw new TypeError( 'Invalid value for <span class="code">height' + '</span>. Make sure you are passing finite numbers to <span ' + 'class="code">setHeight(height)</span>. Did you ' + 'forget the parentheses in <span class="code">getWidth()</span> ' + 'or <span class="code">getHeight()</span>? Or did you perform a ' + 'calculation on a variable that is not a number?' ); } this.height = Math.max(0, height); }; /** * Checks if the passed point is contained in the rectangle. * * @param {number} x - The x coordinate of the point being tested. * @param {number} y - The y coordinate of the point being tested. * @returns {boolean} Whether the passed point is contained in the rectangle. */ Rectangle.prototype.containsPoint = function(x, y) { return x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height; }; /** * Gets the width of the rectangle. * * @returns {number} Width of the rectangle. */ Rectangle.prototype.getWidth = function() { return this.width; }; /** * Gets the height of the rectangle. * * @returns {number} Height of the rectangle. */ Rectangle.prototype.getHeight = function() { return this.height; }; module.exports = Rectangle;