UNPKG

codehs-graphics

Version:

Helpers used to run graphics problems in the CodeHS editor.

205 lines (182 loc) 6.2 kB
'use strict'; var Thing = require('./thing.js'); /** * @class Text * @augments Thing * @param {string|number} label - The words of the text. * @param {string} font - String of the desired font of the text. */ function Text(label, font) { if (arguments.length < 1) { throw new Error('You should pass at least one argument to <span ' + 'class="code">new Text(label, font)</span>. <span class="code">' + 'label</span> is a required parameter.'); } if (typeof label !== 'string' && typeof label !== 'number') { throw new TypeError('Invalid value for <span class="code">label' + '</span>. You passed a value of type ' + typeof label + ' but a string or number is required.'); } font = font === undefined ? '20pt Arial' : font; if (typeof font !== 'string') { throw new TypeError('Invalid value for <span class="code">font' + '</span>. You passed a value of type ' + typeof label + ' but a string is required.'); } Thing.call(this); this.label = label; this.type = 'Text'; this.font = font; // Text needs a graphics context for computing height and width // we set this by default on running any graphics program, but // then it can get over-written the first time we call draw. this.context = null; this.resetDimensions(); } Text.prototype = new Thing(); Text.prototype.constructor = Text; Text.defaultContext = null; /** * Define a default context for the text. * Text objects need access to some 2d graphics context to compute * height and width. This might be done before a draw call. * * @param {CodeHSGraphics} __graphics__ - Instance of the graphics module. */ Text.giveDefaultContext = function(__graphics__) { Text.defaultContext = __graphics__.getContext(); }; /** * Reset the dimensions of the text to the size in the context. */ Text.prototype.resetDimensions = function() { var context = this.context || Text.defaultContext; context.font = this.font; this.width = context.measureText(this.label).width; this.height = context.measureText('m').width * 1.2; /* No height provided */ }; /** * Draw the text in the current context. * * @param {CodeHSGraphics} __graphics__ - Instance of the graphics module. */ Text.prototype.draw = function(__graphics__) { var context = __graphics__.getContext(); this.context = context; // http://stackoverflow.com/questions/17125632/html5-canvas-rotate-object-without-moving-coordinates context.save(); context.fillStyle = this.color.toString(); context.beginPath(); context.font = this.font; this.resetDimensions(); context.translate(this.x, this.y); context.rotate(this.rotation); context.fillText(this.label, 0, 0); context.closePath(); context.fill(); context.restore(); }; /** * Set the font of the text. * Re-calculates the dimensions of the font after font change. * * @param {string} font - String of the desired font for the text. */ Text.prototype.setFont = function(font) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">setFont</span>'); } if (typeof font !== 'string') { throw new TypeError('Invalid value passed to <span class=' + '"code">setFont</span>. You passed a value of type ' + typeof label + ', but a string is required.'); } this.font = font; this.resetDimensions(); }; /** * Set the label of the text. * Re-calculates the dimensions of the font after font change. * * @param {string|number} label - The words of the text. */ Text.prototype.setLabel = function(label) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">setLabel</span>'); } if (typeof label !== 'string' && typeof label !== 'number') { throw new TypeError('Invalid value passed to <span class=' + '"code">setLabel</span>. You passed a value of type ' + typeof label + ', but a string or number is required.'); } this.label = label; this.resetDimensions(); }; /** * Equivalent to `setLabel`. Likely created to prevent errors on * accidental calls. * Re-calculates the dimensions of the font after font change. * * @param {string|number} label - The words of the text. */ Text.prototype.setText = function(label) { if (arguments.length !== 1) { throw new Error('You should pass exactly 1 argument to <span ' + 'class="code">setText</span>'); } if (typeof label !== 'string' && typeof label !== 'number') { throw new TypeError('Invalid value passed to <span class=' + '"code">setText</span>. You passed a value of type ' + typeof label + ', but a string or number is required.'); } this.label = label; this.resetDimensions(); }; /** * Returns the label of a Text object. * * @returns {string} String of the Text's current label. */ Text.prototype.getLabel = function() { return this.label; }; /** * Equivalent to `getLabel`. Likely created to prevent errors on accidental * calls. * Returns the label of a Text object. * * @returns {string} String of the Text's current label. */ Text.prototype.getText = function() { return this.label; }; /** * Returns the width of a Text object. * * @returns {number} The width of the text. */ Text.prototype.getWidth = function() { return this.width; }; /** * Returns the height of a Text object. * * @returns {number} The height of the text. */ Text.prototype.getHeight = function() { return this.height; }; /** * Checks if the passed point is contained in the text. * * @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 text. */ Text.prototype.containsPoint = function(x, y) { return x >= this.x && x <= this.x + this.width && y <= this.y && y >= this.y - this.height; }; module.exports = Text;