在Raphaeljs中悬停在一组元素上

4
我有一个只包含矩形的集合。
var hoverTrigger = this.paper.set();
var outline = this.paper.rect();
outline.attr({
...
hoverTrigger.push(outline)
this.sprite.push(hoverTrigger);

鼠标悬停时,矩形应扩展,并添加一些链接;鼠标移出后,链接消失,矩形再次变小。
hoverTrigger.hover(function () {
  var link = this.paper.text();
  hoverTrigger.push(link);
  outline.animate({
  ...
}, function() {
  link.remove();
  outline.animate({
  ...
});

然而,似乎悬停功能是针对每个项目单独应用的,而不是整个集合,因为当你将鼠标悬停在链接上时,悬停关闭功能会触发并使链接消失。有时框会快速连续地接收到悬停和离开事件,从而出现问题。
有没有一种方法可以将悬停应用于一组东西,这样在集合中两个物品之间移动鼠标不会触发悬停关闭?
4个回答

5

最近我自己也遇到了这个限制,所以我决定编写一个名为hoverInBounds的小扩展来解决它。

简单来说,一旦鼠标进入元素,我们会跟踪它何时移动超出其边界 - 然后执行悬停离开函数,而不是之前执行。

演示:http://jsfiddle.net/amustill/Bh276/1

Raphael.el.hoverInBounds = function(inFunc, outFunc) {
    var inBounds = false;

    // Mouseover function. Only execute if `inBounds` is false.
    this.mouseover(function() {
        if (!inBounds) {
            inBounds = true;
            inFunc.call(this);
        }
    });

    // Mouseout function
    this.mouseout(function(e) {
        var x = e.offsetX || e.clientX,
            y = e.offsetY || e.clientY;

        // Return `false` if we're still inside the element's bounds
        if (this.isPointInside(x, y)) return false;

        inBounds = false;
        outFunc.call(this);
    });

    return this;
}

在创建 Raphael 画布对象之前,请将上述代码块放置到代码中。


1
这在Mac上的Firefox上似乎不起作用(两个圆形的行为相同) - ario
1
@ario 不好意思,感谢您的指出。Firefox和其他浏览器使用clientXclientY来确定鼠标坐标。我已经更新了代码以反映所有浏览器。 - amustill
注意:当在容器内使用时,其中纸张0,0不是屏幕0,0,您可以使用var $elem = $(this[0]).closest('div'), ePos = $elem.offset(); x -= ePos.left + parseInt($elem.css('paddingLeft')) + parseInt($elem.css('borderLeftWidth')); y -= ePos.top + parseInt($elem.css('paddingTop')) + parseInt($elem.css('borderTopWidth'));进行补偿。(假设您的容器是一个div..) - Alex

3
我以前遇到过这个问题。我找到了两种解决方案。
1. 在其他元素上创建一个透明度为0的矩形。 2. 使用CSS属性 "pointer-events: none" 使元素不可点击。
var paper = new Raphael( 0, 0, 100, 100 );
var rect = paper.rect( 0, 0, 100, 100 ).attr({ opacity: 0 });
rect.hover( func_in, func_out );

这仅适用于具有一个总体动作(如点击)的元素。

另一种选择是在悬停在一组元素上时取消悬停功能。

var funcOutTimer;

set.hover( function( ) {
    if( funcOutTimer ) { // Hovered into this element in less than 100 milliseconds => cancel
        window.clearTimeout( funcOutTimer);
    } else {
    // do stuff
    }
},
function( ) {
    funcOutTimer = setTimeout( function( ) {
        // do stuff
    }, 100 ); // wait for 100 milliseconds before executing hover out function
});

基本上,在第一次进入一组元素时,hover in功能只执行一次,而当你最终悬停的元素不属于该组时,hover out功能只会执行一次。


0

Bruno所详细介绍的方法有一个小问题:

如果您在其他元素上创建了一个矩形,如果其他元素是文本,则无法在网页中选择这些文本。但它可以工作。

顺便说一下,“opacity”属性:0是不够的,我必须在我的情况下添加“fill”:“white”属性。

您需要像这样将对象置于前面:obj.toFront(); obj是raphael形状,如“rect”等。

我在mouseover和mouseout事件上进行了测试,它可以工作。

在这里检查我的fiddle:链接到fiddle

function withArray(x,y){
    var rect = paper.rect(x, y, 100, 60).attr({
        fill: "green"
    });
    rect.text = paper.text(x+(100/2), y + 30, 'rect w/array').attr({
        'font-size': 12,
        "fill": "white"
    });
    var rectover = paper.rect(x,y,100,60).attr({
        fill: "white",
        opacity: 0
    });
    var myArray = paper.set();
    myArray.push(rect, rect.text, rectover);
    myArray.mouseover(function() {
    var anim = Raphael.animation({
    transform: ['S', 1.5, 1.5, (rect.attr("x")), (rect.attr("y"))]
        }, 100, "backOut", function() {
    });
    myArray.animate(anim);
    }).mouseout(function() {
        var anim = Raphael.animation({
            transform: [""]
        }, 50, "backOut", function() {
   });
   myArray.stop().animate(anim);
});
}

0
我发现这个与以下内容配合使用。
myCircleElement.hover (
    function(e) { myTextElement.animate({opacity:1}, 800); },
    function(e) {
        var x = e.layerX || e.x,
        y = e.layerY || e.y;
        // Return `false` if we're still inside the element's bounds                                        
        if (this.isPointInside(x, y)) return false;
        // otherwise do something here.. eg below
        myTextElement.animate({opacity:0}, 800); //
    }
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接