Added Scrollview.

This commit is contained in:
2019-05-14 13:56:05 +02:00
parent fada4f9a9d
commit 275a5d0b04
33 changed files with 18231 additions and 2297 deletions
+2
View File
@@ -10,6 +10,7 @@ import Timeline from './timeline.js'
import Theme from './theme.js'
import Button from './button.js'
import ButtonGroup from './buttongroup.js'
import Scrollview from './scrollview.js'
import Slider from './slider.js'
import Switch from './switch.js'
import Popup from './popup.js'
@@ -41,6 +42,7 @@ window.AppTest = AppTest
window.Theme = Theme
window.Button = Button
window.ButtonGroup = ButtonGroup
window.Scrollview = Scrollview
window.Slider = Slider
window.Switch = Switch
window.Popup = Popup
+585
View File
@@ -0,0 +1,585 @@
/**
* pixi.js scrollbox: a masked content box that can scroll vertically or horizontally with scrollbars
*/
export default class Scrollbox extends PIXI.Container {
/**
* create a scrollbox
* @param {object} options
* @param {boolean} [options.dragScroll=true] user may drag the content area to scroll content
* @param {string} [options.overflowX=auto] (none, scroll, hidden, auto) this changes whether the scrollbar is shown
* @param {string} [options.overflowY=auto] (none, scroll, hidden, auto) this changes whether the scrollbar is shown
* @param {string} [options.overflow] (none, scroll, hidden, auto) sets overflowX and overflowY to this value
* @param {number} [options.boxWidth=100] width of scrollbox including scrollbar (in pixels)
* @param {number} [options.boxHeight=100] height of scrollbox including scrollbar (in pixels)
* @param {number} [options.scrollbarSize=10] size of scrollbar (in pixels)
* @param {number} [options.scrollbarOffsetHorizontal=0] offset of horizontal scrollbar (in pixels)
* @param {number} [options.scrollbarOffsetVertical=0] offset of vertical scrollbar (in pixels)
* @param {boolean} [options.stopPropagation=true] call stopPropagation on any events that impact scrollbox
* @param {number} [options.scrollbarBackground=0xdddddd] background color of scrollbar
* @param {number} [options.scrollbarBackgroundAlpha=1] alpha of background of scrollbar
* @param {number} [options.scrollbarForeground=0x888888] foreground color of scrollbar
* @param {number} [options.scrollbarForegroundAlpha=1] alpha of foreground of scrollbar
* @param {string} [options.underflow=top-left] what to do when content underflows the scrollbox size: none: do nothing; (left/right/center AND top/bottom/center); OR center (e.g., 'top-left', 'center', 'none', 'bottomright')
* @param {(boolean|number)} [options.fade] fade the scrollbar when not in use (true = 1000ms)
* @param {number} [options.fadeWait=3000] time to wait before fading the scrollbar if options.fade is set
* @param {(string|function)} [options.fadeEase=easeInOutSine] easing function to use for fading
*/
constructor(options)
{
super()
this.options = Object.assign({}, {
"boxWidth": 100,
"boxHeight": 100,
"scrollbarSize": 10,
"scrollbarBackground": 14540253,
"scrollbarBackgroundAlpha": 1,
"scrollbarForeground": 8947848,
"scrollbarForegroundAlpha": 1,
"dragScroll": true,
"stopPropagation": true,
"scrollbarOffsetHorizontal": 0,
"scrollbarOffsetVertical": 0,
"underflow": "top-left",
"fadeScrollbar": false,
"fadeWait": 3000,
"fadeEase": "easeInOutSine"
}, options)
this.ease = new PIXI.extras.Ease.list()
/**
* content in placed in here
* you can use any function from pixi-viewport on content to manually move the content (see https://davidfig.github.io/pixi-viewport/jsdoc/)
* @type {PIXI.extras.Viewport}
*/
this.content = this.addChild(new PIXI.extras.Viewport({ passiveWheel: this.options.stopPropagation, stopPropagation: this.options.stopPropagation, screenWidth: this.options.boxWidth, screenHeight: this.options.boxHeight }))
this.content
.decelerate()
.on('moved', () => this._drawScrollbars())
/**
* graphics element for drawing the scrollbars
* @type {PIXI.Graphics}
*/
this.scrollbar = this.addChild(new PIXI.Graphics())
this.scrollbar.interactive = true
this.scrollbar.on('pointerdown', this.scrollbarDown, this)
this.interactive = true
this.on('pointermove', this.scrollbarMove, this)
this.on('pointerup', this.scrollbarUp, this)
this.on('pointercancel', this.scrollbarUp, this)
this.on('pointerupoutside', this.scrollbarUp, this)
this._maskContent = this.addChild(new PIXI.Graphics())
this.update()
}
/**
* offset of horizontal scrollbar (in pixels)
* @type {number}
*/
get scrollbarOffsetHorizontal()
{
return this.options.scrollbarOffsetHorizontal
}
set scrollbarOffsetHorizontal(value)
{
this.options.scrollbarOffsetHorizontal = value
}
/**
* offset of vertical scrollbar (in pixels)
* @type {number}
*/
get scrollbarOffsetVertical()
{
return this.options.scrollbarOffsetVertical
}
set scrollbarOffsetVertical(value)
{
this.options.scrollbarOffsetVertical = value
}
/**
* disable the scrollbox (if set to true this will also remove the mask)
* @type {boolean}
*/
get disable()
{
return this._disabled
}
set disable(value)
{
if (this._disabled !== value)
{
this._disabled = value
this.update()
}
}
/**
* call stopPropagation on any events that impact scrollbox
* @type {boolean}
*/
get stopPropagation()
{
return this.options.stopPropagation
}
set stopPropagation(value)
{
this.options.stopPropagation = value
}
/**
* user may drag the content area to scroll content
* @type {boolean}
*/
get dragScroll()
{
return this.options.dragScroll
}
set dragScroll(value)
{
this.options.dragScroll = value
if (value)
{
this.content.drag()
}
else
{
this.content.removePlugin('drag')
}
this.update()
}
/**
* width of scrollbox including the scrollbar (if visible)- this changes the size and not the scale of the box
* @type {number}
*/
get boxWidth()
{
return this.options.boxWidth
}
set boxWidth(value)
{
this.options.boxWidth = value
this.content.screenWidth = value
this.update()
}
/**
* sets overflowX and overflowY to (scroll, hidden, auto) changing whether the scrollbar is shown
* scroll = always show scrollbar
* hidden = hide overflow and do not show scrollbar
* auto = if content is larger than box size, then show scrollbar
* @type {string}
*/
get overflow()
{
return this.options.overflow
}
set overflow(value)
{
this.options.overflow = value
this.options.overflowX = value
this.options.overflowY = value
this.update()
}
/**
* sets overflowX to (scroll, hidden, auto) changing whether the scrollbar is shown
* scroll = always show scrollbar
* hidden = hide overflow and do not show scrollbar
* auto = if content is larger than box size, then show scrollbar
* @type {string}
*/
get overflowX()
{
return this.options.overflowX
}
set overflowX(value)
{
this.options.overflowX = value
this.update()
}
/**
* sets overflowY to (scroll, hidden, auto) changing whether the scrollbar is shown
* scroll = always show scrollbar
* hidden = hide overflow and do not show scrollbar
* auto = if content is larger than box size, then show scrollbar
* @type {string}
*/
get overflowY()
{
return this.options.overflowY
}
set overflowY(value)
{
this.options.overflowY = value
this.update()
}
/**
* height of scrollbox including the scrollbar (if visible) - this changes the size and not the scale of the box
* @type {number}
*/
get boxHeight()
{
return this.options.boxHeight
}
set boxHeight(value)
{
this.options.boxHeight = value
this.content.screenHeight = value
this.update()
}
/**
* scrollbar size in pixels
* @type {number}
*/
get scrollbarSize()
{
return this.options.scrollbarSize
}
set scrollbarSize(value)
{
this.options.scrollbarSize = value
}
/**
* width of scrollbox less the scrollbar (if visible)
* @type {number}
* @readonly
*/
get contentWidth()
{
return this.options.boxWidth - (this.isScrollbarVertical ? this.options.scrollbarSize : 0)
}
/**
* height of scrollbox less the scrollbar (if visible)
* @type {number}
* @readonly
*/
get contentHeight()
{
return this.options.boxHeight - (this.isScrollbarHorizontal ? this.options.scrollbarSize : 0)
}
/**
* is the vertical scrollbar visible
* @type {boolean}
* @readonly
*/
get isScrollbarVertical()
{
return this._isScrollbarVertical
}
/**
* is the horizontal scrollbar visible
* @type {boolean}
* @readonly
*/
get isScrollbarHorizontal()
{
return this._isScrollbarHorizontal
}
/**
* top coordinate of scrollbar
*/
get scrollTop()
{
return this.content.top
}
/**
* left coordinate of scrollbar
*/
get scrollLeft()
{
return this.content.left
}
/**
* width of content area
* if not set then it uses content.width to calculate width
*/
get scrollWidth()
{
return this._scrollWidth || this.content.width
}
set scrollWidth(value)
{
this._scrollWidth = value
}
/**
* height of content area
* if not set then it uses content.height to calculate height
*/
get scrollHeight()
{
return this._scrollHeight || this.content.height
}
set scrollHeight(value)
{
this._scrollHeight = value
}
/**
* draws scrollbars
* @private
*/
_drawScrollbars()
{
this._isScrollbarHorizontal = this.overflowX === 'scroll' ? true : ['hidden', 'none'].indexOf(this.overflowX) !== -1 ? false : this.scrollWidth > this.options.boxWidth
this._isScrollbarVertical = this.overflowY === 'scroll' ? true : ['hidden', 'none'].indexOf(this.overflowY) !== -1 ? false : this.scrollHeight > this.options.boxHeight
this.scrollbar.clear()
let options = {}
options.left = 0
options.right = this.scrollWidth + (this._isScrollbarVertical ? this.options.scrollbarSize : 0)
options.top = 0
options.bottom = this.scrollHeight + (this.isScrollbarHorizontal ? this.options.scrollbarSize : 0)
const width = this.scrollWidth + (this.isScrollbarVertical ? this.options.scrollbarSize : 0)
const height = this.scrollHeight + (this.isScrollbarHorizontal ? this.options.scrollbarSize : 0)
this.scrollbarTop = (this.content.top / height) * this.boxHeight
this.scrollbarTop = this.scrollbarTop < 0 ? 0 : this.scrollbarTop
this.scrollbarHeight = (this.boxHeight / height) * this.boxHeight
this.scrollbarHeight = this.scrollbarTop + this.scrollbarHeight > this.boxHeight ? this.boxHeight - this.scrollbarTop : this.scrollbarHeight
this.scrollbarLeft = (this.content.left / width) * this.boxWidth
this.scrollbarLeft = this.scrollbarLeft < 0 ? 0 : this.scrollbarLeft
this.scrollbarWidth = (this.boxWidth / width) * this.boxWidth
this.scrollbarWidth = this.scrollbarWidth + this.scrollbarLeft > this.boxWidth ? this.boxWidth - this.scrollbarLeft : this.scrollbarWidth
if (this.isScrollbarVertical)
{
this.scrollbar
.beginFill(this.options.scrollbarBackground, this.options.scrollbarBackgroundAlpha)
.drawRect(this.boxWidth - this.scrollbarSize + this.options.scrollbarOffsetVertical, 0, this.scrollbarSize, this.boxHeight)
.endFill()
}
if (this.isScrollbarHorizontal)
{
this.scrollbar
.beginFill(this.options.scrollbarBackground, this.options.scrollbarBackgroundAlpha)
.drawRect(0, this.boxHeight - this.scrollbarSize + this.options.scrollbarOffsetHorizontal, this.boxWidth, this.scrollbarSize)
.endFill()
}
if (this.isScrollbarVertical)
{
this.scrollbar
.beginFill(this.options.scrollbarForeground, this.options.scrollbarForegroundAlpha)
.drawRect(this.boxWidth - this.scrollbarSize + this.options.scrollbarOffsetVertical, this.scrollbarTop, this.scrollbarSize, this.scrollbarHeight)
.endFill()
}
if (this.isScrollbarHorizontal)
{
this.scrollbar
.beginFill(this.options.scrollbarForeground, this.options.scrollbarForegroundAlpha)
.drawRect(this.scrollbarLeft, this.boxHeight - this.scrollbarSize + this.options.scrollbarOffsetHorizontal, this.scrollbarWidth, this.scrollbarSize)
.endFill()
}
// this.content.forceHitArea = new PIXI.Rectangle(0, 0 , this.boxWidth, this.boxHeight)
this.activateFade()
}
/**
* draws mask layer
* @private
*/
_drawMask()
{
this._maskContent
.beginFill(0)
.drawRect(0, 0, this.boxWidth, this.boxHeight)
.endFill()
this.content.mask = this._maskContent
}
/**
* call when scrollbox content changes
*/
update()
{
this.content.mask = null
this._maskContent.clear()
if (!this._disabled)
{
this._drawScrollbars()
this._drawMask()
if (this.options.dragScroll)
{
const direction = this.isScrollbarHorizontal && this.isScrollbarVertical ? 'all' : this.isScrollbarHorizontal ? 'x' : 'y'
if (direction !== null)
{
this.content
.drag({ clampWheel: true, direction })
.clamp({ direction, underflow: this.options.underflow })
}
}
}
}
/**
* show the scrollbar and restart the timer for fade if options.fade is set
*/
activateFade()
{
if (this.options.fade)
{
if (this.fade)
{
this.ease.remove(this.fade)
}
this.scrollbar.alpha = 1
const time = this.options.fade === true ? 1000 : this.options.fade
this.fade = this.ease.to(this.scrollbar, { alpha: 0 }, time, { wait: this.options.fadeWait, ease: this.options.fadeEase })
this.fade.on('each', () => this.content.dirty = true)
}
}
/**
* handle pointer down on scrollbar
* @param {PIXI.interaction.InteractionEvent} e
* @private
*/
scrollbarDown(e)
{
const local = this.toLocal(e.data.global)
if (this.isScrollbarHorizontal)
{
if (local.y > this.boxHeight - this.scrollbarSize)
{
if (local.x >= this.scrollbarLeft && local.x <= this.scrollbarLeft + this.scrollbarWidth)
{
this.pointerDown = { type: 'horizontal', last: local }
}
else
{
if (local.x > this.scrollbarLeft)
{
this.content.left += this.content.worldScreenWidth
this.update()
}
else
{
this.content.left -= this.content.worldScreenWidth
this.update()
}
}
if (this.options.stopPropagation)
{
e.stopPropagation()
}
return
}
}
if (this.isScrollbarVertical)
{
if (local.x > this.boxWidth - this.scrollbarSize)
{
if (local.y >= this.scrollbarTop && local.y <= this.scrollbarTop + this.scrollbarWidth)
{
this.pointerDown = { type: 'vertical', last: local }
}
else
{
if (local.y > this.scrollbarTop)
{
this.content.top += this.content.worldScreenHeight
this.update()
}
else
{
this.content.top -= this.content.worldScreenHeight
this.update()
}
}
if (this.options.stopPropagation)
{
e.stopPropagation()
}
return
}
}
}
/**
* handle pointer move on scrollbar
* @param {PIXI.interaction.InteractionEvent} e
* @private
*/
scrollbarMove(e)
{
if (this.pointerDown)
{
if (this.pointerDown.type === 'horizontal')
{
const local = this.toLocal(e.data.global)
this.content.left += local.x - this.pointerDown.last.x
this.pointerDown.last = local
this.update()
}
else if (this.pointerDown.type === 'vertical')
{
const local = this.toLocal(e.data.global)
this.content.top += local.y - this.pointerDown.last.y
this.pointerDown.last = local
this.update()
}
if (this.options.stopPropagation)
{
e.stopPropagation()
}
}
}
/**
* handle pointer down on scrollbar
* @private
*/
scrollbarUp()
{
this.pointerDown = null
}
/**
* resize the mask for the container
* @param {object} options
* @param {number} [options.boxWidth] width of scrollbox including scrollbar (in pixels)
* @param {number} [options.boxHeight] height of scrollbox including scrollbar (in pixels)
* @param {number} [options.scrollWidth] set the width of the inside of the scrollbox (leave null to use content.width)
* @param {number} [options.scrollHeight] set the height of the inside of the scrollbox (leave null to use content.height)
*/
resize(options)
{
this.options.boxWidth = typeof options.boxWidth !== 'undefined' ? options.boxWidth : this.options.boxWidth
this.options.boxHeight = typeof options.boxHeight !== 'undefined' ? options.boxHeight : this.options.boxHeight
if (options.scrollWidth)
{
this.scrollWidth = options.scrollWidth
}
if (options.scrollHeight)
{
this.scrollHeight = options.scrollHeight
}
this.content.resize(this.options.boxWidth, this.options.boxHeight, this.scrollWidth, this.scrollHeight)
this.update()
}
/**
* ensure that the bounding box is visible
* @param {number} x - relative to content's coordinate system
* @param {number} y
* @param {number} width
* @param {number} height
*/
ensureVisible(x, y, width, height)
{
this.content.ensureVisible(x, y, width, height)
this._drawScrollbars()
}
}
-1
View File
File diff suppressed because one or more lines are too long
+25 -29
View File
@@ -13,7 +13,6 @@
<script src="../../dist/iwmlib.3rdparty.js"></script>
<script src="../../dist/iwmlib.js"></script>
<script src="../../dist/iwmlib.pixi.js"></script>
<!-- <script src="./scrollbox.min.js"></script> -->
</head>
<body onload="Doctest.run()">
<h1>Scrollview</h1>
@@ -37,38 +36,35 @@
const app = new PIXIApp({
view: canvas,
width: 900,
height: 250,
height: 400,
transparent: false
}).setup().run()
// let scrollview1 = new Scrollview({
// x: 10,
// y: 20
// })
app.loader
.add('elephant1', './assets/elephant-1.jpg')
.add('elephant2', './assets/elephant-2.jpg')
.add('elephant3', './assets/elephant-3.jpg')
.load((loader, resources) => {
const sprite1 = new PIXI.Sprite(resources.elephant1.texture)
const sprite2 = new PIXI.Sprite(resources.elephant2.texture)
const sprite3 = new PIXI.Sprite(resources.elephant3.texture)
// let scrollview2 = new Scrollview({
// x: 90,
// y: 20,
// fill: 0xfd355a,
// fillActive: 0x5954d3,
// controlFill: 0xfecd2d,
// controlFillActive: 0xfd413b,
// strokeActiveWidth: 4,
// controlStrokeActive: 0x50d968,
// controlStrokeActiveWidth: 12,
// controlStrokeActiveAlpha: .8,
// tooltip: 'Dies ist ein Switch'
// })
const scrollview1 = new Scrollview({boxWidth: 300, boxHeight: 180})
scrollview1.content.addChild(sprite1)
app.scene.addChild(scrollview1)
// const scrollbox = new PIXI.extras.Scrollbox({boxWidth: 500, boxHeight: 200})
// scrollbox.x = 70
// scrollbox.y = 30
// const sprite = new PIXI.Sprite(resources.fulda.texture)
// sprite.scale.set(.5, .5)
// scrollbox.content.addChild(sprite)
// app.stage.addChild(scrollbox)
// app.scene.addChild(switch1, switch2)
const scrollview2 = new Scrollview({boxWidth: 300, boxHeight: 300})
scrollview2.x = 500
scrollview2.y = 30
sprite2.x = 40
sprite2.y = 40
sprite2.scale.set(.3, .3)
sprite3.x = 60
sprite3.y = 100
sprite3.alpha = .6
sprite3.scale.set(.5, .5)
scrollview2.content.addChild(sprite2, sprite3)
app.scene.addChild(scrollview2)
})
</script>
</body>
+10 -416
View File
@@ -1,5 +1,4 @@
import Theme from './theme.js'
import Tooltip from './tooltip.js'
import Scrollbox from './scrollbox.js'
/**
* Callback for the switch action.
@@ -54,140 +53,22 @@ import Tooltip from './tooltip.js'
* app.scene.addChild(switch1)
*
* @class
* @extends PIXI.Container
* @see {@link http://pixijs.download/dev/docs/PIXI.Container.html|PIXI.Container}
* @see {@link https://www.iwm-tuebingen.de/iwmbrowser/lib/pixi/switch.html|DocTest}
* @extends PIXI.extras.Scrollbox
* @see {@link https://davidfig.github.io/pixi-scrollbox/jsdoc/Scrollbox.html|Scrollbox}
* @see {@link https://davidfig.github.io/pixi-viewport/jsdoc/Viewport.html|Viewport}
*/
export default class Switch extends PIXI.Container {
export default class Scrollview extends Scrollbox {
/**
* Creates an instance of a Switch.
*
* @constructor
* @param {object} [opts] - An options object to specify to style and behaviour of the switch.
* @param {number} [opts.id=auto generated] - The id of the switch.
* @param {number} [opts.x=0] - The x position of the switch. Can be also set after creation with switch.x = 0.
* @param {number} [opts.y=0] - The y position of the switch. Can be also set after creation with switch.y = 0.
* @param {string|Theme} [opts.theme=dark] - The theme to use for this switch. Possible values are dark, light, red
* or a Theme object.
* @param {number} [opts.width=44] - The width of the switch.
* @param {number} [opts.height=28] - The height of the switch.
* @param {number} [opts.fill=Theme.fill] - The color of the switch background as a hex value.
* @param {number} [opts.fillAlpha=Theme.fillAlpha] - The alpha value of the background.
* @param {number} [opts.fillActive=Theme.fillActive] - The color of the switch background when activated.
* @param {number} [opts.fillActiveAlpha=Theme.fillActiveAlpha] - The alpha value of the background when activated.
* @param {number} [opts.stroke=Theme.stroke] - The color of the border as a hex value.
* @param {number} [opts.strokeWidth=Theme.strokeWidth] - The width of the border in pixel.
* @param {number} [opts.strokeAlpha=Theme.strokeAlpha] - The alpha value of the border.
* @param {number} [opts.strokeActive=Theme.strokeActive] - The color of the border when activated.
* @param {number} [opts.strokeActiveWidth=Theme.strokeActiveWidth] - The width of the border in pixel when activated.
* @param {number} [opts.strokeActiveAlpha=Theme.strokeActiveAlpha] - The alpha value of the border when activated.
* @param {number} [opts.controlFill=Theme.stroke] - The color of the switch control background as a hex value.
* @param {number} [opts.controlFillAlpha=Theme.strokeAlpha] - The alpha value of the background.
* @param {number} [opts.controlFillActive=Theme.stroke] - The color of the switch control background when activated.
* @param {number} [opts.controlFillActiveAlpha=Theme.strokeAlpha] - The alpha value of the background when activated.
* @param {number} [opts.controlStroke=Theme.stroke] - The color of the border as a hex value.
* @param {number} [opts.controlStrokeWidth=Theme.strokeWidth * 0.8] - The width of the border in pixel.
* @param {number} [opts.controlStrokeAlpha=Theme.strokeAlpha] - The alpha value of the border.
* @param {number} [opts.controlStrokeActive=Theme.stroke] - The color of the border when activated.
* @param {number} [opts.controlStrokeActiveWidth=Theme.strokeActiveWidth * 0.8] - The width of the border in pixel when activated.
* @param {number} [opts.controlStrokeActiveAlpha=Theme.strokeActiveAlpha] - The alpha value of the border when activated.
* @param {number} [opts.duration=Theme.fast] - The duration of the animation when the switch gets activated in seconds.
* @param {number} [opts.durationActive=Theme.fast] - The duration of the animation when the switch gets deactivated in seconds.
* @param {boolean} [opts.disabled=false] - Is the switch disabled? When disabled, the switch has a lower alpha value
* and cannot be clicked (interactive is set to false).
* @param {boolean} [opts.active=false] - Is the button initially active?
* @param {actionCallback} [opts.action] - Executed when the switch was triggered in inactive state (by pointerup).
* @param {actionActiveCallback} [opts.actionActive] - Executed when the button was triggered in active state (by pointerup).
* @param {beforeActionCallback} [opts.beforeAction] - Executed before an action is triggered.
* @param {afterActionCallback} [opts.afterAction] - Executed after an action was triggered.
* @param {string|object} [opts.tooltip] - A string for the label of the tooltip or an object to configure the tooltip
* to display.
* @param {boolean} [opts.visible=true] - Is the switch initially visible (property visible)?
*/
constructor(opts = {}) {
super()
const theme = Theme.fromString(opts.theme)
this.theme = theme
super(opts)
this.opts = Object.assign({}, {
id: PIXI.utils.uid(),
x: 0,
y: 0,
width: 44,
height: 28,
fill: theme.fill,
fillAlpha: theme.fillAlpha,
fillActive: theme.primaryColor,
fillActiveAlpha: theme.fillActiveAlpha,
stroke: theme.stroke,
strokeWidth: theme.strokeWidth,
strokeAlpha: theme.strokeAlpha,
strokeActive: theme.primaryColor,
strokeActiveWidth: theme.strokeActiveWidth,
strokeActiveAlpha: theme.strokeActiveAlpha,
controlFill: theme.stroke,
controlFillAlpha: theme.strokeAlpha,
controlFillActive: theme.stroke,
controlFillActiveAlpha: theme.strokeAlpha,
controlStroke: theme.stroke,
controlStrokeWidth: theme.strokeWidth * .8,
controlStrokeAlpha: theme.strokeAlpha,
controlStrokeActive: theme.stroke,
controlStrokeActiveWidth: theme.strokeActiveWidth * .8,
controlStrokeActiveAlpha: theme.strokeActiveAlpha,
duration: theme.fast,
durationActive: theme.fast,
disabled: false,
active: false,
action: null,
actionActive: null,
beforeAction: null,
afterAction: null,
tooltip: null,
visible: true
}, opts)
this.opts.controlRadius = this.opts.controlRadius || (this.opts.height / 2)
this.opts.controlRadiusActive = this.opts.controlRadiusActive || this.opts.controlRadius
// Validation
//-----------------
if (this.opts.height > this.opts.width) {
this.opts.height = this.opts.width
}
// Properties
//-----------------
this.id = this.opts.id
this.radius = this.opts.height / 2
this._active = null
this._disabled = null
this.switchObj = null
this.control = null
this.tooltip = null
this.visible = this.opts.visible
// animated
//-----------------
this.tempAnimated = {
fill: this.opts.fill,
fillAlpha: this.opts.fillAlpha,
stroke: this.opts.stroke,
strokeWidth: this.opts.strokeWidth,
strokeAlpha: this.opts.strokeAlpha,
controlFill: this.opts.controlFill,
controlFillAlpha: this.opts.controlFillAlpha,
controlStroke: this.opts.controlStroke,
controlStrokeWidth: this.opts.controlStrokeWidth,
controlStrokeAlpha: this.opts.controlStrokeAlpha,
controlRadius: this.opts.controlRadius
}
this.opts = opts
// setup
//-----------------
@@ -202,306 +83,19 @@ export default class Switch extends PIXI.Container {
* Creates children and instantiates everything.
*
* @private
* @return {Switch} A reference to the switch for chaining.
* @return {Scrollview} A reference to the Scrollview for chaining.
*/
setup() {
// Switch
//-----------------
let switchObj = new PIXI.Graphics()
this.switchObj = switchObj
this.addChild(switchObj)
// Control
//-----------------
this.xInactive = this.opts.controlRadius
this.xActive = this.opts.width - this.opts.controlRadiusActive
let control = new PIXI.Graphics()
control.x = this.opts.active ? this.xActive : this.xInactive
control.y = this.opts.height / 2
this.control = control
this.addChild(this.control)
// interaction
//-----------------
this.switchObj.on('pointerover', e => {
TweenLite.to(this.control, this.theme.fast, {alpha: .83})
})
this.switchObj.on('pointerout', e => {
TweenLite.to(this.control, this.theme.fast, {alpha: 1})
})
this.switchObj.on('pointerdown', e => {
TweenLite.to(this.control, this.theme.fast, {alpha: .7})
})
this.switchObj.on('pointerup', e => {
if (this.opts.beforeAction) {
this.opts.beforeAction.call(this, e, this)
}
this.active = !this.active
if (this.active) {
if (this.opts.action) {
this.opts.action.call(this, e, this)
}
} else {
if (this.opts.actionActive) {
this.opts.actionActive.call(this, e, this)
}
}
TweenLite.to(this.control, this.theme.fast, {alpha: .83})
if (this.opts.afterAction) {
this.opts.afterAction.call(this, e, this)
}
})
// disabled
//-----------------
this.disabled = this.opts.disabled
// active
//-----------------
this.active = this.opts.active
// tooltip
//-----------------
if (this.opts.tooltip) {
if (typeof this.opts.tooltip === 'string') {
this.tooltip = new Tooltip({
object: this,
content: this.opts.tooltip
})
} else {
this.opts.tooltip.object = this
this.tooltip = new Tooltip(this.opts.tooltip)
}
}
return this
}
/**
* Should be called to refresh the layout of the switch. Can be used after resizing.
* Should be called to refresh the layout of the Scrollview. Can be used after resizing.
*
* @return {Switch} A reference to the switch for chaining.
* @return {Scrollview} A reference to the Scrollview for chaining.
*/
layout() {
// set position
//-----------------
this.position.set(this.opts.x, this.opts.y)
// draw
//-----------------
this.draw()
return this
}
/**
* Draws the switch to the canvas.
*
* @private
* @return {Switch} A reference to the switch for chaining.
*/
draw() {
this.switchObj.clear()
if (this.active) {
this.switchObj.lineStyle(this.opts.strokeActiveWidth, this.opts.strokeActive, this.opts.strokeActiveAlpha)
this.switchObj.beginFill(this.opts.fillActive, this.opts.fillActiveAlpha)
} else {
this.switchObj.lineStyle(this.opts.strokeWidth, this.opts.stroke, this.opts.strokeAlpha)
this.switchObj.beginFill(this.opts.fill, this.opts.fillAlpha)
}
this.switchObj.moveTo(this.radius, 0)
this.switchObj.lineTo(this.opts.width - this.radius, 0)
this.switchObj.arcTo(this.opts.width, 0, this.opts.width, this.radius, this.radius)
this.switchObj.lineTo(this.opts.width, this.radius + 1) // BUGFIX: If not specified, there is a small area without a stroke.
this.switchObj.arcTo(this.opts.width, this.opts.height, this.opts.width - this.radius, this.opts.height, this.radius)
this.switchObj.lineTo(this.radius, this.opts.height)
this.switchObj.arcTo(0, this.opts.height, 0, this.radius, this.radius)
this.switchObj.arcTo(0, 0, this.radius, 0, this.radius)
this.switchObj.endFill()
// Draw control
this.control.clear()
if (this.active) {
this.control.lineStyle(this.opts.controlStrokeActiveWidth, this.opts.controlStrokeActive, this.opts.controlStrokeActiveAlpha)
this.control.beginFill(this.opts.controlFillActive, this.opts.controlFillActiveAlpha)
this.control.drawCircle(0, 0, this.opts.controlRadiusActive - 1)
} else {
this.control.lineStyle(this.opts.controlStrokeWidth, this.opts.controlStroke, this.opts.controlStrokeAlpha)
this.control.beginFill(this.opts.controlFill, this.opts.controlFillAlpha)
this.control.drawCircle(0, 0, this.opts.controlRadius - 1)
}
this.control.endFill()
return this
}
/**
* Draws the animation.
*
* @private
* @return {Switch} A reference to the switch for chaining.
*/
drawAnimated() {
this.switchObj.clear()
this.switchObj.lineStyle(this.tempAnimated.strokeWidth, this.tempAnimated.stroke, this.tempAnimated.strokeAlpha)
this.switchObj.beginFill(this.tempAnimated.fill, this.tempAnimated.fillAlpha)
this.switchObj.moveTo(this.radius, 0)
this.switchObj.lineTo(this.opts.width - this.radius, 0)
this.switchObj.arcTo(this.opts.width, 0, this.opts.width, this.radius, this.radius)
this.switchObj.lineTo(this.opts.width, this.radius + 1) // BUGFIX: If not specified, there is a small area without a stroke.
this.switchObj.arcTo(this.opts.width, this.opts.height, this.opts.width - this.radius, this.opts.height, this.radius)
this.switchObj.lineTo(this.radius, this.opts.height)
this.switchObj.arcTo(0, this.opts.height, 0, this.radius, this.radius)
this.switchObj.arcTo(0, 0, this.radius, 0, this.radius)
this.switchObj.endFill()
this.control.clear()
this.control.lineStyle(this.tempAnimated.controlStrokeWidth, this.tempAnimated.controlStroke, this.tempAnimated.controlStrokeAlpha)
this.control.beginFill(this.tempAnimated.controlFill, this.tempAnimated.controlFillAlpha)
this.control.drawCircle(0, 0, this.tempAnimated.controlRadius - 1)
this.control.endFill()
return this
}
/**
* Gets or sets the active state.
*
* @member {boolean}
*/
get active() {
return this._active
}
set active(value) {
this._active = value
if (this._active) {
TweenLite.to(this.control, this.opts.duration, {x: this.xActive})
TweenLite.to(this.tempAnimated, this.opts.duration, {
colorProps: {
fill: this.opts.fillActive,
stroke: this.opts.strokeActive,
controlFill: this.opts.controlFillActive,
controlStroke: this.opts.controlStrokeActive,
format: 'number'
},
fillAlpha: this.opts.fillActiveAlpha,
strokeWidth: this.opts.strokeActiveWidth,
strokeAlpha: this.opts.strokeActiveAlpha,
controlFillAlpha: this.opts.controlFillActiveAlpha,
controlStrokeWidth: this.opts.controlStrokeActiveWidth,
controlStrokeAlpha: this.opts.controlStrokeActiveAlpha,
controlRadius: this.opts.controlRadiusActive,
onUpdate: () => this.drawAnimated(),
onComplete: () => this.draw()
})
} else {
TweenLite.to(this.control, this.opts.durationActive, {x: this.xInactive})
TweenLite.to(this.tempAnimated, this.opts.durationActive, {
colorProps: {
fill: this.opts.fill,
stroke: this.opts.stroke,
controlFill: this.opts.controlFill,
controlStroke: this.opts.controlStroke,
format: 'number'
},
fillAlpha: this.opts.fillAlpha,
strokeWidth: this.opts.strokeWidth,
strokeAlpha: this.opts.strokeAlpha,
controlFillAlpha: this.opts.controlFillAlpha,
controlStrokeWidth: this.opts.controlStrokeWidth,
controlStrokeAlpha: this.opts.controlStrokeAlpha,
controlRadius: this.opts.controlRadius,
onUpdate: () => this.drawAnimated(),
onComplete: () => this.draw()
})
}
}
/**
* Gets or sets the disabled state. When disabled, the switch cannot be clicked.
*
* @member {boolean}
*/
get disabled() {
return this._disabled
}
set disabled(value) {
this._disabled = value
if (this._disabled) {
this.switchObj.interactive = false
this.switchObj.buttonMode = false
this.switchObj.alpha = .5
this.control.alpha = .5
} else {
this.switchObj.interactive = true
this.switchObj.buttonMode = true
this.switchObj.alpha = 1
this.control.alpha = 1
}
}
/**
* Shows the switch (sets his alpha values to 1).
*
* @return {Switch} A reference to the switch for chaining.
*/
show() {
this.opts.strokeAlpha = 1
this.opts.strokeActiveAlpha = 1
this.opts.fillAlpha = 1
this.opts.fillActiveAlpha = 1
this.opts.controlStrokeAlpha = 1
this.opts.controlStrokeActiveAlpha = 1
this.opts.controlFillAlpha = 1
this.opts.controlFillActiveAlpha = 1
this.layout()
return this
}
/**
* Hides the switch (sets his alpha values to 1).
*
* @return {Switch} A reference to the switch for chaining.
*/
hide() {
this.opts.strokeAlpha = 0
this.opts.strokeActiveAlpha = 0
this.opts.fillAlpha = 0
this.opts.fillActiveAlpha = 0
this.opts.controlStrokeAlpha = 0
this.opts.controlStrokeActiveAlpha = 0
this.opts.controlFillAlpha = 0
this.opts.controlFillActiveAlpha = 0
this.layout()
return this
}