iT邦幫忙

DAY 30
7

jQuery 套件開發之我可不可以跳著說系列 第 26

jQuery套件開發之(二十八),套件ryPoint 完成

以前寫小遊戲的時候,為了指導使用者

會用一小箭頭指引使用者點哪裡

這兩天把這個功能寫成套件了
demo
http://ry.url.tw/wp/doc/ryPoint/rP1.htm

<meta charset="utf-8">
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<style>

</style>
<script>
;(function($, W, D)
{
    String.prototype.format = function()
    {
        var args = arguments ;

        return this.replace(/{(\d+)}/g, function(match, number)
        {
            return typeof (args[number] != 'undefined') ? args[number] : match ;
        }) ;
    } ;
    
    var log = function()
    {
        if (logOn)
        {
            console.log(arguments) ;
        }
    }
    
    var pg      = 'ryPoint' ;    //plugin name
    var pgType  = 'troops' ;    //plugin type
    var logOn   = false ;        //log switch
    var innerSettings =  //settings will never affected by outside.
    {
          indexPrefix: 'ry-'+pg+'-'
        , indexSuffix: '-index-'
        // 'data-'+pg+'-index-' + WIDGET ROLE + '-id-' + number
        , pgAttr: 'ry-'+pg+'-number'
        , arrowLength: 187
        , arrowSrcGreen: '../css/images/ryPoint-arrow-green.png'
        , arrowSrcRed: '../css/images/ryPoint-arrow-red.png'
        , actorsClass :
        {
            'widget' : 'ry-'+pg+'-widget'
        }
        , classList:
        {
            'widget' : 'ry-'+pg+'-widget'
        }
        , tpl:
        {
            
        }
    }    
  
    var defaults =            //settings can be rewrited by outside.
    {
          color: 'green'
        , size: innerSettings.arrowLength
        , padding: '5px'
        , effect: 'swing'
        , removeMode: 'afterEffect'
        , direction: null
        , border: false
        , effect: null
    } ;
    
    $[pg] = function()          
    {
        $[pg].args = Array.prototype.slice.call(arguments) ;
        $[pg].pgRouter() ;
    } ;
    
    $[pg].version = '0.1' ;
    $[pg].id = 1 ;
    $[pg].settings = {} ;
    $[pg].pgRouter = function()
    {
        if ($[pg].args.length === 2)
        {
            if ($.isFunction( $[pg][ $[pg].args[0] ] ))
            {
                $[pg][ $[pg].args[0] ]( $[pg].args[1] ) ;
            }
            else
            {
                _.log('wrong method: ' + $[pg].args[0]) ;
            }
        }
        else if ($[pg].args.length === 1 && typeof $[pg].args[0] === 'object')
        {   
            $[pg].mkSettings($[pg].args[0]) ;
            $[pg].init() ;
        }
        else if ($[pg].args.length === 1 && ( $.isFunction( $[pg][ $[pg].args[0] ] ) ))
        {
            $[pg][ $[pg].args[0] ]() ;
        }        
        else
        {       
            $[pg].init() ;
        }
    } ;

    $[pg].init = function()
    {
        log('$[pg].init') ;
        $(document)[pg]() ;
    } ;
    
    $[pg].mkSettings = function(arg)
    {
        log('$[pg].mkSettings') ;

        //    運算值                  預設值  設定值  內定值
        $[pg].settings = $.extend({}, defaults, arg, innerSettings) ; 

        log('$[pg].settings:') ;
        log($[pg].settings) ;
    } ;

/*
make a modal to produce widgets
*/
    function Plugin(element)
    {
        log('function Plugin') ;
        
        this.element = element ;
        this.ele$    = $(element) ;
        this.args    = Plugin.args ;
        this.settings = this.mkSettings() ;
        this.id = $[pg].id++ ;      
        log('this.settings:') ; 
        log(this.settings) ; 
        
        this.actors = {} ;
        this.init() ;
    }
/*
super power those widgets have
*/
    Plugin.prototype =
    {
          mkSettings: function()
        {
            log('mkSettings') ; 
            var self = this ;
            var tmpSet = $.extend({}, defaults, $[pg].settings, self.args[0], innerSettings) ;
            if (typeof tmpSet.size === 'string')
            {
                tmpSet.size = Number( tmpSet.size.replace('px', '') ) ;
            }
            if (typeof tmpSet.padding === 'string')
            {
                tmpSet.padding = Number( tmpSet.padding.replace('px', '') ) ;
            }            

            return tmpSet
        }
        , init: function()
        {        
            log('init') ; 
            var self = this ;
            
            self.target() ;
            self.arrowDirection() ;
            self.arrowSize() ;
            self.arrowXY() ;
            self.point() ;
            self.effect(self.settings.removeMode) ;
            
        }
        , target: function()
        {
            log('target') ; 
            var self = this ;

            if (self.settings.xy)
            {
                var tmpAry = self.settings.xy.split(',') ;
                
                self.targetHalfW = 0 ;
                self.targetHalfH = 0 ;
                
                self.targetCenterX = Number( tmpAry[0] ) ;
                self.targetCenterY = Number( tmpAry[1] ) ;
                console.log(111) ;
            }
            else
            {
                var _offset = self.ele$.offset() ;
                self.targetHalfW = self.ele$.outerWidth() / 2 ;
                self.targetHalfH = self.ele$.outerHeight() / 2 ;
                
                self.targetCenterX = _offset.left + self.targetHalfW ;
                self.targetCenterY = _offset.top + self.targetHalfH ;   
            }
            
            
            if (self.settings.border)
            {
                //is not so easy, u must put one new div on it.
                var _offset = self.ele$.offset() ;
                
                self.actors.border = $('<div />')
                                        .css(
                                        {
                                              border: '2px dashed green'
                                            , position: 'absolute'
                                            , top:_offset.top-2  //border width
                                            , left:_offset.left-2
                                            , width:self.ele$.innerWidth()
                                            , height:self.ele$.innerHeight()
                                        })
                                        .appendTo('body') ;
            }
        }
        , arrowDirection: function()
        {
            log('arrowDirection') ; 
            var self = this ;
            
            var _W = $(window).width() ;
            var _H = $(window).height() ;
            var _topLimit = (_W * 0.1) >> 0 ;
            var _bottomLimit = (_H * 0.9) >> 0 ;
            
            if (self.settings.direction)
            {
                var tmpD = self.settings.direction.toLowerCase() ;
                switch(tmpD)
                {
                    case 'right':
                        self.direction = 'pointRight' ;
                        self.rotateDegree = 90 ;
                        self.posture = 'horizontal' ;
                    break ;

                    case 'top':
                        self.direction = 'pointTop' ;
                        self.rotateDegree = 0 ;
                        self.posture = 'vertical' ;
                    break ;

                    case 'bottom':
                        self.direction = 'pointBottom' ;
                        self.rotateDegree = 180 ;  
                        self.posture = 'vertical' ;
                    break ;

                    case 'left':
                        self.direction = 'pointLeft' ;
                        self.rotateDegree = -90 ;
                        self.posture = 'horizontal' ;
                    break ;
                }
            }
            else
            {
                if (self.targetCenterX >=  Math.max(self.settings.arrowLength))
                {
                    self.direction = 'pointRight' ;
                    self.rotateDegree = 90 ;
                    self.posture = 'horizontal' ;
                }
                else if (self.targetCenterY <= _topLimit)
                {
                    self.direction = 'pointTop' ;
                    self.rotateDegree = 0 ;
                    self.posture = 'vertical' ;                    
                }
                else if (self.targetCenterY >= _bottomLimit)
                {
                    self.direction = 'pointBottom' ;
                    self.rotateDegree = 180 ;          
                    self.posture = 'vertical' ;                    
                }
                else
                {
                    self.direction = 'pointLeft' ;
                    self.rotateDegree = -90 ;
                    self.posture = 'horizontal' ;                    
                }
            }

            self.actors.pointClass = pg + '-' + self.direction ;
        }
        , arrowSize: function()
        {
            log('arrowSize') ; 
            var self = this ;
            
            self.settings.arrowLength = (self.settings.size)? self.settings.size : self.settings.arrowLength ;
            
        }
        , arrowXY: function()
        {
            log('arrowXY') ; 
            var self = this ;
  
            if (self.direction === 'pointRight')
            {
                self.arrowX = self.targetCenterX - self.targetHalfW - self.settings.padding - self.settings.arrowLength ;
                self.arrowY = self.targetCenterY - (self.settings.arrowLength / 2) ;
            }
            else if (self.direction === 'pointLeft')
            {
                self.arrowX = self.targetCenterX + self.targetHalfW + self.settings.padding ;
                self.arrowY = self.targetCenterY - (self.settings.arrowLength / 2) ;            
            }
            else if (self.direction === 'pointTop')
            {
                self.arrowX = self.targetCenterX - (self.settings.arrowLength / 2) ; ;
                self.arrowY = self.targetCenterY + self.targetHalfH + self.settings.padding ;
            }
            else if (self.direction === 'pointBottom')
            {
                self.arrowX = self.targetCenterX - (self.settings.arrowLength / 2) ;
                self.arrowY = self.targetCenterY - self.targetHalfH - self.settings.padding - self.settings.arrowLength ;
            }

        }
        , point: function()
        {
            log('point') ; 
            var self = this ;
            
            self.actors.arrowIndex = self.settings.indexPrefix + 'arrow' + self.settings.indexSuffix + self.id ;
            self.arrowSrc = ( self.settings.color === 'green' )? self.settings.arrowSrcGreen : self.settings.arrowSrcRed ;
            
            //arrow size
            self.actors.arrow = $('<img />')
            .attr('src', self.arrowSrc)
            .css(
            {
                  position: 'absolute'
                , top: self.arrowY
                , left: self.arrowX
                , width: self.settings.size + 'px'
                , '-webkit-transform': 'rotate('+ self.rotateDegree +'deg)'
            })
            .addClass(self.actors.arrowIndex + ' ' + self.actors.pointClass)
            .attr(self.settings.pgAttr, self.id)
            .appendTo('body') ;
        }
        , effect: function(_m)
        {
            log('effect') ; 
            var self = this ;
            
            if (self.settings.effect && $.isFunction(self[self.settings.effect]))
            {
                self[self.settings.effect](_m) ;
            }
        }
        , swing: function(_m)
        {
            log('swing') ; 
            var self = this ;
            
            var animateOjb = {} ;
            
            var _time = 5 ;
            var _speed = 150 ;
            var _diff = 12 ;

            if (self.posture === 'vertical')
            {
                var obj1 =
                {
                    top: '+='+_diff
                } ;
                var obj2 =
                {
                    top: '-='+_diff
                } ;
                
            }
            else
            {
                var obj1 =
                {
                    left: '+='+_diff
                } ;
                var obj2 =
                {
                    left: '-='+_diff
                } ;
                
            }
            
            for(var i=1; i<= _time; i++ )
            {
                self.actors.arrow
                    .animate(
                    obj1, _speed)
                self.actors.arrow
                    .animate(
                    obj2, _speed)
                
                if (i === _time)
                {
                    if (_m === 'afterEffect')
                    {
                        if (self.actors.border !== undefined) 
                        {
                            self.actors.border.remove() ;
                        }
                        self.actors.arrow.fadeOut(function()
                        {
                            $(this).remove() ;
                        }) ;
                    }
                    else
                    {
                        $(document)
                            .one('click', function()
                            {
                                if (self.actors.border !== undefined) 
                                {
                                    self.actors.border.remove() ;
                                }
                                self.actors.arrow.stop(true, true) ;
                                self.actors.arrow.fadeOut(function()
                                {
                                    $(this).remove() ;
                                }) ;
                            }) ;
                    }
                }
            }
            
        }
    }
    
    $.fn[pg] = function() 
    {   
        //處裡套件全域設定
        Plugin.args = Array.prototype.slice.call(arguments) ;
        return this.each(function() {
            if (pgType === 'troops')
            {
                $.data(this, pg+'Num', $[pg].id);
                
                var tmpAry = ( $.isArray($.data(this, 'plugin_' + pg)) )? $.data(this, 'plugin_' + pg) : [] ;
                
                tmpAry[$[pg].id] = new Plugin(this) ;
                
                $.data(this, 'plugin_' + pg, tmpAry) ;
            }
            else
            {
                if (!$.data(this, 'plugin_' + pg)) 
                {
                    $.data(this, 'plugin_' + pg, new Plugin(this));
                }
                else if ($.isFunction(Plugin.prototype[ Plugin.args[0] ]))
                {
                    $.data(this, 'plugin_' + pg)[ Plugin.args[0] ]();  //吃參數
                }
                else
                {
                    console.log('wrong way to use this method:' + Plugin.args[0]) ;
                }            
            }
            log('$(this).data():') ;
            log($(this).data()) ;
        });
    }  

})( jQuery, window, document ) ;

$(function()
{
    $(document).ryPoint(
    {
          xy: '450, 200'
        , direction: 'top'
    }) ;
    $(document).ryPoint(
    {
          xy: '450, 200'
        , direction: 'right'
    }) ;    
    $(document).ryPoint(
    {
          xy: '450, 200'
        , direction: 'bottom'
    }) ;    
    $(document).ryPoint(
    {
          xy: '450, 200'
        , direction: 'left'
    }) ;    
    
    $('#cube1').ryPoint() ;
    $('#cube2').ryPoint(
    {
          color: 'red'  //green or red
    }) ;
    $('#cube3').ryPoint(
    {
          color: 'green'  //green or red
        , size: '100px'
    }) ;    
    $('#cube4').ryPoint(
    {
          color: 'green'  //green or red
        , size: '100px'
        , effect: 'swing'
    }) ;   
    $('#cube5').ryPoint(
    {
          color: 'green'  //green or red
        , size: '100px'
        , effect: 'swing'
        , removeMode: 'afterClick'
    }) ; 
    $('#cube6').ryPoint(
    {
          color: 'green'  //green or red
        , size: '100px'
        , effect: 'swing'
        , removeMode: 'afterClick'
        , direction: 'left'
    }) ;   
    $('#cube7').ryPoint(
    {
          color: 'green'  //green or red
        , size: '100px'
        , effect: 'swing'
        , removeMode: 'afterClick'
        , direction: 'left'
        , border: true
    }) ;     
    $('#cube8').ryPoint(
    {
          color: 'green'  //green or red
        , size: '100px'
        , effect: 'swing'
        , removeMode: 'afterClick'
        , direction: 'left'
        , border: true
        , padding: 50
    }) ;         
}) ;
</script>


<div id="cube1" class="cube" style="position:absolute;top:100px; left:100px;width:100px;height:150px;background-color:red;"></div>
<div id="cube2" class="cube" style="position:absolute;top:500px; left:100px;width:100px;height:150px;background-color:orange;"></div>
<div id="cube3" class="cube" style="position:absolute;top:250px; left:400px;width:100px;height:150px;background-color:yellow;"></div>
<div id="cube4" class="cube" style="position:absolute;top:100px; left:900px;width:100px;height:150px;background-color:green;"></div>
<div id="cube5" class="cube" style="position:absolute;top:500px; left:600px;width:100px;height:150px;background-color:blue;"></div>
<div id="cube6" class="cube" style="position:absolute;top:-80px; left:250px;width:100px;height:150px;background-color:purple;"></div>
<div id="cube7" class="cube" style="position:absolute;top:-80px;   left:0px;width:100px;height:150px;background-color:black"></div>

上一篇
jQuery套件開發之(二十七),canvas練習,畫圓、畫cone
系列文
jQuery 套件開發之我可不可以跳著說26

1 則留言

0

我要留言

立即登入留言