Implemented stacked button groups.

This commit is contained in:
2019-07-31 16:12:00 +02:00
parent 73342a0506
commit 614b4d8350
70 changed files with 1782 additions and 880 deletions
+16 -4
View File
@@ -245,7 +245,7 @@ const buttonGroup14 = new ButtonGroup({
{label: 'Stacked button 7', action: event => console.log('clicked 7')},
{label: 'Stacked button 8', action: event => console.log('clicked 8')}
],
stacked: true,
stackPadding: 6,
maxWidth: 620,
app
})
@@ -263,18 +263,30 @@ const buttonGroup15 = new ButtonGroup({
{icon: 'battery_charging_full', type: 'checkbox', iconColorActive: 0x9c71b7}
],
orientation: 'vertical',
margin: 0,
stacked: true,
margin: 1,
maxHeight: 200,
app
})
const buttons16 = []
for (let i = 1; i < 51; i++) {
buttons16.push({label: `Button ${i}`, stroke: Math.floor(Math.random() * 16777215), strokeWidth: 3, radius: 16})
}
const buttonGroup16 = new ButtonGroup({
x: 90,
y: 1040,
buttons: buttons16,
stackPadding: 3,
maxWidth: 700,
app
})
app.scene.addChild(buttonGroup1, buttonGroup2, buttonGroup3)
app.scene.addChild(buttonGroup4)
app.scene.addChild(buttonGroup5, buttonGroup6)
app.scene.addChild(buttonGroup7, buttonGroup8)
app.scene.addChild(buttonGroup9, buttonGroup10, buttonGroup11, buttonGroup12, buttonGroup13)
app.scene.addChild(buttonGroup14, buttonGroup15)
app.scene.addChild(buttonGroup14, buttonGroup15, buttonGroup16)
</script>
</body>
</html>
+103 -33
View File
@@ -42,10 +42,10 @@ export default class ButtonGroup extends PIXI.Container {
* or a Theme object.
* @param {number} [opts.minWidth=44] - Button: The minimum width of one button.
* @param {number} [opts.minHeight=44] - Button: The minimum height of one button.
* @param {number} [opts.maxWidth] - The maximum width of the button group. Only used if stacked is true and the orientation is horizontal.
* @param {number} [opts.maxHeight] - The maximum height of the button group. Only used if stacked is true and the orientation is vertical.
* @param {boolean} [opts.stacked=false] - If set to true, the buttons of the button group gets stacked if they are broader or higher than the maximum permitted width or height, depending on orientation.
* @param {PIXI.Application} [opts.app] - The PixiJS Application. Must be set if you want to use the mousewheel to scroll your button group.
* @param {number} [opts.maxWidth] - The maximum width of the button group. If the buttons are wider than the maximum width, the buttons get stacked. Note: The buttons can only be stacked if margin is not zero.
* @param {number} [opts.maxHeight] - The maximum height of the button group. If the buttons are higher than the maximum height, the buttons get stacked. Note: The buttons can only be stacked if margin is not zero.
* @param {number} [opts.stackPadding=10] - The padding for stacked buttons.
* @param {PIXI.Application} [opts.app] - The PixiJS Application. Must be set if you want to use the mousewheel to scroll your button group. Only used when the buttons are stacked (with maxWidth or maxHeight).
* @param {number} [opts.padding=Theme.padding] - Button: The inner spacing (distance from icon and/or label) the the border.
* @param {number} [opts.margin=Theme.margin] - The outer spacing (distance from one button to the previous/next button).
* @param {string} [opts.iconPosition=left] - Button: The position of the icon in relation to the label. Can be left or right.
@@ -96,7 +96,7 @@ export default class ButtonGroup extends PIXI.Container {
minHeight: 44,
maxWidth: null,
maxHeight: null,
stacked: false,
stackPadding: 10,
app: null,
padding: theme.padding,
margin: theme.margin,
@@ -159,6 +159,7 @@ export default class ButtonGroup extends PIXI.Container {
// Buttons
//-----------------
let position = 0
let index = 0
for (let it of this.opts.buttons) {
delete it.x
@@ -237,6 +238,9 @@ export default class ButtonGroup extends PIXI.Container {
}
position += (this.opts.orientation === 'horizontal' ? button.width : button.height) + this.opts.margin
button.__initIndex = index
index++
}
if (this.opts.orientation === 'vertical') {
@@ -256,7 +260,7 @@ export default class ButtonGroup extends PIXI.Container {
// interaction
//--------------------
if (this.opts.stacked) {
if (this.opts.margin > 0 && (this.opts.maxWidth || this.opts.maxHeight)) {
this.interactive = true
this.on('pointerdown', this.onStart.bind(this))
this.on('pointermove', this.onMove.bind(this))
@@ -288,7 +292,6 @@ export default class ButtonGroup extends PIXI.Container {
this.addChildAt(background, 0)
this.__initWidth = this.container.width
this.__deltaWidth = this.container.width - this.opts.maxWidth
}
return this
@@ -308,9 +311,9 @@ export default class ButtonGroup extends PIXI.Container {
//-----------------
this.draw()
// stacked
// stack
//-----------------
if (this.opts.stacked) {
if (this.opts.margin > 0 && (this.opts.maxWidth || this.opts.maxHeight)) {
this.stack()
}
@@ -438,9 +441,7 @@ export default class ButtonGroup extends PIXI.Container {
this.container.position.y = event.data.global.y + this.__delta.y
}
if (this.opts.stacked) {
this.stack()
}
this.stack()
}
}
@@ -515,9 +516,7 @@ export default class ButtonGroup extends PIXI.Container {
}
}
if (this.opts.stacked) {
this.stack()
}
this.stack()
}
/**
@@ -534,35 +533,106 @@ export default class ButtonGroup extends PIXI.Container {
*
*/
stack() {
if (this.opts.maxWidth) {
this._stackHorizontal()
} else if (this.opts.maxHeight) {
this._stackVertical()
}
}
/**
*
*/
_stackHorizontal() {
const sorted = []
let reverseCounter = this.buttons.length - 1
this.buttons.forEach((it, index) => {
if (it.__originalPosition.x + this.container.x < 0) {
const leftCorner = it.__originalPosition.x + this.container.x
const rightCorner = it.__originalPosition.x + it.width
const paddingLeft = index * this.opts.stackPadding
const paddingRight = reverseCounter * this.opts.stackPadding
if (leftCorner < paddingLeft) {
// left border
it.x = -this.container.x
} else if (it.__originalPosition.x + it.width > Math.abs(this.container.x) + this.opts.maxWidth) {
it.x = -this.container.x + paddingLeft
} else if (rightCorner > -this.container.x + this.opts.maxWidth - paddingRight) {
// right border
it.x = Math.abs(this.container.x) + this.opts.maxWidth - it.width
it.x = -this.container.x + this.opts.maxWidth - it.width - paddingRight
} else {
it.x = it.__originalPosition.x
}
reverseCounter--
sorted.push(it)
})
this.buttons.sort((a, b) => {
const delta = Math.abs(this.container.x) + this.opts.maxWidth / 2
const distanceA = Math.abs(a.x - delta)
const distanceB = Math.abs(b.x - delta)
if (distanceA > distanceB) {
return -1
} else if (distanceB > distanceA) {
return 1
const min = Math.min(...sorted.map(it => it.x))
const max = Math.max(...sorted.map(it => it.x))
const center = (min + max) / 2
// z-index
sorted
.sort((a, b) => {
const distanceA = Math.abs(a.x - center)
const distanceB = Math.abs(b.x - center)
if (distanceA < distanceB) {
return 1
} else if (distanceA > distanceB) {
return -1
} else {
return 0
}
})
.forEach(it => it.parent.addChild(it))
}
/**
*
*/
_stackVertical() {
const sorted = []
let reverseCounter = this.buttons.length - 1
this.buttons.forEach((it, index) => {
const topCorner = it.__originalPosition.y + this.container.y
const bottomCorner = it.__originalPosition.y + it.height
const paddingTop = index * this.opts.stackPadding
const paddingBottom = reverseCounter * this.opts.stackPadding
if (topCorner < paddingTop) {
// top border
it.y = -this.container.y + paddingTop
} else if (bottomCorner > -this.container.y + this.opts.maxHeight - paddingBottom) {
// bottom border
it.y = -this.container.y + this.opts.maxHeight - it.height - paddingBottom
} else {
return 0
it.y = it.__originalPosition.y
}
reverseCounter--
sorted.push(it)
})
this.buttons.forEach(it => {
const parent = it.parent
parent.removeChild(it)
parent.addChild(it)
})
const min = Math.min(...sorted.map(it => it.y))
const max = Math.max(...sorted.map(it => it.y))
const center = (min + max) / 2
// z-index
sorted
.sort((a, b) => {
const distanceA = Math.abs(a.y - center)
const distanceB = Math.abs(b.y - center)
if (distanceA < distanceB) {
return 1
} else if (distanceA > distanceB) {
return -1
} else {
return 0
}
})
.forEach(it => it.parent.addChild(it))
}
}