Sunday, December 11, 2011

How to Make a Hover-and-Click Trigger for Circular Web Elements with jQuery


How to Make a Hover-and-Click Trigger for Circular Web Elements with jQuery
by: Carmela

Ever tried designing a circular web element and learn web design that ends up being clickable even outside its area? Frustrating, isn’t it? Yet if you use square or rectangular element, the overall web design suffers. 

So web designer and developer Manoela Ilic aka. Mary Lou has developed a hover-and-click trigger for circular web elements using jQuery. This was to address the problem of the hover event occurring within the square area a circular element is placed in, when hovering and clicking should only happen within the circle itself.

Here’s the demo to illustrate the issue and for you to see the effect after you apply Mary Lou’s plugin code.

This is how the code works:

First you’ll create a structure like so:

<a href="#" id="circle" class="ec-circle">

    <h3>Hovered</h3>


</a>

And this will be its style:


.ec-circle{

    width: 420px;


    height: 420px;

    -webkit-border-radius: 210px;


    -moz-border-radius: 210px;

    border-radius: 50%;


    text-align: center;

    overflow: hidden;


    font-family:'Kelly Slab', Georgia, serif;

    background: #dda994 url(../images/1.jpg) no-repeat center center;


    box-shadow:

        inset 0 0 1px 230px rgba(0,0,0,0.6),


        inset 0 0 0 7px #d5ad94;

    transition: box-shadow 400ms ease-in-out;


    display: block;

    outline: none;


}
Next, you should define a class for the hover effect but NOT a dynamic pseudo-class :hover.  This class is applied with jQuery once you enter the element’s circular area:

.ec-circle-hover{

    box-shadow:


        inset 0 0 0 0 rgba(0,0,0,0.6),

        inset 0 0 0 20px #c18167,


        0 0 10px rgba(0,0,0,0.3);

}

Disable your Javascript first, then add your pseudo-class.  You can find this script in noscript:css.
.ec-circle:hover{

    box-shadow:


        inset 0 0 0 0 rgba(0,0,0,0.6),

        inset 0 0 0 20px #c18167,


        0 0 10px rgba(0,0,0,0.3);

}

Javascript Code
This simple plugin that basically redefines the ‘mousenter,’ ‘mouseleave,’ and ‘click’ events  so that they only come into effect when you hover on your circular shape:
$.CircleEventManager            = function( options, element ) {




    this.$el            = $( element );




    this._init( options );




};




$.CircleEventManager.defaults   = {

    onMouseEnter    : function() { return false },


    onMouseLeave    : function() { return false },

    onClick         : function() { return false }


};




$.CircleEventManager.prototype  = {

    _init               : function( options ) {




        this.options        = $.extend( true, {}, $.CircleEventManager.defaults, options );




        // set the default cursor on the element


        this.$el.css( 'cursor', 'default' );




        this._initEvents();




    },

    _initEvents         : function() {




        var _self   = this;




        this.$el.on({


            'mouseenter.circlemouse'    : function( event ) {




                var el  = $(event.target),




                          circleWidth   = el.outerWidth( true ),

                          circleHeight  = el.outerHeight( true ),


                          circleLeft    = el.offset().left,

                          circleTop     = el.offset().top,


                          circlePos     = {

                              x     : circleLeft + circleWidth / 2,


                              y     : circleTop + circleHeight / 2,

                              radius: circleWidth / 2


                          };




                // save cursor type

                var cursor  = 'default';




                if( _self.$el.css('cursor') === 'pointer' || _self.$el.is('a') )


                    cursor = 'pointer';




                el.data( 'cursor', cursor );




                el.on( 'mousemove.circlemouse', function( event ) {




                    var distance    = Math.sqrt( Math.pow( event.pageX - circlePos.x, 2 ) + Math.pow( event.pageY - circlePos.y, 2 ) );




                    if( !Modernizr.borderradius ) {




                        // inside element / circle

                        el.css( 'cursor', el.data('cursor') ).data( 'inside', true );


                        _self.options.onMouseEnter( _self.$el );




                    }

                    else {




                        if( distance <= circlePos.radius && !el.data('inside') ) {




                            // inside element / circle


                            el.css( 'cursor', el.data('cursor') ).data( 'inside', true );

                            _self.options.onMouseEnter( _self.$el );




                        }


                        else if( distance > circlePos.radius && el.data('inside') ) {




                            // inside element / outside circle

                            el.css( 'cursor', 'default' ).data( 'inside', false );


                            _self.options.onMouseLeave( _self.$el );




                        }




                    }




                });




            },

            'mouseleave.circlemouse'    : function( event ) {




                var el  = $(event.target);




                el.off('mousemove');




                if( el.data( 'inside' ) ) {




                    el.data( 'inside', false );


                    _self.options.onMouseLeave( _self.$el );




                }




            },

            'click.circlemouse'         : function( event ) {




                // allow the click only when inside the circle




                var el  = $(event.target);




                if( !el.data( 'inside' ) )


                    return false;

                else


                    _self.options.onClick( _self.$el );




            }

        });




    },


    destroy             : function() {




        this.$el.unbind('.circlemouse').removeData('inside').removeData('cursor');








    }

};



 The idea is that when you enter the square bounding box or square perimeter around your circular element, you bind the ‘mousemove’ event to the shape. This way you can track the distance of the mouse to the center of the circle.  If the distance is longer than the radius, then no hovering occurs. 




Your mouse only stars hovering when it enters the radial area of your circular element. This triggers the ‘mouseenter’ event. Also, this is the only time when you can click on the element, triggering the ‘click’ event.  

When you apply this plugin to your circle, you add the hover class on ‘mouseenter’ and remove it on ‘mouseleave’.

$('#circle').circlemouse({

    onMouseEnter    : function( el ) {







        el.addClass('ec-circle-hover');




    },


    onMouseLeave    : function( el ) {




        el.removeClass('ec-circle-hover');




    },

    onClick         : function( el ) {




        alert('clicked');




    }


});

The regular pseudo :hover class is also defined in the noscript.css. This is applied when JavaScript is disabled. You can also download the plugin HERE.
Give this plugin a try and let us know how it works out for you. Good luck!

No comments:

Post a Comment