Chapter 4: Make Your Own Curve

by Stéphane Cabaret

HTML

<div id="holder"></div>

CSS

#holder {
            background-color: #fff;
        }

JavaScript

var r = Raphael("holder", window.innerWidth, window.innerHeight)

function findReflected(coord, about) {
    var diff = about - coord;
    return about + diff;
}

function curve(x1,y1, cx1,cy1, cx2,cy2, x2,y2, cx3,cy3, x3,y3, color) {  //zx --x1
    var cx2b = findReflected(cx2, x2),
        cy2b = findReflected(cy2, y2),
        path = [["M", x1, y1], ["C", cx1,cy1, cx2,cy2, x2,y2, "S", cx3,cy3, x3,y3]],
        path2 = [["M", x1, y1], ["L", cx1, cy1], 
                 ["M", cx2, cy2], ["L", cx2b, cy2b],
                 ["M", x3,y3],['L', cx3,cy3]],
        curve = r.path(path).attr({stroke: color || Raphael.getColor(), "stroke-width": 4, "stroke-linecap": "round"}),
        controls = r.set(
            r.path(path2).attr({stroke: "#ccc", "stroke-dasharray": ". ","stroke-width":2}),
            r.circle(x1, y1, 5).attr({fill: "red", stroke: "none"}),
            r.circle(cx1, cy1, 5).attr({fill: "green", stroke: "none"}),
            r.circle(cx2, cy2, 5).attr({fill: "blue", stroke: "none"}),
            r.circle(x2, y2, 5).attr({fill: "yellow", stroke: "none"}),
            r.circle(cx2b, cy2b, 5).attr({fill: "pink", stroke: "none"}),
            r.circle(cx3, cy3, 5).attr({fill: "grey", stroke: "none"}),
            r.circle(x3, y3, 5).attr({fill: "brown", stroke: "none"})

        );
    controls[1].update = function (x, y) {
        var X = this.attr("cx") + x,
            Y = this.attr("cy") + y;
        this.attr({cx: X, cy: Y});
        path[0][1] = X;
        path[0][2] = Y;
        path2[0][1] = X;
        path2[0][2] = Y;
        controls[2].update(x, y);
    };
    controls[2].update = function (x, y) {
        var X = this.attr("cx") + x,
            Y = this.attr("cy") + y;
        this.attr({cx: X, cy: Y});
        path[1][1] = X;
        path[1][2] = Y;
        path2[1][1] = X;
        path2[1][2] = Y;
        curve.attr({path: path});
        controls[0].attr({path: path2});
    };
    controls[3].update = function (x, y, doReflect) {
       ...