// ┌─────────────────────────────────────────────────────────────────────┐ \\
-// │ "Raphaël 2.0" - JavaScript Vector Library │ \\
+// │ "Raphaël 2.0.1" - JavaScript Vector Library │ \\
// ├─────────────────────────────────────────────────────────────────────┤ \\
// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
- height (number)
- callback (function) #optional callback function which is going to be executed in the context of newly created paper
* or
- - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>})
+ - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>}). See @Paper.add.
- callback (function) #optional callback function which is going to be executed in the context of newly created paper
* or
- onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`.
if (R.is(first, "function")) {
return loaded ? first() : eve.on("DOMload", first);
} else if (R.is(first, array)) {
- var a = first,
- cnv = R._engine.create[apply](R, a.splice(0, 3 + R.is(a[0], nu))),
- res = cnv.set(),
- i = 0,
- ii = a.length,
- j;
- for (; i < ii; i++) {
- j = a[i] || {};
- elements[has](j.type) && res.push(cnv[j.type]().attr(j));
- }
- return res;
+ return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);
} else {
var args = Array.prototype.slice.call(arguments, 0);
if (R.is(args[args.length - 1], "function")) {
}
}
}
- R.version = "2.0.0";
+ R.version = "2.0.1";
R.eve = eve;
var loaded,
separator = /[, ]+/,
was: Object.prototype[has].call(g.win, "Raphael"),
is: g.win.Raphael
},
- Paper = function () {},
+ Paper = function () {
+ /*\
+ * Paper.ca
+ [ property (object) ]
+ **
+ * Shortcut for @Paper.customAttributes
+ \*/
+ /*\
+ * Paper.customAttributes
+ [ property (object) ]
+ **
+ * If you have a set of attributes that you would like to represent
+ * as a function of some number you can do it easily with custom attributes:
+ > Usage
+ | paper.customAttributes.hue = function (num) {
+ | num = num % 1;
+ | return {fill: "hsb(" + num + ", 0.75, 1)"};
+ | };
+ | // Custom attribute “hue” will change fill
+ | // to be given hue with fixed saturation and brightness.
+ | // Now you can use it like this:
+ | var c = paper.circle(10, 10, 10).attr({hue: .45});
+ | // or even like this:
+ | c.animate({hue: 1}, 1e3);
+ |
+ | // You could also create custom attribute
+ | // with multiple parameters:
+ | paper.customAttributes.hsb = function (h, s, b) {
+ | return {fill: "hsb(" + [h, s, b].join(",") + ")"};
+ | };
+ | c.attr({hsb: "0.5 .8 1"});
+ | c.animate({hsb: [1, 0, 0.5]}, 1e3);
+ \*/
+ this.ca = this.customAttributes = {};
+ },
paperproto,
appendChild = "appendChild",
apply = "apply",
S = " ",
Str = String,
split = "split",
- events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel".split(S),
+ events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S),
touchMap = {
mousedown: "touchstart",
mousemove: "touchmove",
paper = {},
push = "push",
ISURL = R._ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i,
- colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,
+ colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,
isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1},
bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
round = math.round,
setAttribute = "setAttribute",
toFloat = parseFloat,
toInt = parseInt,
- ms = " progid:DXImageTransform.Microsoft",
upperCase = Str.prototype.toUpperCase,
availableAttrs = R._availableAttrs = {
"arrow-end": "none",
gradient: 0,
height: 0,
href: "http://raphaeljs.com/",
+ "letter-spacing": 0,
opacity: 1,
path: "M0,0",
r: 0,
return a.key - b.key;
},
sortByNumber = function (a, b) {
- return a - b;
+ return toFloat(a) - toFloat(b);
},
fun = function () {},
pipe = function (x) {
return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
}
},
- mapPath = function (path, matrix) {
+ mapPath = R.mapPath = function (path, matrix) {
if (!matrix) {
return path;
}
- var x, y, i, j, pathi;
+ var x, y, i, j, ii, jj, pathi;
path = path2curve(path);
for (i = 0, ii = path.length; i < ii; i++) {
pathi = path[i];
**
* You can add your own method to the canvas. For example if you want to draw a pie chart,
* you can create your own pie chart function and ship it as a Raphaël plugin. To do this
- * you need to extend the `Raphael.fn` object. Please note that you can create your own namespaces
- * inside the `fn` object — methods will be run in the context of canvas anyway. You should alter
- * the `fn` object before a Raphaël instance is created, otherwise it will take no effect.
+ * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a
+ * Raphaël instance is created, otherwise it will take no effect. Please note that the
+ * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to
+ * ensure any namespacing ensures proper context.
> Usage
| Raphael.fn.arrow = function (x1, y1, x2, y2, size) {
| return this.path( ... );
| paper.mystuff.star();
\*/
R.fn = paperproto = Paper.prototype = R.prototype;
- /*\
- * Paper.customAttributes
- [ property (object) ]
- **
- * If you have a set of attributes that you would like to represent
- * as a function of some number you can do it easily with custom attributes:
- > Usage
- | paper.customAttributes.hue = function (num) {
- | num = num % 1;
- | return {fill: "hsb(" + num + ", .75, 1)"};
- | };
- | // Custom attribute “hue” will change fill
- | // to be given hue with fixed saturation and brightness.
- | // Now you can use it like this:
- | var c = paper.circle(10, 10, 10).attr({hue: .45});
- | // or even like this:
- | c.animate({hue: 1}, 1e3);
- |
- | // You could also create custom attribute
- | // with multiple parameters:
- | paper.customAttributes.hsb = function (h, s, b) {
- | return {fill: "hsb(" + [h, s, b].join(",") + ")"};
- | };
- | c.attr({hsb: ".5 .8 1"});
- | c.animate({hsb: "1 0 .5"}, 1e3);
- \*/
- paperproto.customAttributes = {};
R._id = 0;
R._oid = 0;
/*\
return o instanceof Array;
}
return (type == "null" && o === null) ||
- (type == typeof o) ||
+ (type == typeof o && o !== null) ||
(type == "object" && o === Object(o)) ||
(type == "array" && Array.isArray && Array.isArray(o)) ||
objectToString.call(o).slice(8, -1).toLowerCase() == type;
return value;
};
- var createUUID = R._createUUID = (function (uuidRegEx, uuidReplacer) {
+ /*\
+ * Raphael.createUUID
+ [ method ]
+ **
+ * Returns RFC4122, version 4 ID
+ \*/
+ var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {
return function () {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase();
};
eve("setWindow", R, g.win, newwin);
g.win = newwin;
g.doc = g.win.document;
- if (initWin) {
- initWin(g.win);
+ if (R._engine.initWin) {
+ R._engine.initWin(g.win);
}
};
var toHex = function (color) {
clr.v = rgb.b;
} else {
clr = {hex: "none"};
- crl.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;
+ clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;
}
}
clr.toString = rgbtoString;
var preload = R._preload = function (src, f) {
var img = g.doc.createElement("img");
- img.style.cssText = "position:absolute;left:-9999em;top-9999em";
+ img.style.cssText = "position:absolute;left:-9999em;top:-9999em";
img.onload = function () {
f.call(this);
this.onload = null;
red = toInt((t = rgb[3].charAt(1)) + t, 16);
}
if (rgb[4]) {
- values = rgb[4].split(commaSpaces);
+ values = rgb[4][split](commaSpaces);
red = toFloat(values[0]);
values[0].slice(-1) == "%" && (red *= 2.55);
green = toFloat(values[1]);
values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
}
if (rgb[5]) {
- values = rgb[5].split(commaSpaces);
+ values = rgb[5][split](commaSpaces);
red = toFloat(values[0]);
values[0].slice(-1) == "%" && (red *= 2.55);
green = toFloat(values[1]);
return R.hsb2rgb(red, green, blue, opacity);
}
if (rgb[6]) {
- values = rgb[6].split(commaSpaces);
+ values = rgb[6][split](commaSpaces);
red = toFloat(values[0]);
values[0].slice(-1) == "%" && (red *= 2.55);
green = toFloat(values[1]);
delete this.start;
};
+ // http://schepers.cc/getting-to-the-point
+ function catmullRom2bezier(crp) {
+ var d = [];
+ for (var i = 0, iLen = crp.length; iLen - 2 > i; i += 2) {
+ var p = [{x: +crp[i], y: +crp[i + 1]},
+ {x: +crp[i], y: +crp[i + 1]},
+ {x: +crp[i + 2], y: +crp[i + 3]},
+ {x: +crp[i + 4], y: +crp[i + 5]}];
+ if (iLen - 4 == i) {
+ p[0] = {x: +crp[i - 2], y: +crp[i - 1]};
+ p[3] = p[2];
+ } else if (i) {
+ p[0] = {x: +crp[i - 2], y: +crp[i - 1]};
+ }
+ d.push(["C",
+ (-p[0].x + 6 * p[1].x + p[2].x) / 6,
+ (-p[0].y + 6 * p[1].y + p[2].y) / 6,
+ (p[1].x + 6 * p[2].x - p[3].x) / 6,
+ (p[1].y + 6*p[2].y - p[3].y) / 6,
+ p[2].x,
+ p[2].y
+ ]);
+ }
+
+ return d;
+ }
/*\
* Raphael.parsePathString
[ method ]
if (!data.length) {
Str(pathString).replace(pathCommand, function (a, b, c) {
var params = [],
- name = lowerCase.call(b);
+ name = b.toLowerCase();
c.replace(pathValues, function (a, b) {
b && params.push(+b);
});
name = "l";
b = b == "m" ? "l" : "L";
}
- while (params.length >= paramCounts[name]) {
+ if (name == "r") {
+ data.push([b][concat](params));
+ } else while (params.length >= paramCounts[name]) {
data.push([b][concat](params.splice(0, paramCounts[name])));
if (!paramCounts[name]) {
break;
c.replace(pathValues, function (a, b) {
b && params.push(+b);
});
- data.push([name][concat](params));
+ data.push([b][concat](params));
});
}
data.toString = R._path2string;
alpha: alpha
};
};
+ R._removedFactory = function (methodname) {
+ return function () {
+ throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object");
+ };
+ };
var pathDimensions = cacher(function (path) {
if (!path) {
return {x: 0, y: 0, width: 0, height: 0};
start++;
res[0] = ["M", x, y];
}
- for (var i = start, ii = pathArray.length; i < ii; i++) {
- var r = res[i] = [],
- pa = pathArray[i];
+ for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
+ res.push(r = []);
+ pa = pathArray[i];
if (pa[0] != upperCase.call(pa[0])) {
r[0] = upperCase.call(pa[0]);
switch (r[0]) {
case "H":
r[1] = +pa[1] + x;
break;
+ case "R":
+ var dots = [x, y][concat](pa.slice(1));
+ for (var j = 2, jj = dots.length; j < jj; j++) {
+ dots[j] = +dots[j] + x;
+ dots[++j] = +dots[j] + y;
+ }
+ res.pop();
+ res = res[concat](catmullRom2bezier(dots));
+ break;
case "M":
mx = +pa[1] + x;
my = +pa[2] + y;
default:
- for (var j = 1, jj = pa.length; j < jj; j++) {
+ for (j = 1, jj = pa.length; j < jj; j++) {
r[j] = +pa[j] + ((j % 2) ? x : y);
}
}
+ } else if (pa[0] == "R") {
+ dots = [x, y][concat](pa.slice(1));
+ res.pop();
+ res = res[concat](catmullRom2bezier(dots));
+ r = ["R"][concat](pa.slice(-2));
} else {
for (var k = 0, kk = pa.length; k < kk; k++) {
- res[i][k] = pa[k];
+ r[k] = pa[k];
}
}
switch (r[0]) {
y = r[1];
break;
case "M":
- mx = res[i][res[i].length - 2];
- my = res[i][res[i].length - 1];
+ mx = r[r.length - 2];
+ my = r[r.length - 1];
default:
- x = res[i][res[i].length - 2];
- y = res[i][res[i].length - 1];
+ x = r[r.length - 2];
+ y = r[r.length - 1];
}
}
res.toString = R._path2string;
if (recursive) {
return [m2, m3, m4][concat](res);
} else {
- res = [m2, m3, m4][concat](res).join().split(",");
+ res = [m2, m3, m4][concat](res).join()[split](",");
var newres = [];
for (var i = 0, ii = res.length; i < ii; i++) {
newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
el2.prev = el;
el.next = el2;
},
- removed = function (methodname) {
- return function () {
- throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object");
- };
- },
extractTransform = R._extractTransform = function (el, tstr) {
if (tstr == null) {
return el._.transform;
for (var i = 0, ii = tdata.length; i < ii; i++) {
var t = tdata[i],
tlen = t.length,
+ command = Str(t[0]).toLowerCase(),
+ absolute = t[0] != command,
+ inver = absolute ? m.invert() : 0,
+ x1,
+ y1,
+ x2,
+ y2,
bb;
- t[0] = Str(t[0]).toLowerCase();
- if (t[0] == "t" && tlen == 3) {
- m.translate(t[1], t[2]);
- } else if (t[0] == "r") {
+ if (command == "t" && tlen == 3) {
+ if (absolute) {
+ x1 = inver.x(0, 0);
+ y1 = inver.y(0, 0);
+ x2 = inver.x(t[1], t[2]);
+ y2 = inver.y(t[1], t[2]);
+ m.translate(x2 - x1, y2 - y1);
+ } else {
+ m.translate(t[1], t[2]);
+ }
+ } else if (command == "r") {
if (tlen == 2) {
bb = bb || el.getBBox(1);
m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);
deg += t[1];
} else if (tlen == 4) {
- m.rotate(t[1], t[2], t[3]);
+ if (absolute) {
+ x2 = inver.x(t[2], t[3]);
+ y2 = inver.y(t[2], t[3]);
+ m.rotate(t[1], x2, y2);
+ } else {
+ m.rotate(t[1], t[2], t[3]);
+ }
deg += t[1];
}
- } else if (t[0] == "s") {
+ } else if (command == "s") {
if (tlen == 2 || tlen == 3) {
bb = bb || el.getBBox(1);
m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);
sx *= t[1];
sy *= t[tlen - 1];
} else if (tlen == 5) {
- m.scale(t[1], t[2], t[3], t[4]);
+ if (absolute) {
+ x2 = inver.x(t[3], t[4]);
+ y2 = inver.y(t[3], t[4]);
+ m.scale(t[1], t[2], x2, y2);
+ } else {
+ m.scale(t[1], t[2], t[3], t[4]);
+ }
sx *= t[1];
sy *= t[2];
}
- } else if (t[0] == "m" && tlen == 7) {
+ } else if (command == "m" && tlen == 7) {
m.add(t[1], t[2], t[3], t[4], t[5], t[6]);
}
_.dirtyT = 1;
}
},
getEmpty = function (item) {
- switch (item[0]) {
- case "t": return ["t", 0, 0];
- case "m": return ["m", 1, 0, 0, 1, 0, 0];
+ var l = item[0];
+ switch (l.toLowerCase()) {
+ case "t": return [l, 0, 0];
+ case "m": return [l, 1, 0, 0, 1, 0, 0];
case "r": if (item.length == 4) {
- return ["r", 0, item[2], item[3]];
+ return [l, 0, item[2], item[3]];
} else {
- return ["r", 0];
+ return [l, 0];
}
case "s": if (item.length == 5) {
- return ["s", 1, 1, item[3], item[4]];
+ return [l, 1, 1, item[3], item[4]];
} else if (item.length == 3) {
- return ["s", 1, 1];
+ return [l, 1, 1];
} else {
- return ["s", 1];
+ return [l, 1];
}
}
},
tt1 = t1[i] || getEmpty(t2[i]);
tt2 = t2[i] || getEmpty(tt1);
if ((tt1[0] != tt2[0]) ||
- (tt1[0] == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
- (tt1[0] == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
+ (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
+ (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
) {
return;
}
* Return transform string that represents given matrix
= (string) transform string
\*/
- matrixproto.toTransformString = function () {
- var s = this.split();
+ matrixproto.toTransformString = function (shorter) {
+ var s = shorter || this[split]();
if (s.isSimple) {
- return "t" + [s.dx, s.dy] + "s" + [s.scalex, s.scaley, 0, 0] + "r" + [s.rotate, 0, 0];
+ s.scalex = +s.scalex.toFixed(4);
+ s.scaley = +s.scaley.toFixed(4);
+ s.rotate = +s.rotate.toFixed(4);
+ return (s.dx && s.dy ? "t" + [s.dx, s.dy] : E) +
+ (s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) +
+ (s.rotate ? "r" + [s.rotate, 0, 0] : E);
} else {
return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
}
elproto.unhover = function (f_in, f_out) {
return this.unmouseover(f_in).unmouseout(f_out);
};
+ var draggable = [];
/*\
* Element.drag
[ method ]
eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);
}
this._drag = {};
+ draggable.push({el: this, start: start});
this.mousedown(start);
return this;
};
**
* Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id).
> Parameters
- - f (function) handler for event
+ - f (function) handler for event, first argument would be the element you are dragging over
\*/
elproto.onDragOver = function (f) {
f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id);
* Removes all drag event handlers from given element.
\*/
elproto.undrag = function () {
- var i = drag.length;
- while (i--) if (drag[i].el == this) {
- R.unmousedown(drag[i].start);
- drag.splice(i++, 1);
+ var i = draggable.length;
+ while (i--) if (draggable[i].el == this) {
+ this.unmousedown(draggable[i].start);
+ draggable.splice(i, 1);
eve.unbind("drag.*." + this.id);
}
- !drag.length && R.unmousemove(dragMove).unmouseup(dragUp);
+ !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);
};
/*\
* Paper.circle
[ method ]
**
* Creates a path element by given path data string.
- **
> Parameters
- **
- - pathString (string) path data in SVG path string format.
- = (object) Raphaël element object with type “path”
- # Details of a path's data attribute's format are described in the <a href="http://www.w3.org/TR/SVG/paths.html#PathData">SVG specification</a>.
- **
+ - pathString (string) #optional path string in SVG format.
+ * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example:
+ | "M10,20L30,40"
+ * Here we can see two commands: “M”, with arguments `(10, 20)` and “L” with arguments `(30, 40)`. Upper case letter mean command is absolute, lower case—relative.
+ *
+ # <p>Here is short list of commands available, for more details see <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path's data attribute's format are described in the SVG specification.">SVG path string format</a>.</p>
+ # <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody>
+ # <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr>
+ # <tr><td>Z</td><td>closepath</td><td>(none)</td></tr>
+ # <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr>
+ # <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr>
+ # <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr>
+ # <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr>
+ # <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr>
+ # <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr>
+ # <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr>
+ # <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr>
+ # <tr><td>R</td><td><a href="http://en.wikipedia.org/wiki/Catmull–Rom_spline#Catmull.E2.80.93Rom_spline">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table>
+ * * “Catmull-Rom curveto” is a not standard SVG command and added in 2.0 to make life easier.
> Usage
| var c = paper.path("M10 10L90 90");
| // draw a diagonal line:
if (this.removed) {
return null;
}
- return this.paper[this.type]().attr(this.attr());
+ var out = this.paper[this.type]().attr(this.attr());
+ this.__set__ && this.__set__.push(out);
+ return out;
};
/*\
* Element.glow
sp += p.shift() + p;
}
subpaths.end = sp;
- point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], 1);
+ point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
return point;
};
= (string) pathstring for the segment
\*/
R.getSubpath = function (path, from, to) {
- if (abs(this.getTotalLength(path) - to) < 1e-6) {
+ if (this.getTotalLength(path) - to < 1e-6) {
return getSubpathsAtLength(path, from).end;
}
var a = getSubpathsAtLength(path, to, 1);
t = e.t,
that = e.el,
set = {},
- now;
+ now,
+ init = {},
+ key;
if (e.initstatus) {
time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;
e.status = e.initstatus;
}
break;
default:
- var from2 = [].concat(from[attr]);
+ var from2 = [][concat](from[attr]);
now = [];
i = that.paper.customAttributes[attr].length;
while (i--) {
that.attr(to);
animationElements.splice(l--, 1);
if (e.repeat > 1 && !e.next) {
+ for (key in to) if (to[has](key)) {
+ init[key] = e.totalOrigin[key];
+ }
+ e.el.attr(init);
runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);
}
if (e.next && !e.stop) {
= (object) original element
\*/
elproto.animateWith = function (element, anim, params, ms, easing, callback) {
- var a = params ? R.animation(params, ms, easing, callback) : anim;
+ var a = params ? R.animation(params, ms, easing, callback) : anim,
status = element.status(anim);
- this.animate(a);
- return this.status(a, status * anim.ms / a.ms);
+ return this.animate(a).status(a, status * anim.ms / a.ms);
};
function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
var cx = 3 * p1x,
return this;
};
function Animation(anim, ms) {
- var percents = [];
- this.anim = anim;
+ var percents = [],
+ newAnim = {};
this.ms = ms;
this.times = 1;
- if (this.anim) {
- for (var attr in this.anim) if (this.anim[has](attr)) {
- percents.push(+attr);
+ if (anim) {
+ for (var attr in anim) if (anim[has](attr)) {
+ newAnim[toFloat(attr)] = anim[attr];
+ percents.push(toFloat(attr));
}
percents.sort(sortByNumber);
}
+ this.anim = newAnim;
this.top = percents[percents.length - 1];
this.percents = percents;
}
- delay (number) number of ms to pass between animation start and actual animation
**
= (object) new altered Animation object
+ | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3);
+ | circle1.animate(anim); // run the given animation immediately
+ | circle2.animate(anim.delay(500)); // run the given animation after 500 ms
\*/
Animation.prototype.delay = function (delay) {
var a = new Animation(this.anim, this.ms);
return;
}
if (!isInAnim) {
- for (attr in params) if (params[has](attr)) {
+ for (var attr in params) if (params[has](attr)) {
if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
from[attr] = element.attr(attr);
(from[attr] == null) && (from[attr] = availableAttrs[attr]);
}
break;
case "csv":
- var values = Str(params[attr]).split(separator),
- from2 = Str(from[attr]).split(separator);
+ var values = Str(params[attr])[split](separator),
+ from2 = Str(from[attr])[split](separator);
if (attr == "clip-rect") {
from[attr] = from2;
diff[attr] = [];
to[attr] = values;
break;
default:
- values = [].concat(params[attr]);
- from2 = [].concat(from[attr]);
+ values = [][concat](params[attr]);
+ from2 = [][concat](from[attr]);
diff[attr] = [];
i = element.paper.customAttributes[attr].length;
while (i--) {
var p = {},
json,
attr;
- for (attr in params) if (params[has](attr) && toFloat(attr) != attr) {
+ for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) {
json = true;
p[attr] = params[attr];
}
\*/
setproto.forEach = function (callback, thisArg) {
for (var i = 0, ii = this.items.length; i < ii; i++) {
- if (callback.call(thisArg, this.items[i]) === false) {
+ if (callback.call(thisArg, this.items[i], i) === false) {
return this;
}
}
= (boolean) `true` if object was found & removed from the set
\*/
setproto.exclude = function (el) {
- for (var i = 0, ii = this.length, found; i < ii; i++) if (found || this[i] == el) {
- this[i] = this[i + 1];
- found = 1;
- }
- if (found) {
- this.length--;
- delete this[i];
+ for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {
+ this.splice(i, 1);
return true;
}
};
origin = origin || "middle"; // baseline|middle
letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
var out = this.set(),
- letters = Str(string).split(E),
+ letters = Str(string)[split](E),
shift = 0,
path = E,
scale;
R.is(font, string) && (font = this.getFont(font));
if (font) {
scale = (size || 16) / font.face["units-per-em"];
- var bb = font.face.bbox.split(separator),
+ var bb = font.face.bbox[split](separator),
top = +bb[0],
height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2);
for (var i = 0, ii = letters.length; i < ii; i++) {
return out;
};
+ /*\
+ * Paper.add
+ [ method ]
+ **
+ * Imports elements in JSON array in format `{type: type, <attributes>}`
+ **
+ > Parameters
+ **
+ - json (array)
+ = (object) resulting set of imported elements
+ > Usage
+ | paper.import([
+ | {
+ | type: "circle",
+ | cx: 10,
+ | cy: 10,
+ | r: 5
+ | },
+ | {
+ | type: "rect",
+ | x: 10,
+ | y: 10,
+ | width: 10,
+ | height: 10,
+ | fill: "#fc0"
+ | }
+ | ]);
+ \*/
+ paperproto.add = function (json) {
+ if (R.is(json, "array")) {
+ var res = this.set(),
+ i = 0,
+ ii = json.length,
+ j;
+ for (; i < ii; i++) {
+ j = json[i] || {};
+ elements[has](j.type) && res.push(this[j.type]().attr(j));
+ }
+ }
+ return res;
+ };
+
/*\
* Raphael.format
[ method ]
| width = 40,
| height = 50;
| // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z"
- | paper.path(Raphael.format("M{1},{2}h{3}v{4}h{5}z", x, y, width, height, -width));
+ | paper.path(Raphael.format("M{0},{1}h{2}v{3}h{4}z", x, y, width, height, -width));
\*/
R.format = function (token, params) {
var args = R.is(params, array) ? [0][concat](params) : arguments;
eve.on("DOMload", function () {
loaded = true;
});
-})();
\ No newline at end of file
+})();