user2165265
user2165265

Reputation: 49

How to draw a polygon with control point for each corner using raphael.js

How can I draw a polygon shape with control points in each corner of the polygon using raphael.js.

The control points should be draggable and when the control points moving the related line also should move. Any idea please??

Upvotes: 3

Views: 4077

Answers (2)

frumbert
frumbert

Reputation: 2427

I was looking for the same. It's not draggable as the previous answer is, but the polygon create code is pretty easy:

http://davidbau.com/javascript/learn/10-polygon.html

Upvotes: 1

Divi Booster
Divi Booster

Reputation: 709

Here's one way to do this. First draw a circle for each control point, like so:

// Creates canvas
var paper = Raphael("canvas1", "100%", "100%");

// create small circle for each polygon point
var p1 = paper.circle(150, 50, 5).attr("fill", "blue");
var p2 = paper.circle(200, 100, 5).attr("fill", "blue");
var p3 = paper.circle(200, 200, 5).attr("fill", "blue");
var p4 = paper.circle(100, 200, 5).attr("fill", "blue");
var p5 = paper.circle(100, 100, 5).attr("fill", "blue");

Next we need to connect the control points in such a way that the lines will automatically redraw if updated. There is a handy function for doing so in this question, I've reproduced it here, slightly modified to suit our needs (it now listens for the drag event, accepts line attributes as an argument and fixes a bug I noted in my comment on the original question):

// Modified from: https://stackoverflow.com/questions/9956186/raphael-js-maintain-path-between-two-objects
// Call paper.connect(obj1,obj2,attributes)
// That draws a line between the two objects and maintains the line when the objects are animated
Raphael.fn.connect = function(obj1, obj2, attribs) {
    // list of paths each object has
    if (!obj1.connections) obj1.connections = []
    if (!obj2.connections) obj2.connections = []
    // get the bounding box of each object
    var box1 = obj1.getBBox()
    var box2 = obj2.getBBox()
    // create a line/path from object 1 to object 2
    var p = this.path("M" + (box1.x + box1.width / 2) + ","
            + (box1.y + box1.height / 2) + "L" + (box2.x + box2.width / 2)
            + "," + (box2.y + box2.height / 2))
    // adjust attributes of the path
    p.attr(attribs)
    // set the start and end element for this path
    p.startElement = obj1;
    p.endElement = obj2;
    // add the path to each of the object
    obj1.connections.push(p)
    obj2.connections.push(p)
    // mark each object as being connected
    obj1.connected = true;
    obj2.connected = true;
    // listen for the Raphael frame event
    eve.on("raphael.drag.*", function(obj) {
        // if the object the frame event is fired on is connected
        if (this.connected) {
            // for each connection on this object
            for ( var c in this.connections) {
                var path = this.connections[c]; // temp path
                var b1 = path.startElement.getBBox(); // get the current
                                                        // location of start
                                                        // element
                var b2 = path.endElement.getBBox();// get the current location
                                                    // of end element
                // move the path to the new locations
                path.attr({
                    path : "M " + (b1.x + b1.width / 2) + " "
                            + (b1.y + b1.height / 2) + "L "
                            + (b2.x + b2.width / 2) + " "
                            + (b2.y + b2.height / 2),
                    opacity : Math.max(path.startElement.attr('opacity'),
                            path.endElement.attr('opacity'))
                });
            }
        }
    });
}

Using this function we can now connect the adjacent control points.

// connect adjacent polygon points
paper.connect(p1,p2,{stroke:"red"});
paper.connect(p2,p3,{stroke:"red"});
paper.connect(p3,p4,{stroke:"red"});
paper.connect(p4,p5,{stroke:"red"});
paper.connect(p5,p1,{stroke:"red"});

Next we want to make our control points draggable. We can do this as follows:

// make points draggable
var start = function () {
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
},
move = function (dx, dy) {
    this.attr({cx: this.ox + dx, cy: this.oy + dy});
},
up = function () {};
paper.set(p1,p2,p3,p4,p5).drag(move, start, up);

Putting all this together will give you a polygon with draggable vertices and edges which update as the vertices are dragged.

You can see an example of it in action here

Upvotes: 8

Related Questions