From 7a0d5f34a0d40c28aea33da3599df3fb7b175971 Mon Sep 17 00:00:00 2001 From: Baz Utsahajit Date: Fri, 22 Mar 2024 19:59:04 +0000 Subject: [PATCH] Address Feedback --- src/FancyButton.ts | 88 ++++++++++++++++--- ...FancyButtonNineSlicePlaneSprite.stories.ts | 20 ++--- src/utils/helpers/fit.ts | 30 +++++-- 3 files changed, 111 insertions(+), 27 deletions(-) diff --git a/src/FancyButton.ts b/src/FancyButton.ts index 71fe23a2..3c82e61e 100644 --- a/src/FancyButton.ts +++ b/src/FancyButton.ts @@ -62,6 +62,8 @@ export type ButtonOptions = ViewsInput & { offset?: Offset; textOffset?: Offset; iconOffset?: Offset; + textScale?: Pos | number; + iconScale?: Pos | number; animations?: StateAnimations; nineSlicePlane?: [number, number, number, number]; ignoreRefitting?: boolean; @@ -137,8 +139,11 @@ export class FancyButton extends ButtonContainer /** Anchor point of the button. */ anchor: ObservablePoint; - protected _textBaseScale = 1; - protected _iconBaseScale = 1; + /** Base text scaling to take into account when fitting inside the button */ + protected _textBaseScale: Pos = { x: 1, y: 1 }; + + /** Base icon scaling to take into account when fitting inside the button */ + protected _iconBaseScale: Pos = { x: 1, y: 1 }; /** * Creates a button with a lot of tweaks. @@ -177,6 +182,8 @@ export class FancyButton extends ButtonContainer offset, textOffset, iconOffset, + textScale, + iconScale, scale, anchor, anchorX, @@ -194,6 +201,8 @@ export class FancyButton extends ButtonContainer this.offset = offset; this.textOffset = textOffset; this.iconOffset = iconOffset; + this.textBaseScale = textScale; + this.iconBaseScale = iconScale; this.scale.set(scale ?? 1); if (animations) @@ -302,7 +311,15 @@ export class FancyButton extends ButtonContainer protected createTextView(text: AnyText) { this._views.textView = getTextView(text); - this._textBaseScale = this._views.textView.scale.x; + + // If text scale has not manually been set, we will overwrite the base scale with the new text view scale. + if (this.options?.textScale === undefined) + { + const { x, y } = this._views.textView.scale; + + this._textBaseScale = { x, y }; + } + this._views.textView.anchor.set(0); this.innerView.addChild(this._views.textView); @@ -378,12 +395,12 @@ export class FancyButton extends ButtonContainer if (activeView) { - if (!this.options.ignoreRefitting) + if (this.options && !this.options.ignoreRefitting) { - this._views.textView.scale.set(this._textBaseScale); + this._views.textView.scale.set(this._textBaseScale.x, this._textBaseScale.y); } - fitToView(activeView, this._views.textView, this.padding); + fitToView(activeView, this._views.textView, this.padding, false); this._views.textView.x = activeView.x + (activeView.width / 2); this._views.textView.y = activeView.y + (activeView.height / 2); @@ -412,12 +429,12 @@ export class FancyButton extends ButtonContainer return; } - if (!this.options.ignoreRefitting) + if (this.options && !this.options.ignoreRefitting) { - this._views.iconView.scale.set(this._iconBaseScale); + this._views.iconView.scale.set(this._iconBaseScale.x, this._iconBaseScale.y); } - fitToView(activeView, this._views.iconView, this.padding); + fitToView(activeView, this._views.iconView, this.padding, false); (this._views.iconView as Sprite).anchor?.set(0); @@ -641,7 +658,14 @@ export class FancyButton extends ButtonContainer } this._views.iconView = getView(view); - this._iconBaseScale = this._views.iconView.scale.x; + + // If icon scale has not manually been set, we will overwrite the base scale with the new icon view scale. + if (this.options?.iconScale === undefined) + { + const { x, y } = this._views.iconView.scale; + + this._iconBaseScale = { x, y }; + } if (!this._views.iconView.parent) { @@ -811,6 +835,50 @@ export class FancyButton extends ButtonContainer return this._textOffset; } + /** + * Sets the base scale for the text view to take into account when fitting inside the button. + * @param {Pos | number} scale - base scale of the text view. + */ + set textBaseScale(scale: Pos | number) + { + // Apply to the options so that the manual scale is prioritized. + this.options.textScale = scale; + if (scale === undefined) return; + const isNumber = typeof scale === 'number'; + + this._textBaseScale.x = isNumber ? scale : scale.x ?? 1; + this._textBaseScale.y = isNumber ? scale : scale.y ?? 1; + this.adjustTextView(this.state); + } + + /** Returns the text view base scale. */ + get textBaseScale(): Pos + { + return this.textBaseScale; + } + + /** + * Sets the base scale for the icon view to take into account when fitting inside the button. + * @param {Pos | number} scale - base scale of the icon view. + */ + set iconBaseScale(scale: Pos | number) + { + // Apply to the options so that the manual scale is prioritized. + this.options.iconScale = scale; + if (scale === undefined) return; + const isNumber = typeof scale === 'number'; + + this._iconBaseScale.x = isNumber ? scale : scale.x ?? 1; + this._iconBaseScale.y = isNumber ? scale : scale.y ?? 1; + this.adjustIconView(this.state); + } + + /** Returns the icon view base scale. */ + get iconBaseScale(): Pos + { + return this.iconBaseScale; + } + /** * Sets width of a FancyButtons state views. * If nineSlicePlane is set, then width will be set to nineSlicePlanes of a views. diff --git a/src/stories/fancyButton/FancyButtonNineSlicePlaneSprite.stories.ts b/src/stories/fancyButton/FancyButtonNineSlicePlaneSprite.stories.ts index 1fb180bc..48f8658a 100644 --- a/src/stories/fancyButton/FancyButtonNineSlicePlaneSprite.stories.ts +++ b/src/stories/fancyButton/FancyButtonNineSlicePlaneSprite.stories.ts @@ -60,8 +60,16 @@ export const UseNineSlicePlane = ({ ...defaultTextStyle, fill: textColor || defaultTextStyle.fill }), + icon: new MaskedFrame({ + target: `avatar-01.png`, + mask: `avatar_mask.png`, + borderWidth: 10, + borderColor: 0xFFFFFF + }), padding, textOffset: { x: 30, y: -5 }, + iconOffset: { x: -100, y: -7 }, + iconScale: 0.2, animations: { hover: { props: { @@ -80,18 +88,6 @@ export const UseNineSlicePlane = ({ }, }); - const buttonIcon = new MaskedFrame({ - target: `avatar-01.png`, - mask: `avatar_mask.png`, - borderWidth: 10, - borderColor: 0xFFFFFF - }); - - buttonIcon.scale.set(0.2); - - button.iconView = buttonIcon; - button.iconOffset = { x: -100, y: -7 }; - button.anchor.set(anchorX, anchorY); if (disabled) diff --git a/src/utils/helpers/fit.ts b/src/utils/helpers/fit.ts index 578a0386..d83c6bba 100644 --- a/src/utils/helpers/fit.ts +++ b/src/utils/helpers/fit.ts @@ -1,6 +1,6 @@ import { Container } from '@pixi/display'; -export function fitToView(parent: Container, child: Container, padding = 0) +export function fitToView(parent: Container, child: Container, padding = 0, uniformScaling = true) { let scaleX = child.scale.x; let scaleY = child.scale.y; @@ -18,18 +18,38 @@ export function fitToView(parent: Container, child: Container, padding = 0) if (widthOverflow < 0) { - scaleX = maxWidth / (child.width * scaleX); + scaleX = maxWidth / (child.width / scaleX); } if (heightOverflow < 0) { - scaleY = maxHeight / (child.height * scaleY); + scaleY = maxHeight / (child.height / scaleY); } if (scaleX <= 0 || scaleY <= 0) { - child.visible = false; + child.scale.set(0); + + return; } - child.scale.set(Math.min(scaleX, scaleY)); + if (uniformScaling || child.scale.x === child.scale.y) + { + const scale = Math.min(scaleX, scaleY); + + child.scale.set(scale, scale); + } + else + { + const ratio = child.scale.x / child.scale.y; + + if (widthOverflow < heightOverflow) + { + child.scale.set(scaleX, scaleX / ratio); + } + else + { + child.scale.set(scaleY * ratio, scaleY); + } + } }