开发者

Onclick event for rect using Raphaeljs

I am trying to draw a simple Rectangle with some text on it. Since a shape cannot have text on it, I am creating a set with the same coordinates for the text and the rect objects. I need to change something on onclick event. Hence, I have used the obj.node.onclick = statement and written a handler. My problem is that if the text object is used for onclick the event handler gets called开发者_运维问答 only if i click on the text. If I use the rect for onclick I must click on the border area only. My requirement is that the click can come on the entire area of the shape along with the text in it.

   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");}; 

I have tried to use a div to overlay on the rect and write text on it but no success. I can see the div in firebug but not on the webpage! I have given it style properties for top left width and height as well as stated the position as absolute. But no success.

Please help me with this. Any help is appreciated! Kavita

I tried using the frontlayer backlayer solution. I cloned the backlayer and added a click handler to it. I did not use 'this' at all. The event never got fired! Please help me with this! Kavita


Create a set for all elements in the button. Then add a click (or mouseup) handler to the group. Note that rects must have a fill, otherwise they don't get mouse events. For a transparent button use opacity 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");
}); 


Here are two ways to do this. In both of them, I'm just adding an onclick for the text. In other words, have the same onclick for the rectangle and for the text.

1) Just add this line at the end

group[group.length - 1].node.onclick = function () { c2.attr("fill", "red");};

2) Or, you could create another variable c3, like c2, and attach the onclick the same way. Here's how all of your code would look.

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");};

I made the text really large here so you could be sure you're clicking on the text and not the rectangle.


It's nice to actually provide a 3 layer object because you can colour the back-layer how you like. The front layer is the same shape as your back layer but it has an opacity of zero so that you can see the text on the middle layer. I also don't like to use node for handling events but the natively available Raphael event handling mechanism. The below example is taken from one of the examples on my website, I have cut it down even further so it's more readily understood. Also note it is a button made up of a front and back layer circle with a text sandwiched between the two layers. They could just as easily be rectangles/rounded rectangles. The functionality includes the colours inverting on mouseover/mouseout...

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");

Hope that helped.


What about using the same handler for the text and the rect, using a fill-opacity of 0?


You've used the set property of Raphael (http://raphaeljs.com/reference.html#set). Have you tried adding the onclick to that?

group.click(function(event) {
    c2.attr({fill: "red"});
});


Consider just ignoring pointer events on the text nodes and letting them pass through to the parent rect.

svg text {
    pointer-events: none;
}


onmousedown worked for me in IE 7,8, and 9

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

I tried some other methods as well, abstracting the function to a variable but it didnt work. In my case I cannot add a rectangle to the display and have people click on this, it was a poor solution for several reasons.

Hope this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜