diff --git a/src/visual/ButtonStim.js b/src/visual/ButtonStim.js index 4055de4..bc422e5 100644 --- a/src/visual/ButtonStim.js +++ b/src/visual/ButtonStim.js @@ -7,10 +7,8 @@ * @license Distributed under the terms of the MIT License */ - -import {TextBox} from './TextBox.js'; -import {Mouse} from '../core/Mouse.js'; - +import { Mouse } from "../core/Mouse.js"; +import { TextBox } from "./TextBox.js"; /** *

ButtonStim visual stimulus.

@@ -39,28 +37,71 @@ import {Mouse} from '../core/Mouse.js'; */ export class ButtonStim extends TextBox { - constructor({win, name, text, font, pos, size, padding, anchor = 'center', units, color, fillColor = 'darkgrey', borderColor, borderWidth = 0, opacity, letterHeight, bold = true, italic, autoDraw, autoLog} = {}) + constructor( + { + win, + name, + text, + font, + pos, + size, + padding, + anchor = "center", + units, + color, + fillColor = "darkgrey", + borderColor, + borderWidth = 0, + opacity, + letterHeight, + bold = true, + italic, + autoDraw, + autoLog, + } = {}, + ) { - super({win, name, text, font, pos, size, padding, anchor, units, color, fillColor, borderColor, borderWidth, opacity, letterHeight, bold, italic, alignment: 'center', autoDraw, autoLog}); + super({ + win, + name, + text, + font, + pos, + size, + padding, + anchor, + units, + color, + fillColor, + borderColor, + borderWidth, + opacity, + letterHeight, + bold, + italic, + alignment: "center", + autoDraw, + autoLog, + }); - this.psychoJS.logger.debug('create a new Button with name: ', name); + this.psychoJS.logger.debug("create a new Button with name: ", name); - this.listener = new Mouse({name, win, autoLog}); + this.listener = new Mouse({ name, win, autoLog }); this._addAttribute( - 'wasClicked', - false + "wasClicked", + false, ); // Arrays to store times of clicks on and off this._addAttribute( - 'timesOn', - [] + "timesOn", + [], ); this._addAttribute( - 'timesOff', - [] + "timesOff", + [], ); if (this._autoLog) @@ -69,8 +110,6 @@ export class ButtonStim extends TextBox } } - - /** * How many times has this button been clicked on? * @@ -82,8 +121,6 @@ export class ButtonStim extends TextBox return this.timesOn.length; } - - /** * Is this button currently being clicked on? * @@ -94,5 +131,4 @@ export class ButtonStim extends TextBox { return this.listener.isPressedIn(this, [1, 0, 0]); } - } diff --git a/src/visual/Form.js b/src/visual/Form.js index a526ffd..5d7001f 100644 --- a/src/visual/Form.js +++ b/src/visual/Form.js @@ -7,19 +7,16 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {Color} from '../util/Color.js'; -import {ColorMixin} from '../util/ColorMixin.js'; -import * as util from '../util/Util.js'; -import {TrialHandler} from '../data/TrialHandler.js'; -import {TextStim} from './TextStim.js'; -import {TextBox} from './TextBox.js'; -import {VisualStim} from './VisualStim.js'; -import {Slider} from './Slider.js'; +import * as PIXI from "pixi.js-legacy"; +import { TrialHandler } from "../data/TrialHandler.js"; +import { Color } from "../util/Color.js"; +import { ColorMixin } from "../util/ColorMixin.js"; import { to_pixiPoint } from "../util/Pixi.js"; - - +import * as util from "../util/Util.js"; +import { Slider } from "./Slider.js"; +import { TextBox } from "./TextBox.js"; +import { TextStim } from "./TextStim.js"; +import { VisualStim } from "./VisualStim.js"; /** * Form stimulus. @@ -58,99 +55,127 @@ import { to_pixiPoint } from "../util/Pixi.js"; */ export class Form extends util.mix(VisualStim).with(ColorMixin) { - constructor({name, win, pos, size, units, borderColor, fillColor, itemColor, markerColor, responseColor, color, contrast, opacity, depth, items, randomize, itemPadding, font, fontFamily, bold, italic, fontSize, clipMask, autoDraw, autoLog} = {}) + constructor( + { + name, + win, + pos, + size, + units, + borderColor, + fillColor, + itemColor, + markerColor, + responseColor, + color, + contrast, + opacity, + depth, + items, + randomize, + itemPadding, + font, + fontFamily, + bold, + italic, + fontSize, + clipMask, + autoDraw, + autoLog, + } = {}, + ) { - super({name, win, units, opacity, depth, pos, size, clipMask, autoDraw, autoLog}); + super({ name, win, units, opacity, depth, pos, size, clipMask, autoDraw, autoLog }); this._addAttribute( - 'itemPadding', + "itemPadding", itemPadding, - util.to_unit([20, 0], 'pix', win, this._units)[0], - this._onChange(true, false) + util.to_unit([20, 0], "pix", win, this._units)[0], + this._onChange(true, false), ); // colors: this._addAttribute( - 'color', + "color", // Same as itemColor color, undefined, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'borderColor', + "borderColor", borderColor, fillColor, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'fillColor', + "fillColor", fillColor, undefined, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'itemColor', + "itemColor", itemColor, undefined, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'markerColor', + "markerColor", markerColor, undefined, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'responseColor', + "responseColor", responseColor, undefined, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'contrast', + "contrast", contrast, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); // fonts: this._addAttribute( - 'font', + "font", font, - 'Arial', - this._onChange(true, true) + "Arial", + this._onChange(true, true), ); // Not in use at present this._addAttribute( - 'fontFamily', + "fontFamily", fontFamily, - 'Helvetica', - this._onChange(true, true) + "Helvetica", + this._onChange(true, true), ); this._addAttribute( - 'fontSize', + "fontSize", fontSize, - (this._units === 'pix') ? 14 : 0.03, - this._onChange(true, true) + (this._units === "pix") ? 14 : 0.03, + this._onChange(true, true), ); this._addAttribute( - 'bold', + "bold", bold, false, - this._onChange(true, true) + this._onChange(true, true), ); this._addAttribute( - 'italic', + "italic", italic, false, - this._onChange(true, true) + this._onChange(true, true), ); // callback to deal with changes to items: @@ -166,16 +191,17 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) }; this._addAttribute( - 'items', + "items", items, [], - onItemChange); + onItemChange, + ); this._addAttribute( - 'randomize', + "randomize", randomize, false, - onItemChange); - + onItemChange, + ); this._scrollbarWidth = 0.02; this._responseTextHeightRatio = 0.8; @@ -192,8 +218,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } } - - /** * Force a refresh of the stimulus. * @@ -218,8 +242,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } } - - /** * Overridden draw that also calls the draw method of all form elements. * @@ -260,8 +282,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._scrollbar.draw(); } - - /** * Overridden hide that also calls the hide method of all form elements. * @@ -276,7 +296,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) super.hide(); // hide the stimuli: - if (typeof this._items !== 'undefined') + if (typeof this._items !== "undefined") { for (let i = 0; i < this._items.length; ++i) { @@ -298,8 +318,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } } - - /** * Reset the form. * @@ -309,7 +327,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) */ reset() { - this.psychoJS.logger.debug('reset Form: ', this._name); + this.psychoJS.logger.debug("reset Form: ", this._name); // reset the stimuli: for (let i = 0; i < this._items.length; ++i) @@ -327,8 +345,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._needUpdate = true; } - - /** * Collate the questions and responses into a single dataset. * @@ -352,9 +368,9 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) item.response = responseStim.getRating(); item.rt = responseStim.getRT(); - if (typeof item.response === 'undefined') + if (typeof item.response === "undefined") { - ++ nbIncompleteResponse; + ++nbIncompleteResponse; } } else if (item.type === Form.Types.FREE_TEXT) @@ -364,7 +380,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) if (item.response.length === 0) { - ++ nbIncompleteResponse; + ++nbIncompleteResponse; } } } @@ -372,9 +388,8 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._items._complete = (nbIncompleteResponse === 0); - // return a copy of this._items: - return this._items.map(item => Object.assign({}, item)); + return this._items.map((item) => Object.assign({}, item)); } /** * Check if the form is complete. @@ -386,7 +401,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) */ formComplete() { - //same as complete but might be used by some experiments before 2020.2 + // same as complete but might be used by some experiments before 2020.2 this.getData(); return this._items._complete; } @@ -399,15 +414,21 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) * @param {module:data.ExperimentHandler} experiment - the experiment into which to insert the form data * @param {string} [format= 'rows'] - whether to insert the data as rows or as columns */ - addDataToExp(experiment, format = 'rows') + addDataToExp(experiment, format = "rows") { - const addAsColumns = ['cols', 'columns'].includes(format.toLowerCase()); + const addAsColumns = ["cols", "columns"].includes(format.toLowerCase()); const data = this.getData(); const _doNotSave = [ - 'itemCtrl', 'responseCtrl', - 'itemColor', 'options', 'ticks', 'tickLabels', - 'responseWidth', 'responseColor', 'layout' + "itemCtrl", + "responseCtrl", + "itemColor", + "options", + "ticks", + "tickLabels", + "responseWidth", + "responseColor", + "layout", ]; for (const item of this.getData()) @@ -420,7 +441,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) const columnName = (addAsColumns) ? `${this._name}[${index}]${field}` : `${this._name}${field}`; experiment.addData(columnName, item[field]); } - ++ index; + ++index; } if (!addAsColumns) @@ -435,8 +456,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } } - - /** * Import and process the form items from either a spreadsheet resource files (.csv, .xlsx, etc.) or from an array. * @@ -447,8 +466,8 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) _processItems() { const response = { - origin: 'Form._processItems', - context: 'when processing the form items' + origin: "Form._processItems", + context: "when processing the form items", }; try @@ -456,7 +475,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) if (this._autoLog) { // note: we use the same log message as PsychoPy even though we called this method differently - this._psychoJS.experimentLogger.exp('Importing items...'); + this._psychoJS.experimentLogger.exp("Importing items..."); } // import the items: @@ -474,12 +493,10 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) catch (error) { // throw { ...response, error }; - throw Object.assign(response, {error}); + throw Object.assign(response, { error }); } } - - /** * Import the form items from either a spreadsheet resource files (.csv, .xlsx, etc.) or from an array. * @@ -490,8 +507,8 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) _importItems() { const response = { - origin: 'Form._importItems', - context: 'when importing the form items' + origin: "Form._importItems", + context: "when importing the form items", }; try @@ -499,17 +516,15 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) const itemsType = typeof this._items; // we treat undefined items as a list with a single default entry: - if (itemsType === 'undefined') + if (itemsType === "undefined") { this._items = [Form._defaultItems]; } - // if items is a string, we treat it as the name of a resource file and import it: - else if (itemsType === 'string') + else if (itemsType === "string") { this._items = TrialHandler.importConditions(this._psychoJS.serverManager, this._items); } - // unknown items type: else { @@ -521,17 +536,14 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) { this._items = [Form._defaultItems]; } - } catch (error) { // throw { ...response, error }; - throw Object.assign(response, {error}); + throw Object.assign(response, { error }); } } - - /** * Sanitize the form items: check that the keys are valid, and fill in default values. * @@ -542,8 +554,8 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) _sanitizeItems() { const response = { - origin: 'Form._sanitizeItems', - context: 'when sanitizing the form items' + origin: "Form._sanitizeItems", + context: "when sanitizing the form items", }; try @@ -552,7 +564,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) for (const item of this._items) { // old style forms have questionText instead of itemText: - if (typeof item.questionText !== 'undefined') + if (typeof item.questionText !== "undefined") { item.itemText = item.questionText; delete item.questionText; @@ -561,12 +573,11 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) delete item.questionWidth; // for items of type 'rating, the ticks are in 'options' instead of in 'ticks': - if (item.type === 'rating' || item.type === 'slider') + if (item.type === "rating" || item.type === "slider") { item.ticks = item.options; item.options = undefined; } - } } @@ -584,9 +595,8 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) missingKeys.add(key); item[key] = Form._defaultItems[key]; } - // undefined value: - else if (typeof item[key] === 'undefined') + else if (typeof item[key] === "undefined") { // TODO: options = '' for FREE_TEXT item[key] = Form._defaultItems[key]; @@ -596,16 +606,17 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) if (missingKeys.size > 0) { - this._psychoJS.logger.warn(`Missing headers: ${Array.from(missingKeys).join(', ')}\nNote, headers are case sensitive and must match: ${Array.from(defaultKeys).join(', ')}`); + this._psychoJS.logger.warn( + `Missing headers: ${Array.from(missingKeys).join(", ")}\nNote, headers are case sensitive and must match: ${Array.from(defaultKeys).join(", ")}`, + ); } - // check the types and options: const formTypes = Object.getOwnPropertyNames(Form.Types); for (const item of this._items) { // convert type to upper case, replace spaces by underscores - item.type = item.type.toUpperCase().replace(' ', '_'); + item.type = item.type.toUpperCase().replace(" ", "_"); // check that the type is valid: if (!formTypes.includes(item.type)) @@ -614,9 +625,9 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } // Support the 'radio' type found on older versions of PsychoPy - if (item.type === 'RADIO') + if (item.type === "RADIO") { - item.type = 'CHOICE'; + item.type = "CHOICE"; } // convert item type to symbol: @@ -625,18 +636,17 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) // turn the option into an array and check length, where applicable: if (item.type === Form.Types.CHOICE) { - item.options = item.options.split(','); + item.options = item.options.split(","); if (item.options.length < 2) { throw `at least two choices should be provided for choice item: ${item.itemText}`; } } - // turn the ticks and tickLabels into arrays, where applicable: else if (item.type === Form.Types.RATING || item.type === Form.Types.SLIDER) { - item.ticks = item.ticks.split(',').map( (_,t) => parseInt(t) ); - item.tickLabels = (item.tickLabels.length > 0) ? item.tickLabels.split(',') : []; + item.ticks = item.ticks.split(",").map((_, t) => parseInt(t)); + item.tickLabels = (item.tickLabels.length > 0) ? item.tickLabels.split(",") : []; } // TODO @@ -645,7 +655,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } // check the layout: - const formLayouts = ['HORIZ', 'VERT']; + const formLayouts = ["HORIZ", "VERT"]; for (const item of this._items) { // convert layout to upper case: @@ -658,18 +668,16 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } // convert item layout to symbol: - item.layout = (item.layout === 'HORIZ') ? Form.Layout.HORIZONTAL : Form.Layout.VERTICAL; + item.layout = (item.layout === "HORIZ") ? Form.Layout.HORIZONTAL : Form.Layout.VERTICAL; } } catch (error) { // throw { ...response, error }; - throw Object.assign(response, {error}); + throw Object.assign(response, { error }); } } - - /** * Estimate the bounding box. * @@ -685,12 +693,10 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._pos[0] - this._size[0] / 2.0, this._pos[1] - this._size[1] / 2.0, this._size[0], - this._size[1] + this._size[1], ); } - - /** * Setup the stimuli, and the scrollbar. * @@ -706,7 +712,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } // clean up the previously setup stimuli: - if (typeof this._visual !== 'undefined') + if (typeof this._visual !== "undefined") { for (const textStim of this._visual.textStims) { @@ -724,31 +730,30 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) textStims: [], responseStims: [], visibles: [], - stimuliTotalHeight: 0 + stimuliTotalHeight: 0, }; // instantiate the clip mask that will be used by all stimuli: this._stimuliClipMask = new PIXI.Graphics(); - // default stimulus options: const textStimOption = { win: this._win, - name: 'item text', + name: "item text", font: this.font, units: this._units, - alignHoriz: 'left', - alignVert: 'top', + alignHoriz: "left", + alignVert: "top", height: this._fontSize, color: this.itemColor, ori: 0, opacity: 1, depth: this._depth + 1, - clipMask: this._stimuliClipMask + clipMask: this._stimuliClipMask, }; const sliderOption = { win: this._win, - name: 'choice response', + name: "choice response", units: this._units, flip: false, // Not part of Slider options as things stand @@ -763,13 +768,13 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) opacity: 1, depth: this._depth + 1, clipMask: this._stimuliClipMask, - granularity: 1 + granularity: 1, }; const textBoxOption = { win: this._win, - name: 'free text response', + name: "free text response", units: this._units, - anchor: 'left-top', + anchor: "left-top", flip: false, opacity: 1, depth: this._depth + 1, @@ -777,7 +782,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) letterHeight: this._fontSize * this._responseTextHeightRatio, bold: false, italic: false, - alignment: 'left', + alignment: "left", color: this.responseColor, fillColor: this.fillColor, contrast: 1.0, @@ -785,17 +790,16 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) borderWidth: 0.002, padding: 0.01, editable: true, - clipMask: this._stimuliClipMask + clipMask: this._stimuliClipMask, }; // we use for the slider's tick size the height of a word: - const textStim = new TextStim(Object.assign(textStimOption, { text: 'Ag', pos: [0, 0]})); + const textStim = new TextStim(Object.assign(textStimOption, { text: "Ag", pos: [0, 0] })); const textMetrics_px = textStim.getTextMetrics(); const sliderTickSize = this._getLengthUnits(textMetrics_px.height) / 2; textStim.release(false); - - let stimulusOffset = - this._itemPadding; + let stimulusOffset = -this._itemPadding; for (const item of this._items) { // initially, all items are invisible: @@ -806,8 +810,10 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) // - description: + + + = this._size[0] // - choice with vert layout: + + + = this._size[0] let rowWidth; - if (item.type === Form.Types.HEADING || item.type === Form.Types.DESCRIPTION || - (item.type === Form.Types.CHOICE && item.layout === Form.Layout.VERTICAL)) + if ( + item.type === Form.Types.HEADING || item.type === Form.Types.DESCRIPTION + || (item.type === Form.Types.CHOICE && item.layout === Form.Layout.VERTICAL) + ) { rowWidth = (this._size[0] - this._itemPadding * 2 - this._scrollbarWidth); } @@ -818,12 +824,13 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } // item text - const itemWidth = rowWidth * item.itemWidth; + const itemWidth = rowWidth * item.itemWidth; const textStim = new TextStim( Object.assign(textStimOption, { text: item.itemText, - wrapWidth: itemWidth - })); + wrapWidth: itemWidth, + }), + ); textStim._relativePos = [this._itemPadding, stimulusOffset]; const textHeight = textStim.boundingBox.height; this._visual.textStims.push(textStim); @@ -847,7 +854,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } else { - sliderSize = [sliderTickSize, (sliderTickSize*1.5) * item.options.length]; + sliderSize = [sliderTickSize, (sliderTickSize * 1.5) * item.options.length]; compact = false; flip = true; } @@ -882,23 +889,23 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) labels, ticks, compact, - flip - }) + flip, + }), ); responseHeight = responseStim.boundingBox.height; if (item.layout === Form.Layout.HORIZONTAL) { responseStim._relativePos = [ this._itemPadding * 2 + itemWidth + responseWidth / 2, - stimulusOffset - //- Math.max(0, (textHeight - responseHeight) / 2) // (vertical centering) + stimulusOffset, + // - Math.max(0, (textHeight - responseHeight) / 2) // (vertical centering) ]; } else { responseStim._relativePos = [ - this._itemPadding * 2 + itemWidth, //this._itemPadding + sliderTickSize, - stimulusOffset - responseHeight / 2 - textHeight - this._itemPadding + this._itemPadding * 2 + itemWidth, // this._itemPadding + sliderTickSize, + stimulusOffset - responseHeight / 2 - textHeight - this._itemPadding, ]; // since rowHeight will be the max of itemHeight and responseHeight, we need to alter responseHeight @@ -906,20 +913,19 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) responseHeight += textHeight + this._itemPadding; } } - // FREE TEXT else if (item.type === Form.Types.FREE_TEXT) { responseStim = new TextBox( Object.assign(textBoxOption, { text: item.options, - size: [responseWidth, -1] - }) + size: [responseWidth, -1], + }), ); responseHeight = responseStim.boundingBox.height; responseStim._relativePos = [ this._itemPadding * 2 + itemWidth, - stimulusOffset + stimulusOffset, ]; } @@ -932,13 +938,12 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) } this._visual.stimuliTotalHeight = stimulusOffset; - // scrollbar // note: we add this Form as a dependent stimulus such that the Form is redrawn whenever // the slider is updated this._scrollbar = new Slider({ win: this._win, - name: 'scrollbar', + name: "scrollbar", units: this._units, color: this.itemColor, depth: this._depth + 1, @@ -946,24 +951,20 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) size: [this._scrollbarWidth, this._size[1]], style: [Slider.Style.SLIDER], ticks: [0, -this._visual.stimuliTotalHeight / this._size[1]], - dependentStims: [this] + dependentStims: [this], }); this._prevScrollbarMarkerPos = 0; this._scrollbar.setMarkerPos(this._prevScrollbarMarkerPos); - // estimate the bounding box: this._estimateBoundingBox(); - if (this._autoLog) { this._psychoJS.experimentLogger.exp(`Layout set for: ${this.name}`); } } - - /** * Update the form visual representation, if necessary. * @@ -991,17 +992,18 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) [this._leftEdge, this._topEdge], this.units, this.win, - true); + true, + ); [this._rightEdge_px, this._bottomEdge_px] = util.to_px( [this._rightEdge, this._bottomEdge], this.units, this.win, - true); + true, + ); this._itemPadding_px = this._getLengthPix(this._itemPadding); this._scrollbarWidth_px = this._getLengthPix(this._scrollbarWidth, true); this._size_px = util.to_px(this._size, this.units, this.win, true); - // update the stimuli clip mask // note: the clip mask is in screen coordinates this._stimuliClipMask.clear(); @@ -1010,11 +1012,10 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._win._rootContainer.position.x + this._leftEdge_px + 2, this._win._rootContainer.position.y + this._bottomEdge_px + 2, this._size_px[0] - 4, - this._size_px[1] - 6 + this._size_px[1] - 6, ); this._stimuliClipMask.endFill(); - // position the scrollbar and get the scrollbar offset, in form units: this._scrollbar.setPos([this._rightEdge - this._scrollbarWidth / 2, this._pos[1]], false); this._scrollbar.setOpacity(0.5); @@ -1025,8 +1026,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._updateDecorations(); } - - /** * Update the visible stimuli. * @@ -1042,7 +1041,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) const textStim = this._visual.textStims[i]; const textStimPos = [ this._leftEdge + textStim._relativePos[0], - this._topEdge + textStim._relativePos[1] - this._scrollbarOffset + this._topEdge + textStim._relativePos[1] - this._scrollbarOffset, ]; textStim.setPos(textStimPos); @@ -1052,7 +1051,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) { const responseStimPos = [ this._leftEdge + responseStim._relativePos[0], - this._topEdge + responseStim._relativePos[1] - this._scrollbarOffset + this._topEdge + responseStim._relativePos[1] - this._scrollbarOffset, ]; responseStim.setPos(responseStimPos); } @@ -1078,11 +1077,8 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._visual.visibles[i] = false; } } - } - - /** * Update the form decorations (bounding box, lines between items, etc.) * @@ -1092,7 +1088,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) */ _updateDecorations() { - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { this._pixi.destroy(true); } @@ -1109,7 +1105,6 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) // apply the form clip mask (n.b., that is not the stimuli clip mask): this._pixi.mask = this._clipMask; - // form background: this._pixi.lineStyle(1, new Color(this.borderColor).int, this._opacity, 0.5); // this._decorations.beginFill(this._barFillColor.int, this._opacity); @@ -1122,7 +1117,7 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) this._decorations = new PIXI.Graphics(); this._pixi.addChild(this._decorations); this._decorations.mask = this._stimuliClipMask; - this._decorations.lineStyle(1, new Color('gray').int, this._opacity, 0.5); + this._decorations.lineStyle(1, new Color("gray").int, this._opacity, 0.5); this._decorations.alpha = 0.5; for (let i = 0; i < this._items.length; ++i) @@ -1136,27 +1131,23 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) const textStim = this._visual.textStims[i]; const textStimPos = [ this._leftEdge + textStim._relativePos[0], - this._topEdge + textStim._relativePos[1] - this._scrollbarOffset + this._topEdge + textStim._relativePos[1] - this._scrollbarOffset, ]; const textStimPos_px = util.to_px(textStimPos, this._units, this._win); - this._decorations.beginFill(new Color('darkgray').int); + this._decorations.beginFill(new Color("darkgray").int); this._decorations.drawRect( textStimPos_px[0] - this._itemPadding_px / 2, textStimPos_px[1] + this._itemPadding_px / 2, this._size_px[0] - this._itemPadding_px - this._scrollbarWidth_px, - -this._getLengthPix(this._visual.rowHeights[i]) - this._itemPadding_px + -this._getLengthPix(this._visual.rowHeights[i]) - this._itemPadding_px, ); this._decorations.endFill(); } } } - - } } - - /** * Form item types. * @@ -1165,17 +1156,15 @@ export class Form extends util.mix(VisualStim).with(ColorMixin) * @public */ Form.Types = { - HEADING: Symbol.for('HEADING'), - DESCRIPTION: Symbol.for('DESCRIPTION'), - RATING: Symbol.for('RATING'), - SLIDER: Symbol.for('SLIDER'), - FREE_TEXT: Symbol.for('FREE_TEXT'), - CHOICE: Symbol.for('CHOICE'), - RADIO: Symbol.for('RADIO') + HEADING: Symbol.for("HEADING"), + DESCRIPTION: Symbol.for("DESCRIPTION"), + RATING: Symbol.for("RATING"), + SLIDER: Symbol.for("SLIDER"), + FREE_TEXT: Symbol.for("FREE_TEXT"), + CHOICE: Symbol.for("CHOICE"), + RADIO: Symbol.for("RADIO"), }; - - /** * Form item layout. * @@ -1184,12 +1173,10 @@ Form.Types = { * @public */ Form.Layout = { - HORIZONTAL: Symbol.for('HORIZONTAL'), - VERTICAL: Symbol.for('VERTICAL') + HORIZONTAL: Symbol.for("HORIZONTAL"), + VERTICAL: Symbol.for("VERTICAL"), }; - - /** * Default form item. * @@ -1198,18 +1185,16 @@ Form.Layout = { * */ Form._defaultItems = { - 'itemText': 'Default question', - 'type': 'rating', - 'options': 'Yes, No', - 'tickLabels': '', - 'itemWidth': 0.7, - 'itemColor': 'white', + "itemText": "Default question", + "type": "rating", + "options": "Yes, No", + "tickLabels": "", + "itemWidth": 0.7, + "itemColor": "white", - 'responseWidth': 0.3, - 'responseColor': 'white', + "responseWidth": 0.3, + "responseColor": "white", - 'index': 0, - 'layout': 'horiz' + "index": 0, + "layout": "horiz", }; - - diff --git a/src/visual/ImageStim.js b/src/visual/ImageStim.js index 39479a8..29c542a 100644 --- a/src/visual/ImageStim.js +++ b/src/visual/ImageStim.js @@ -7,14 +7,12 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {VisualStim} from './VisualStim.js'; -import {Color} from '../util/Color.js'; -import {ColorMixin} from '../util/ColorMixin.js'; -import * as util from '../util/Util.js'; +import * as PIXI from "pixi.js-legacy"; +import { Color } from "../util/Color.js"; +import { ColorMixin } from "../util/ColorMixin.js"; import { to_pixiPoint } from "../util/Pixi.js"; - +import * as util from "../util/Util.js"; +import { VisualStim } from "./VisualStim.js"; /** * Image Stimulus. @@ -46,53 +44,53 @@ import { to_pixiPoint } from "../util/Pixi.js"; */ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) { - constructor({name, win, image, mask, pos, units, ori, size, color, opacity, contrast, texRes, depth, interpolate, flipHoriz, flipVert, autoDraw, autoLog} = {}) + constructor({ name, win, image, mask, pos, units, ori, size, color, opacity, contrast, texRes, depth, interpolate, flipHoriz, flipVert, autoDraw, autoLog } = {}) { - super({name, win, units, ori, opacity, depth, pos, size, autoDraw, autoLog}); + super({ name, win, units, ori, opacity, depth, pos, size, autoDraw, autoLog }); this._addAttribute( - 'image', - image + "image", + image, ); this._addAttribute( - 'mask', - mask + "mask", + mask, ); this._addAttribute( - 'color', + "color", color, - 'white', - this._onChange(true, false) + "white", + this._onChange(true, false), ); this._addAttribute( - 'contrast', + "contrast", contrast, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'texRes', + "texRes", texRes, 128, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'interpolate', + "interpolate", interpolate, false, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'flipHoriz', + "flipHoriz", flipHoriz, false, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'flipVert', + "flipVert", flipVert, false, - this._onChange(false, false) + this._onChange(false, false), ); // estimate the bounding box: @@ -104,8 +102,6 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) } } - - /** * Setter for the image attribute. * @@ -117,22 +113,22 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) setImage(image, log = false) { const response = { - origin: 'ImageStim.setImage', - context: 'when setting the image of ImageStim: ' + this._name + origin: "ImageStim.setImage", + context: "when setting the image of ImageStim: " + this._name, }; try { // image is undefined: that's fine but we raise a warning in case this is a symptom of an actual problem - if (typeof image === 'undefined') + if (typeof image === "undefined") { - this.psychoJS.logger.warn('setting the image of ImageStim: ' + this._name + ' with argument: undefined.'); - this.psychoJS.logger.debug('set the image of ImageStim: ' + this._name + ' as: undefined'); + this.psychoJS.logger.warn("setting the image of ImageStim: " + this._name + " with argument: undefined."); + this.psychoJS.logger.debug("set the image of ImageStim: " + this._name + " as: undefined"); } else { // image is a string: it should be the name of a resource, which we load - if (typeof image === 'string') + if (typeof image === "string") { image = this.psychoJS.serverManager.getResource(image); } @@ -140,16 +136,16 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) // image should now be an actual HTMLImageElement: we raise an error if it is not if (!(image instanceof HTMLImageElement)) { - throw 'the argument: ' + image.toString() + ' is not an image" }'; + throw "the argument: " + image.toString() + ' is not an image" }'; } - this.psychoJS.logger.debug('set the image of ImageStim: ' + this._name + ' as: src= ' + image.src + ', size= ' + image.width + 'x' + image.height); + this.psychoJS.logger.debug("set the image of ImageStim: " + this._name + " as: src= " + image.src + ", size= " + image.width + "x" + image.height); } const existingImage = this.getImage(); const hasChanged = existingImage ? existingImage.src !== image.src : true; - this._setAttribute('image', image, log); + this._setAttribute("image", image, log); if (hasChanged) { @@ -158,12 +154,10 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) } catch (error) { - throw Object.assign(response, {error}); + throw Object.assign(response, { error }); } } - - /** * Setter for the mask attribute. * @@ -175,22 +169,22 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) setMask(mask, log = false) { const response = { - origin: 'ImageStim.setMask', - context: 'when setting the mask of ImageStim: ' + this._name + origin: "ImageStim.setMask", + context: "when setting the mask of ImageStim: " + this._name, }; try { // mask is undefined: that's fine but we raise a warning in case this is a sympton of an actual problem - if (typeof mask === 'undefined') + if (typeof mask === "undefined") { - this.psychoJS.logger.warn('setting the mask of ImageStim: ' + this._name + ' with argument: undefined.'); - this.psychoJS.logger.debug('set the mask of ImageStim: ' + this._name + ' as: undefined'); + this.psychoJS.logger.warn("setting the mask of ImageStim: " + this._name + " with argument: undefined."); + this.psychoJS.logger.debug("set the mask of ImageStim: " + this._name + " as: undefined"); } else { // mask is a string: it should be the name of a resource, which we load - if (typeof mask === 'string') + if (typeof mask === "string") { mask = this.psychoJS.serverManager.getResource(mask); } @@ -198,24 +192,22 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) // mask should now be an actual HTMLImageElement: we raise an error if it is not if (!(mask instanceof HTMLImageElement)) { - throw 'the argument: ' + mask.toString() + ' is not an image" }'; + throw "the argument: " + mask.toString() + ' is not an image" }'; } - this.psychoJS.logger.debug('set the mask of ImageStim: ' + this._name + ' as: src= ' + mask.src + ', size= ' + mask.width + 'x' + mask.height); + this.psychoJS.logger.debug("set the mask of ImageStim: " + this._name + " as: src= " + mask.src + ", size= " + mask.width + "x" + mask.height); } - this._setAttribute('mask', mask, log); + this._setAttribute("mask", mask, log); this._onChange(true, false)(); } catch (error) { - throw Object.assign(response, {error}); + throw Object.assign(response, { error }); } } - - /** * Estimate the bounding box. * @@ -227,21 +219,19 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) _estimateBoundingBox() { const size = this._getDisplaySize(); - if (typeof size !== 'undefined') + if (typeof size !== "undefined") { this._boundingBox = new PIXI.Rectangle( this._pos[0] - size[0] / 2, this._pos[1] - size[1] / 2, size[0], - size[1] + size[1], ); } // TODO take the orientation into account } - - /** * Update the stimulus, if necessary. * @@ -261,14 +251,14 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) { this._needPixiUpdate = false; - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { this._pixi.destroy(true); } this._pixi = undefined; // no image to draw: return immediately - if (typeof this._image === 'undefined') + if (typeof this._image === "undefined") { return; } @@ -279,7 +269,7 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) this._pixi = PIXI.Sprite.from(this._texture); // add a mask if need be: - if (typeof this._mask !== 'undefined') + if (typeof this._mask !== "undefined") { this._pixi.mask = PIXI.Sprite.from(this._mask); @@ -330,8 +320,6 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) this._estimateBoundingBox(); } - - /** * Get the size of the display image, which is either that of the ImageStim or that of the image * it contains. @@ -344,18 +332,16 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) { let displaySize = this.size; - if (typeof displaySize === 'undefined') + if (typeof displaySize === "undefined") { // use the size of the texture, if we have access to it: - if (typeof this._texture !== 'undefined' && this._texture.width > 0) + if (typeof this._texture !== "undefined" && this._texture.width > 0) { const textureSize = [this._texture.width, this._texture.height]; - displaySize = util.to_unit(textureSize, 'pix', this.win, this.units); + displaySize = util.to_unit(textureSize, "pix", this.win, this.units); } } return displaySize; } - - } diff --git a/src/visual/MovieStim.js b/src/visual/MovieStim.js index 475b05f..945e471 100644 --- a/src/visual/MovieStim.js +++ b/src/visual/MovieStim.js @@ -7,15 +7,13 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {VisualStim} from './VisualStim.js'; -import {Color} from '../util/Color.js'; -import {ColorMixin} from '../util/ColorMixin.js'; -import * as util from '../util/Util.js'; -import {PsychoJS} from "../core/PsychoJS.js"; +import * as PIXI from "pixi.js-legacy"; +import { PsychoJS } from "../core/PsychoJS.js"; +import { Color } from "../util/Color.js"; +import { ColorMixin } from "../util/ColorMixin.js"; import { to_pixiPoint } from "../util/Pixi.js"; - +import * as util from "../util/Util.js"; +import { VisualStim } from "./VisualStim.js"; /** * Movie Stimulus. @@ -49,82 +47,81 @@ import { to_pixiPoint } from "../util/Pixi.js"; */ export class MovieStim extends VisualStim { - constructor({name, win, movie, pos, units, ori, size, color, opacity, contrast, interpolate, flipHoriz, flipVert, loop, volume, noAudio, autoPlay, autoDraw, autoLog} = {}) + constructor({ name, win, movie, pos, units, ori, size, color, opacity, contrast, interpolate, flipHoriz, flipVert, loop, volume, noAudio, autoPlay, autoDraw, autoLog } = {}) { - super({name, win, units, ori, opacity, pos, size, autoDraw, autoLog}); + super({ name, win, units, ori, opacity, pos, size, autoDraw, autoLog }); - this.psychoJS.logger.debug('create a new MovieStim with name: ', name); + this.psychoJS.logger.debug("create a new MovieStim with name: ", name); // movie and movie control: this._addAttribute( - 'movie', - movie + "movie", + movie, ); this._addAttribute( - 'volume', + "volume", volume, 1.0, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'noAudio', + "noAudio", noAudio, false, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'autoPlay', + "autoPlay", autoPlay, true, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'flipHoriz', + "flipHoriz", flipHoriz, false, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'flipVert', + "flipVert", flipVert, false, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'interpolate', + "interpolate", interpolate, false, - this._onChange(true, false) + this._onChange(true, false), ); // colors: this._addAttribute( - 'color', + "color", color, - 'white', - this._onChange(true, false) + "white", + this._onChange(true, false), ); this._addAttribute( - 'contrast', + "contrast", contrast, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'loop', + "loop", loop, false, - this._onChange(false, false) + this._onChange(false, false), ); - // estimate the bounding box: this._estimateBoundingBox(); // check whether the fastSeek method on HTMLVideoElement is implemented: - const videoElement = document.createElement('video'); - this._hasFastSeek = (typeof videoElement.fastSeek === 'function'); + const videoElement = document.createElement("video"); + this._hasFastSeek = (typeof videoElement.fastSeek === "function"); if (this._autoLog) { @@ -132,8 +129,6 @@ export class MovieStim extends VisualStim } } - - /** * Setter for the movie attribute. * @@ -146,22 +141,22 @@ export class MovieStim extends VisualStim setMovie(movie, log = false) { const response = { - origin: 'MovieStim.setMovie', - context: 'when setting the movie of MovieStim: ' + this._name + origin: "MovieStim.setMovie", + context: "when setting the movie of MovieStim: " + this._name, }; try { // movie is undefined: that's fine but we raise a warning in case this is a symptom of an actual problem - if (typeof movie === 'undefined') + if (typeof movie === "undefined") { - this.psychoJS.logger.warn('setting the movie of MovieStim: ' + this._name + ' with argument: undefined.'); - this.psychoJS.logger.debug('set the movie of MovieStim: ' + this._name + ' as: undefined'); + this.psychoJS.logger.warn("setting the movie of MovieStim: " + this._name + " with argument: undefined."); + this.psychoJS.logger.debug("set the movie of MovieStim: " + this._name + " as: undefined"); } else { // movie is a string: it should be the name of a resource, which we load - if (typeof movie === 'string') + if (typeof movie === "string") { movie = this.psychoJS.serverManager.getResource(movie); } @@ -169,7 +164,7 @@ export class MovieStim extends VisualStim // movie should now be an actual HTMLVideoElement: we raise an error if it is not if (!(movie instanceof HTMLVideoElement)) { - throw 'the argument: ' + movie.toString() + ' is not a video" }'; + throw "the argument: " + movie.toString() + ' is not a video" }'; } this.psychoJS.logger.debug(`set the movie of MovieStim: ${this._name} as: src= ${movie.src}, size= ${movie.videoWidth}x${movie.videoHeight}, duration= ${movie.duration}s`); @@ -186,20 +181,16 @@ export class MovieStim extends VisualStim } } - - - this._setAttribute('movie', movie, log); + this._setAttribute("movie", movie, log); this._needUpdate = true; this._needPixiUpdate = true; } catch (error) { - throw Object.assign(response, {error}); + throw Object.assign(response, { error }); } } - - /** * Reset the stimulus. * @@ -212,8 +203,6 @@ export class MovieStim extends VisualStim this.seek(0, log); } - - /** * Start playing the movie. * @@ -228,18 +217,17 @@ export class MovieStim extends VisualStim if (playPromise !== undefined) { - playPromise.catch((error) => { + playPromise.catch((error) => + { throw { - origin: 'MovieStim.play', + origin: "MovieStim.play", context: `when attempting to play MovieStim: ${this._name}`, - error + error, }; }); } } - - /** * Pause the movie. * @@ -251,8 +239,6 @@ export class MovieStim extends VisualStim this._movie.pause(); } - - /** * Stop the movie and reset to 0s. * @@ -265,8 +251,6 @@ export class MovieStim extends VisualStim this.seek(0, log); } - - /** * Jump to a specific timepoint * @@ -280,9 +264,9 @@ export class MovieStim extends VisualStim if (timePoint < 0 || timePoint > this._movie.duration) { throw { - origin: 'MovieStim.seek', + origin: "MovieStim.seek", context: `when seeking to timepoint: ${timePoint} of MovieStim: ${this._name}`, - error: `the timepoint does not belong to [0, ${this._movie.duration}` + error: `the timepoint does not belong to [0, ${this._movie.duration}`, }; } @@ -299,16 +283,14 @@ export class MovieStim extends VisualStim catch (error) { throw { - origin: 'MovieStim.seek', + origin: "MovieStim.seek", context: `when seeking to timepoint: ${timePoint} of MovieStim: ${this._name}`, - error + error, }; } } } - - /** * Estimate the bounding box. * @@ -320,21 +302,19 @@ export class MovieStim extends VisualStim _estimateBoundingBox() { const size = this._getDisplaySize(); - if (typeof size !== 'undefined') + if (typeof size !== "undefined") { this._boundingBox = new PIXI.Rectangle( this._pos[0] - size[0] / 2, this._pos[1] - size[1] / 2, size[0], - size[1] + size[1], ); } // TODO take the orientation into account } - - /** * Update the stimulus, if necessary. * @@ -354,20 +334,20 @@ export class MovieStim extends VisualStim { this._needPixiUpdate = false; - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { // Leave original video in place // https://pixijs.download/dev/docs/PIXI.Sprite.html#destroy this._pixi.destroy({ children: true, texture: true, - baseTexture: false + baseTexture: false, }); } this._pixi = undefined; // no movie to draw: return immediately - if (typeof this._movie === 'undefined') + if (typeof this._movie === "undefined") { return; } @@ -414,8 +394,6 @@ export class MovieStim extends VisualStim this._estimateBoundingBox(); } - - /** * Get the size of the display image, which is either that of the ImageStim or that of the image * it contains. @@ -428,18 +406,16 @@ export class MovieStim extends VisualStim { let displaySize = this.size; - if (typeof displaySize === 'undefined') + if (typeof displaySize === "undefined") { // use the size of the texture, if we have access to it: - if (typeof this._texture !== 'undefined' && this._texture.width > 0) + if (typeof this._texture !== "undefined" && this._texture.width > 0) { const textureSize = [this._texture.width, this._texture.height]; - displaySize = util.to_unit(textureSize, 'pix', this.win, this.units); + displaySize = util.to_unit(textureSize, "pix", this.win, this.units); } } return displaySize; } - - } diff --git a/src/visual/Polygon.js b/src/visual/Polygon.js index 1f74e8d..7e8196d 100644 --- a/src/visual/Polygon.js +++ b/src/visual/Polygon.js @@ -7,10 +7,8 @@ * @license Distributed under the terms of the MIT License */ - -import {ShapeStim} from './ShapeStim.js'; -import {Color} from '../util/Color.js'; - +import { Color } from "../util/Color.js"; +import { ShapeStim } from "./ShapeStim.js"; /** *

Polygonal visual stimulus.

@@ -39,7 +37,7 @@ import {Color} from '../util/Color.js'; */ export class Polygon extends ShapeStim { - constructor({name, win, lineWidth, lineColor, fillColor, opacity, edges, radius, pos, size, ori, units, contrast, depth, interpolate, autoDraw, autoLog} = {}) + constructor({ name, win, lineWidth, lineColor, fillColor, opacity, edges, radius, pos, size, ori, units, contrast, depth, interpolate, autoDraw, autoLog } = {}) { super({ name, @@ -56,20 +54,20 @@ export class Polygon extends ShapeStim depth, interpolate, autoDraw, - autoLog + autoLog, }); - this._psychoJS.logger.debug('create a new Polygon with name: ', name); + this._psychoJS.logger.debug("create a new Polygon with name: ", name); this._addAttribute( - 'edges', + "edges", edges, - 3 + 3, ); this._addAttribute( - 'radius', + "radius", radius, - 0.5 + 0.5, ); this._updateVertices(); @@ -80,8 +78,6 @@ export class Polygon extends ShapeStim } } - - /** * Setter for the radius attribute. * @@ -92,7 +88,7 @@ export class Polygon extends ShapeStim */ setRadius(radius, log = false) { - const hasChanged = this._setAttribute('radius', radius, log); + const hasChanged = this._setAttribute("radius", radius, log); if (hasChanged) { @@ -100,8 +96,6 @@ export class Polygon extends ShapeStim } } - - /** * Setter for the edges attribute. * @@ -112,7 +106,7 @@ export class Polygon extends ShapeStim */ setEdges(edges, log = false) { - const hasChanged = this._setAttribute('edges', Math.round(edges), log); + const hasChanged = this._setAttribute("edges", Math.round(edges), log); if (hasChanged) { @@ -120,8 +114,6 @@ export class Polygon extends ShapeStim } } - - /** * Update the vertices. * @@ -130,7 +122,7 @@ export class Polygon extends ShapeStim */ _updateVertices() { - this._psychoJS.logger.debug('update the vertices of Polygon: ', this.name); + this._psychoJS.logger.debug("update the vertices of Polygon: ", this.name); const angle = 2.0 * Math.PI / this._edges; const vertices = []; @@ -141,5 +133,4 @@ export class Polygon extends ShapeStim this.setVertices(vertices); } - } diff --git a/src/visual/Rect.js b/src/visual/Rect.js index 43740bf..e067f84 100644 --- a/src/visual/Rect.js +++ b/src/visual/Rect.js @@ -7,10 +7,8 @@ * @license Distributed under the terms of the MIT License */ - -import {ShapeStim} from './ShapeStim.js'; -import {Color} from '../util/Color.js'; - +import { Color } from "../util/Color.js"; +import { ShapeStim } from "./ShapeStim.js"; /** *

Rectangular visual stimulus.

@@ -39,7 +37,7 @@ import {Color} from '../util/Color.js'; */ export class Rect extends ShapeStim { - constructor({name, win, lineWidth, lineColor, fillColor, opacity, width, height, pos, size, ori, units, contrast, depth, interpolate, autoDraw, autoLog} = {}) + constructor({ name, win, lineWidth, lineColor, fillColor, opacity, width, height, pos, size, ori, units, contrast, depth, interpolate, autoDraw, autoLog } = {}) { super({ name, @@ -56,20 +54,20 @@ export class Rect extends ShapeStim depth, interpolate, autoDraw, - autoLog + autoLog, }); - this._psychoJS.logger.debug('create a new Rect with name: ', name); + this._psychoJS.logger.debug("create a new Rect with name: ", name); this._addAttribute( - 'width', + "width", width, - 0.5 + 0.5, ); this._addAttribute( - 'height', + "height", height, - 0.5 + 0.5, ); this._updateVertices(); @@ -80,8 +78,6 @@ export class Rect extends ShapeStim } } - - /** * Setter for the width attribute. * @@ -92,9 +88,9 @@ export class Rect extends ShapeStim */ setWidth(width, log = false) { - this._psychoJS.logger.debug('set the width of Rect: ', this.name, 'to: ', width); + this._psychoJS.logger.debug("set the width of Rect: ", this.name, "to: ", width); - const hasChanged = this._setAttribute('width', width, log); + const hasChanged = this._setAttribute("width", width, log); if (hasChanged) { @@ -102,8 +98,6 @@ export class Rect extends ShapeStim } } - - /** * Setter for the height attribute. * @@ -114,9 +108,9 @@ export class Rect extends ShapeStim */ setHeight(height, log = false) { - this._psychoJS.logger.debug('set the height of Rect: ', this.name, 'to: ', height); + this._psychoJS.logger.debug("set the height of Rect: ", this.name, "to: ", height); - const hasChanged = this._setAttribute('height', height, log); + const hasChanged = this._setAttribute("height", height, log); if (hasChanged) { @@ -124,8 +118,6 @@ export class Rect extends ShapeStim } } - - /** * Update the vertices. * @@ -134,7 +126,7 @@ export class Rect extends ShapeStim */ _updateVertices() { - this._psychoJS.logger.debug('update the vertices of Rect: ', this.name); + this._psychoJS.logger.debug("update the vertices of Rect: ", this.name); const halfWidth = this._width / 2.0; const halfHeight = this._height / 2.0; @@ -143,8 +135,7 @@ export class Rect extends ShapeStim [-halfWidth, -halfHeight], [halfWidth, -halfHeight], [halfWidth, halfHeight], - [-halfWidth, halfHeight] + [-halfWidth, halfHeight], ]); } - } diff --git a/src/visual/ShapeStim.js b/src/visual/ShapeStim.js index 8aeab4b..7baea8b 100644 --- a/src/visual/ShapeStim.js +++ b/src/visual/ShapeStim.js @@ -8,15 +8,13 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {VisualStim} from './VisualStim.js'; -import {Color} from '../util/Color.js'; -import {ColorMixin} from '../util/ColorMixin.js'; -import * as util from '../util/Util.js'; +import * as PIXI from "pixi.js-legacy"; +import { WindowMixin } from "../core/WindowMixin.js"; +import { Color } from "../util/Color.js"; +import { ColorMixin } from "../util/ColorMixin.js"; import { to_pixiPoint } from "../util/Pixi.js"; -import {WindowMixin} from "../core/WindowMixin.js"; - +import * as util from "../util/Util.js"; +import { VisualStim } from "./VisualStim.js"; /** *

This class provides the basic functionality of shape stimuli.

@@ -45,9 +43,9 @@ import {WindowMixin} from "../core/WindowMixin.js"; */ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin) { - constructor({name, win, lineWidth, lineColor, fillColor, opacity, vertices, closeShape, pos, size, ori, units, contrast, depth, interpolate, autoDraw, autoLog} = {}) + constructor({ name, win, lineWidth, lineColor, fillColor, opacity, vertices, closeShape, pos, size, ori, units, contrast, depth, interpolate, autoDraw, autoLog } = {}) { - super({name, win, units, ori, opacity, pos, depth, size, autoDraw, autoLog}); + super({ name, win, units, ori, opacity, pos, depth, size, autoDraw, autoLog }); // the PIXI polygon corresponding to the vertices, in pixel units: this._pixiPolygon_px = undefined; @@ -55,58 +53,56 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin this._vertices_px = undefined; // shape: - if (typeof size === 'undefined' || size === null) + if (typeof size === "undefined" || size === null) { this.size = [1.0, 1.0]; } this._addAttribute( - 'vertices', + "vertices", vertices, - [[-0.5, 0], [0, 0.5], [0.5, 0]] + [[-0.5, 0], [0, 0.5], [0.5, 0]], ); this._addAttribute( - 'closeShape', + "closeShape", closeShape, true, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'interpolate', + "interpolate", interpolate, true, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'lineWidth', + "lineWidth", lineWidth, 1.5, - this._onChange(true, true) + this._onChange(true, true), ); // colors: this._addAttribute( - 'lineColor', + "lineColor", lineColor, - 'white', - this._onChange(true, false) + "white", + this._onChange(true, false), ); this._addAttribute( - 'fillColor', + "fillColor", fillColor, undefined, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'contrast', + "contrast", contrast, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); } - - /** * Setter for the vertices attribute. * @@ -118,16 +114,16 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin setVertices(vertices, log = false) { const response = { - origin: 'ShapeStim.setVertices', - context: 'when setting the vertices of ShapeStim: ' + this._name + origin: "ShapeStim.setVertices", + context: "when setting the vertices of ShapeStim: " + this._name, }; - this._psychoJS.logger.debug('set the vertices of ShapeStim:', this.name); + this._psychoJS.logger.debug("set the vertices of ShapeStim:", this.name); try { // if vertices is a string, we check whether it is a known shape: - if (typeof vertices === 'string') + if (typeof vertices === "string") { if (vertices in ShapeStim.KnownShapes) { @@ -139,18 +135,16 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin } } - this._setAttribute('vertices', vertices, log); + this._setAttribute("vertices", vertices, log); this._onChange(true, true)(); } catch (error) { - throw Object.assign(response, {error: error}); + throw Object.assign(response, { error: error }); } } - - /** * Determine whether an object is inside the bounding box of the ShapeStim. * @@ -168,24 +162,22 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin // get the position of the object, in pixel coordinates: const objectPos_px = util.getPositionFromObject(object, units); - if (typeof objectPos_px === 'undefined') + if (typeof objectPos_px === "undefined") { throw { - origin: 'VisualStim.contains', - context: 'when determining whether VisualStim: ' + this._name + ' contains object: ' + util.toString(object), - error: 'unable to determine the position of the object' + origin: "VisualStim.contains", + context: "when determining whether VisualStim: " + this._name + " contains object: " + util.toString(object), + error: "unable to determine the position of the object", }; } // test for inclusion: const pos_px = util.to_px(this.pos, this.units, this.win); this._getVertices_px(); - const polygon_px = this._vertices_px.map(v => [v[0] + pos_px[0], v[1] + pos_px[1]]); + const polygon_px = this._vertices_px.map((v) => [v[0] + pos_px[0], v[1] + pos_px[1]]); return util.IsPointInsidePolygon(objectPos_px, polygon_px); } - - /** * Estimate the bounding box. * @@ -203,7 +195,7 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, - Number.NEGATIVE_INFINITY + Number.NEGATIVE_INFINITY, ]; for (const vertex of this._vertices_px) { @@ -217,14 +209,12 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin this._pos[0] + this._getLengthUnits(limits_px[0]), this._pos[1] + this._getLengthUnits(limits_px[1]), this._getLengthUnits(limits_px[2] - limits_px[0]), - this._getLengthUnits(limits_px[3] - limits_px[1]) + this._getLengthUnits(limits_px[3] - limits_px[1]), ); // TODO take the orientation into account } - - /** * Update the stimulus, if necessary. * @@ -244,7 +234,7 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin { this._needPixiUpdate = false; - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { this._pixi.destroy(true); } @@ -256,13 +246,13 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin // prepare the polygon in the given color and opacity: this._pixi = new PIXI.Graphics(); this._pixi.lineStyle(this._lineWidth, this._lineColor.int, this._opacity, 0.5); - if (typeof this._fillColor !== 'undefined' && this._fillColor !== null) + if (typeof this._fillColor !== "undefined" && this._fillColor !== null) { const contrastedColor = this.getContrastedColor(new Color(this._fillColor), this._contrast); this._pixi.beginFill(contrastedColor.int, this._opacity); } this._pixi.drawPolygon(this._pixiPolygon_px); - if (typeof this._fillColor !== 'undefined' && this._fillColor !== null) + if (typeof this._fillColor !== "undefined" && this._fillColor !== null) { this._pixi.endFill(); } @@ -273,8 +263,6 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin this._pixi.rotation = this.ori * Math.PI / 180.0; } - - /** * Get the PIXI polygon (in pixel units) corresponding to the vertices. * @@ -312,8 +300,6 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin return this._pixiPolygon_px; } - - /** * Get the vertices in pixel units. * @@ -325,28 +311,28 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin { // handle flipping: let flip = [1.0, 1.0]; - if ('_flipHoriz' in this && this._flipHoriz) + if ("_flipHoriz" in this && this._flipHoriz) { flip[0] = -1.0; } - if ('_flipVert' in this && this._flipVert) + if ("_flipVert" in this && this._flipVert) { flip[1] = -1.0; } // handle size, flipping, and convert to pixel units: - this._vertices_px = this._vertices.map(v => util.to_px( - [v[0] * this._size[0] * flip[0], v[1] * this._size[1] * flip[1]], - this._units, - this._win) + this._vertices_px = this._vertices.map((v) => + util.to_px( + [v[0] * this._size[0] * flip[0], v[1] * this._size[1] * flip[1]], + this._units, + this._win, + ) ); return this._vertices_px; } - } - /** * Known shapes. * @@ -358,15 +344,15 @@ ShapeStim.KnownShapes = { [-0.1, +0.5], // up [+0.1, +0.5], [+0.1, +0.1], - [+0.5, +0.1], // right + [+0.5, +0.1], // right [+0.5, -0.1], [+0.1, -0.1], - [+0.1, -0.5], // down + [+0.1, -0.5], // down [-0.1, -0.5], [-0.1, -0.1], - [-0.5, -0.1], // left + [-0.5, -0.1], // left [-0.5, +0.1], - [-0.1, +0.1] + [-0.1, +0.1], ], star7: [ @@ -383,7 +369,6 @@ ShapeStim.KnownShapes = { [-0.49, -0.11], [-0.19, 0.04], [-0.39, 0.31], - [-0.09, 0.18] - ] - + [-0.09, 0.18], + ], }; diff --git a/src/visual/Slider.js b/src/visual/Slider.js index aab8448..8d6985f 100644 --- a/src/visual/Slider.js +++ b/src/visual/Slider.js @@ -7,17 +7,15 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {VisualStim} from './VisualStim.js'; -import {Color} from '../util/Color.js'; -import {ColorMixin} from '../util/ColorMixin.js'; -import {WindowMixin} from '../core/WindowMixin.js'; -import {Clock} from '../util/Clock.js'; -import * as util from '../util/Util.js'; -import {PsychoJS} from "../core/PsychoJS.js"; +import * as PIXI from "pixi.js-legacy"; +import { PsychoJS } from "../core/PsychoJS.js"; +import { WindowMixin } from "../core/WindowMixin.js"; +import { Clock } from "../util/Clock.js"; +import { Color } from "../util/Color.js"; +import { ColorMixin } from "../util/ColorMixin.js"; import { to_pixiPoint } from "../util/Pixi.js"; - +import * as util from "../util/Util.js"; +import { VisualStim } from "./VisualStim.js"; /** * Slider stimulus. @@ -70,9 +68,38 @@ import { to_pixiPoint } from "../util/Pixi.js"; */ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) { - constructor({name, win, pos, size, ori, units, color, markerColor, lineColor, contrast, opacity, style, ticks, labels, granularity, flip, readOnly, font, bold, italic, fontSize, compact, clipMask, autoDraw, autoLog, dependentStims} = {}) + constructor( + { + name, + win, + pos, + size, + ori, + units, + color, + markerColor, + lineColor, + contrast, + opacity, + style, + ticks, + labels, + granularity, + flip, + readOnly, + font, + bold, + italic, + fontSize, + compact, + clipMask, + autoDraw, + autoLog, + dependentStims, + } = {}, + ) { - super({name, win, units, ori, opacity, pos, size, clipMask, autoDraw, autoLog}); + super({ name, win, units, ori, opacity, pos, size, clipMask, autoDraw, autoLog }); this._needMarkerUpdate = false; @@ -96,119 +123,117 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) }; this._addAttribute( - 'style', + "style", style, [Slider.Style.RATING], - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'ticks', + "ticks", ticks, [1, 2, 3, 4, 5], - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'labels', + "labels", labels, [], - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'granularity', + "granularity", granularity, 0, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'readOnly', + "readOnly", readOnly, - false + false, ); this._addAttribute( - 'compact', + "compact", compact, false, - this._onChange(true, true) + this._onChange(true, true), ); // font: this._addAttribute( - 'font', + "font", font, - 'Arial', - this._onChange(true, true) + "Arial", + this._onChange(true, true), ); this._addAttribute( - 'fontSize', + "fontSize", fontSize, - (this._units === 'pix') ? 14 : 0.03, - this._onChange(true, true) + (this._units === "pix") ? 14 : 0.03, + this._onChange(true, true), ); this._addAttribute( - 'bold', + "bold", bold, true, - this._onChange(true, true) + this._onChange(true, true), ); this._addAttribute( - 'italic', + "italic", italic, false, - this._onChange(true, true) + this._onChange(true, true), ); this._addAttribute( - 'flip', + "flip", flip, false, - this._onChange(true, true) + this._onChange(true, true), ); // color: this._addAttribute( - 'color', + "color", color, - 'lightgray', - this._onChange(true, false) + "lightgray", + this._onChange(true, false), ); this._addAttribute( - 'lineColor', + "lineColor", lineColor, - 'lightgray', - this._onChange(true, false) + "lightgray", + this._onChange(true, false), ); this._addAttribute( - 'markerColor', + "markerColor", markerColor, - 'red', - this._onChange(true, false) + "red", + this._onChange(true, false), ); this._addAttribute( - 'contrast', + "contrast", contrast, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'dependentStims', + "dependentStims", dependentStims, [], - this._onChange(false, false) + this._onChange(false, false), ); - - // slider rating (which might be different from the visible marker rating): - this._addAttribute('rating', undefined); + this._addAttribute("rating", undefined); // visible marker rating (which might be different from the actual rating): - this._addAttribute('markerPos', undefined); + this._addAttribute("markerPos", undefined); // full history of ratings and response times: - this._addAttribute('history', []); + this._addAttribute("history", []); // various graphical components: - this._addAttribute('lineAspectRatio', 0.01); + this._addAttribute("lineAspectRatio", 0.01); // check for attribute conflicts, missing values, etc.: this._sanitizeAttributes(); @@ -225,8 +250,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Force a refresh of the stimulus. * @@ -240,8 +263,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._needMarkerUpdate = true; } - - /** * Reset the slider. * @@ -250,7 +271,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) */ reset() { - this.psychoJS.logger.debug('reset Slider: ', this._name); + this.psychoJS.logger.debug("reset Slider: ", this._name); this._markerPos = undefined; this._history = []; @@ -262,14 +283,12 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._needUpdate = true; // the marker should be invisible when markerPos is undefined: - if (typeof this._marker !== 'undefined') + if (typeof this._marker !== "undefined") { this._marker.alpha = 0; } } - - /** * Get the current value of the rating. * @@ -290,8 +309,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Get the response time of the most recent change to the rating. * @@ -312,8 +329,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Setter for the readOnly attribute. * @@ -327,7 +342,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) */ setReadOnly(readOnly = true, log = false) { - const hasChanged = this._setAttribute('readOnly', readOnly, log); + const hasChanged = this._setAttribute("readOnly", readOnly, log); if (hasChanged) { @@ -345,8 +360,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Setter for the markerPos attribute. * @@ -372,8 +385,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Setter for the rating attribute. * @@ -393,60 +404,51 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) rating = this._labels[Math.round(rating)]; } - this._setAttribute('rating', rating, log); + this._setAttribute("rating", rating, log); } - - /** Let `borderColor` alias `lineColor` to parallel PsychoPy */ - set borderColor(color) { + set borderColor(color) + { this.lineColor = color; } - - - setBorderColor(color) { + setBorderColor(color) + { this.setLineColor(color); } - - - get borderColor() { + get borderColor() + { return this.lineColor; } - - - getBorderColor() { + getBorderColor() + { return this.getLineColor(); } - /** Let `fillColor` alias `markerColor` to parallel PsychoPy */ - set fillColor(color) { + set fillColor(color) + { this.markerColor = color; } - - - setFillColor(color) { + setFillColor(color) + { this.setMarkerColor(color); } - - - get fillColor() { + get fillColor() + { return this.markerColor; } - - - getFillColor() { + getFillColor() + { return this.getMarkerColor(); } - - /** * Estimate the bounding box. * @@ -462,18 +464,18 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) { // setup the slider's style (taking into account the Window dimension, etc.): this._setupStyle(); - + // calculate various values in pixel units: this._tickSize_px = util.to_px(this._tickSize, this._units, this._win); this._fontSize_px = this._getLengthPix(this._fontSize); - this._barSize_px = util.to_px(this._barSize, this._units, this._win, true).map(v => Math.max(1, v)); + this._barSize_px = util.to_px(this._barSize, this._units, this._win, true).map((v) => Math.max(1, v)); this._markerSize_px = util.to_px(this._markerSize, this._units, this._win, true); const pos_px = util.to_px(this._pos, this._units, this._win); const size_px = util.to_px(this._size, this._units, this._win); // calculate the position of the ticks: const tickPositions = this._ratingToPos(this._ticks); - this._tickPositions_px = tickPositions.map(p => util.to_px(p, this._units, this._win)); + this._tickPositions_px = tickPositions.map((p) => util.to_px(p, this._units, this._win)); // left, top, right, bottom limits: const limits_px = [0, 0, size_px[0], size_px[1]]; @@ -490,7 +492,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) for (let l = 0; l < this._labels.length; ++l) { - const tickPositionIndex = Math.round( l / (this._labels.length - 1) * (this._ticks.length - 1) ); + const tickPositionIndex = Math.round(l / (this._labels.length - 1) * (this._ticks.length - 1)); this._labelPositions_px[l] = this._tickPositions_px[tickPositionIndex]; const labelBounds = PIXI.TextMetrics.measureText(this._labels[l].toString(), labelTextStyle); @@ -515,8 +517,10 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } // ensure that that labels are not overlapping: - if (prevLabelBounds && - (this._labelPositions_px[l - 1][0] + prevLabelBounds.width + tolerance >= this._labelPositions_px[l][0])) + if ( + prevLabelBounds + && (this._labelPositions_px[l - 1][0] + prevLabelBounds.width + tolerance >= this._labelPositions_px[l][0]) + ) { if (prevNonOverlapOffset === 0) { @@ -576,12 +580,10 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._getLengthUnits(position_px.x + limits_px[0]), this._getLengthUnits(position_px.y + limits_px[1]), this._getLengthUnits(limits_px[2] - limits_px[0]), - this._getLengthUnits(limits_px[3] - limits_px[1]) + this._getLengthUnits(limits_px[3] - limits_px[1]), ); } - - /** * Sanitize the slider attributes: check for attribute conflicts, missing values, etc. * @@ -592,9 +594,9 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) _sanitizeAttributes() { // convert potential string styles into Symbols: - this._style.forEach( (style, index) => + this._style.forEach((style, index) => { - if (typeof style === 'string') + if (typeof style === "string") { this._style[index] = Symbol.for(style.toUpperCase()); } @@ -606,14 +608,11 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._isCategorical = (this._ticks.length === 0); if (this._isCategorical) { - this._ticks = [...Array(this._labels.length)].map( (_, i) => i ); + this._ticks = [...Array(this._labels.length)].map((_, i) => i); this._granularity = 1.0; } - } - - /** * Set the current rating. * @@ -629,7 +628,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) recordRating(rating, responseTime = undefined, log = false) { // get response time: - if (typeof responseTime === 'undefined') + if (typeof responseTime === "undefined") { responseTime = this._responseClock.getTime(); } @@ -640,15 +639,14 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this.setRating(rating, log); // add rating and response time to history: - this._history.push({rating: this._rating, responseTime}); - this.psychoJS.logger.debug('record a new rating: ', this._rating, 'with response time: ', responseTime, 'for Slider: ', this._name); + this._history.push({ rating: this._rating, responseTime }); + this.psychoJS.logger.debug("record a new rating: ", this._rating, "with response time: ", responseTime, "for Slider: ", this._name); // update slider: this._needMarkerUpdate = true; this._needUpdate = true; } - /** * Update the stimulus, if necessary. * @@ -682,7 +680,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - /** * Estimate the position of the slider, taking the compactness into account. * @@ -693,8 +690,10 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) _getPosition_px() { const position = to_pixiPoint(this.pos, this.units, this.win, true); - if (this._compact && - (this._style.indexOf(Slider.Style.RADIO) > -1 || this._style.indexOf(Slider.Style.RATING) > -1)) + if ( + this._compact + && (this._style.indexOf(Slider.Style.RADIO) > -1 || this._style.indexOf(Slider.Style.RATING) > -1) + ) { if (this._isHorizontal()) { @@ -709,8 +708,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) return position; } - - /** * Update the position of the marker if necessary. * @@ -725,9 +722,9 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } this._needMarkerUpdate = false; - if (typeof this._marker !== 'undefined') + if (typeof this._marker !== "undefined") { - if (typeof this._markerPos !== 'undefined') + if (typeof this._markerPos !== "undefined") { const visibleMarkerPos = this._ratingToPos([this._markerPos]); this._marker.position = to_pixiPoint(visibleMarkerPos[0], this.units, this.win, true); @@ -740,8 +737,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Setup the PIXI components of the slider (bar, ticks, labels, marker, etc.). * @@ -759,17 +754,15 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._setupStyle(); - // calculate various values in pixel units: this._tickSize_px = util.to_px(this._tickSize, this._units, this._win); this._fontSize_px = this._getLengthPix(this._fontSize); - this._barSize_px = util.to_px(this._barSize, this._units, this._win, true).map(v => Math.max(1, v)); + this._barSize_px = util.to_px(this._barSize, this._units, this._win, true).map((v) => Math.max(1, v)); this._markerSize_px = util.to_px(this._markerSize, this._units, this._win, true); const tickPositions = this._ratingToPos(this._ticks); - this._tickPositions_px = tickPositions.map(p => util.to_px(p, this._units, this._win)); + this._tickPositions_px = tickPositions.map((p) => util.to_px(p, this._units, this._win)); - - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { this._pixi.destroy(true); } @@ -782,7 +775,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._body.interactive = true; this._pixi.addChild(this._body); - // ensure that pointer events will be captured along the slider body, even outside of // marker and labels: if (this._tickType === Slider.Shape.DISC) @@ -792,7 +784,8 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) -this._barSize_px[0] / 2 - maxTickSize_px, -this._barSize_px[1] / 2 - maxTickSize_px, this._barSize_px[0] + maxTickSize_px * 2, - this._barSize_px[1] + maxTickSize_px * 2); + this._barSize_px[1] + maxTickSize_px * 2, + ); } else { @@ -800,7 +793,8 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) -this._barSize_px[0] / 2 - this._tickSize_px[0] / 2, -this._barSize_px[1] / 2 - this._tickSize_px[1] / 2, this._barSize_px[0] + this._tickSize_px[0], - this._barSize_px[1] + this._tickSize_px[1]); + this._barSize_px[1] + this._tickSize_px[1], + ); } // central bar: @@ -816,8 +810,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._setupMarker(); } - - /** * Setup the central bar. * @@ -830,7 +822,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) if (this._barLineWidth_px > 0) { this._body.lineStyle(this._barLineWidth_px, this._barLineColor.int, 1, 0.5); - if (typeof this._barFillColor !== 'undefined') + if (typeof this._barFillColor !== "undefined") { this._body.beginFill(this._barFillColor.int, 1); } @@ -838,17 +830,15 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) Math.round(-this._barSize_px[0] / 2), Math.round(-this._barSize_px[1] / 2), Math.round(this._barSize_px[0]), - Math.round(this._barSize_px[1]) + Math.round(this._barSize_px[1]), ); - if (typeof this._barFillColor !== 'undefined') + if (typeof this._barFillColor !== "undefined") { this._body.endFill(); } } } - - /** * Setup the marker, and the associated mouse events. * @@ -858,7 +848,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) */ _setupMarker() { -/* this is now deprecated and replaced by _body.hitArea + /* this is now deprecated and replaced by _body.hitArea // transparent rectangle necessary to capture pointer events outside of marker and labels: const eventCaptureRectangle = new PIXI.Graphics(); eventCaptureRectangle.beginFill(0, 0); @@ -870,7 +860,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) ); eventCaptureRectangle.endFill(); this._pixi.addChild(eventCaptureRectangle); -*/ + */ // marker: this._marker = new PIXI.Graphics(); @@ -927,7 +917,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) Math.round(-this._markerSize_px[0] / 2), Math.round(-this._markerSize_px[1] / 2), this._markerSize_px[0], - this._markerSize_px[1] + this._markerSize_px[1], ); this._marker.endFill(); @@ -935,7 +925,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) // this._marker.drawCircle(0, 0, this._markerSize_px[0] / 3); } - // marker mouse events: const self = this; self._markerDragging = false; @@ -1001,7 +990,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } }; - // (*) slider mouse events outside of marker // note: this only works thanks to eventCaptureRectangle /* not quite right just yet (as of May 2020) @@ -1035,8 +1023,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) }; } - - /** * Setup the ticks. * @@ -1072,8 +1058,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Get the PIXI Text Style applied to the PIXI.Text labels. * @@ -1084,19 +1068,17 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) _getTextStyle() { this._fontSize_px = this._getLengthPix(this._fontSize); - + return new PIXI.TextStyle({ fontFamily: this._font, fontSize: Math.round(this._fontSize_px), - fontWeight: (this._bold) ? 'bold' : 'normal', - fontStyle: (this._italic) ? 'italic' : 'normal', + fontWeight: (this._bold) ? "bold" : "normal", + fontStyle: (this._italic) ? "italic" : "normal", fill: this.getContrastedColor(this._labelColor, this._contrast).hex, - align: 'center', + align: "center", }); } - - /** * Setup the labels. * @@ -1121,8 +1103,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Apply a particular style to the slider. * @@ -1158,7 +1138,8 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._tickType = Slider.Shape.LINE; this._tickColor = (!skin.TICK_COLOR) ? new Color(this._lineColor) : skin.TICK_COLOR; - if (this.markerColor === undefined) { + if (this.markerColor === undefined) + { this.markerColor = skin.MARKER_COLOR; } @@ -1171,7 +1152,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._labelOri = 0; - // rating: if (this._style.indexOf(Slider.Style.RATING) > -1) { @@ -1184,8 +1164,8 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._markerType = Slider.Shape.TRIANGLE; if (!this._skin.MARKER_SIZE) { - this._markerSize = this._markerSize.map(s => s * 2); - } + this._markerSize = this._markerSize.map((s) => s * 2); + } } // slider: @@ -1194,9 +1174,9 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) this._markerType = Slider.Shape.BOX; if (!this._skin.MARKER_SIZE) { - this._markerSize = (this._isHorizontal()) ? - [this._size[0] / (this._ticks[this._ticks.length - 1] - this._ticks[0]), this._size[1]] : - [this._size[0], this._size[1] / (this._ticks[this._ticks.length - 1] - this._ticks[0])]; + this._markerSize = (this._isHorizontal()) + ? [this._size[0] / (this._ticks[this._ticks.length - 1] - this._ticks[0]), this._size[1]] + : [this._size[0], this._size[1] / (this._ticks[this._ticks.length - 1] - this._ticks[0])]; } this._barSize = [this._size[0], this._size[1]]; this._barFillColor = this.getContrastedColor(new Color(this.color), 0.5); @@ -1235,12 +1215,10 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) if (!this._skin.MARKER_SIZE) { - this._markerSize = this._markerSize.map(s => s * 0.7); + this._markerSize = this._markerSize.map((s) => s * 0.7); + } } } - } - - /** * Convert an array of ratings into an array of [x,y] positions (in Slider units, with 0 at the center of the Slider) @@ -1260,20 +1238,22 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) // in compact mode the circular markers of RADIO sliders must fit within the width: if (this._compact && this._style.indexOf(Slider.Style.RADIO) > -1) { - return ratings.map(v => [ - ((v - this._ticks[0]) / range) * (this._size[0] - this._tickSize[1]*2) - - (this._size[0] / 2) + this._tickSize[1], - 0]); + return ratings.map((v) => [ + ((v - this._ticks[0]) / range) * (this._size[0] - this._tickSize[1] * 2) + - (this._size[0] / 2) + this._tickSize[1], + 0, + ]); } else if (this._style.indexOf(Slider.Style.SLIDER) > -1) { - return ratings.map(v => [ + return ratings.map((v) => [ ((v - this._ticks[0]) / range - 0.5) * (this._size[0] - this._markerSize[0]), - 0]); + 0, + ]); } else { - return ratings.map(v => [((v - this._ticks[0]) / range - 0.5) * this._size[0], 0]); + return ratings.map((v) => [((v - this._ticks[0]) / range - 0.5) * this._size[0], 0]); } } else @@ -1281,25 +1261,26 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) // in compact mode the circular markers of RADIO sliders must fit within the height: if (this._compact && this._style.indexOf(Slider.Style.RADIO) > -1) { - return ratings.map(v => [0, - ((v - this._ticks[0]) / range) * (this._size[1] - this._tickSize[0]*2) - - (this._size[1] / 2) + this._tickSize[0]]); + return ratings.map((v) => [ + 0, + ((v - this._ticks[0]) / range) * (this._size[1] - this._tickSize[0] * 2) + - (this._size[1] / 2) + this._tickSize[0], + ]); } else if (this._style.indexOf(Slider.Style.SLIDER) > -1) { - return ratings.map(v => [ + return ratings.map((v) => [ 0, - ((v - this._ticks[0]) / range - 0.5) * (this._size[1] - this._markerSize[1])]); + ((v - this._ticks[0]) / range - 0.5) * (this._size[1] - this._markerSize[1]), + ]); } else { - return ratings.map(v => [0, (1.0 - (v - this._ticks[0]) / range - 0.5) * this._size[1]]); + return ratings.map((v) => [0, (1.0 - (v - this._ticks[0]) / range - 0.5) * this._size[1]]); } } } - - /** * Convert a [x,y] position, in pixel units, relative to the slider, into a rating. * @@ -1339,8 +1320,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) } } - - /** * Determine whether the slider is horizontal. * @@ -1356,8 +1335,6 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) return (this._size[0] > this._size[1]); } - - /** * Calculate the rating once granularity has been taken into account. * @@ -1369,7 +1346,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) */ _granularise(rating) { - if (typeof rating === 'undefined') + if (typeof rating === "undefined") { return undefined; } @@ -1382,10 +1359,8 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) return rating; } - } - /** * Shape of the marker and of the ticks. * @@ -1395,13 +1370,12 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin) * @public */ Slider.Shape = { - DISC: Symbol.for('DISC'), - TRIANGLE: Symbol.for('TRIANGLE'), - LINE: Symbol.for('LINE'), - BOX: Symbol.for('BOX') + DISC: Symbol.for("DISC"), + TRIANGLE: Symbol.for("TRIANGLE"), + LINE: Symbol.for("LINE"), + BOX: Symbol.for("BOX"), }; - /** * Styles. * @@ -1411,15 +1385,14 @@ Slider.Shape = { * @public */ Slider.Style = { - RATING: Symbol.for('RATING'), - TRIANGLE_MARKER: Symbol.for('TRIANGLE_MARKER'), - SLIDER: Symbol.for('SLIDER'), - WHITE_ON_BLACK: Symbol.for('WHITE_ON_BLACK'), - LABELS_45: Symbol.for('LABELS_45'), - RADIO: Symbol.for('RADIO') + RATING: Symbol.for("RATING"), + TRIANGLE_MARKER: Symbol.for("TRIANGLE_MARKER"), + SLIDER: Symbol.for("SLIDER"), + WHITE_ON_BLACK: Symbol.for("WHITE_ON_BLACK"), + LABELS_45: Symbol.for("LABELS_45"), + RADIO: Symbol.for("RADIO"), }; - /** * Skin. * @@ -1433,15 +1406,15 @@ Slider.Style = { Slider.Skin = { MARKER_SIZE: null, STANDARD: { - MARKER_COLOR: new Color('red'), + MARKER_COLOR: new Color("red"), BAR_LINE_COLOR: null, TICK_COLOR: null, - LABEL_COLOR: null + LABEL_COLOR: null, }, WHITE_ON_BLACK: { - MARKER_COLOR: new Color('white'), - BAR_LINE_COLOR: new Color('black'), - TICK_COLOR: new Color('black'), - LABEL_COLOR: new Color('black') - } + MARKER_COLOR: new Color("white"), + BAR_LINE_COLOR: new Color("black"), + TICK_COLOR: new Color("black"), + LABEL_COLOR: new Color("black"), + }, }; diff --git a/src/visual/TextBox.js b/src/visual/TextBox.js index 313f5d9..af42324 100644 --- a/src/visual/TextBox.js +++ b/src/visual/TextBox.js @@ -7,14 +7,13 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {VisualStim} from './VisualStim.js'; -import {Color} from '../util/Color.js'; -import {ColorMixin} from '../util/ColorMixin.js'; -import {TextInput} from './TextInput.js'; -import {ButtonStim} from './ButtonStim.js'; -import * as util from '../util/Util.js'; +import * as PIXI from "pixi.js-legacy"; +import { Color } from "../util/Color.js"; +import { ColorMixin } from "../util/ColorMixin.js"; +import * as util from "../util/Util.js"; +import { ButtonStim } from "./ButtonStim.js"; +import { TextInput } from "./TextInput.js"; +import { VisualStim } from "./VisualStim.js"; // TODO finish documenting all options /** @@ -50,122 +49,154 @@ import * as util from '../util/Util.js'; */ export class TextBox extends util.mix(VisualStim).with(ColorMixin) { - constructor({name, win, pos, anchor, size, units, ori, opacity, depth, text, font, letterHeight, bold, italic, alignment, color, contrast, flipHoriz, flipVert, fillColor, borderColor, borderWidth, padding, editable, multiline, autofocus, clipMask, autoDraw, autoLog} = {}) + constructor( + { + name, + win, + pos, + anchor, + size, + units, + ori, + opacity, + depth, + text, + font, + letterHeight, + bold, + italic, + alignment, + color, + contrast, + flipHoriz, + flipVert, + fillColor, + borderColor, + borderWidth, + padding, + editable, + multiline, + autofocus, + clipMask, + autoDraw, + autoLog, + } = {}, + ) { - super({name, win, pos, size, units, ori, opacity, depth, clipMask, autoDraw, autoLog}); + super({ name, win, pos, size, units, ori, opacity, depth, clipMask, autoDraw, autoLog }); this._addAttribute( - 'text', + "text", text, - '', - this._onChange(true, true) + "", + this._onChange(true, true), ); this._addAttribute( - 'placeholder', + "placeholder", text, - '', - this._onChange(true, true) - ); + "", + this._onChange(true, true), + ); this._addAttribute( - 'anchor', + "anchor", anchor, - 'center', - this._onChange(false, true) + "center", + this._onChange(false, true), ); this._addAttribute( - 'flipHoriz', + "flipHoriz", flipHoriz, false, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'flipVert', + "flipVert", flipVert, false, - this._onChange(false, false) + this._onChange(false, false), ); // font: this._addAttribute( - 'font', + "font", font, - 'Arial', - this._onChange(true, true) + "Arial", + this._onChange(true, true), ); this._addAttribute( - 'letterHeight', + "letterHeight", letterHeight, this._getDefaultLetterHeight(), - this._onChange(true, true) + this._onChange(true, true), ); this._addAttribute( - 'bold', + "bold", bold, false, - this._onChange(true, true) + this._onChange(true, true), ); this._addAttribute( - 'italic', + "italic", italic, false, - this._onChange(true, true) + this._onChange(true, true), ); this._addAttribute( - 'alignment', + "alignment", alignment, - 'left', - this._onChange(true, true) + "left", + this._onChange(true, true), ); // colors: this._addAttribute( - 'color', + "color", color, - 'white', - this._onChange(true, false) + "white", + this._onChange(true, false), ); this._addAttribute( - 'fillColor', + "fillColor", fillColor, - 'lightgrey', - this._onChange(true, false) + "lightgrey", + this._onChange(true, false), ); this._addAttribute( - 'borderColor', + "borderColor", borderColor, this.fillColor, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'contrast', + "contrast", contrast, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); // default border width: 1px this._addAttribute( - 'borderWidth', + "borderWidth", borderWidth, - util.to_unit([1, 0], 'pix', win, this._units)[0], - this._onChange(true, true) + util.to_unit([1, 0], "pix", win, this._units)[0], + this._onChange(true, true), ); // default padding: half of the letter height this._addAttribute( - 'padding', + "padding", padding, this._letterHeight / 2.0, - this._onChange(true, true) + this._onChange(true, true), ); - this._addAttribute('multiline', multiline, false, this._onChange(true, true)); - this._addAttribute('editable', editable, false, this._onChange(true, true)); - this._addAttribute('autofocus', autofocus, true, this._onChange(true, false)); - // this._setAttribute({ - // name: 'vertices', - // value: vertices, - // assert: v => (v != null) && (typeof v !== 'undefined') && Array.isArray(v) ) - // log); + this._addAttribute("multiline", multiline, false, this._onChange(true, true)); + this._addAttribute("editable", editable, false, this._onChange(true, true)); + this._addAttribute("autofocus", autofocus, true, this._onChange(true, false)); + // this._setAttribute({ + // name: 'vertices', + // value: vertices, + // assert: v => (v != null) && (typeof v !== 'undefined') && Array.isArray(v) ) + // log); // estimate the bounding box: this._estimateBoundingBox(); @@ -176,7 +207,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) } } - /** * Clears the current text value or sets it back to match the placeholder. * @@ -185,13 +215,11 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) */ reset() { - const text = this.editable ? '' : this.placeholder; + const text = this.editable ? "" : this.placeholder; this.setText(this.placeholder); } - - /** * Clears the current text value. * @@ -203,8 +231,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) this.setText(); } - - /** * For tweaking the underlying input value. * @@ -212,9 +238,9 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) * @public * @param {string} text */ - setText(text = '') + setText(text = "") { - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { this._pixi.text = text; } @@ -222,7 +248,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) this._text = text; } - /** * For accessing the underlying input value. * @@ -232,7 +257,7 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) */ getText() { - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { return this._pixi.text; } @@ -240,7 +265,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) return this._text; } - /** * Setter for the size attribute. * @@ -253,25 +277,25 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) { // test with the size is undefined, or [undefined, undefined]: let isSizeUndefined = ( - (typeof size === 'undefined') || (size === null) || - ( Array.isArray(size) && size.every( v => typeof v === 'undefined' || v === null) ) - ); + (typeof size === "undefined") || (size === null) + || (Array.isArray(size) && size.every((v) => typeof v === "undefined" || v === null)) + ); if (isSizeUndefined) { size = TextBox._defaultSizeMap.get(this._units); - if (typeof size === 'undefined') + if (typeof size === "undefined") { throw { - origin: 'TextBox.setSize', - context: 'when setting the size of TextBox: ' + this._name, - error: 'no default size for unit: ' + this._units + origin: "TextBox.setSize", + context: "when setting the size of TextBox: " + this._name, + error: "no default size for unit: " + this._units, }; } } - const hasChanged = this._setAttribute('size', size, log); + const hasChanged = this._setAttribute("size", size, log); if (hasChanged) { @@ -283,8 +307,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) } } - - /** * Get the default letter height given the stimulus' units. * @@ -296,20 +318,18 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) { const height = TextBox._defaultLetterHeightMap.get(this._units); - if (typeof height === 'undefined') + if (typeof height === "undefined") { throw { - origin: 'TextBox._getDefaultLetterHeight', - context: 'when getting the default height of TextBox: ' + this._name, - error: 'no default letter height for unit: ' + this._units + origin: "TextBox._getDefaultLetterHeight", + context: "when getting the default height of TextBox: " + this._name, + error: "no default letter height for unit: " + this._units, }; } return height; } - - /** * Get the TextInput options applied to the PIXI.TextInput. * @@ -328,24 +348,24 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) return { input: { fontFamily: this._font, - fontSize: letterHeight_px + 'px', + fontSize: letterHeight_px + "px", color: new Color(this._color).hex, - fontWeight: (this._bold) ? 'bold' : 'normal', - fontStyle: (this._italic) ? 'italic' : 'normal', + fontWeight: (this._bold) ? "bold" : "normal", + fontStyle: (this._italic) ? "italic" : "normal", - padding: padding_px + 'px', + padding: padding_px + "px", multiline, text: this._text, - height: multiline ? (height_px - 2 * padding_px) + 'px' : undefined, - width: (width_px - 2 * padding_px) + 'px' + height: multiline ? (height_px - 2 * padding_px) + "px" : undefined, + width: (width_px - 2 * padding_px) + "px", }, box: { fill: new Color(this._fillColor).int, rounded: 5, stroke: { color: new Color(this._borderColor).int, - width: borderWidth_px - } + width: borderWidth_px, + }, /*default: { fill: new Color(this._fillColor).int, rounded: 5, @@ -370,12 +390,10 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) width: borderWidth_px } }*/ - } + }, }; } - - /** * Estimate the bounding box. * @@ -395,14 +413,12 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) this._pos[0] - anchor[0] * this._size[0], this._pos[1] - anchor[1] * boxHeight, this._size[0], - boxHeight + boxHeight, ); // TODO take the orientation into account } - - /** * Update the stimulus, if necessary. * @@ -424,13 +440,13 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) { this._needPixiUpdate = false; - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { this._pixi.destroy(true); } // Get the currently entered text - let enteredText = this._pixi !== undefined? this._pixi.text: ''; - // Create new TextInput + let enteredText = this._pixi !== undefined ? this._pixi.text : ""; + // Create new TextInput this._pixi = new TextInput(this._getTextInputOptions()); // listeners required for regular textboxes, but may cause problems with button stimuli @@ -441,7 +457,7 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) // check if other TextBox instances are already in focus const { _drawList = [] } = this.psychoJS.window; - const otherTextBoxWithFocus = _drawList.some(item => item instanceof TextBox && item._pixi && item._pixi._hasFocus()); + const otherTextBoxWithFocus = _drawList.some((item) => item instanceof TextBox && item._pixi && item._pixi._hasFocus()); if (this._autofocus && !otherTextBoxWithFocus) { this._pixi._onSurrogateFocus(); @@ -452,7 +468,7 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) } if (this._editable) { - this.text = enteredText; + this.text = enteredText; this._pixi.placeholder = this._placeholder; } else @@ -479,8 +495,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) this._pixi.mask = this._clipMask; } - - /** * Convert the anchor attribute into numerical values. * @@ -493,30 +507,27 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) { const anchor = [0.5, 0.5]; - if (this._anchor.indexOf('left') > -1) + if (this._anchor.indexOf("left") > -1) { anchor[0] = 0; } - else if (this._anchor.indexOf('right') > -1) + else if (this._anchor.indexOf("right") > -1) { anchor[0] = 1; } - if (this._anchor.indexOf('top') > -1) + if (this._anchor.indexOf("top") > -1) { anchor[1] = 0; } - else if (this._anchor.indexOf('bottom') > -1) + else if (this._anchor.indexOf("bottom") > -1) { anchor[1] = 1; } return anchor; } - - } - /** *

This map associates units to default letter height.

* @@ -525,18 +536,17 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin) * @private */ TextBox._defaultLetterHeightMap = new Map([ - ['cm', 1.0], - ['deg', 1.0], - ['degs', 1.0], - ['degFlatPos', 1.0], - ['degFlat', 1.0], - ['norm', 0.1], - ['height', 0.2], - ['pix', 20], - ['pixels', 20] + ["cm", 1.0], + ["deg", 1.0], + ["degs", 1.0], + ["degFlatPos", 1.0], + ["degFlat", 1.0], + ["norm", 0.1], + ["height", 0.2], + ["pix", 20], + ["pixels", 20], ]); - /** *

This map associates units to default sizes.

* @@ -545,13 +555,13 @@ TextBox._defaultLetterHeightMap = new Map([ * @private */ TextBox._defaultSizeMap = new Map([ - ['cm', [15.0, -1]], - ['deg', [15.0, -1]], - ['degs', [15.0, -1]], - ['degFlatPos', [15.0, -1]], - ['degFlat', [15.0, -1]], - ['norm', [1, -1]], - ['height', [1, -1]], - ['pix', [500, -1]], - ['pixels', [500, -1]] + ["cm", [15.0, -1]], + ["deg", [15.0, -1]], + ["degs", [15.0, -1]], + ["degFlatPos", [15.0, -1]], + ["degFlat", [15.0, -1]], + ["norm", [1, -1]], + ["height", [1, -1]], + ["pix", [500, -1]], + ["pixels", [500, -1]], ]); diff --git a/src/visual/TextInput.js b/src/visual/TextInput.js index af7292a..b343507 100644 --- a/src/visual/TextInput.js +++ b/src/visual/TextInput.js @@ -24,7 +24,7 @@ export class TextInput extends PIXI.Container outline: "none", text: "", transformOrigin: "0 0", - lineHeight: "1" + lineHeight: "1", }, styles.input, ); @@ -58,7 +58,7 @@ export class TextInput extends PIXI.Container this._restrict_value = ""; this._createDOMInput(); this.substituteText = !this._multiline; - this._setState('DEFAULT'); + this._setState("DEFAULT"); } // GETTERS & SETTERS @@ -638,7 +638,7 @@ export class TextInput extends PIXI.Container } else if (components.length == 4) { - let padding = components.map(component => + let padding = components.map((component) => { return parseFloat(component); }); diff --git a/src/visual/TextStim.js b/src/visual/TextStim.js index c214377..b48da12 100644 --- a/src/visual/TextStim.js +++ b/src/visual/TextStim.js @@ -7,14 +7,12 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {VisualStim} from './VisualStim.js'; -import {Color} from '../util/Color.js'; -import {ColorMixin} from '../util/ColorMixin.js'; -import * as util from '../util/Util.js'; +import * as PIXI from "pixi.js-legacy"; +import { Color } from "../util/Color.js"; +import { ColorMixin } from "../util/ColorMixin.js"; import { to_pixiPoint } from "../util/Pixi.js"; - +import * as util from "../util/Util.js"; +import { VisualStim } from "./VisualStim.js"; /** * @name module:visual.TextStim @@ -49,9 +47,34 @@ import { to_pixiPoint } from "../util/Pixi.js"; */ export class TextStim extends util.mix(VisualStim).with(ColorMixin) { - constructor({name, win, text, font, pos, color, opacity, depth, contrast, units, ori, height, bold, italic, alignHoriz, alignVert, wrapWidth, flipHoriz, flipVert, clipMask, autoDraw, autoLog} = {}) + constructor( + { + name, + win, + text, + font, + pos, + color, + opacity, + depth, + contrast, + units, + ori, + height, + bold, + italic, + alignHoriz, + alignVert, + wrapWidth, + flipHoriz, + flipVert, + clipMask, + autoDraw, + autoLog, + } = {}, + ) { - super({name, win, units, ori, opacity, depth, pos, clipMask, autoDraw, autoLog}); + super({ name, win, units, ori, opacity, depth, pos, clipMask, autoDraw, autoLog }); // callback to deal with text metrics invalidation: const onChange = (withPixi = false, withBoundingBox = false, withMetrics = false) => @@ -69,81 +92,80 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) // text and font: this._addAttribute( - 'text', + "text", text, - 'Hello World', - onChange(true, true, true) + "Hello World", + onChange(true, true, true), ); this._addAttribute( - 'alignHoriz', + "alignHoriz", alignHoriz, - 'center', - onChange(true, true, true) + "center", + onChange(true, true, true), ); this._addAttribute( - 'alignVert', + "alignVert", alignVert, - 'center', - onChange(true, true, true) + "center", + onChange(true, true, true), ); this._addAttribute( - 'flipHoriz', + "flipHoriz", flipHoriz, false, - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'flipVert', + "flipVert", flipVert, false, - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'font', + "font", font, - 'Arial', - this._onChange(true, true) + "Arial", + this._onChange(true, true), ); this._addAttribute( - 'height', + "height", height, this._getDefaultLetterHeight(), - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'wrapWidth', + "wrapWidth", wrapWidth, this._getDefaultWrapWidth(), - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'bold', + "bold", bold, false, - onChange(true, true, true) + onChange(true, true, true), ); this._addAttribute( - 'italic', + "italic", italic, false, - onChange(true, true, true) + onChange(true, true, true), ); // color: this._addAttribute( - 'color', + "color", color, - 'white', - this._onChange(true, false) + "white", + this._onChange(true, false), ); this._addAttribute( - 'contrast', + "contrast", contrast, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); - // estimate the bounding box (using TextMetrics): this._estimateBoundingBox(); @@ -153,8 +175,6 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) } } - - /** * Get the metrics estimated for the text and style. * @@ -166,7 +186,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) */ getTextMetrics() { - if (typeof this._textMetrics === 'undefined') + if (typeof this._textMetrics === "undefined") { this._textMetrics = PIXI.TextMetrics.measureText(this._text, this._getTextStyle()); } @@ -174,8 +194,6 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) return this._textMetrics; } - - /** * Get the default letter height given the stimulus' units. * @@ -187,20 +205,18 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) { const height = TextStim._defaultLetterHeightMap.get(this._units); - if (typeof height === 'undefined') + if (typeof height === "undefined") { throw { - origin: 'TextStim._getDefaultLetterHeight', - context: 'when getting the default height of TextStim: ' + this._name, - error: 'no default letter height for unit: ' + this._units + origin: "TextStim._getDefaultLetterHeight", + context: "when getting the default height of TextStim: " + this._name, + error: "no default letter height for unit: " + this._units, }; } return height; } - - /** * Get the default wrap width given the stimulus' units. * @@ -212,20 +228,18 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) { const wrapWidth = TextStim._defaultWrapWidthMap.get(this._units); - if (typeof wrapWidth === 'undefined') + if (typeof wrapWidth === "undefined") { throw { - origin: 'TextStim._getDefaultWrapWidth', - context: 'when getting the default wrap width of TextStim: ' + this._name, - error: 'no default wrap width for unit: ' + this._units + origin: "TextStim._getDefaultWrapWidth", + context: "when getting the default wrap width of TextStim: " + this._name, + error: "no default wrap width for unit: " + this._units, }; } return wrapWidth; } - - /** * Estimate the bounding box. * @@ -238,11 +252,11 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) { // size of the text, irrespective of the orientation: const textMetrics = this.getTextMetrics(); - const textSize = util.to_unit( + const textSize = util.to_unit( [textMetrics.width, textMetrics.height], - 'pix', + "pix", this._win, - this._units + this._units, ); // take the alignment into account: @@ -251,14 +265,12 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) this._pos[0] - anchor[0] * textSize[0], this._pos[1] - anchor[1] * textSize[1], textSize[0], - textSize[1] + textSize[1], ); // TODO take the orientation into account } - - /** * Get the PIXI Text Style applied to the PIXI.Text * @@ -270,17 +282,15 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) return new PIXI.TextStyle({ fontFamily: this._font, fontSize: Math.round(this._getLengthPix(this._height)), - fontWeight: (this._bold) ? 'bold' : 'normal', - fontStyle: (this._italic) ? 'italic' : 'normal', + fontWeight: (this._bold) ? "bold" : "normal", + fontStyle: (this._italic) ? "italic" : "normal", fill: this.getContrastedColor(new Color(this._color), this._contrast).hex, align: this._alignHoriz, - wordWrap: (typeof this._wrapWidth !== 'undefined'), - wordWrapWidth: (typeof this._wrapWidth !== 'undefined') ? this._getHorLengthPix(this._wrapWidth) : 0 + wordWrap: (typeof this._wrapWidth !== "undefined"), + wordWrapWidth: (typeof this._wrapWidth !== "undefined") ? this._getHorLengthPix(this._wrapWidth) : 0, }); } - - /** * Update the stimulus, if necessary. * @@ -301,7 +311,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) { this._needPixiUpdate = false; - if (typeof this._pixi !== 'undefined') + if (typeof this._pixi !== "undefined") { this._pixi.destroy(true); } @@ -326,7 +336,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) // update the size attributes: this._size = [ this._getLengthUnits(Math.abs(this._pixi.width)), - this._getLengthUnits(Math.abs(this._pixi.height)) + this._getLengthUnits(Math.abs(this._pixi.height)), ]; // refine the estimate of the bounding box: @@ -334,12 +344,10 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) this._pos[0] - anchor[0] * this._size[0], this._pos[1] - anchor[1] * this._size[1], this._size[0], - this._size[1] + this._size[1], ); } - - /** * Convert the alignment attributes into an anchor. * @@ -354,36 +362,33 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) switch (this._alignHoriz) { - case 'left': + case "left": anchor.push(0); break; - case 'right': + case "right": anchor.push(1); break; default: - case 'center': + case "center": anchor.push(0.5); } switch (this._alignVert) { - case 'top': + case "top": anchor.push(0); break; - case 'bottom': + case "bottom": anchor.push(1); break; default: - case 'center': + case "center": anchor.push(0.5); } return anchor; } - } - - /** *

This map associates units to default letter height.

* @@ -392,19 +397,17 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin) * @private */ TextStim._defaultLetterHeightMap = new Map([ - ['cm', 1.0], - ['deg', 1.0], - ['degs', 1.0], - ['degFlatPos', 1.0], - ['degFlat', 1.0], - ['norm', 0.1], - ['height', 0.2], - ['pix', 20], - ['pixels', 20] + ["cm", 1.0], + ["deg", 1.0], + ["degs", 1.0], + ["degFlatPos", 1.0], + ["degFlat", 1.0], + ["norm", 0.1], + ["height", 0.2], + ["pix", 20], + ["pixels", 20], ]); - - /** *

This map associates units to default wrap width.

* @@ -413,13 +416,13 @@ TextStim._defaultLetterHeightMap = new Map([ * @private */ TextStim._defaultWrapWidthMap = new Map([ - ['cm', 15.0], - ['deg', 15.0], - ['degs', 15.0], - ['degFlatPos', 15.0], - ['degFlat', 15.0], - ['norm', 1], - ['height', 1], - ['pix', 500], - ['pixels', 500] + ["cm", 15.0], + ["deg", 15.0], + ["degs", 15.0], + ["degFlatPos", 15.0], + ["degFlat", 15.0], + ["norm", 1], + ["height", 1], + ["pix", 500], + ["pixels", 500], ]); diff --git a/src/visual/VisualStim.js b/src/visual/VisualStim.js index 7c6919b..02ae2d9 100644 --- a/src/visual/VisualStim.js +++ b/src/visual/VisualStim.js @@ -7,12 +7,10 @@ * @license Distributed under the terms of the MIT License */ - -import * as PIXI from 'pixi.js-legacy'; -import {MinimalStim} from '../core/MinimalStim.js'; -import {WindowMixin} from '../core/WindowMixin.js'; -import * as util from '../util/Util.js'; - +import * as PIXI from "pixi.js-legacy"; +import { MinimalStim } from "../core/MinimalStim.js"; +import { WindowMixin } from "../core/WindowMixin.js"; +import * as util from "../util/Util.js"; /** * Base class for all visual stimuli. @@ -36,55 +34,54 @@ import * as util from '../util/Util.js'; */ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) { - constructor({name, win, units, ori, opacity, depth, pos, size, clipMask, autoDraw, autoLog} = {}) + constructor({ name, win, units, ori, opacity, depth, pos, size, clipMask, autoDraw, autoLog } = {}) { - super({win, name, autoDraw, autoLog}); + super({ win, name, autoDraw, autoLog }); this._addAttribute( - 'units', + "units", units, - (typeof win !== 'undefined' && win !== null) ? win.units : 'height', - this._onChange(true, true) + (typeof win !== "undefined" && win !== null) ? win.units : "height", + this._onChange(true, true), ); this._addAttribute( - 'pos', + "pos", pos, - [0, 0] + [0, 0], ); this._addAttribute( - 'size', + "size", size, - undefined + undefined, ); this._addAttribute( - 'ori', + "ori", ori, - 0.0 + 0.0, ); this._addAttribute( - 'opacity', + "opacity", opacity, 1.0, - this._onChange(true, false) + this._onChange(true, false), ); this._addAttribute( - 'depth', + "depth", depth, 0, - this._onChange(false, false) + this._onChange(false, false), ); this._addAttribute( - 'clipMask', + "clipMask", clipMask, null, - this._onChange(false, false) + this._onChange(false, false), ); // bounding box of the stimulus, in stimulus units // note: boundingBox does not take the orientation into account - this._addAttribute('boundingBox', PIXI.Rectangle.EMPTY); + this._addAttribute("boundingBox", PIXI.Rectangle.EMPTY); - // the stimulus need to be updated: this._needUpdate = true; @@ -92,8 +89,6 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) this._needPixiUpdate = true; } - - /** * Force a refresh of the stimulus. * @@ -107,8 +102,6 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) this._onChange(true, true)(); } - - /** * Setter for the size attribute. * @@ -120,7 +113,7 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) setSize(size, log = false) { // size is either undefined, null, or a tuple of numbers: - if (typeof size !== 'undefined' && size !== null) + if (typeof size !== "undefined" && size !== null) { size = util.toNumerical(size); if (!Array.isArray(size)) @@ -129,7 +122,7 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) } } - const hasChanged = this._setAttribute('size', size, log); + const hasChanged = this._setAttribute("size", size, log); if (hasChanged) { @@ -137,8 +130,6 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) } } - - /** * Setter for the orientation attribute. * @@ -149,20 +140,17 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) */ setOri(ori, log = false) { - const hasChanged = this._setAttribute('ori', ori, log); + const hasChanged = this._setAttribute("ori", ori, log); if (hasChanged) { let radians = -ori * 0.017453292519943295; - this._rotationMatrix = [[Math.cos(radians), -Math.sin(radians)], - [Math.sin(radians), Math.cos(radians)]]; + this._rotationMatrix = [[Math.cos(radians), -Math.sin(radians)], [Math.sin(radians), Math.cos(radians)]]; this._onChange(true, true)(); } } - - /** * Setter for the position attribute. * @@ -174,20 +162,18 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) setPos(pos, log = false) { const prevPos = this._pos; - const hasChanged = this._setAttribute('pos', util.toNumerical(pos), log); + const hasChanged = this._setAttribute("pos", util.toNumerical(pos), log); if (hasChanged) { this._needUpdate = true; - + // update the bounding box, without calling _estimateBoundingBox: this._boundingBox.x += this._pos[0] - prevPos[0]; this._boundingBox.y += this._pos[1] - prevPos[1]; } } - - /** * Determine whether an object is inside the bounding box of the stimulus. * @@ -202,12 +188,12 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) // get the position of the object, in pixel coordinates: const objectPos_px = util.getPositionFromObject(object, units); - if (typeof objectPos_px === 'undefined') + if (typeof objectPos_px === "undefined") { throw { - origin: 'VisualStim.contains', - context: 'when determining whether VisualStim: ' + this._name + ' contains object: ' + util.toString(object), - error: 'unable to determine the position of the object' + origin: "VisualStim.contains", + context: "when determining whether VisualStim: " + this._name + " contains object: " + util.toString(object), + error: "unable to determine the position of the object", }; } @@ -215,8 +201,6 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) return this._getBoundingBox_px().contains(objectPos_px[0], objectPos_px[1]); } - - /** * Estimate the bounding box. * @@ -227,14 +211,12 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) _estimateBoundingBox() { throw { - origin: 'VisualStim._estimateBoundingBox', + origin: "VisualStim._estimateBoundingBox", context: `when estimating the bounding box of visual stimulus: ${this._name}`, - error: 'this method is abstract and should not be called.' + error: "this method is abstract and should not be called.", }; } - - /** * Get the bounding box in pixel coordinates * @@ -245,37 +227,35 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) */ _getBoundingBox_px() { - if (this._units === 'pix') + if (this._units === "pix") { return this._boundingBox.clone(); } - else if (this._units === 'norm') + else if (this._units === "norm") { return new PIXI.Rectangle( this._boundingBox.x * this._win.size[0] / 2, this._boundingBox.y * this._win.size[1] / 2, this._boundingBox.width * this._win.size[0] / 2, - this._boundingBox.height * this._win.size[1] / 2 + this._boundingBox.height * this._win.size[1] / 2, ); } - else if (this._units === 'height') + else if (this._units === "height") { const minSize = Math.min(this._win.size[0], this._win.size[1]); return new PIXI.Rectangle( this._boundingBox.x * minSize, this._boundingBox.y * minSize, this._boundingBox.width * minSize, - this._boundingBox.height * minSize + this._boundingBox.height * minSize, ); } else { - throw Object.assign(response, {error: `unknown units: ${this._units}`}); + throw Object.assign(response, { error: `unknown units: ${this._units}` }); } } - - /** * Generate a callback that prepares updates to the stimulus. * This is typically called in the constructor of a stimulus, when attributes are added with _addAttribute. @@ -302,5 +282,4 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin) } }; } - } diff --git a/src/visual/index.js b/src/visual/index.js index bef7d96..834e0a8 100644 --- a/src/visual/index.js +++ b/src/visual/index.js @@ -1,12 +1,12 @@ -export * from './ButtonStim.js'; -export * from './Form.js'; -export * from './ImageStim.js'; -export * from './MovieStim.js'; -export * from './Polygon.js'; -export * from './Rect.js'; -export * from './ShapeStim.js'; -export * from './Slider.js'; -export * from './TextBox.js'; -export * from './TextInput.js'; -export * from './TextStim.js'; -export * from './VisualStim.js'; +export * from "./ButtonStim.js"; +export * from "./Form.js"; +export * from "./ImageStim.js"; +export * from "./MovieStim.js"; +export * from "./Polygon.js"; +export * from "./Rect.js"; +export * from "./ShapeStim.js"; +export * from "./Slider.js"; +export * from "./TextBox.js"; +export * from "./TextInput.js"; +export * from "./TextStim.js"; +export * from "./VisualStim.js";