mirror of
https://github.com/psychopy/psychojs.git
synced 2025-05-10 10:40:54 +00:00
Merge pull request #519 from lightest/CU-25m6jrz_anchor_for_web
Unified anchor implementation for visual stims
This commit is contained in:
commit
e79f0d8e1f
@ -468,7 +468,7 @@ export class GratingStim extends VisualStim
|
||||
*/
|
||||
_getDisplaySize()
|
||||
{
|
||||
let displaySize = this.size;
|
||||
let displaySize = this._size;
|
||||
|
||||
if (typeof displaySize === "undefined")
|
||||
{
|
||||
@ -518,10 +518,10 @@ export class GratingStim extends VisualStim
|
||||
geometry.addAttribute(
|
||||
"aVertexPosition",
|
||||
[
|
||||
0, 0,
|
||||
this._size_px[0], 0,
|
||||
this._size_px[0], this._size_px[1],
|
||||
0, this._size_px[1]
|
||||
-this._size_px[0] * .5, -this._size_px[1] * .5,
|
||||
this._size_px[0] * .5, -this._size_px[1] * .5,
|
||||
this._size_px[0] * .5, this._size_px[1] * .5,
|
||||
-this._size_px[0] * .5, this._size_px[1] * .5
|
||||
],
|
||||
2
|
||||
);
|
||||
@ -643,6 +643,25 @@ export class GratingStim extends VisualStim
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the anchor attribute.
|
||||
*
|
||||
* @param {string} anchor - anchor of the stim
|
||||
* @param {boolean} [log= false] - whether or not to log
|
||||
*/
|
||||
setAnchor (anchor = "center", log = false)
|
||||
{
|
||||
this._setAttribute("anchor", anchor, log);
|
||||
if (this._pixi !== undefined)
|
||||
{
|
||||
// Vertices are set directly with origin at [0, 0], centered around it.
|
||||
// Subtracting 0.5 from anchorNum vals to get desired effect.
|
||||
const anchorNum = this._anchorTextToNum(this._anchor);
|
||||
this._pixi.pivot.x = (anchorNum[0] - 0.5) * this._pixi.scale.x * this._pixi.width;
|
||||
this._pixi.pivot.y = (anchorNum[1] - 0.5) * this._pixi.scale.y * this._pixi.height;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the stimulus, if necessary.
|
||||
*
|
||||
@ -660,6 +679,7 @@ export class GratingStim extends VisualStim
|
||||
if (this._needPixiUpdate)
|
||||
{
|
||||
this._needPixiUpdate = false;
|
||||
this._size_px = util.to_px(this._size, this.units, this.win);
|
||||
let shaderName;
|
||||
let shaderUniforms;
|
||||
let currentUniforms = {};
|
||||
@ -706,7 +726,6 @@ export class GratingStim extends VisualStim
|
||||
};
|
||||
}
|
||||
this._pixi = this._getPixiMeshFromPredefinedShaders(shaderName, Object.assign(shaderUniforms, currentUniforms));
|
||||
this._pixi.pivot.set(this._pixi.width * 0.5, this._pixi.width * 0.5);
|
||||
this._pixi.filters = [this._adjustmentFilter];
|
||||
|
||||
// add a mask if need be:
|
||||
@ -751,16 +770,12 @@ export class GratingStim extends VisualStim
|
||||
|
||||
this._pixi.zIndex = -this._depth;
|
||||
this.opacity = this._opacity;
|
||||
this.anchor = this._anchor;
|
||||
|
||||
// set the scale:
|
||||
const displaySize = this._getDisplaySize();
|
||||
this._size_px = util.to_px(displaySize, this.units, this.win);
|
||||
const scaleX = this._size_px[0] / this._pixi.width;
|
||||
const scaleY = this._size_px[1] / this._pixi.height;
|
||||
this._pixi.scale.x = this.flipHoriz ? -scaleX : scaleX;
|
||||
this._pixi.scale.y = this.flipVert ? scaleY : -scaleY;
|
||||
this._pixi.scale.x = 1;
|
||||
this._pixi.scale.y = -1;
|
||||
|
||||
// set the position, rotation, and anchor (image centered on pos):
|
||||
let pos = to_pixiPoint(this.pos, this.units, this.win);
|
||||
this._pixi.position.set(pos.x, pos.y);
|
||||
this._pixi.rotation = -this.ori * Math.PI / 180;
|
||||
|
@ -2,8 +2,8 @@
|
||||
* Image Stimulus.
|
||||
*
|
||||
* @author Alain Pitiot
|
||||
* @version 2021.2.3
|
||||
* @copyright (c) 2017-2020 Ilixa Ltd. (http://ilixa.com) (c) 2020-2021 Open Science Tools Ltd. (https://opensciencetools.org)
|
||||
* @version 2022.2.3
|
||||
* @copyright (c) 2017-2020 Ilixa Ltd. (http://ilixa.com) (c) 2020-2022 Open Science Tools Ltd. (https://opensciencetools.org)
|
||||
* @license Distributed under the terms of the MIT License
|
||||
*/
|
||||
|
||||
@ -32,6 +32,7 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
* @param {string | HTMLImageElement} options.mask - the name of the mask resource or HTMLImageElement corresponding to the mask
|
||||
* @param {string} [options.units= "norm"] - the units of the stimulus (e.g. for size, position, vertices)
|
||||
* @param {Array.<number>} [options.pos= [0, 0]] - the position of the center of the stimulus
|
||||
* @param {string} [options.anchor = "center"] - sets the origin point of the stim
|
||||
* @param {string} [options.units= 'norm'] - the units of the stimulus vertices, size and position
|
||||
* @param {number} [options.ori= 0.0] - the orientation (in degrees)
|
||||
* @param {number} [options.size] - the size of the rendered image (the size of the image will be used if size is not specified)
|
||||
@ -46,9 +47,9 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
* @param {boolean} [options.autoDraw= false] - whether or not the stimulus should be automatically drawn on every frame flip
|
||||
* @param {boolean} [options.autoLog= false] - whether or not to log
|
||||
*/
|
||||
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, anchor, 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, anchor, size, autoDraw, autoLog });
|
||||
|
||||
this._addAttribute(
|
||||
"image",
|
||||
@ -350,14 +351,13 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
const size_px = util.to_px(displaySize, this.units, this.win);
|
||||
const scaleX = size_px[0] / this._texture.width;
|
||||
const scaleY = size_px[1] / this._texture.height;
|
||||
this.anchor = this._anchor;
|
||||
this._pixi.scale.x = this.flipHoriz ? -scaleX : scaleX;
|
||||
this._pixi.scale.y = this.flipVert ? scaleY : -scaleY;
|
||||
|
||||
// set the position, rotation, and anchor (image centered on pos):
|
||||
this._pixi.position = to_pixiPoint(this.pos, this.units, this.win);
|
||||
this._pixi.rotation = -this.ori * Math.PI / 180;
|
||||
this._pixi.anchor.x = 0.5;
|
||||
this._pixi.anchor.y = 0.5;
|
||||
|
||||
// re-estimate the bounding box, as the texture's width may now be available:
|
||||
this._estimateBoundingBox();
|
||||
|
@ -34,6 +34,7 @@ export class MovieStim extends VisualStim
|
||||
* movie resource or of a HTMLVideoElement or of a Camera component
|
||||
* @param {string} [options.units= "norm"] - the units of the stimulus (e.g. for size, position, vertices)
|
||||
* @param {Array.<number>} [options.pos= [0, 0]] - the position of the center of the stimulus
|
||||
* @param {string} [options.anchor = "center"] - sets the origin point of the stim
|
||||
* @param {string} [options.units= 'norm'] - the units of the stimulus vertices, size and position
|
||||
* @param {number} [options.ori= 0.0] - the orientation (in degrees)
|
||||
* @param {number} [options.size] - the size of the rendered image (the size of the image will be used if size is not specified)
|
||||
@ -50,9 +51,9 @@ export class MovieStim extends VisualStim
|
||||
* @param {boolean} [options.autoDraw= false] - whether or not the stimulus should be automatically drawn on every frame flip
|
||||
* @param {boolean} [options.autoLog= false] - whether or not to log
|
||||
*/
|
||||
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, anchor, 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, anchor, size, autoDraw, autoLog });
|
||||
|
||||
this.psychoJS.logger.debug("create a new MovieStim with name: ", name);
|
||||
|
||||
@ -403,8 +404,7 @@ export class MovieStim extends VisualStim
|
||||
// set the position, rotation, and anchor (movie centered on pos):
|
||||
this._pixi.position = to_pixiPoint(this.pos, this.units, this.win);
|
||||
this._pixi.rotation = -this.ori * Math.PI / 180;
|
||||
this._pixi.anchor.x = 0.5;
|
||||
this._pixi.anchor.y = 0.5;
|
||||
this.anchor = this._anchor;
|
||||
|
||||
// re-estimate the bounding box, as the texture's width may now be available:
|
||||
this._estimateBoundingBox();
|
||||
|
@ -29,6 +29,7 @@ export class Rect extends ShapeStim
|
||||
* @param {number} [options.width= 0.5] - the width of the rectangle
|
||||
* @param {number} [options.height= 0.5] - the height of the rectangle
|
||||
* @param {Array.<number>} [options.pos= [0, 0]] - the position
|
||||
* @param {string} [options.anchor = "center"] - sets the origin point of the stim
|
||||
* @param {number} [options.size= 1.0] - the size
|
||||
* @param {number} [options.ori= 0.0] - the orientation (in degrees)
|
||||
* @param {string} [options.units= "height"] - the units of the stimulus vertices, size and position
|
||||
@ -38,7 +39,7 @@ export class Rect extends ShapeStim
|
||||
* @param {boolean} [options.autoDraw= false] - whether or not the stimulus should be automatically drawn on every frame flip
|
||||
* @param {boolean} [options.autoLog= false] - whether or not to log
|
||||
*/
|
||||
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, anchor, size, ori, units, contrast, depth, interpolate, autoDraw, autoLog } = {})
|
||||
{
|
||||
super({
|
||||
name,
|
||||
@ -48,6 +49,7 @@ export class Rect extends ShapeStim
|
||||
fillColor,
|
||||
opacity,
|
||||
pos,
|
||||
anchor,
|
||||
ori,
|
||||
size,
|
||||
units,
|
||||
|
@ -35,6 +35,7 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin
|
||||
* @param {Array.<Array.<number>>} [options.vertices= [[-0.5, 0], [0, 0.5], [0.5, 0]]] - the shape vertices
|
||||
* @param {boolean} [options.closeShape= true] - whether or not the shape is closed
|
||||
* @param {Array.<number>} [options.pos= [0, 0]] - the position of the center of the shape
|
||||
* @param {string} [options.anchor = "center"] - sets the origin point of the stim
|
||||
* @param {number} [options.size= 1.0] - the size
|
||||
* @param {number} [options.ori= 0.0] - the orientation (in degrees)
|
||||
* @param {string} options.units - the units of the stimulus vertices, size and position
|
||||
@ -44,9 +45,9 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin
|
||||
* @param {boolean} [options.autoDraw= false] - whether or not the stimulus should be automatically drawn on every frame flip
|
||||
* @param {boolean} [options.autoLog= false] - whether or not to log
|
||||
*/
|
||||
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, anchor, 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, anchor, depth, size, autoDraw, autoLog });
|
||||
|
||||
// the PIXI polygon corresponding to the vertices, in pixel units:
|
||||
this._pixiPolygon_px = undefined;
|
||||
@ -175,6 +176,26 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin
|
||||
return util.IsPointInsidePolygon(objectPos_px, polygon_px);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the anchor attribute.
|
||||
*
|
||||
* @param {string} anchor - anchor of the stim
|
||||
* @param {boolean} [log= false] - whether or not to log
|
||||
*/
|
||||
setAnchor (anchor = "center", log = false)
|
||||
{
|
||||
this._setAttribute("anchor", anchor, log);
|
||||
if (this._pixi !== undefined)
|
||||
{
|
||||
// since vertices are passed directly, usually assuming origin at [0, 0]
|
||||
// and already being centered around it, subtracting 0.5 from anchorNum vals
|
||||
// to get a desired effect.
|
||||
const anchorNum = this._anchorTextToNum(this._anchor);
|
||||
this._pixi.pivot.x = (anchorNum[0] - 0.5) * this._pixi.scale.x * this._pixi.width;
|
||||
this._pixi.pivot.y = (anchorNum[1] - 0.5) * -this._pixi.scale.y * this._pixi.height;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimate the bounding box.
|
||||
*
|
||||
@ -252,6 +273,7 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin
|
||||
}
|
||||
|
||||
this._pixi.zIndex = -this._depth;
|
||||
this.anchor = this._anchor;
|
||||
}
|
||||
|
||||
// set polygon position and rotation:
|
||||
@ -288,7 +310,6 @@ export class ShapeStim extends util.mix(VisualStim).with(ColorMixin, WindowMixin
|
||||
coords_px.push(coords_px[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// destroy the previous PIXI polygon and create a new one:
|
||||
this._pixiPolygon_px = new PIXI.Polygon(coords_px);
|
||||
this._pixiPolygon_px.closeStroke = this._closeShape;
|
||||
|
@ -432,6 +432,24 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the anchor attribute.
|
||||
*
|
||||
* @param {string} anchor - anchor of the stim
|
||||
* @param {boolean} [log= false] - whether or not to log
|
||||
*/
|
||||
setAnchor (anchor = "center", log = false)
|
||||
{
|
||||
this._setAttribute("anchor", anchor, log);
|
||||
if (this._pixi !== undefined)
|
||||
{
|
||||
// container has origin at [0, 0], subtracting 0.5 from anchorNum vals to get a desired effect.
|
||||
const anchorNum = this._anchorTextToNum(this._anchor);
|
||||
this._pixi.pivot.x = (anchorNum[0] - 0.5) * this._pixi.scale.x * this._pixi.width;
|
||||
this._pixi.pivot.y = (anchorNum[1] - 0.5) * this._pixi.scale.y * this._pixi.height;
|
||||
}
|
||||
}
|
||||
|
||||
/** Let `borderColor` alias `lineColor` to parallel PsychoPy */
|
||||
set borderColor(color)
|
||||
{
|
||||
@ -748,6 +766,7 @@ export class Slider extends util.mix(VisualStim).with(ColorMixin, WindowMixin)
|
||||
|
||||
this._pixi.alpha = this._opacity;
|
||||
this._pixi.zIndex = -this._depth;
|
||||
this.anchor = this._anchor;
|
||||
|
||||
// make sure that the dependent Stimuli are also updated:
|
||||
for (const dependentStim of this._dependentStims)
|
||||
|
@ -39,7 +39,7 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin)
|
||||
* @param {number} [options.letterHeight= <default value>] - the height of the text
|
||||
* @param {boolean} [options.bold= false] - whether or not the text is bold
|
||||
* @param {boolean} [options.italic= false] - whether or not the text is italic
|
||||
* @param {string} [options.anchor = 'left'] - horizontal alignment
|
||||
* @param {string} [options.anchor = "center"] - sets the origin point of the stim
|
||||
*
|
||||
* @param {boolean} [options.multiline= false] - whether or not a multiline element is used
|
||||
* @param {boolean} [options.autofocus= true] - whether or not the first input should receive focus by default
|
||||
@ -89,7 +89,7 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin)
|
||||
} = {},
|
||||
)
|
||||
{
|
||||
super({ name, win, pos, size, units, ori, opacity, depth, clipMask, autoDraw, autoLog });
|
||||
super({ name, win, pos, anchor, size, units, ori, opacity, depth, clipMask, autoDraw, autoLog });
|
||||
|
||||
this._addAttribute(
|
||||
"text",
|
||||
@ -102,11 +102,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin)
|
||||
"",
|
||||
this._onChange(true, true),
|
||||
);
|
||||
this._addAttribute(
|
||||
"anchor",
|
||||
anchor,
|
||||
"center"
|
||||
);
|
||||
this._addAttribute(
|
||||
"flipHoriz",
|
||||
flipHoriz,
|
||||
@ -269,22 +264,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the anchor attribute.
|
||||
*
|
||||
* @param {boolean} anchor - anchor of the textbox
|
||||
* @param {boolean} [log= false] - whether or not to log
|
||||
*/
|
||||
setAnchor (anchor = "center", log = false)
|
||||
{
|
||||
this._setAttribute("anchor", anchor, log);
|
||||
if (this._pixi !== undefined) {
|
||||
const anchorUnits = this._getAnchor();
|
||||
this._pixi.anchor.x = anchorUnits[0];
|
||||
this._pixi.anchor.y = anchorUnits[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For tweaking the underlying input value.
|
||||
*
|
||||
@ -574,7 +553,7 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin)
|
||||
const boxHeight = this._letterHeight + 2 * this._padding + 2 * this._borderWidth;
|
||||
|
||||
// take the alignment into account:
|
||||
const anchor = this._getAnchor();
|
||||
const anchor = this._anchorTextToNum(this._anchor);
|
||||
this._boundingBox = new PIXI.Rectangle(
|
||||
this._pos[0] - anchor[0] * this._size[0],
|
||||
this._pos[1] - anchor[1] * boxHeight,
|
||||
@ -665,36 +644,6 @@ export class TextBox extends util.mix(VisualStim).with(ColorMixin)
|
||||
// apply the clip mask:
|
||||
this._pixi.mask = this._clipMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the anchor attribute into numerical values.
|
||||
*
|
||||
* @protected
|
||||
* @return {number[]} - the anchor, as an array of numbers in [0,1]
|
||||
*/
|
||||
_getAnchor()
|
||||
{
|
||||
const anchor = [0.5, 0.5];
|
||||
|
||||
if (this._anchor.indexOf("left") > -1)
|
||||
{
|
||||
anchor[0] = 0;
|
||||
}
|
||||
else if (this._anchor.indexOf("right") > -1)
|
||||
{
|
||||
anchor[0] = 1;
|
||||
}
|
||||
if (this._anchor.indexOf("top") > -1)
|
||||
{
|
||||
anchor[1] = 0;
|
||||
}
|
||||
else if (this._anchor.indexOf("bottom") > -1)
|
||||
{
|
||||
anchor[1] = 1;
|
||||
}
|
||||
|
||||
return anchor;
|
||||
}
|
||||
}
|
||||
|
||||
TextBox._alignmentToFlexboxMap = new Map([
|
||||
|
@ -31,6 +31,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
* @param {string} [options.text="Hello World"] - the text to be rendered
|
||||
* @param {string} [options.font= "Arial"] - the font family
|
||||
* @param {Array.<number>} [options.pos= [0, 0]] - the position of the center of the text
|
||||
* @param {string} [options.anchor = "center"] - sets the origin point of the stim
|
||||
* @param {Color} [options.color= 'white'] the background color
|
||||
* @param {number} [options.opacity= 1.0] - the opacity
|
||||
* @param {number} [options.depth= 0] - the depth (i.e. the z order)
|
||||
@ -56,6 +57,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
text,
|
||||
font,
|
||||
pos,
|
||||
anchor,
|
||||
color,
|
||||
opacity,
|
||||
depth,
|
||||
@ -76,7 +78,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
} = {},
|
||||
)
|
||||
{
|
||||
super({ name, win, units, ori, opacity, depth, pos, clipMask, autoDraw, autoLog });
|
||||
super({ name, win, units, ori, opacity, depth, pos, anchor, clipMask, autoDraw, autoLog });
|
||||
|
||||
// callback to deal with text metrics invalidation:
|
||||
const onChange = (withPixi = false, withBoundingBox = false, withMetrics = false) =>
|
||||
@ -166,6 +168,13 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
this._onChange(true, false)
|
||||
);
|
||||
|
||||
// alignHoriz and alignVert should be deprecated and replaced by anchor, but leaving this here
|
||||
// for compatibility for a while.
|
||||
if (typeof alignVert === "string" && typeof alignHoriz === "string")
|
||||
{
|
||||
this.anchor = `${alignVert}-${alignHoriz}`;
|
||||
}
|
||||
|
||||
// estimate the bounding box (using TextMetrics):
|
||||
this._estimateBoundingBox();
|
||||
|
||||
@ -328,7 +337,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
);
|
||||
|
||||
// take the alignment into account:
|
||||
const anchor = this._getAnchor();
|
||||
const anchor = this._anchorTextToNum(this._anchor);
|
||||
this._boundingBox = new PIXI.Rectangle(
|
||||
this._pos[0] - anchor[0] * textSize[0],
|
||||
this._pos[1] - textSize[1] + anchor[1] * textSize[1],
|
||||
@ -405,7 +414,7 @@ export class TextStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
// this._pixi.updateText();
|
||||
}
|
||||
|
||||
const anchor = this._getAnchor();
|
||||
const anchor = this._anchorTextToNum(this._anchor);
|
||||
[this._pixi.anchor.x, this._pixi.anchor.y] = anchor;
|
||||
|
||||
this._pixi.scale.x = this._flipHoriz ? -1 : 1;
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Base class for all visual stimuli.
|
||||
*
|
||||
* @author Alain Pitiot
|
||||
* @version 2022.2.0
|
||||
* @version 2022.2.3
|
||||
* @copyright (c) 2017-2020 Ilixa Ltd. (http://ilixa.com) (c) 2020-2022 Open Science Tools Ltd. (https://opensciencetools.org)
|
||||
* @license Distributed under the terms of the MIT License
|
||||
*/
|
||||
@ -30,12 +30,13 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin)
|
||||
* @param {number} [options.opacity= 1.0] - the opacity
|
||||
* @param {number} [options.depth= 0] - the depth (i.e. the z order)
|
||||
* @param {Array.<number>} [options.pos= [0, 0]] - the position of the center of the stimulus
|
||||
* @param {string} [options.anchor = "center"] - sets the origin point of the stim
|
||||
* @param {number} [options.size= 1.0] - the size
|
||||
* @param {PIXI.Graphics} [options.clipMask= null] - the clip mask
|
||||
* @param {boolean} [options.autoDraw= false] - whether or not the stimulus should be automatically drawn on every frame flip
|
||||
* @param {boolean} [options.autoLog= false] - whether or not to log
|
||||
*/
|
||||
constructor({ name, win, units, ori, opacity, depth, pos, size, clipMask, autoDraw, autoLog } = {})
|
||||
constructor({ name, win, units, ori, opacity, depth, pos, anchor, size, clipMask, autoDraw, autoLog } = {})
|
||||
{
|
||||
super({ win, name, autoDraw, autoLog });
|
||||
|
||||
@ -50,6 +51,11 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin)
|
||||
pos,
|
||||
[0, 0],
|
||||
);
|
||||
this._addAttribute(
|
||||
"anchor",
|
||||
anchor,
|
||||
"center",
|
||||
);
|
||||
this._addAttribute(
|
||||
"size",
|
||||
size,
|
||||
@ -211,6 +217,62 @@ export class VisualStim extends util.mix(MinimalStim).with(WindowMixin)
|
||||
return this._getBoundingBox_px().contains(objectPos_px[0], objectPos_px[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the anchor attribute.
|
||||
*
|
||||
* @param {string} anchor - anchor of the stim
|
||||
* @param {boolean} [log= false] - whether or not to log
|
||||
*/
|
||||
setAnchor (anchor = "center", log = false)
|
||||
{
|
||||
this._setAttribute("anchor", anchor, log);
|
||||
if (this._pixi !== undefined)
|
||||
{
|
||||
const anchorNum = this._anchorTextToNum(this._anchor);
|
||||
if (this._pixi.anchor !== undefined)
|
||||
{
|
||||
this._pixi.anchor.x = anchorNum[0];
|
||||
this._pixi.anchor.y = anchorNum[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
this._pixi.pivot.x = anchorNum[0] * this._pixi.scale.x * this._pixi.width;
|
||||
this._pixi.pivot.y = anchorNum[1] * this._pixi.scale.y * this._pixi.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the anchor attribute into numerical values.
|
||||
*
|
||||
* @protected
|
||||
* @param {string} anchorText - text version of anchor value ["top-left", "top-right", "center", ...]
|
||||
* @return {number[]} - the anchor, as an array of numbers in [0,1]
|
||||
*/
|
||||
_anchorTextToNum(anchorText = "")
|
||||
{
|
||||
const anchor = [0.5, 0.5];
|
||||
|
||||
if (anchorText.indexOf("left") > -1)
|
||||
{
|
||||
anchor[0] = 0.0;
|
||||
}
|
||||
else if (anchorText.indexOf("right") > -1)
|
||||
{
|
||||
anchor[0] = 1.0;
|
||||
}
|
||||
if (anchorText.indexOf("top") > -1)
|
||||
{
|
||||
anchor[1] = 0.0;
|
||||
}
|
||||
else if (anchorText.indexOf("bottom") > -1)
|
||||
{
|
||||
anchor[1] = 1.0;
|
||||
}
|
||||
|
||||
return anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimate the bounding box.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user