1 changed files with 150 additions and 144 deletions
@ -1,159 +1,165 @@ |
|||
import { Text, Graphics, Container, TextStyle, NineSlicePlane, Texture, NineSliceSprite, Ticker } from "pixi.js"; |
|||
|
|||
interface IOpts { |
|||
text: string; |
|||
autoUpdate: Boolean; |
|||
bg: Texture; |
|||
pressBg: Texture; |
|||
position: null | any; |
|||
click(): void; |
|||
} |
|||
import { |
|||
Container, |
|||
Text, |
|||
Graphics, |
|||
TextStyle, |
|||
NineSliceSprite, |
|||
Ticker, |
|||
Texture, |
|||
} from "pixi.js"; |
|||
|
|||
const defaultOpts: IOpts = { |
|||
autoUpdate: true, |
|||
text: "", |
|||
bg: null, |
|||
position: null, |
|||
pressBg: null, |
|||
click() { }, |
|||
}; |
|||
|
|||
function getConfig() { |
|||
return Object.assign({}, defaultOpts) |
|||
export interface ButtonOptions { |
|||
text: string; |
|||
bg?: Texture; |
|||
pressBg?: Texture; |
|||
position?: () => { x: number; y: number }; |
|||
onClick: () => void; |
|||
autoUpdate?: boolean; |
|||
padding?: { x: number; y: number }; |
|||
fontSize?: number; |
|||
} |
|||
|
|||
export class Button { |
|||
config: IOpts |
|||
_comp: Container |
|||
textObj: Text |
|||
bgRect: Graphics |
|||
bgNine: NineSliceSprite |
|||
padding = { x: 60, y: 40 } |
|||
getComp(){ |
|||
return this._comp |
|||
} |
|||
constructor(opts: Partial<IOpts>) { |
|||
this.config = getConfig(); |
|||
; (Object.keys(defaultOpts) as (keyof IOpts)[]).forEach((key) => { |
|||
if (opts[key] != undefined) { |
|||
this.config[key] = opts[key] as any; |
|||
} |
|||
}); |
|||
|
|||
this._comp = new Container(); |
|||
this._comp.cursor = 'pointer'; |
|||
this._comp.interactive = true; |
|||
|
|||
if (!this.config.bg) { |
|||
this.createRect() |
|||
this._comp.addChild(this.bgRect) |
|||
} else { |
|||
this.createNine() |
|||
this._comp.addChild(this.bgNine) |
|||
} |
|||
this.createText() |
|||
this._comp.addChild(this.textObj) |
|||
if (this.config.autoUpdate) { |
|||
const update = () => { |
|||
this.updateView() |
|||
} |
|||
Ticker.shared.add(update) |
|||
this._comp.on("destroyed", ()=>{ |
|||
console.log("销毁了"); |
|||
Ticker.shared.remove(update, this) |
|||
}) |
|||
} |
|||
const downFN = () => { |
|||
if (this.config.pressBg && this.bgNine) { |
|||
this.bgNine.texture = this.config.pressBg |
|||
} else { |
|||
this._comp.alpha = 0.8; |
|||
this._comp.scale = { x: .8, y: .8 } |
|||
} |
|||
} |
|||
this._comp.on("mousedown", downFN); |
|||
this._comp.on("touchstart", downFN); |
|||
const upFN = () => { |
|||
if (this.config.pressBg && this.bgNine) { |
|||
this.bgNine.texture = this.config.bg |
|||
} else { |
|||
this._comp.alpha = 1; |
|||
this._comp.scale = { x: 1, y: 1 } |
|||
} |
|||
this.config.click(); |
|||
} |
|||
this._comp.on('mouseup', upFN); |
|||
this._comp.on('touchend', upFN); |
|||
const upOutsideFN = () => { |
|||
if (this.config.pressBg) { |
|||
this.bgNine.texture = this.config.bg |
|||
} else { |
|||
this._comp.alpha = 1; |
|||
this._comp.scale = { x: 1, y: 1 } |
|||
} |
|||
} |
|||
this._comp.on("mouseupoutside", upOutsideFN); |
|||
this._comp.on("touchendoutside", upOutsideFN); |
|||
private config: ButtonOptions; |
|||
private _container: Container; |
|||
private textObj: Text; |
|||
private bgRect?: Graphics; |
|||
private bgNine?: NineSliceSprite; |
|||
private padding: { x: number; y: number }; |
|||
|
|||
constructor(opts: ButtonOptions) { |
|||
this.config = { |
|||
autoUpdate: true, |
|||
padding: { x: 60, y: 40 }, |
|||
fontSize: 30, |
|||
...opts, |
|||
}; |
|||
this.padding = this.config.padding!; |
|||
|
|||
this._container = new Container(); |
|||
this._container.cursor = "pointer"; |
|||
this._container.interactive = true; |
|||
|
|||
if (!this.config.bg) { |
|||
this.createRectBackground(); |
|||
} else { |
|||
this.createNineSliceBackground(); |
|||
} |
|||
|
|||
updateView() { |
|||
if(this._comp.destroyed) return |
|||
let width = this.textObj.width + this.padding.x; |
|||
let height = this.textObj.height + this.padding.y; |
|||
this._comp.pivot.set(width / 2, height / 2) |
|||
this.textObj.x = this.padding.x / 2; |
|||
this.textObj.y = this.padding.y / 2 - 2; |
|||
|
|||
if (this.bgRect) { |
|||
this.bgRect.rect(0, 0, width, height); |
|||
this.bgRect.fill(0xff0000); |
|||
} |
|||
if (this.bgNine) { |
|||
this.bgNine.width = width |
|||
this.bgNine.height = height |
|||
} |
|||
|
|||
if (this.config.position) { |
|||
this._comp.position = this.config.position() |
|||
} |
|||
this.createText(); |
|||
this._container.addChild(this.textObj); |
|||
|
|||
this.setupEvents(); |
|||
|
|||
if (this.config.autoUpdate) { |
|||
const update = () => this.updateView(); |
|||
Ticker.shared.add(update); |
|||
this._container.on("destroyed", () => { |
|||
Ticker.shared.remove(update); |
|||
}); |
|||
} |
|||
|
|||
createNine() { |
|||
this.bgNine = new NineSliceSprite({ |
|||
texture: this.config.bg, |
|||
leftWidth: 10, |
|||
topHeight: 10, |
|||
rightWidth: 10, |
|||
bottomHeight: 10, |
|||
}); |
|||
this.bgNine.cursor = 'pointer'; |
|||
this.bgNine.label = "nine-pic" |
|||
this.bgNine.interactive = true; |
|||
// plane9.buttonMode = true;
|
|||
this.updateView(); |
|||
} |
|||
|
|||
get container(): Container { |
|||
return this._container; |
|||
} |
|||
|
|||
updateView(): void { |
|||
if (this._container.destroyed) return; |
|||
|
|||
const width = this.textObj.width + this.padding.x; |
|||
const height = this.textObj.height + this.padding.y; |
|||
|
|||
this._container.pivot.set(width / 2, height / 2); |
|||
this.textObj.position.set(this.padding.x / 2, this.padding.y / 2 - 2); |
|||
|
|||
if (this.bgRect) { |
|||
this.bgRect.clear(); |
|||
this.bgRect.rect(0, 0, width, height); |
|||
this.bgRect.fill(0xff0000); |
|||
} |
|||
|
|||
createRect() { |
|||
this.bgRect = new Graphics(); |
|||
this.bgRect.label = "rect"; |
|||
this.bgRect.interactive = true; |
|||
this.bgRect.cursor = 'pointer'; |
|||
// rect.buttonMode = true;
|
|||
if (this.bgNine) { |
|||
this.bgNine.width = width; |
|||
this.bgNine.height = height; |
|||
} |
|||
|
|||
createText() { |
|||
let textStyle = new TextStyle({ |
|||
fontFamily: "Arial", |
|||
fontSize: 30, |
|||
fill: 0xffffff, |
|||
align: "center", |
|||
}); |
|||
this.textObj = new Text({ |
|||
text: this.config.text, |
|||
style: textStyle |
|||
}); |
|||
this.textObj.cursor = 'pointer'; |
|||
this.textObj.label = "text" |
|||
if (this.config.position) { |
|||
this._container.position = this.config.position(); |
|||
} |
|||
} |
|||
|
|||
private createRectBackground(): void { |
|||
this.bgRect = new Graphics(); |
|||
this.bgRect.label = "button-bg-rect"; |
|||
this._container.addChild(this.bgRect); |
|||
} |
|||
|
|||
private createNineSliceBackground(): void { |
|||
if (!this.config.bg) return; |
|||
this.bgNine = new NineSliceSprite({ |
|||
texture: this.config.bg, |
|||
leftWidth: 10, |
|||
topHeight: 10, |
|||
rightWidth: 10, |
|||
bottomHeight: 10, |
|||
}); |
|||
this.bgNine.label = "button-bg-nine"; |
|||
this._container.addChild(this.bgNine); |
|||
} |
|||
|
|||
private createText(): void { |
|||
const style = new TextStyle({ |
|||
fontFamily: "Arial", |
|||
fontSize: this.config.fontSize!, |
|||
fill: 0xffffff, |
|||
align: "center", |
|||
}); |
|||
this.textObj = new Text({ |
|||
text: this.config.text, |
|||
style, |
|||
}); |
|||
this.textObj.label = "button-text"; |
|||
} |
|||
|
|||
private setupEvents(): void { |
|||
const onPointerDown = () => { |
|||
if (this.config.pressBg && this.bgNine && this.config.bg) { |
|||
this.bgNine.texture = this.config.pressBg; |
|||
} else { |
|||
this._container.alpha = 0.8; |
|||
this._container.scale.set(0.8, 0.8); |
|||
} |
|||
}; |
|||
|
|||
const onPointerUp = () => { |
|||
if (this.config.pressBg && this.bgNine && this.config.bg) { |
|||
this.bgNine.texture = this.config.bg; |
|||
} else { |
|||
this._container.alpha = 1; |
|||
this._container.scale.set(1, 1); |
|||
} |
|||
this.config.onClick(); |
|||
}; |
|||
|
|||
const onPointerUpOutside = () => { |
|||
if (this.config.pressBg && this.bgNine && this.config.bg) { |
|||
this.bgNine.texture = this.config.bg; |
|||
} else { |
|||
this._container.alpha = 1; |
|||
this._container.scale.set(1, 1); |
|||
} |
|||
}; |
|||
|
|||
this._container.on("mousedown", onPointerDown); |
|||
this._container.on("touchstart", onPointerDown); |
|||
this._container.on("mouseup", onPointerUp); |
|||
this._container.on("touchend", onPointerUp); |
|||
this._container.on("mouseupoutside", onPointerUpOutside); |
|||
this._container.on("touchendoutside", onPointerUpOutside); |
|||
} |
|||
} |
|||
|
|||
export default Button |
|||
export default Button; |
|||
Loading…
Reference in new issue