使用Raphaeljs为矩形添加点击事件

13

我正在尝试绘制一个简单的矩形,上面有一些文本。由于形状上不能有文本,所以我创建了一个与文本和矩形对象具有相同坐标的集合。我需要在 onclick 事件中更改某些内容。因此,我使用了 obj.node.onclick = 语句并编写了一个处理程序。我的问题是,如果将文本对象用于 onclick,则只有在单击文本时才调用事件处理程序。如果我将矩形用于 onclick,则必须仅单击边框区域。我的要求是点击可以覆盖整个形状区域以及其中的文本。

   var paper = Raphael(10, 10, 320, 200);
var group = paper.set();
var c1 = paper.path("M35 60 L35 90");
var c2 = paper.rect(10, 10, 50, 50,10);
group.push(c2);
group.push(paper.text(35, 35, "Hello"));

c2.attr("fill", "blue");
c2.node.onclick = function () { c2.attr("fill", "red");}; 

我尝试使用div覆盖在矩形上并在其上写入文本,但没有成功。我可以在Firebug中看到div,但在网页上无法看到!我已经给它设置了样式属性来确定顶部左侧的宽度和高度,并将位置设置为absolute。但是没有成功。

请帮助我解决这个问题。 感激不尽! Kavita

我尝试使用前景层和背景层的解决方案。我克隆了背景层,并向其中添加了一个点击处理程序。我根本没有使用“this”。事件从未被触发! 请帮助我解决这个问题! Kavita

7个回答

14
创建一个集合来包含按钮中的所有元素。然后将点击(或 mouseup)处理程序添加到该组中。请注意,矩形必须具有填充,否则它们不会获得鼠标事件。对于透明按钮,请使用不透明度0。
var paper = Raphael(10, 10, 320, 200);
var group = paper.set();
var COLOR_NORMAL = 'blue';
var COLOR_HOVER = 'red';
var background = paper.rect(10, 10, 50, 50,10).attr({
    fill: COLOR_NORMAL
});
var label = paper.text(35, 35, "Hello");

group.push(background);
group.push(label);

group.attr({
    cursor: 'pointer',
}).mouseover(function(e) {
    background.attr('fill', COLOR_HOVER);
}).mouseout(function(e) {
    background.attr('fill', COLOR_NORMAL);
}).mouseup(function(e) {
    alert("clicked");
}); 

2
这里有两种方法可以实现此功能。在这两种方法中,我只是为文本添加了一个onclick事件。换句话说,矩形和文本都具有相同的onclick事件。
1)只需在末尾添加以下一行代码:
group[group.length - 1].node.onclick = function () { c2.attr("fill", "red");};

2) 或者,您可以像c2一样创建另一个变量c3,并以同样的方式附加onclick。以下是您的所有代码。

var paper = Raphael(10, 10, 320, 200);
var group = paper.set();
var c1 = paper.path("M35 60 L35 90");
var c2 = paper.rect(10, 10, 50, 50,10);
var c3 = paper.text(35, 35, "Hello").attr({"font-size":36});
group.push(c2);
group.push(c3);

c2.attr("fill", "blue");
c2.node.onclick = function () { c2.attr("fill", "red");}; 
c3.node.onclick = function () { c2.attr("fill", "red");};

我把这里的文本放大了,这样你就可以确保你点击的是文本而不是矩形。


我不想让文本太大,但是我需要在整个矩形区域内单击!至于解决方案1,我认为它做的事情相同,但避免使用变量。 - kavita

2
很高兴能够提供一个三层对象,因为你可以自己选择背景层的颜色。前层与背景层相同,但不透明度为零,这样你就可以看到中间层上的文本。 我也不喜欢使用节点来处理事件,而是使用Raphael本地可用的事件处理机制。 下面的示例取自我的网站上的一个示例,我已经将其缩小,以便更容易理解。 还请注意,这是一个由前后两个圆形层和夹在两个层之间的文本组成的按钮。它们也可以很容易地变成矩形/圆角矩形。 功能包括鼠标悬停/移出时颜色反转...
button = function (paper, xpos, ypos, r, labeltext) 
{

this.backLayer = paper.circle(xpos, ypos, r).attr({ fill: "#FFFF00", 'fill-opacity': 0  , stroke: "#FF0000",'stroke-width':5, 'stroke-opacity':0});

/*The text automatically centres itself as this is the default text positioning for Raphael text*/
this.label = paper.text(xpos, ypos, labeltext).attr({fill:'#ff0000', 'font-size':18});

/*Now we make a copy for the front layer and we also make the back layer opaque. So that you can see it's yellow fill*/
this.frontLayer = this.backLayer.clone();
this.backLayer.attr({'fill-opacity': 1, 'stroke-opacity':1});

/*Now make the back layer and the text referencable for the mouseover, mouseout and click event of the front layer*/ 
this.frontLayer.backLayer= this.backLayer;
this.frontLayer.label = this.label;

/*Add a preferred cursor by referencing the underlying DOM object of the frontLayer*/
this.frontLayer.node.style.cursor = 'pointer';

/*Now you can interact with the lower layers behind the invisible covering layer ( frontLayer ) in it's event methods*/
this.frontLayer.mouseover(
function (e) {
    this.backLayer.animate({ fill: "#FF0000", stroke: "#FFFF00" }, 1000);
    this.label.animate({ fill: "#FFFF00" }, 1000);
    }
);  
this.frontLayer.mouseout(
function (e) {
    this.backLayer.animate({ fill: "#FFFF00", stroke: "#FF0000" }, 1000);
    this.label.animate({ fill: "#FF0000" }, 1000);
    }
);
this.frontLayer.click(      
function (e) {
        alert("Creating loads of custom buttons is easy\n\nYou made this one with the following specification:\n"+
        "Button Text      : "+this.label.attr("text")+"\n"+
        "Button Centre @ X: "+this.backLayer.attr("cx")+"\n"+
        "Button Centre @ Y: "+this.backLayer.attr("cy")+"\n"+
        "Button Radius    : "+this.backLayer.attr("r"));
    }

);  
}
/*Create the button*/
rappyButton = new button(paper, 250, 200, 75, "Raphael");

希望这有所帮助。

我已经更新了问题,并附上了这个解决方案的结果。但是没有用:( - kavita

1
你使用了 Raphael 的 `set` 属性(http://raphaeljs.com/reference.html#set)。你尝试给它添加 `onclick` 了吗?
group.click(function(event) {
    c2.attr({fill: "red"});
});

1
考虑忽略文本节点上的指针事件,让它们通过到父矩形。
svg text {
    pointer-events: none;
}

这似乎是个不错的解决方案。但是有什么缺点吗?如果我想允许用户选择/复制文本怎么办?是否有一种方法可以开启双击并允许复制? - Mutant

1

使用相同的处理程序来处理文本和矩形,使用fill-opacity为0怎么样?


0

在IE 7、8和9中,onmousedown对我有效。

            st[0].onclick = function () {
                myFunc(dataObj);
                st.toFront();
                R.safari();
            };
            st[0].onmousedown = function () {
                myFunc(dataObj);
                st.toFront();
                R.safari();
            };

我也尝试了其他方法,比如将函数抽象为变量,但都没有成功。在我的情况下,我不能将一个矩形添加到显示器上并让人们点击它,这是一个不好的解决方案,因为有几个原因。

希望这可以帮到你!


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