200 lines
5.4 KiB
JavaScript
200 lines
5.4 KiB
JavaScript
/**
|
|
*
|
|
*/
|
|
export default class Popover extends PIXI.Graphics {
|
|
constructor({
|
|
title = null,
|
|
text = null,
|
|
x = 0,
|
|
y = 0,
|
|
placement = 'top',
|
|
width = 250,
|
|
titleStyle = {},
|
|
textStyle = { fontSize: '1.6em' }
|
|
} = {}) {
|
|
super()
|
|
|
|
this.opts = {
|
|
title,
|
|
text,
|
|
x,
|
|
y,
|
|
placement,
|
|
width,
|
|
titleStyle,
|
|
textStyle
|
|
}
|
|
|
|
this.padding = 12
|
|
|
|
let style = {
|
|
fontFamily: 'Arial',
|
|
fontSize: '2em',
|
|
stroke: '#f6f6f6',
|
|
strokeThickness: 3,
|
|
wordWrap: true,
|
|
wordWrapWidth: width - this.padding * 2
|
|
}
|
|
|
|
this.titleTextStyle = new PIXI.TextStyle(Object.assign({}, style, titleStyle))
|
|
this.textTextStyle = new PIXI.TextStyle(Object.assign({}, style, textStyle))
|
|
|
|
if (title || text) {
|
|
this.setup()
|
|
this.draw()
|
|
this.positioning()
|
|
}
|
|
}
|
|
|
|
setup() {
|
|
this.removeChildren()
|
|
|
|
if (this.opts.title) {
|
|
this.titleText = new PIXI.Text(this.opts.title, this.titleTextStyle)
|
|
this.titleText.position.set(this.padding, this.padding)
|
|
this.addChild(this.titleText)
|
|
}
|
|
|
|
this.titleY = this.titleText ? this.titleText.y : 0
|
|
this.titleHeight = this.titleText ? this.titleText.height : 0
|
|
|
|
if (this.opts.text) {
|
|
this.textText = new PIXI.Text(this.opts.text, this.textTextStyle)
|
|
this.textText.position.set(this.padding, this.titleY + this.titleHeight + this.padding)
|
|
this.addChild(this.textText)
|
|
}
|
|
|
|
this.textY = this.textText ? this.textText.y : 0
|
|
this.textHeight = this.textText ? this.textText.height : 0
|
|
}
|
|
|
|
close() {
|
|
this.parent.removeChild(this)
|
|
}
|
|
|
|
draw() {
|
|
this.clear()
|
|
this.beginFill(0xffffff, 1)
|
|
this.lineStyle(1, 0x282828, 0.5)
|
|
|
|
// Draw rounded rectangle
|
|
const height = this.height + this.padding
|
|
this.drawRoundedRect(0, 0, this.opts.width, height, 8)
|
|
|
|
// Draw anchor
|
|
this.drawAnchor(this.opts.placement)
|
|
|
|
// Draw title background
|
|
if (this.opts.title) {
|
|
this.lineStyle(0)
|
|
this.beginFill(0xf7f7f7, 1)
|
|
let x = 1
|
|
let y = this.titleText.x + this.titleText.height + this.padding / 2
|
|
this.moveTo(x, y)
|
|
y = 9
|
|
this.lineTo(x, y)
|
|
this.quadraticCurveTo(x, y - 8, x + 8, y - 8)
|
|
x += this.opts.width - 7
|
|
y -= 8
|
|
this.lineTo(x, y)
|
|
this.quadraticCurveTo(x + 5, y, x + 5, y + 8)
|
|
x += 5
|
|
y += this.titleText.x + this.titleText.height + this.padding / 2
|
|
this.lineTo(x, y)
|
|
if (this.opts.text) {
|
|
x = 1
|
|
this.lineTo(x, y)
|
|
} else {
|
|
this.quadraticCurveTo(x, y, x - 5, y + 4)
|
|
x = 6
|
|
y += 4
|
|
this.lineTo(x, y)
|
|
this.quadraticCurveTo(x, y, x - 5, y - 4)
|
|
}
|
|
}
|
|
|
|
this.endFill()
|
|
}
|
|
|
|
drawAnchor(placement) {
|
|
let x = 0
|
|
let y = 0
|
|
|
|
switch (placement) {
|
|
case 'bottom':
|
|
if (this.opts.title) {
|
|
this.beginFill(0xf7f7f7, 1)
|
|
}
|
|
x = this.width / 2 - 10
|
|
y = 1
|
|
this.moveTo(x, y)
|
|
x += 10
|
|
y -= 10
|
|
this.lineTo(x, y)
|
|
x += 10
|
|
y += 10
|
|
this.lineTo(x, y)
|
|
break
|
|
case 'right':
|
|
x = 1
|
|
y = this.height / 2 - 10
|
|
if (this.titleY + this.titleHeight > y) {
|
|
this.beginFill(0xf7f7f7, 1)
|
|
}
|
|
this.moveTo(x, y)
|
|
x -= 10
|
|
y += 10
|
|
this.lineTo(x, y)
|
|
x += 10
|
|
y += 10
|
|
this.lineTo(x, y)
|
|
break
|
|
case 'left':
|
|
x = this.width - 2
|
|
y = this.height / 2 - 10
|
|
if (this.titleY + this.titleHeight > y) {
|
|
this.beginFill(0xf7f7f7, 1)
|
|
}
|
|
this.moveTo(x, y)
|
|
x += 10
|
|
y += 10
|
|
this.lineTo(x, y)
|
|
x -= 10
|
|
y += 10
|
|
this.lineTo(x, y)
|
|
break
|
|
default:
|
|
x = this.width / 2 - 10
|
|
y = this.height - 2
|
|
this.moveTo(x, y)
|
|
x += 10
|
|
y += 10
|
|
this.lineTo(x, y)
|
|
x += 10
|
|
y -= 10
|
|
this.lineTo(x, y)
|
|
break
|
|
}
|
|
}
|
|
|
|
positioning() {
|
|
const x = this.opts.x
|
|
const y = this.opts.y
|
|
|
|
switch (this.opts.placement) {
|
|
case 'bottom':
|
|
this.position.set(x - this.width / 2, y + 10)
|
|
break
|
|
case 'right':
|
|
this.position.set(x, y - this.height / 2)
|
|
break
|
|
case 'left':
|
|
this.position.set(x - this.width, y - this.height / 2)
|
|
break
|
|
default:
|
|
this.position.set(x - this.width / 2, y - this.height)
|
|
break
|
|
}
|
|
}
|
|
}
|