Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here's one way to do this. First draw a circle for each control point, like so:</p> <pre><code>// 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"); </code></pre> <p>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 <a href="https://stackoverflow.com/questions/9956186/raphael-js-maintain-path-between-two-objects">this question</a>, I've reproduced it here, slightly modified to suit our needs (it now listens for the <code>drag</code> event, accepts line attributes as an argument and fixes a bug I noted in my comment on the original question):</p> <pre><code>// 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')) }); } } }); } </code></pre> <p>Using this function we can now connect the adjacent control points.</p> <pre><code>// 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"}); </code></pre> <p>Next we want to make our control points draggable. We can do this as follows:</p> <pre><code>// 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); </code></pre> <p>Putting all this together will give you a polygon with draggable vertices and edges which update as the vertices are dragged. </p> <p>You can see an example of it in action <a href="http://calcatraz.com/raphael/draggable-polygon" rel="nofollow noreferrer">here</a></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload