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
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |