Сегодня мы хотим поделиться с вами действенным решением, которое поможет вам решить данную проблему. Мы разработаем плагин, который будет обрабатывать события «mouseenter», «mouseleave» и «click», и запускать их только тогда, когда курсор мыши достигает видимой области элемента.
Изображения, использованные в демо, были предоставлены Андреем и Лили. Они распространяются под лицензионным соглашением Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0).
Как оно работает
В нашем примере мы создадим окружность с эффектом при наведении. Структура будет очень простой:
<a href="#" id="circle" class="ec-circle">
<h3>Hovered</h3>
</a>
А стили будут следующими:
.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;
}
Теперь мы определим класс для эффекта при наведении, который, кстати, не будет динамическом псевдо-классом :hover. Идея заключается в том, чтобы задать этот класс позже, посредством jQuery, когда мы уже добавим окружную область к нашему элементу:
.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. Данный стиль можно найти в 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-код
Мы создадим новый плагин, который просто «переопределяет» 3 события, о которых мы упоминали ранее. Мы сделаем так, что события будут применимы только к окружной фигуре:
$.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');
}
};
Когда курсор мыши попадает в область блока, в котором расположена окружность, элементу задается событие mousemove, и таким образом мы можем отслеживать расстояние от курсора до центра элемента. Если расстояние больше указанного радиуса, то эффект при наведении не задействуется.
Как только расстояние от курсора мыши до центра становится меньше указанного радиуса, это означает, что курсор достиг окружности, и тогда запускается пользовательское событие mouseenter.
Также и событие click запускается только тогда, когда курсор достигает окружности.
В нашем примере мы применяем наш плагин к соответствующему элементу. В нашем случае мы задаем класс при наведении к событию mouseenter и отключаем его от mouseleave.
$('#circle').circlemouse({
onMouseEnter : function( el ) {
el.addClass('ec-circle-hover');
},
onMouseLeave : function( el ) {
el.removeClass('ec-circle-hover');
},
onclick : function( el ) {
alert('clicked');
}
});
Помните, что «нормальный» класс псевдо-наведения также определяется в noscript.css, который применяется в случае отключенной поддержки javascript.
Надеемся, данное руководство окажется для вас полезным.
Демо | Скачать архивом
Внимание! У вас нет прав для просмотра скрытого текста.