Commit e3fb35b7 by Dmitry Baranovskiy

1.5.0

• fixed IE8 issue with the HTML element named Raphael
• fixed precision for arcs in IE
• added caching to getPointAtSegmentLength function
• added ability to do more than one animation of an element at the same time
• added "cubic-bezier()" as an easing method
• added new syntax for animation (keyframes)
• hsl2rgb now accept h as degree (0..360), s and b as % (0..100)
• show="new" instead of target="blank" for SVG
• added angle method
• added snapTo method
• cached popup || activeX for IE
• fixed insertAfter
• fixed timeouts for animation
• added customAttributes
parent f4336cc1
This source diff could not be displayed because it is too large. You can view the blob instead.
/*!
* Raphael 1.4.7 - JavaScript Vector Library
* Raphael 1.5.0 - JavaScript Vector Library
*
* Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*/
Raphael = (function () {
(function () {
function R() {
if (R.is(arguments[0], array)) {
var a = arguments[0],
......@@ -13,15 +12,16 @@ Raphael = (function () {
res = cnv.set();
for (var i = 0, ii = a[length]; i < ii; i++) {
var j = a[i] || {};
elements.test(j.type) && res[push](cnv[j.type]().attr(j));
elements[has](j.type) && res[push](cnv[j.type]().attr(j));
}
return res;
}
return create[apply](R, arguments);
}
R.version = "1.4.7";
R.version = "1.5.0";
var separator = /[, ]+/,
elements = /^(circle|rect|path|ellipse|text|image)$/,
elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},
formatrg = /\{(\d+)\}/g,
proto = "prototype",
has = "hasOwnProperty",
doc = document,
......@@ -30,7 +30,10 @@ Raphael = (function () {
was: Object[proto][has].call(win, "Raphael"),
is: win.Raphael
},
Paper = function () {},
Paper = function () {
this.customAttributes = {};
},
paperproto,
appendChild = "appendChild",
apply = "apply",
concat = "concat",
......@@ -47,10 +50,11 @@ Raphael = (function () {
},
join = "join",
length = "length",
lowerCase = String[proto].toLowerCase,
lowerCase = Str[proto].toLowerCase,
math = Math,
mmax = math.max,
mmin = math.min,
pow = math.pow,
nu = "number",
string = "string",
array = "array",
......@@ -58,20 +62,31 @@ Raphael = (function () {
fillString = "fill",
objectToString = Object[proto][toString],
paper = {},
pow = math.pow,
push = "push",
rg = /^(?=[\da-f]$)/,
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*\)|rgba?\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%(?:\s*,\s*[\d\.]+%)?)\s*\)|hsb\(\s*([\d\.]+(?:deg|\xb0)?\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hsb\(\s*([\d\.]+(?:deg|\xb0|%)\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\)|hsl\(\s*([\d\.]+(?:deg|\xb0)?\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hsl\(\s*([\d\.]+(?:deg|\xb0|%)\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\))\s*$/i,
isnan = /^(NaN|-?Infinity)$/,
bezierrg = /^cubic-bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
round = math.round,
setAttribute = "setAttribute",
toFloat = parseFloat,
toInt = parseInt,
ms = " progid:DXImageTransform.Microsoft",
upperCase = String[proto].toUpperCase,
upperCase = Str[proto].toUpperCase,
availableAttrs = {blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", opacity: 1, path: "M0,0", r: 0, rotation: 0, rx: 0, ry: 0, scale: "1 1", src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", translation: "0 0", width: 0, x: 0, y: 0},
availableAnimAttrs = {along: "along", blur: nu, "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rotation: "csv", rx: nu, ry: nu, scale: "csv", stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, translation: "csv", width: nu, x: nu, y: nu},
rp = "replace";
rp = "replace",
p2s = /,?([achlmqrstvxz]),?/gi,
commaSpaces = /\s*,\s*/,
hsrg = {hs: 1, rg: 1},
animKeyFrames= /^(from|to|\d+%)$/,
pathCommand = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,
sortByKey = function (a, b) {
return a.key - b.key;
};
R.type = (win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
if (R.type == "VML") {
var d = doc.createElement("div"),
......@@ -86,16 +101,41 @@ Raphael = (function () {
}
R.svg = !(R.vml = R.type == "VML");
Paper[proto] = R[proto];
paperproto = Paper[proto];
R._id = 0;
R._oid = 0;
R.fn = {};
R.is = function (o, type) {
type = lowerCase.call(type);
return (type == "object" && o === Object(o)) ||
(type == "undefined" && typeof o == type) ||
(type == "null" && o == null) ||
if (type == "finite") {
return !isnan.test(+o);
}
return (type == "null" && o === null) ||
(type == typeof o) ||
(type == "object" && o === Object(o)) ||
(type == "array" && Array.isArray && Array.isArray(o)) ||
lowerCase.call(objectToString.call(o).slice(8, -1)) == type;
objectToString.call(o).slice(8, -1).toLowerCase() == type;
};
R.angle = function (x1, y1, x2, y2, x3, y3) {
if (x3 == null) {
var x = x1 - x2,
y = y1 - y2;
if (!x && !y) {
return 0;
}
return ((x < 0) * 180 + math.atan(-y / -x) * 180 / math.PI + 360) % 360;
} else {
return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);
}
};
R.snapTo = function (values, value, tolerance) {
tolerance = tolerance || 10;
values = [][concat](values);
var i = values.length;
while (i--) if (math.abs(values[i] - value) <= tolerance) {
return values[i];
}
return value;
};
R.setWindow = function (newwin) {
......@@ -107,20 +147,19 @@ Raphael = (function () {
if (R.vml) {
// http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
var trim = /^\s+|\s+$/g;
toHex = cacher(function (color) {
var bod;
color = Str(color)[rp](trim, E);
try {
var docum = new win.ActiveXObject("htmlfile");
var docum = new ActiveXObject("htmlfile");
docum.write("<body>");
docum.close();
bod = docum.body;
} catch(e) {
bod = win.createPopup().document.body;
bod = createPopup().document.body;
}
var range = bod.createTextRange();
toHex = cacher(function (color) {
try {
bod.style.color = color;
bod.style.color = Str(color)[rp](trim, E);
var value = range.queryCommandValue("ForeColor");
value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);
return "#" + ("000000" + value[toString](16)).slice(-6);
......@@ -164,9 +203,9 @@ Raphael = (function () {
h = h.h;
}
if (h > 1 || s > 1 || l > 1) {
h /= 255;
s /= 255;
l /= 255;
h /= 360;
s /= 100;
l /= 100;
}
var rgb = {},
channels = ["r", "g", "b"],
......@@ -295,9 +334,6 @@ Raphael = (function () {
hsl.toString = hsltoString;
return hsl;
};
var p2s = /,?([achlmqrstvxz]),?/gi,
commaSpaces = /\s*,\s*/,
hsrg = {hs: 1, rg: 1};
R._path2string = function () {
return this.join(",")[rp](p2s, "$1");
};
......@@ -418,8 +454,6 @@ Raphael = (function () {
delete this.start;
};
// path utilities
var pathCommand = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;
R.parsePathString = cacher(function (pathString) {
if (!pathString) {
return null;
......@@ -715,8 +749,8 @@ Raphael = (function () {
math.sqrt(math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
cx = k * rx * y / ry + (x1 + x2) / 2,
cy = k * -ry * x / rx + (y1 + y2) / 2,
f1 = math.asin(((y1 - cy) / ry).toFixed(7)),
f2 = math.asin(((y2 - cy) / ry).toFixed(7));
f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
f2 = math.asin(((y2 - cy) / ry).toFixed(9));
f1 = x1 < cx ? PI - f1 : f1;
f2 = x2 < cx ? PI - f2 : f2;
......@@ -785,8 +819,8 @@ Raphael = (function () {
y = [p1y, p2y],
x = [p1x, p2x],
dot;
math.abs(t1) > 1e12 && (t1 = .5);
math.abs(t2) > 1e12 && (t2 = .5);
math.abs(t1) > "1e12" && (t1 = .5);
math.abs(t2) > "1e12" && (t2 = .5);
if (t1 > 0 && t1 < 1) {
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
x[push](dot.x);
......@@ -802,8 +836,8 @@ Raphael = (function () {
c = p1y - c1y;
t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
math.abs(t1) > 1e12 && (t1 = .5);
math.abs(t2) > 1e12 && (t2 = .5);
math.abs(t1) > "1e12" && (t1 = .5);
math.abs(t2) > "1e12" && (t2 = .5);
if (t1 > 0 && t1 < 1) {
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
x[push](dot.x);
......@@ -1039,8 +1073,8 @@ Raphael = (function () {
R.pathToRelative = pathToRelative;
// SVG
if (R.svg) {
Paper[proto].svgns = "http://www.w3.org/2000/svg";
Paper[proto].xlink = "http://www.w3.org/1999/xlink";
paperproto.svgns = "http://www.w3.org/2000/svg";
paperproto.xlink = "http://www.w3.org/1999/xlink";
round = function (num) {
return +num + (~~num === num) * .5;
};
......@@ -1052,7 +1086,7 @@ Raphael = (function () {
}
}
} else {
el = doc.createElementNS(Paper[proto].svgns, el);
el = doc.createElementNS(paperproto.svgns, el);
el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
return el;
}
......@@ -1203,7 +1237,11 @@ Raphael = (function () {
hl[appendChild](node);
pn = hl;
}
if (att == "target" && value == "blank") {
pn.setAttributeNS(o.paper.xlink, "show", "new");
} else {
pn.setAttributeNS(o.paper.xlink, att, value);
}
break;
case "cursor":
node.style.cursor = value;
......@@ -1454,6 +1492,7 @@ Raphael = (function () {
svg.top = this;
this.next = null;
};
var elproto = Element[proto];
Element[proto].rotate = function (deg, cx, cy) {
if (this.removed) {
return this;
......@@ -1471,7 +1510,7 @@ Raphael = (function () {
cy = toFloat(deg[2]);
}
deg = toFloat(deg[0]);
if (cx != null) {
if (cx != null && cx !== false) {
this._.rt.deg = deg;
} else {
this._.rt.deg += deg;
......@@ -1580,10 +1619,17 @@ Raphael = (function () {
if (value != null) {
var params = {};
params[name] = value;
setFillAndStroke(this, params);
} else if (name != null && R.is(name, "object")) {
setFillAndStroke(this, name);
params = name;
}
for (var key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
var par = this.paper.customAttributes[key].apply(this, [][concat](params[key]));
this.attrs[key] = params[key];
for (var subkey in par) if (par[has](subkey)) {
params[subkey] = par[subkey];
}
}
setFillAndStroke(this, params);
return this;
};
Element[proto].toFront = function () {
......@@ -1610,7 +1656,7 @@ Raphael = (function () {
if (this.removed) {
return this;
}
var node = element.node || element[element.length].node;
var node = element.node || element[element.length - 1].node;
if (node.nextSibling) {
node.parentNode.insertBefore(this.node, node.nextSibling);
} else {
......@@ -1658,8 +1704,8 @@ Raphael = (function () {
res.type = "circle";
$(el, res.attrs);
return res;
};
var theRect = function (svg, x, y, w, h, r) {
},
theRect = function (svg, x, y, w, h, r) {
var el = $("rect");
svg.canvas && svg.canvas[appendChild](el);
var res = new Element(el, svg);
......@@ -1667,8 +1713,8 @@ Raphael = (function () {
res.type = "rect";
$(el, res.attrs);
return res;
};
var theEllipse = function (svg, x, y, rx, ry) {
},
theEllipse = function (svg, x, y, rx, ry) {
var el = $("ellipse");
svg.canvas && svg.canvas[appendChild](el);
var res = new Element(el, svg);
......@@ -1676,8 +1722,8 @@ Raphael = (function () {
res.type = "ellipse";
$(el, res.attrs);
return res;
};
var theImage = function (svg, src, x, y, w, h) {
},
theImage = function (svg, src, x, y, w, h) {
var el = $("image");
$(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
el.setAttributeNS(svg.xlink, "href", src);
......@@ -1686,8 +1732,8 @@ Raphael = (function () {
res.attrs = {x: x, y: y, width: w, height: h, src: src};
res.type = "image";
return res;
};
var theText = function (svg, x, y, text) {
},
theText = function (svg, x, y, text) {
var el = $("text");
$(el, {x: x, y: y, "text-anchor": "middle"});
svg.canvas && svg.canvas[appendChild](el);
......@@ -1696,15 +1742,15 @@ Raphael = (function () {
res.type = "text";
setFillAndStroke(res, res.attrs);
return res;
};
var setSize = function (width, height) {
},
setSize = function (width, height) {
this.width = width || this.width;
this.height = height || this.height;
this.canvas[setAttribute]("width", this.width);
this.canvas[setAttribute]("height", this.height);
return this;
};
var create = function () {
},
create = function () {
var con = getContainer[apply](0, arguments),
container = con && con.container,
x = con.x,
......@@ -1743,7 +1789,7 @@ Raphael = (function () {
container.clear();
return container;
};
Paper[proto].clear = function () {
paperproto.clear = function () {
var c = this.canvas;
while (c.firstChild) {
c.removeChild(c.firstChild);
......@@ -1753,7 +1799,7 @@ Raphael = (function () {
c[appendChild](this.desc);
c[appendChild](this.defs = $("defs"));
};
Paper[proto].remove = function () {
paperproto.remove = function () {
this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
for (var i in this) {
this[i] = removed(i);
......@@ -1765,6 +1811,7 @@ Raphael = (function () {
if (R.vml) {
var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
bites = /([clmz]),?([^clmz]*)/gi,
blurregexp = / progid:\S+Blur\([^\)]+\)/g,
val = /-?[^,\s-]+/g,
coordsize = 1e3 + S + 1e3,
zoom = 10,
......@@ -1821,7 +1868,6 @@ Raphael = (function () {
var p = new Element(el, g, vml),
attr = {fill: "none", stroke: "#000"};
pathString && (attr.path = pathString);
p.isAbsolute = true;
p.type = "path";
p.path = [];
p.Path = E;
......@@ -1925,8 +1971,7 @@ Raphael = (function () {
!fill && (newfill = fill = createNode(fillString));
if ("fill-opacity" in params || "opacity" in params) {
var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
opacity < 0 && (opacity = 0);
opacity > 1 && (opacity = 1);
opacity = mmin(mmax(opacity, 0), 1);
fill.opacity = opacity;
}
params.fill && (fill.on = true);
......@@ -1966,8 +2011,7 @@ Raphael = (function () {
stroke.on && params.stroke && (stroke.color = strokeColor.hex);
opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
var width = (toFloat(params["stroke-width"]) || 1) * .75;
opacity < 0 && (opacity = 0);
opacity > 1 && (opacity = 1);
opacity = mmin(mmax(opacity, 0), 1);
params["stroke-width"] == null && (width = a["stroke-width"]);
params["stroke-width"] && (stroke.weight = width);
width && width < 1 && (opacity *= width) && (stroke.weight = 1);
......@@ -2103,7 +2147,8 @@ Raphael = (function () {
vml.top = this;
this.next = null;
};
Element[proto].rotate = function (deg, cx, cy) {
elproto = Element[proto];
elproto.rotate = function (deg, cx, cy) {
if (this.removed) {
return this;
}
......@@ -2136,7 +2181,7 @@ Raphael = (function () {
// !R.is(fill.angle, "undefined") && (fill.angle = b);
return this;
};
Element[proto].setBox = function (params, cx, cy) {
elproto.setBox = function (params, cx, cy) {
if (this.removed) {
return this;
}
......@@ -2225,15 +2270,15 @@ Raphael = (function () {
os.height != (t = h + "px") && (os.height = t);
}
};
Element[proto].hide = function () {
elproto.hide = function () {
!this.removed && (this.Group.style.display = "none");
return this;
};
Element[proto].show = function () {
elproto.show = function () {
!this.removed && (this.Group.style.display = "block");
return this;
};
Element[proto].getBBox = function () {
elproto.getBBox = function () {
if (this.removed) {
return this;
}
......@@ -2247,7 +2292,7 @@ Raphael = (function () {
height: this.H
};
};
Element[proto].remove = function () {
elproto.remove = function () {
if (this.removed) {
return;
}
......@@ -2260,7 +2305,7 @@ Raphael = (function () {
}
this.removed = true;
};
Element[proto].attr = function (name, value) {
elproto.attr = function (name, value) {
if (this.removed) {
return this;
}
......@@ -2274,7 +2319,7 @@ Raphael = (function () {
res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
return res;
}
if (value == null && R.is(name, string)) {
if (value == null && R.is(name, "string")) {
if (name == "translation") {
return translate.call(this);
}
......@@ -2303,6 +2348,13 @@ Raphael = (function () {
}
value == null && R.is(name, "object") && (params = name);
if (params) {
for (var key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
var par = this.paper.customAttributes[key].apply(this, [][concat](params[key]));
this.attrs[key] = params[key];
for (var subkey in par) if (par[has](subkey)) {
params[subkey] = par[subkey];
}
}
if (params.text && this.type == "text") {
this.node.string = params.text;
}
......@@ -2314,12 +2366,12 @@ Raphael = (function () {
}
return this;
};
Element[proto].toFront = function () {
elproto.toFront = function () {
!this.removed && this.Group.parentNode[appendChild](this.Group);
this.paper.top != this && tofront(this, this.paper);
return this;
};
Element[proto].toBack = function () {
elproto.toBack = function () {
if (this.removed) {
return this;
}
......@@ -2329,12 +2381,12 @@ Raphael = (function () {
}
return this;
};
Element[proto].insertAfter = function (element) {
elproto.insertAfter = function (element) {
if (this.removed) {
return this;
}
if (element.constructor == Set) {
element = element[element.length];
element = element[element.length - 1];
}
if (element.Group.nextSibling) {
element.Group.parentNode.insertBefore(this.Group, element.Group.nextSibling);
......@@ -2344,7 +2396,7 @@ Raphael = (function () {
insertafter(this, element, this.paper);
return this;
};
Element[proto].insertBefore = function (element) {
elproto.insertBefore = function (element) {
if (this.removed) {
return this;
}
......@@ -2355,8 +2407,7 @@ Raphael = (function () {
insertbefore(this, element, this.paper);
return this;
};
var blurregexp = / progid:\S+Blur\([^\)]+\)/g;
Element[proto].blur = function (size) {
elproto.blur = function (size) {
var s = this.node.runtimeStyle,
f = s.filter;
f = f.replace(blurregexp, E);
......@@ -2430,8 +2481,7 @@ Raphael = (function () {
};
theImage = function (vml, src, x, y, w, h) {
var g = createNode("group"),
o = createNode("image"),
ol = o.style;
o = createNode("image");
g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";
g.coordsize = coordsize;
g.coordorigin = vml.coordorigin;
......@@ -2529,7 +2579,7 @@ Raphael = (function () {
res.span = doc.createElement("span");
res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
c[appendChild](res.span);
cs.cssText = R.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
if (container == 1) {
doc.body[appendChild](c);
cs.left = x + "px";
......@@ -2545,14 +2595,14 @@ Raphael = (function () {
plugins.call(res, res, R.fn);
return res;
};
Paper[proto].clear = function () {
paperproto.clear = function () {
this.canvas.innerHTML = E;
this.span = doc.createElement("span");
this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
this.canvas[appendChild](this.span);
this.bottom = this.top = null;
};
Paper[proto].remove = function () {
paperproto.remove = function () {
this.canvas.parentNode.removeChild(this.canvas);
for (var i in this) {
this[i] = removed(i);
......@@ -2563,13 +2613,14 @@ Raphael = (function () {
// rest
// WebKit rendering bug workaround method
if ((navigator.vendor == "Apple Computer, Inc.") && (navigator.userAgent.match(/Version\/(.*?)\s/)[1] < 4 || win.navigator.platform.slice(0, 2) == "iP")) {
Paper[proto].safari = function () {
var version = navigator.userAgent.match(/Version\/(.*?)\s/);
if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP")) {
paperproto.safari = function () {
var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"});
win.setTimeout(function () {rect.remove();});
};
} else {
Paper[proto].safari = function () {};
paperproto.safari = function () {};
}
// Events
......@@ -2631,6 +2682,8 @@ Raphael = (function () {
dragMove = function (e) {
var x = e.clientX,
y = e.clientY,
scrollY = doc.documentElement.scrollTop || doc.body.scrollTop,
scrollX = doc.documentElement.scrollLeft || doc.body.scrollLeft,
dragi,
j = drag.length;
while (j--) {
......@@ -2650,6 +2703,8 @@ Raphael = (function () {
} else {
e.preventDefault();
}
x += scrollX;
y += scrollY;
dragi.move && dragi.move.call(dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y);
}
},
......@@ -2686,62 +2741,64 @@ Raphael = (function () {
};
})(events[i]);
}
Element[proto].hover = function (f_in, f_out) {
elproto.hover = function (f_in, f_out) {
return this.mouseover(f_in).mouseout(f_out);
};
Element[proto].unhover = function (f_in, f_out) {
elproto.unhover = function (f_in, f_out) {
return this.unmouseover(f_in).unmouseout(f_out);
};
Element[proto].drag = function (onmove, onstart, onend) {
elproto.drag = function (onmove, onstart, onend) {
this._drag = {};
this.mousedown(function (e) {
(e.originalEvent || e).preventDefault();
this._drag.x = e.clientX;
this._drag.y = e.clientY;
var scrollY = doc.documentElement.scrollTop || doc.body.scrollTop,
scrollX = doc.documentElement.scrollLeft || doc.body.scrollLeft;
this._drag.x = e.clientX + scrollX;
this._drag.y = e.clientY + scrollY;
this._drag.id = e.identifier;
onstart && onstart.call(this, e.clientX, e.clientY);
onstart && onstart.call(this, e.clientX + scrollX, e.clientY + scrollY);
!drag.length && R.mousemove(dragMove).mouseup(dragUp);
drag.push({el: this, move: onmove, end: onend});
});
return this;
};
Element[proto].undrag = function (onmove, onstart, onend) {
elproto.undrag = function (onmove, onstart, onend) {
var i = drag.length;
while (i--) {
drag[i].el == this && (drag[i].move == onmove && drag[i].end == onend) && drag.splice(i, 1);
!drag.length && R.unmousemove(dragMove).unmouseup(dragUp);
}
};
Paper[proto].circle = function (x, y, r) {
paperproto.circle = function (x, y, r) {
return theCircle(this, x || 0, y || 0, r || 0);
};
Paper[proto].rect = function (x, y, w, h, r) {
paperproto.rect = function (x, y, w, h, r) {
return theRect(this, x || 0, y || 0, w || 0, h || 0, r || 0);
};
Paper[proto].ellipse = function (x, y, rx, ry) {
paperproto.ellipse = function (x, y, rx, ry) {
return theEllipse(this, x || 0, y || 0, rx || 0, ry || 0);
};
Paper[proto].path = function (pathString) {
paperproto.path = function (pathString) {
pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
return thePath(R.format[apply](R, arguments), this);
};
Paper[proto].image = function (src, x, y, w, h) {
paperproto.image = function (src, x, y, w, h) {
return theImage(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
};
Paper[proto].text = function (x, y, text) {
return theText(this, x || 0, y || 0, text || E);
paperproto.text = function (x, y, text) {
return theText(this, x || 0, y || 0, Str(text));
};
Paper[proto].set = function (itemsArray) {
paperproto.set = function (itemsArray) {
arguments[length] > 1 && (itemsArray = Array[proto].splice.call(arguments, 0, arguments[length]));
return new Set(itemsArray);
};
Paper[proto].setSize = setSize;
Paper[proto].top = Paper[proto].bottom = null;
Paper[proto].raphael = R;
paperproto.setSize = setSize;
paperproto.top = paperproto.bottom = null;
paperproto.raphael = R;
function x_y() {
return this.x + S + this.y;
}
Element[proto].resetScale = function () {
elproto.resetScale = function () {
if (this.removed) {
return this;
}
......@@ -2749,7 +2806,7 @@ Raphael = (function () {
this._.sy = 1;
this.attrs.scale = "1 1";
};
Element[proto].scale = function (x, y, cx, cy) {
elproto.scale = function (x, y, cx, cy) {
if (this.removed) {
return this;
}
......@@ -2880,7 +2937,7 @@ Raphael = (function () {
}
return this;
};
Element[proto].clone = function () {
elproto.clone = function () {
if (this.removed) {
return null;
}
......@@ -2889,18 +2946,32 @@ Raphael = (function () {
delete attr.translation;
return this.paper[this.type]().attr(attr);
};
var getPointAtSegmentLength = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
var curveslengths = {},
getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
var len = 0,
old;
for (var i = 0; i < 1.01; i+=.01) {
var dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i);
name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(),
cache = curveslengths[name],
old, dot;
!cache && (curveslengths[name] = cache = {data: []});
cache.timer && clearTimeout(cache.timer);
cache.timer = setTimeout(function () {delete curveslengths[name];}, 2000);
for (var i = 0; i < 101; i++) {
if (cache.data[length] > i) {
dot = cache.data[i * 100];
} else {
dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / 100);
cache.data[i] = dot;
}
i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5));
if (len >= length) {
if (length != null && len >= length) {
return dot;
}
old = dot;
}
}),
if (length == null) {
return len;
}
},
getLengthFactory = function (istotal, subpath) {
return function (path, length, onlystart) {
path = path2curve(path);
......@@ -2912,7 +2983,7 @@ Raphael = (function () {
x = +p[1];
y = +p[2];
} else {
l = segmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
if (len + l > length) {
if (subpath && !subpaths.start) {
point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
......@@ -2941,37 +3012,27 @@ Raphael = (function () {
point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
return point;
};
},
segmentLength = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
var old = {x: 0, y: 0},
len = 0;
for (var i = 0; i < 1.01; i+=.01) {
var dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i);
i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5));
old = dot;
}
return len;
});
};
var getTotalLength = getLengthFactory(1),
getPointAtLength = getLengthFactory(),
getSubpathsAtLength = getLengthFactory(0, 1);
Element[proto].getTotalLength = function () {
elproto.getTotalLength = function () {
if (this.type != "path") {return;}
if (this.node.getTotalLength) {
return this.node.getTotalLength();
}
return getTotalLength(this.attrs.path);
};
Element[proto].getPointAtLength = function (length) {
elproto.getPointAtLength = function (length) {
if (this.type != "path") {return;}
if (this.node.getPointAtLength) {
return this.node.getPointAtLength(length);
}
return getPointAtLength(this.attrs.path, length);
};
Element[proto].getSubpath = function (from, to) {
elproto.getSubpath = function (from, to) {
if (this.type != "path") {return;}
if (math.abs(this.getTotalLength() - to) < 1e-6) {
if (math.abs(this.getTotalLength() - to) < "1e-6") {
return getSubpathsAtLength(this.attrs.path, from).end;
}
var a = getSubpathsAtLength(this.attrs.path, to, 1);
......@@ -3038,14 +3099,12 @@ Raphael = (function () {
}
};
var animationElements = {length : 0},
var animationElements = [],
animation = function () {
var Now = +new Date;
for (var l in animationElements) if (l != "length" && animationElements[has](l)) {
for (var l = 0; l < animationElements[length]; l++) {
var e = animationElements[l];
if (e.stop || e.el.removed) {
delete animationElements[l];
animationElements[length]--;
continue;
}
var time = Now - e.start,
......@@ -3055,13 +3114,11 @@ Raphael = (function () {
diff = e.diff,
to = e.to,
t = e.t,
prev = e.prev || 0,
that = e.el,
callback = e.callback,
set = {},
now;
if (time < ms) {
var pos = R.easing_formulas[easing] ? R.easing_formulas[easing](time / ms) : time / ms;
var pos = easing(time / ms);
for (var attr in from) if (from[has](attr)) {
switch (availableAnimAttrs[attr]) {
case "along":
......@@ -3098,8 +3155,8 @@ Raphael = (function () {
case "csv":
switch (attr) {
case "translation":
var x = diff[attr][0] * (time - prev),
y = diff[attr][1] * (time - prev);
var x = pos * ms * diff[attr][0] - t.x,
y = pos * ms * diff[attr][1] - t.y;
t.x += x;
t.y += y;
now = x + S + y;
......@@ -3120,6 +3177,14 @@ Raphael = (function () {
break;
}
break;
default:
var from2 = [].concat(from[attr]);
now = [];
i = that.paper.customAttributes[attr].length;
while (i--) {
now[i] = +from2[i] + pos * ms * diff[attr][i];
}
break;
}
set[attr] = now;
}
......@@ -3134,15 +3199,18 @@ Raphael = (function () {
(t.x || t.y) && that.translate(-t.x, -t.y);
to.scale && (to.scale += E);
that.attr(to);
delete animationElements[l];
animationElements[length]--;
that.in_animation = null;
R.is(callback, "function") && callback.call(that);
animationElements.splice(l--, 1);
}
e.prev = time;
}
R.svg && that && that.paper && that.paper.safari();
animationElements[length] && win.setTimeout(animation);
animationElements[length] && setTimeout(animation);
},
keyframesRun = function (attr, element, time, prev, prevcallback) {
var dif = time - prev;
element.timeouts.push(setTimeout(function () {
R.is(prevcallback, "function") && prevcallback.call(element);
element.animate(attr, dif, attr.easing);
}, prev));
},
upto255 = function (color) {
return mmax(mmin(color, 255), 0);
......@@ -3172,12 +3240,16 @@ Raphael = (function () {
}
return this;
};
Element[proto].animateWith = function (element, params, ms, easing, callback) {
animationElements[element.id] && (params.start = animationElements[element.id].start);
elproto.animateWith = function (element, params, ms, easing, callback) {
for (var i = 0, ii = animationElements.length; i < ii; i++) {
if (animationElements[i].el.id == element.id) {
params.start = animationElements[i].start;
}
}
return this.animate(params, ms, easing, callback);
};
Element[proto].animateAlong = along();
Element[proto].animateAlongBack = along(1);
elproto.animateAlong = along();
elproto.animateAlongBack = along(1);
function along(isBack) {
return function (path, ms, rotate, callback) {
var params = {back: isBack};
......@@ -3187,27 +3259,87 @@ Raphael = (function () {
return this.animate(params, ms, callback);
};
}
Element[proto].onAnimation = function (f) {
function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
var cx = 3 * p1x,
bx = 3 * (p2x - p1x) - cx,
ax = 1 - cx - bx,
cy = 3 * p1y,
by = 3 * (p2y - p1y) - cy,
ay = 1 - cy - by;
function sampleCurveX(t) {
return ((ax * t + bx) * t + cx) * t;
}
function solve(x, epsilon) {
var t = solveCurveX(x, epsilon);
return ((ay * t + by) * t + cy) * t;
}
function solveCurveX(x, epsilon) {
var t0, t1, t2, x2, d2, i;
for(t2 = x, i = 0; i < 8; i++) {
x2 = sampleCurveX(t2) - x;
if (math.abs(x2) < epsilon) {
return t2;
}
d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
if (math.abs(d2) < 1e-6) {
break;
}
t2 = t2 - x2 / d2;
}
t0 = 0;
t1 = 1;
t2 = x;
if (t2 < t0) {
return t0;
}
if (t2 > t1) {
return t1;
}
while (t0 < t1) {
x2 = sampleCurveX(t2);
if (math.abs(x2 - x) < epsilon) {
return t2;
}
if (x > x2) {
t0 = t2;
} else {
t1 = t2;
}
t2 = (t1 - t0) / 2 + t0;
}
return t2;
}
return solve(t, 1 / (200 * duration));
}
elproto.onAnimation = function (f) {
this._run = f || 0;
return this;
};
Element[proto].animate = function (params, ms, easing, callback) {
elproto.animate = function (params, ms, easing, callback) {
var element = this;
element.timeouts = element.timeouts || [];
if (R.is(easing, "function") || !easing) {
callback = easing || null;
}
if (element.removed) {
callback && callback.call(element);
return element;
}
var from = {},
to = {},
animateable = false,
diff = {};
for (var attr in params) if (params[has](attr)) {
if (availableAnimAttrs[has](attr)) {
from[attr] = this.attr(attr);
if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
animateable = true;
from[attr] = element.attr(attr);
(from[attr] == null) && (from[attr] = availableAttrs[attr]);
to[attr] = params[attr];
switch (availableAnimAttrs[attr]) {
case "along":
var len = getTotalLength(params[attr]);
var point = getPointAtLength(params[attr], len * !!params.back);
var bb = this.getBBox();
var bb = element.getBBox();
diff[attr] = len / ms;
diff.tx = bb.x;
diff.ty = bb.y;
......@@ -3216,7 +3348,7 @@ Raphael = (function () {
to.rot = params.rot;
to.back = params.back;
to.len = len;
params.rot && (diff.r = toFloat(this.rotate()) || 0);
params.rot && (diff.r = toFloat(element.rotate()) || 0);
break;
case nu:
diff[attr] = (to[attr] - from[attr]) / ms;
......@@ -3269,34 +3401,88 @@ Raphael = (function () {
break;
}
to[attr] = values;
break;
default:
values = [].concat(params[attr]);
from2 = [].concat(from[attr]);
diff[attr] = [];
i = element.paper.customAttributes[attr][length];
while (i--) {
diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;
}
break;
}
}
}
if (!animateable) {
var attrs = [],
lastcall;
for (var key in params) if (params[has](key) && animKeyFrames.test(key)) {
attr = {value: params[key]};
key == "from" && (key = 0);
key == "to" && (key = 100);
attr.key = toInt(key, 10);
attrs.push(attr);
}
attrs.sort(sortByKey);
if (attrs[0].key) {
attrs.unshift({key: 0, value: element.attrs});
}
for (i = 0, ii = attrs[length]; i < ii; i++) {
keyframesRun(attrs[i].value, element, ms / 100 * attrs[i].key, ms / 100 * (attrs[i - 1] && attrs[i - 1].key || 0), attrs[i - 1] && attrs[i - 1].value.callback);
}
this.stop();
this.in_animation = 1;
animationElements[this.id] = {
lastcall = attrs[attrs[length] - 1].value.callback;
if (lastcall) {
element.timeouts.push(setTimeout(function () {lastcall.call(element);}, ms));
}
} else {
var easyeasy = R.easing_formulas[easing];
if (!easyeasy) {
easyeasy = Str(easing).match(bezierrg);
if (easyeasy && easyeasy[length] == 5) {
var curve = easyeasy;
easyeasy = function (t) {
return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);
};
} else {
easyeasy = function (t) {
return t;
};
}
}
animationElements.push({
start: params.start || +new Date,
ms: ms,
easing: easing,
easing: easyeasy,
from: from,
diff: diff,
to: to,
el: this,
callback: callback,
el: element,
t: {x: 0, y: 0}
};
++animationElements[length] == 1 && animation();
});
R.is(callback, "function") && (element._ac = setTimeout(function () {
callback.call(element);
}, ms));
animationElements[length] == 1 && setTimeout(animation);
}
return this;
};
Element[proto].stop = function () {
animationElements[this.id] && animationElements[length]--;
delete animationElements[this.id];
elproto.stop = function () {
for (var i = 0; i < animationElements.length; i++) {
animationElements[i].el.id == this.id && animationElements.splice(i--, 1);
}
for (i = 0, ii = this.timeouts && this.timeouts.length; i < ii; i++) {
clearTimeout(this.timeouts[i]);
}
this.timeouts = [];
clearTimeout(this._ac);
delete this._ac;
return this;
};
Element[proto].translate = function (x, y) {
elproto.translate = function (x, y) {
return this.attr({translation: x + " " + y});
};
Element[proto][toString] = function () {
elproto[toString] = function () {
return "Rapha\xebl\u2019s object";
};
R.ae = animationElements;
......@@ -3332,7 +3518,7 @@ Raphael = (function () {
delete this[this[length]--];
return this.items.pop();
};
for (var method in Element[proto]) if (Element[proto][has](method)) {
for (var method in elproto) if (elproto[has](method)) {
Set[proto][method] = (function (methodname) {
return function () {
for (var i = 0, ii = this.items[length]; i < ii; i++) {
......@@ -3367,7 +3553,7 @@ Raphael = (function () {
easing = R.is(easing, string) ? easing : collector;
item = this.items[--i].animate(params, ms, easing, collector);
while (i--) {
this.items[i].animateWith(item, params, ms, easing, collector);
this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, params, ms, easing, collector);
}
return this;
};
......@@ -3446,7 +3632,7 @@ Raphael = (function () {
}
return font;
};
Paper[proto].getFont = function (family, weight, style, stretch) {
paperproto.getFont = function (family, weight, style, stretch) {
stretch = stretch || "normal";
style = style || "normal";
weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;
......@@ -3474,8 +3660,9 @@ Raphael = (function () {
}
return thefont;
};
Paper[proto].print = function (x, y, string, font, size, origin) {
paperproto.print = function (x, y, string, font, size, origin, letter_spacing) {
origin = origin || "middle"; // baseline|middle
letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
var out = this.set(),
letters = Str(string)[split](E),
shift = 0,
......@@ -3490,7 +3677,7 @@ Raphael = (function () {
for (var i = 0, ii = letters[length]; i < ii; i++) {
var prev = i && font.glyphs[letters[i - 1]] || {},
curr = font.glyphs[letters[i]];
shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) : 0;
shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;
curr && curr.d && out[push](this.path(curr.d).attr({fill: "#000", stroke: "none", translation: [shift, 0]}));
}
out.scale(scale, scale, top, height).translate(x - top, y - height);
......@@ -3498,7 +3685,6 @@ Raphael = (function () {
return out;
};
var formatrg = /\{(\d+)\}/g;
R.format = function (token, params) {
var args = R.is(params, array) ? [0][concat](params) : arguments;
token && R.is(token, string) && args[length] - 1 && (token = token[rp](formatrg, function (str, i) {
......@@ -3507,9 +3693,11 @@ Raphael = (function () {
return token || E;
};
R.ninja = function () {
oldRaphael.was ? (Raphael = oldRaphael.is) : delete Raphael;
oldRaphael.was ? (win.Raphael = oldRaphael.is) : delete Raphael;
return R;
};
R.el = Element[proto];
return R;
R.el = elproto;
R.st = Set[proto];
oldRaphael.was ? (win.Raphael = R) : (Raphael = R);
})();
\ No newline at end of file
<!DOCTYPE html><html lang="en">
<!DOCTYPE html>
<html lang="en">
<head>
<title>Raphaël Reference</title>
<meta http-equiv="content-language" content="en">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta charset="utf-8">
<meta name="author" content="Dmitry Baranovskiy">
<meta name="description" content="Vector Graphics JavaScript Library">
<meta name="keywords" content="JavaScript Library, Raphael, SVG, VML">
......@@ -20,7 +21,7 @@
<div id="top">&nbsp;</div>
<div id="column-1">
<h2>Main Function</h2>
<h3 id="Raphael">
<h3 id="RAPHAEL">
Raphael
</h3>
<p>
......@@ -392,9 +393,15 @@ c.attr({
<ol>
<li>newAttrs <em>object</em> A parameters object of the animation results. (Not all attributes can be animated.)</li>
<li>ms <em>number</em> The duration of the animation, given in milliseconds.</li>
<li>easing <em>string</em> [“<samp>></samp>”, “<samp>&lt;</samp>”, “<samp>&lt;></samp>”, “<samp>backIn</samp>”, “<samp>backOut</samp>”, “<samp>bounce</samp>”, “<samp>elastic</samp>] or <em>function</em> [optional]</li>
<li>easing <em>string</em> [“<samp>></samp>”, “<samp>&lt;</samp>”, “<samp>&lt;></samp>”, “<samp>backIn</samp>”, “<samp>backOut</samp>”, “<samp>bounce</samp>”, “<samp>elastic</samp>, “<samp>cubic-bezier(p1, p2, p3, p4)</samp>”] or <em>function</em> [optional], see <a href="http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag" title="CSS Transitions Module Level 3">explanation re cubic-bezier syntax</a></li>
<li>callback <em>function</em> [optional]</li>
</ol>
<p>or</p>
<ol>
<li>keyFrames <em>object</em> Key-value map, where key represents keyframe timing: [“from”, “20%”, “to”, “35%”, etc] and value is the same as <code>newAttrs</code> from above, except it could also have <samp>easing</samp> and <samp>callback</samp> properties</li>
<li>ms <em>number</em> The duration of the animation, given in milliseconds.</li>
</ol>
<p>Look at the <a href="bounce.html">example of keyframes usage</a></p>
<h4>Attributes that can be animated</h4>
<p>The <code>newAttrs</code> parameter accepts an object whose properties are the attributes to animate. However, not all attributes listed in the <code>attr</code> method reference can be animated. The following is a list of those properties that can be animated:</p>
<ul>
......@@ -425,9 +432,14 @@ c.attr({
For easing use built in functions or add your own by adding new functions to <code>Raphael.easing_formulas</code> object. Look at the <a href="easing.html">example of easing usage</a>.
</p>
<h4>Usage</h4>
<pre class="javascript code"><code>var c = paper.circle(10, 10, 10);</code>
<code>c.animate({cx: 20, r: 20}, 2000);</code>
<code>c.animate({cx: 20, r: 20}, 2000, "bounce");</code></pre>
<pre class="javascript code"><code>var c = paper.circle(10, 10, 10);
c.animate({cx: 20, r: 20}, 2000);
c.animate({cx: 20, r: 20}, 2000, "bounce");
c.animate({
"20%": {cx: 20, r: 20, easing: ">"},
"50%": {cx: 70, r: 120, callback: function () {…}},
"100%": {cx: 10, r: 10}
}, 2000);</code></pre>
<h3 id="animateWith">
animateWith
</h3>
......@@ -753,10 +765,13 @@ paper.circle(100, 100, 20).red();
<li>#•••••• — full length HTML colour: (“<samp>#000000</samp>”, “<samp>#bd2300</samp>”)</li>
<li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<samp>rgb(200,&nbsp;100,&nbsp;0)</samp>”)</li>
<li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<samp>rgb(100%,&nbsp;175%,&nbsp;0%)</samp>”)</li>
<li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<samp>rgb(200,&nbsp;100,&nbsp;0, .5)</samp>”)</li>
<li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<samp>rgb(100%,&nbsp;175%,&nbsp;0%, 50%)</samp>”)</li>
<li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<samp>hsb(0.5,&nbsp;0.25,&nbsp;1)</samp>”)</li>
<li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
<li>hsl(•••, •••, •••) — same as hsb</li>
<li>hsl(•••%, •••%, •••%) — same as hsb</li>
<li>hsl(•••, •••, •••) — almost the same as hsb, see <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV - Wikipedia, the free encyclopedia">Wikipedia page</a></li>
<li>hsl(•••%, •••%, •••%) — almost the same as hsb</li>
<li>Optionally for hsb and hsl you could specify hue as a degree: “<samp>hsl(240deg,&nbsp;1,&nbsp;.5)</samp>” or, if you want to go fancy, “<samp>hsl(240°,&nbsp;1,&nbsp;.5)</samp></li>
</ul>
<h4>Usage</h4>
<pre class="javascript code"><code>paper.circle(100, 100, 20).attr({
......@@ -819,6 +834,42 @@ element.hover(function (event) {
<p>
To unbind events use the same method names with “un” prefix, i.e. <samp>element.unclick(f);</samp>
</p>
<h3 id="drag-n-drop">
Drag ’n’ Drop
</h3>
<p>
To make element “draggable” you need to call method <code>drag</code> on element.
</p>
<h4>Parameters</h4>
<ol>
<li>onmove <em>function</em> event handler for moving</li>
<li>onstart <em>function</em> event handler for start</li>
<li>onend <em>function</em> event handler for end of the drag</li>
</ol>
<h4>Usage</h4>
<pre class="javascript code"><code>var c = R.circle(100, 100, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5
});
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
this.attr({cx: this.ox + dx, cy: this.oy + dy});
},
up = function () {
// restoring state
this.attr({opacity: .5});
};
c.drag(move, start, up);</code></pre>
<p>
To unbind drag use the <samp>undrag</samp> method.
</p>
</div>
<div id="column-2">
<h2>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment