X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F20_ui%2F15_ScrollBox.js;h=5e49890b668810226afc62a0017fc1482b257081;hb=3d352d8bf476ab57cc333e8d02d0e6ea5efa69b7;hp=15a613ff318433c393d9a8b957fb889689de0448;hpb=f01f21c6d473692d016cb2b286a61d55380be3b3;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/20_ui/15_ScrollBox.js b/0.6.x/js/20_ui/15_ScrollBox.js index 15a613f..5e49890 100644 --- a/0.6.x/js/20_ui/15_ScrollBox.js +++ b/0.6.x/js/20_ui/15_ScrollBox.js @@ -1,32 +1,5 @@ -function X_UI_ScrollBox_momentum( current, start, time, lowerMargin, wrapperSize, deceleration ){ - var distance = current - start, - speed = Math.abs( distance ) / time, - destination, - duration; - - deceleration = deceleration === undefined ? 0.0006 : deceleration; - - destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); - duration = speed / deceleration; - - if( destination < lowerMargin ){ - destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; - distance = Math.abs( destination - current ); - duration = distance / speed; - } else - if ( destination > 0 ) { - destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; - distance = Math.abs( current ) + destination; - duration = distance / speed; - }; - - return { - destination : Math.round( destination ), - duration : duration - }; -}; var X_UI_ScrollBox_SUPPORT_ATTRS = { // スクロール開始するために必要な移動距離、縦か横、どちらか制限する場合、より重要 @@ -35,18 +8,19 @@ var X_UI_ScrollBox_SUPPORT_ATTRS = { scrollYEnabled : [ true, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ], scrollEnabled : [ true, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ], bounceEnabled : [ true, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ], - bounceTime : [ 600, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.TIME ], + bounceTime : [ 300, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.TIME ], useWheel : [ true, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ], useKey : [ true, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ], hasScrollShadow : [ true, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ], scrollShadowColor : [ '#000', XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.COLOR ] }; - var XUI_ScrollBox = XUI_ChromeBox.inherits( '_ScrollBox', - X_Class.PRIVATE_DATA, + X_Class.NONE, { + layout : XUI_Layout_Canvas, + directionLockThreshold : 10, scrollXEnabled : true, scrollYEnabled : true, @@ -59,8 +33,6 @@ var XUI_ScrollBox = XUI_ChromeBox.inherits( hasScrollShadow : true, scrollShadowColor : '#000', - supportAttrs : XUI_Attr_createAttrDef( XUI_Attr_Support, X_UI_ScrollBox_SUPPORT_ATTRS ), - scrolling : false, initiated : '', @@ -68,7 +40,6 @@ var XUI_ScrollBox = XUI_ChromeBox.inherits( directionLocked : '', startTime : 0, endTime : 0, - isAnimating : false, isInTransition : false, hasHScroll : false, @@ -105,9 +76,9 @@ var XUI_ScrollBox = XUI_ChromeBox.inherits( _containerNode : null, xnodeSlider : null, - Constructor : function( layout, args ){ - this[ 'Super' ]( layout, args ); - this._containerNode = X_Class_getPrivate( this.containerNode ); + Constructor : function( user, layout, args ){ + this[ 'Super' ]( user, layout, args ); + this._containerNode = X_Pair_get( this.containerNode ); this.xnodeSlider = this._containerNode.xnode[ 'className' ]( 'ScrollSlider' ).listen( X_EVENT_ANIME_END, this, X_UI_ScrollBox_onAnimeEnd ); this.xnode[ 'className' ]( 'ScrollBox' ); }, @@ -159,51 +130,51 @@ var XUI_ScrollBox = XUI_ChromeBox.inherits( ); function X_UI_ScrollBox_onLayoutBefore( e ){ + if( e[ 'cancelable' ] && this.isInTransition && X_Node_Anime_translateZ ){ + this[ 'listenOnce' ]( XUI_Event.SCROLL_END, X_UI_rootData, X_UI_rootData.calculate ); + return X_CALLBACK_PREVENT_DEFAULT; + }; this.scrollXRatio = this.scrollX ? this.scrollXMax / this.scrollX : 0; this.scrollYRatio = this.scrollY ? this.scrollYMax / this.scrollY : 0; this.xnodeSlider.stop(); + this.isInTransition = false; + return X_CALLBACK_NONE; }; function X_UI_ScrollBox_onLayoutComplete( e ){ // scroll の停止、GPU の解除 var font = this.fontSize = this.xnodeSlider.call( 'fontSize' ); - - this.scrollXMax = ( this.boxWidth - this._containerNode.boxWidth ) * font; - this.scrollYMax = ( this.boxHeight - this._containerNode.boxHeight ) * font; - this.hasHScroll = this.scrollXEnabled && this.scrollXMax < 0; - this.hasVScroll = this.scrollYEnabled && this.scrollYMax < 0; + this.scrollXMax = ( this.boxWidth - this._containerNode.boxWidth ) * font | 0; + this.scrollYMax = ( this.boxHeight - this._containerNode.boxHeight ) * font | 0; + + this.hasHScroll = this.scrollXEnabled && ( this.scrollXMax < -1 ); // < 0 だと + this.hasVScroll = this.scrollYEnabled && ( this.scrollYMax < -1 ); if( !this.hasHScroll ){ this.scrollXMax = 0; - //this.scrollWidth = this.boxWidth; }; if( !this.hasVScroll ){ this.scrollYMax = 0; - //this.scrollHeight = this.boxHeight; }; delete this.endTime; delete this.directionX; delete this.directionY; - //this.wrapperOffset = this.xnodeWrapper[ 'offset' ](); - - //this[ 'dispatch' ]('refresh'); - X_UI_ScrollBox_resetPosition( this, 0 ); if( this.hasHScroll || this.hasVScroll ){ // scroll が必要。 if( this.scrolling ){ - X_UI_ScrollBox_translate( this, this.scrollXMax * this.scrollXRatio, this.scrollYMax * this.scrollYRatio, 0, '', 0 ); + X_UI_ScrollBox_translate( this, this.scrollXMax * this.scrollXRatio, this.scrollYMax * this.scrollYRatio, 100, '', 300 ); } else { // scroller 作る this[ 'listen' ]( XUI_Event._POINTER_DOWN, this, X_UI_ScrollBox_onStart ); X_UI_rootData[ 'listen' ]( XUI_Event.LAYOUT_BEFORE, this, X_UI_ScrollBox_onLayoutBefore ); - X_UI_ScrollBox_translate( this, this.scrollXMax * this.scrollXRatio, this.scrollYMax * this.scrollYRatio, 0, '', 0 ); + X_UI_ScrollBox_translate( this, this.scrollXMax * this.scrollXRatio, this.scrollYMax * this.scrollYRatio, 100, '', 300 ); this.scrolling = true; }; } else @@ -213,7 +184,7 @@ function X_UI_ScrollBox_onLayoutComplete( e ){ this[ 'unlisten' ]( XUI_Event._POINTER_DOWN, this, X_UI_ScrollBox_onStart ); X_UI_rootData[ 'unlisten' ]( XUI_Event.LAYOUT_BEFORE, this, X_UI_ScrollBox_onLayoutBefore ); - ( this.scrollX !== 0 || this.scrollY !== 0 ) && X_UI_ScrollBox_translate( this, 0, 0, 0, '', 0 ); + ( this.scrollX !== 0 || this.scrollY !== 0 ) && X_UI_ScrollBox_translate( this, 0, 0, 100, '', 300 ); delete this.scrolling; delete this.scrollXRatio; @@ -221,6 +192,7 @@ function X_UI_ScrollBox_onLayoutComplete( e ){ }; }; + // TODO use scrollLeft, scrollTop function X_UI_ScrollBox_translate( that, x, y, opt_time, opt_easing, opt_release ){ opt_time = 0 <= opt_time ? opt_time : 0; @@ -250,7 +222,7 @@ function X_UI_ScrollBox_onLayoutComplete( e ){ }; function X_UI_ScrollBox_onStart( e ){ - var ret = X_Callback_NONE; + var ret = X_CALLBACK_NONE; // React to left mouse button only if( e.pointerType === 'mouse' && e.button !== 0 ){ @@ -271,9 +243,11 @@ function X_UI_ScrollBox_onStart( e ){ this.startTime = X_Timer_now(); // スクロール中の停止 - if( this.isInTransition || this.isAnimating ){ - this.isInTransition = this.isAnimating = false; + if( this.isInTransition ){ + this.isInTransition = false; this[ 'dispatch' ]( XUI_Event.SCROLL_END ); + // TODO current位置 + this.xnodeSlider.stop(); }; this.startX = this.scrollX; @@ -283,19 +257,23 @@ function X_UI_ScrollBox_onStart( e ){ this.pointX = e.pageX; this.pointY = e.pageY; + console.log( 'scrollstart ' + e.pageY ); + this[ 'listen' ]( XUI_Event._POINTER_MOVE, this, X_UI_ScrollBox_onMove ); this[ 'listen' ]( [ XUI_Event._POINTER_UP, XUI_Event._POINTER_CANCEL ], this, X_UI_ScrollBox_onEnd ); - return ret | X_Callback_PREVENT_DEFAULT; + return ret | X_CALLBACK_PREVENT_DEFAULT; }; function X_UI_ScrollBox_onMove( e ){ - var ret = X_Callback_NONE, + var ret = X_CALLBACK_NONE, deltaX, deltaY, timestamp, newX, newY, absDistX, absDistY; // 規定以上の move でスクロール開始 - + +//console.log( 'scrollmove ' + e.buttons + ' ' + e.button ); + if( !this.scrollEnabled || e.pointerType !== this.initiated ){ return ret; }; @@ -385,11 +363,11 @@ function X_UI_ScrollBox_onMove( e ){ this.startY = this.scrollY; }; // イベントの拘束 - return ret | X_Callback_PREVENT_DEFAULT | X_Callback_CAPTURE_POINTER; + return ret | X_CALLBACK_PREVENT_DEFAULT | X_CALLBACK_CAPTURE_POINTER; }; function X_UI_ScrollBox_onEnd( e ){ - var ret = X_Callback_NONE, + var ret = X_CALLBACK_NONE, time = 0, easing = '', newX, newY, @@ -421,7 +399,7 @@ function X_UI_ScrollBox_onEnd( e ){ // we scrolled less than 10 pixels if( !this.moved ){ // this[ 'dispatch' ]( X_EVENT_CANCELED ); - console.log( 'we scrolled less than 10 pixels' ); + console.log( 'we scrolled less than 10 pixels ' + e.pageY ); return ret; }; @@ -485,8 +463,8 @@ function X_UI_ScrollBox_resetPosition( that, time ){ return false; }; - //console.log( 'バウンド!' ); - //console.log( 'rese x:' + x + ' y:' + y ); + console.log( ' ===> resetPosition - バウンド!' ); + console.log( ' x:' + x + ' y:' + y ); that.scrollTo( x, y, time, that.bounceEasing, 1000 ); return true; @@ -494,61 +472,96 @@ function X_UI_ScrollBox_resetPosition( that, time ){ function X_UI_ScrollBox_onAnimeEnd( e ){ if( e.target !== this.xnodeSlider || !this.isInTransition ){ - return X_Callback_NONE; + return X_CALLBACK_NONE; }; if( !X_UI_ScrollBox_resetPosition( this, this.bounceTime ) ){ this.isInTransition = false; - this.dispatch( XUI_Event.SCROLL_END ); + this[ 'dispatch' ]( XUI_Event.SCROLL_END ); + }; + return X_CALLBACK_NONE; +}; + +function X_UI_ScrollBox_momentum( current, start, time, lowerMargin, wrapperSize, deceleration ){ + var distance = current - start, + speed = Math.abs( distance ) / time, + destination, + duration; + + deceleration = deceleration === undefined ? 0.0006 : deceleration; + + destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); + duration = speed / deceleration; + + if( destination < lowerMargin ){ + destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; + distance = Math.abs( destination - current ); + duration = distance / speed; + } else + if ( destination > 0 ) { + destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; + distance = Math.abs( current ) + destination; + duration = distance / speed; + }; + + return { + destination : Math.round( destination ), + duration : duration }; - return X_Callback_NONE; }; X.UI.ScrollBox = X.UI.ChromeBox.inherits( 'ScrollBox', X_Class.NONE, - XUI_ScrollBox, { Constructor : function(){ + var supports, slider; + + if( XUI_ScrollBox.prototype.usableAttrs === XUI_ChromeBox.prototype.usableAttrs ){ + XUI_ScrollBox.prototype.usableAttrs = supports = XUI_Attr_createAttrDef( XUI_Attr_Support, X_UI_ScrollBox_SUPPORT_ATTRS ); + + XUI_ScrollBox.prototype.attrClass = XUI_Attr_preset( XUI_Box.prototype.attrClass, supports, { width : '100%', height : '100%', bgColor : 0x111111 } ); + }; + var args = [ XUI_Layout_Vertical, { - name : 'ScrollBox-Scroller', - role : 'container', - width : 'auto', - minWidth : '100%', - height : 'auto', - minHeight : '100%' + name : 'ScrollBox-Scroller', + role : 'container', + width : 'auto', + minWidth : '100%', + height : 'auto', + minHeight : '100%' } ], i = arguments.length, - arg, layout, attr; + arg, attr; for( ; i; ){ arg = arguments[ --i ]; if( arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( XUI_LayoutBase ) ){ - layout = arg; + args[ 0 ] = arg; } else if( arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( X.UI.AbstractUINode ) ){ args[ args.length ] = arg; } else if( X_Type_isObject( arg ) ){ - attr = arg; + args[ args.length ] = attr = arg; + slider = attr.scrollSlider; }; }; - X_Class_newPrivate( + X_Pair_create( this, - XUI_Layout_Canvas, - [ - { - width : '100%', - height : '100%' - }, - X.UI.VBox.apply( 0, args ) - ] + XUI_ScrollBox( + this, + null, + [ + slider || X.UI.VBox.apply( 0, args ) + ] + ) ); - attr && this.attr( attr ); + //attr && this.attr( attr ); }, scrollX : function(){ @@ -566,4 +579,5 @@ X.UI.ScrollBox = X.UI.ChromeBox.inherits( } } -); \ No newline at end of file +); +