dragonbones-runtime
Version:
the tools to build dragonbones file for diffrent framework
598 lines (557 loc) • 21.9 kB
text/typescript
//////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014-present, Egret Technology.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Egret nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////////////
namespace eui {
/**
* @private
*/
export const enum Keys {
clickOffsetX,
clickOffsetY,
moveStageX,
moveStageY,
touchDownTarget,
animation,
slideDuration,
pendingValue,
slideToValue,
liveDragging
}
/**
* The SliderBase class lets users select a value by moving a slider thumb between
* the end points of the slider track.
* The current value of the slider is determined by the relative location of
* the thumb between the end points of the slider,
* corresponding to the slider's minimum and maximum values.
* The SliderBase class is a base class for HSlider and VSlider.
*
* @event eui.UIEvent.CHANGE_START Dispatched when the scroll position is going to change
* @event eui.UIEvent.CHANGE_END Dispatched when the scroll position changed complete
* @event egret.Event.CHANGE Dispatched when the scroll position is changing
*
* @see eui.HSlider
* @see eui.VSlider
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 滑块控件基类,通过使用 SliderBase 类,用户可以在滑块轨道的端点之间移动滑块来选择值。
* 滑块的当前值由滑块端点(对应于滑块的最小值和最大值)之间滑块的相对位置确定。
* SliderBase 类是 HSlider 和 VSlider 的基类。
*
* @event eui.UIEvent.CHANGE_START 滚动位置改变开始
* @event eui.UIEvent.CHANGE_END 滚动位置改变结束
* @event egret.Event.CHANGE 滚动位置改变的时候
*
* @see eui.HSlider
* @see eui.VSlider
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
export class SliderBase extends Range {
/**
* Constructor
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 创建一个 SliderBase 实例
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public constructor() {
super();
this.$SliderBase = {
0: 0, //clickOffsetX,
1: 0, //clickOffsetY,
2: 0, //moveStageX,
3: 0, //moveStageY,
4: null, //touchDownTarget
5: null, //animation,
6: 300, //slideDuration,
7: 0, //pendingValue
8: 0, //slideToValue,
9: true, //liveDragging
};
this.maximum = 10;
this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin, this);
}
/**
* @private
*/
$SliderBase:Object;
/**
* [SkinPart] Highlight of track.
* @skinPart
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* [SkinPart] 轨道高亮显示对象。
* @skinPart
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public trackHighlight:egret.DisplayObject = null;
/**
* [SkinPart] Thumb display object.
* @skinPart
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* [SkinPart]滑块显示对象。
* @skinPart
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public thumb:eui.UIComponent = null;
/**
* [SkinPart] Track display object.
* @skinPart
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* [SkinPart]轨道显示对象。
* @skinPart
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public track:eui.UIComponent = null;
/**
* Duration in milliseconds for the sliding animation when you tap on the track to move a thumb.
*
* @default 300
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 在轨道上单击以移动滑块时,滑动动画持续的时间(以毫秒为单位)。设置为0将不执行缓动。
*
* @default 300
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public get slideDuration():number {
return this.$SliderBase[Keys.slideDuration];
}
public set slideDuration(value:number) {
this.$SliderBase[Keys.slideDuration] = +value || 0;
}
/**
* Converts a track-relative x,y pixel location into a value between
* the minimum and maximum, inclusive.
*
* @param x The x coordinate of the location relative to the track's origin.
* @param y The y coordinate of the location relative to the track's origin.
* @return A value between the minimum and maximum, inclusive.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 将相对于轨道的 x,y 像素位置转换为介于最小值和最大值(包括两者)之间的一个值。
*
* @param x 相对于轨道原点的位置的x坐标。
* @param y 相对于轨道原点的位置的y坐标。
* @return 介于最小值和最大值(包括两者)之间的一个值。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
protected pointToValue(x:number, y:number):number {
return this.minimum;
}
/**
* Specifies whether live dragging is enabled for the slider. If true, sets the value
* and values properties and dispatches the change event continuously as
* the user moves the thumb.
*
* @default true
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 如果为 true,则将在沿着轨道拖动滑块时,而不是在释放滑块按钮时,提交此滑块的值。
*
* @default true
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public get liveDragging():boolean {
return this.$SliderBase[Keys.liveDragging];
}
public set liveDragging(value:boolean) {
this.$SliderBase[Keys.liveDragging] = !!value;
}
/**
* The value the slider will have when the touch is end.
* This property is updated when the slider thumb moves, even if <code>liveDragging</code> is false.<p/>
* If the <code>liveDragging</code> style is false, then the slider's value is only set
* when the touch is end.
*
* @default 0
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 触摸结束时滑块将具有的值。
* 无论 liveDragging 是否为 true,在滑块拖动期间始终更新此属性。
* 而 value 属性在当 liveDragging 为 false 时,只在触摸释放时更新一次。
*
* @default 0
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
public get pendingValue():number {
return this.$SliderBase[Keys.pendingValue];
}
public set pendingValue(value:number) {
value = +value || 0;
let values = this.$SliderBase;
if (value === values[Keys.pendingValue])
return;
values[Keys.pendingValue] = value;
this.invalidateDisplayList();
}
/**
* @inheritDoc
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
*/
protected setValue(value:number):void {
this.$SliderBase[Keys.pendingValue] = value;
super.setValue(value);
}
/**
* @inheritDoc
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
*/
protected partAdded(partName:string, instance:any):void {
super.partAdded(partName, instance);
if (instance == this.thumb) {
this.thumb.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onThumbTouchBegin, this);
this.thumb.addEventListener(egret.Event.RESIZE, this.onTrackOrThumbResize, this);
}
else if (instance == this.track) {
this.track.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTrackTouchBegin, this);
this.track.addEventListener(egret.Event.RESIZE, this.onTrackOrThumbResize, this);
}
else if (instance === this.trackHighlight) {
this.trackHighlight.touchEnabled = false;
if (egret.is(this.trackHighlight, "egret.DisplayObjectContainer")) {
(<egret.DisplayObjectContainer> this.trackHighlight).touchChildren = false;
}
}
}
/**
* @inheritDoc
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
*/
protected partRemoved(partName:string, instance:any):void {
super.partRemoved(partName, instance);
if (instance == this.thumb) {
this.thumb.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onThumbTouchBegin, this);
this.thumb.removeEventListener(egret.Event.RESIZE, this.onTrackOrThumbResize, this);
}
else if (instance == this.track) {
this.track.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTrackTouchBegin, this);
this.track.removeEventListener(egret.Event.RESIZE, this.onTrackOrThumbResize, this);
}
}
/**
* @private
* 滑块或轨道尺寸改变事件
*/
private onTrackOrThumbResize(event:egret.Event):void {
this.updateSkinDisplayList();
}
/**
* Handle touch-begin events on the scroll thumb. Records the touch begin point in clickOffset.
*
* @param The <code>egret.TouchEvent</code> object.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 滑块触摸开始事件,记录触碰开始的坐标偏移量。
*
* @param event 事件 <code>egret.TouchEvent</code> 的对象.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
protected onThumbTouchBegin(event:egret.TouchEvent):void {
let values = this.$SliderBase;
if (values[Keys.animation] && values[Keys.animation].isPlaying)
this.stopAnimation();
let stage = this.$stage;
stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onStageTouchMove, this);
stage.addEventListener(egret.TouchEvent.TOUCH_END, this.onStageTouchEnd, this);
let clickOffset = this.thumb.globalToLocal(event.stageX, event.stageY, egret.$TempPoint);
values[Keys.clickOffsetX] = clickOffset.x;
values[Keys.clickOffsetY] = clickOffset.y;
UIEvent.dispatchUIEvent(this, UIEvent.CHANGE_START);
}
/**
* @private
* 舞台上触摸移动事件
*/
private onStageTouchMove(event:egret.TouchEvent):void {
let values = this.$SliderBase;
values[Keys.moveStageX] = event.$stageX;
values[Keys.moveStageY] = event.$stageY;
let track = this.track;
if (!track)
return;
let p = track.globalToLocal(values[Keys.moveStageX], values[Keys.moveStageY], egret.$TempPoint);
let newValue = this.pointToValue(p.x - values[Keys.clickOffsetX], p.y - values[Keys.clickOffsetY]);
newValue = this.nearestValidValue(newValue, this.snapInterval);
this.updateWhenTouchMove(newValue);
event.updateAfterEvent();
}
/**
* Capture touch-move events anywhere on or off the stage.
* @param newValue new value
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 监听舞台的触碰移动事件。
* @param newValue 新的值
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
protected updateWhenTouchMove(newValue:number):void {
if (newValue != this.$SliderBase[Keys.pendingValue]) {
if (this.liveDragging) {
this.setValue(newValue);
this.dispatchEventWith(egret.Event.CHANGE);
}
else {
this.pendingValue = newValue;
}
}
}
/**
* Handle touch-end events anywhere on or off the stage.
*
* @param The <code>egret.Event</code> object.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 触摸结束事件
*
* @param event 事件 <code>egret.Event</code> 的对象。
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
protected onStageTouchEnd(event:egret.Event):void {
let stage:egret.Stage = event.$currentTarget;
stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this.onStageTouchMove, this);
stage.removeEventListener(egret.TouchEvent.TOUCH_END, this.onStageTouchEnd, this);
UIEvent.dispatchUIEvent(this, UIEvent.CHANGE_END);
let values = this.$SliderBase;
if (!this.liveDragging && this.value != values[Keys.pendingValue]) {
this.setValue(values[Keys.pendingValue]);
this.dispatchEventWith(egret.Event.CHANGE);
}
}
/**
* @private
* 当在组件上按下时记录被按下的子显示对象
*/
private onTouchBegin(event:egret.TouchEvent):void {
this.$stage.addEventListener(egret.TouchEvent.TOUCH_END, this.stageTouchEndHandler, this);
this.$SliderBase[Keys.touchDownTarget] = <egret.DisplayObject> (event.$target);
}
/**
* @private
* 当结束时,若不是在 touchDownTarget 上弹起,而是另外的子显示对象上弹起时,额外抛出一个触摸单击事件。
*/
private stageTouchEndHandler(event:egret.TouchEvent):void {
let target:egret.DisplayObject = event.$target;
let values = this.$SliderBase;
event.$currentTarget.removeEventListener(egret.TouchEvent.TOUCH_END, this.stageTouchEndHandler, this);
if (values[Keys.touchDownTarget] != target && this.contains(<egret.DisplayObject> (target))) {
egret.TouchEvent.dispatchTouchEvent(this, egret.TouchEvent.TOUCH_TAP, true, true,
event.$stageX, event.$stageY, event.touchPointID);
}
values[Keys.touchDownTarget] = null;
}
/**
* @private
* 动画播放更新数值
*/
$animationUpdateHandler(animation:sys.Animation):void {
this.pendingValue = animation.currentValue;
}
/**
* @private
* 动画播放完毕
*/
private animationEndHandler(animation:sys.Animation):void {
this.setValue(this.$SliderBase[Keys.slideToValue]);
this.dispatchEventWith(egret.Event.CHANGE);
UIEvent.dispatchUIEvent(this, UIEvent.CHANGE_END);
}
/**
* @private
* 停止播放动画
*/
private stopAnimation():void {
this.$SliderBase[Keys.animation].stop();
this.setValue(this.nearestValidValue(this.pendingValue, this.snapInterval));
this.dispatchEventWith(egret.Event.CHANGE);
UIEvent.dispatchUIEvent(this, UIEvent.CHANGE_END);
}
/**
* Handle touch-begin events for the slider track. We
* calculate the value based on the new position and then
* move the thumb to the correct location as well as
* commit the value.
* @param The <code>egret.TouchEvent</code> object.
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language en_US
*/
/**
* 轨道的触碰开始事件。我们会在这里根据新的坐标位置计算value,然后移动滑块到当前位置。
*
* @param event 事件 <code>egret.TouchEvent</code> 的对象.
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web,Native
* @language zh_CN
*/
protected onTrackTouchBegin(event:egret.TouchEvent):void {
let thumbW = this.thumb ? this.thumb.width : 0;
let thumbH = this.thumb ? this.thumb.height : 0;
let offsetX = event.$stageX - (thumbW / 2);
let offsetY = event.$stageY - (thumbH / 2);
let p = this.track.globalToLocal(offsetX, offsetY, egret.$TempPoint);
let rangeValues = this.$Range
let newValue = this.pointToValue(p.x, p.y);
newValue = this.nearestValidValue(newValue, rangeValues[sys.RangeKeys.snapInterval]);
let values = this.$SliderBase;
if (newValue != values[Keys.pendingValue]) {
if (values[Keys.slideDuration] != 0) {
if (!values[Keys.animation]) {
values[Keys.animation] = new sys.Animation(this.$animationUpdateHandler, this);
values[Keys.animation].endFunction = this.animationEndHandler;
}
let animation = values[Keys.animation];
if (animation.isPlaying)
this.stopAnimation();
values[Keys.slideToValue] = newValue;
animation.duration = values[Keys.slideDuration] *
(Math.abs(values[Keys.pendingValue] - values[Keys.slideToValue]) / (rangeValues[sys.RangeKeys.maximum] - rangeValues[sys.RangeKeys.minimum]));
animation.from = values[Keys.pendingValue];
animation.to = values[Keys.slideToValue];
UIEvent.dispatchUIEvent(this, UIEvent.CHANGE_START);
animation.play();
}
else {
this.setValue(newValue);
this.dispatchEventWith(egret.Event.CHANGE);
}
}
}
}
}