views:

84

answers:

2

Hello all, currently I am using Raphael.js to drag and drop a circle around a canvas. However, I would like to disallow the user to drag the circle out of the canvas. My code is generally as follows:

<script type="text/javascript" src="Javascript/raphael.js"></script>
    <script type="text/javascript">
        window.onload = function() {  
            //create canvas matching the image's dimensions
            var paper = new Raphael(document.getElementById('canvas_container'), <%=width%>, <%=height%>);

            //put the schematic image onto the canvas
            paper.image("<%=path%>",0,0,<%=width%>,<%=height%>);

            //create the marker on the canvas
            var c = paper.circle(<%=markerx%>, <%=markery%>, 5).attr({
                fill: "#800517",
                stroke: "none"

            });
            var start = function () {
                // storing original coordinates
                this.ox = this.attr("cx");
                this.oy = this.attr("cy");                    
            },
            move = function (dx, dy) {
                // move will be called with dx and dy
                if (this.ox + dx >= <%=width%> || this.oy + dy >= <%=height%>){
                    this.attr({cx: <%=width%>, cy: <%=height%>});
                }else{
                    this.attr({cx: this.ox + dx, cy: this.oy + dy});
                }
            },
            up = function () {
                // restoring state                    
            };

            c.drag(move, start, up);

        }
    </script> 

I was wondering if there was anyone out there who has tried to do something like this and managed to get it right.

A: 

Hey guys, i managed to solve it. I realised it was I should not have used this.attr to set the cx and cy instead I should've used c.attr to identify the attr to my circle instead.

raabie
That shouldn't make any difference. When you're moving the circle, then `this` is equal to `c` within, `start()`, `move()`, and `up()`.
Peter Ajtai
A: 

With an if statement, you don't have to do anything if you don't want to move. Also, don't forget about the radius of the circle, and don't forget about checking for the value being to small, not just too big:

                                                        // If the new position is
           if (this.ox + dx <= width - radius &&        // not too far right
               this.oy + dy <= height - radius &&       // and not too far down
               this.ox + dx >= 0 + radius &&            // and not too far left
               this.oy + dy >= 0 + radius)              // and not too far up
           {                                            // ... then move
                this.attr({cx: this.ox + dx, cy: this.oy + dy});  
           }                                            // else nothing

jsFiddle example


But I like to use min and max more:

var nowX, nowY, w = ..., h=..., r=...,
move = function (dx, dy) {
    // move will be called with dx and dy
    // restrict movement of circle to within boundaries
        // You can combine the following 4 lines into 2 or even 1,
        //     but I left it as 4 for readability.
    nowX = Math.max(0 + r, this.ox + dx);
    nowY = Math.max(0 + r, this.oy + dy);
    nowX = Math.min(w - r, nowX);
    nowY = Math.min(h - r, nowY);    
    this.attr({cx: nowX, cy: nowY});
}


So, here's a full working example (jsFiddle)

window.onload = function() {
var nowX, nowY, w = 300, h=300, r=30, R = Raphael("canvas", w, h),   
    c = R.circle(100, 100, r).attr({
    fill: "hsb(.8, 1, 1)",
    stroke: "none",
    opacity: .5,
    cursor: "move"
});
var start = function () {
    // storing original coordinates
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
    this.attr({opacity: 1});
},
move = function (dx, dy) {
    // move will be called with dx and dy
    // restrict movement of circle to within boundaries
    nowX = Math.max(0 + r, this.ox + dx);
    nowY = Math.max(0 + r, this.oy + dy);
    nowX = Math.min(w - r, nowX);
    nowY = Math.min(h - r, nowY);    
    this.attr({cx: nowX, cy: nowY});
},
up = function () {
    // restoring state
    this.attr({opacity: .5});
};
c.drag(move, start, up);    
};​
Peter Ajtai