Commit f7cbfd3d by Dmitry Baranovskiy

Split raphael into 3 development files. Added build process. Fixed…

Split raphael into 3 development files. Added build process. Fixed transformation issues, PNG opacity in IE, etc
parent 737137c3
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// ┌─────────────────────────────────────────────────────────────────────┐ \\
// │ Raphaël 2 - JavaScript Vector Library │ \\
// ├─────────────────────────────────────────────────────────────────────┤ \\
// │ SVG Module │ \\
// ├─────────────────────────────────────────────────────────────────────┤ \\
// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
// └─────────────────────────────────────────────────────────────────────┘ \\
window.Raphael.svg && function (R) {
var has = "hasOwnProperty",
Str = String,
toFloat = parseFloat,
toInt = parseInt,
math = Math,
mmax = math.max,
abs = math.abs,
separator = /[, ]+/,
E = "";
// SVG
var xlink = "http://www.w3.org/1999/xlink",
markers = {
block: "M5,0 0,2.5 5,5z",
classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
open: "M6,1 1,3.5 6,6",
oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
},
markerCounter = {};
R.toString = function () {
return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
};
var $ = function (el, attr) {
if (attr) {
if (typeof el == "string") {
el = $(el);
}
for (var key in attr) if (attr[has](key)) {
if (key.substring(0, 6) == "xlink:") {
el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
} else {
el.setAttribute(key, Str(attr[key]));
}
}
} else {
el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)");
}
return el;
},
gradients = {},
rgGrad = /^url\(#(.*)\)$/,
removeGradientFill = function (node, paper) {
var oid = node.getAttribute("fill");
oid = oid && oid.match(rgGrad);
if (oid && !--gradients[oid[1]]) {
delete gradients[oid[1]];
paper.defs.removeChild(g.doc.getElementById(oid[1]));
}
},
addGradientFill = function (element, gradient) {
var type = "linear",
id = element.id + gradient,
fx = .5, fy = .5,
o = element.node,
SVG = element.paper,
s = o.style,
el = R._g.doc.getElementById(id);
if (!el) {
gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {
type = "radial";
if (_fx && _fy) {
fx = toFloat(_fx);
fy = toFloat(_fy);
var dir = ((fy > .5) * 2 - 1);
pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&
(fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&
fy != .5 &&
(fy = fy.toFixed(5) - 1e-5 * dir);
}
return E;
});
gradient = gradient.split(/\s*\-\s*/);
if (type == "linear") {
var angle = gradient.shift();
angle = -toFloat(angle);
if (isNaN(angle)) {
return null;
}
var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],
max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
vector[2] *= max;
vector[3] *= max;
if (vector[2] < 0) {
vector[0] = -vector[2];
vector[2] = 0;
}
if (vector[3] < 0) {
vector[1] = -vector[3];
vector[3] = 0;
}
}
var dots = R._parseDots(gradient);
if (!dots) {
return null;
}
if (element.gradient) {
SVG.defs.removeChild(element.gradient);
delete element.gradient;
}
id = id.replace(/[\(\)\s,\xb0#]/g, "-");
el = $(type + "Gradient", {id: id});
element.gradient = el;
$(el, type == "radial" ? {
fx: fx,
fy: fy
} : {
x1: vector[0],
y1: vector[1],
x2: vector[2],
y2: vector[3],
gradientTransform: element.matrix.invert()
});
SVG.defs.appendChild(el);
for (var i = 0, ii = dots.length; i < ii; i++) {
el.appendChild($("stop", {
offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
"stop-color": dots[i].color || "#fff"
}));
}
}
$(o, {
fill: "url(#" + id + ")",
opacity: 1,
"fill-opacity": 1
});
s.fill = E;
s.opacity = 1;
s.fillOpacity = 1;
return 1;
},
updatePosition = function (o) {
var bbox = o.getBBox(1);
$(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
},
addArrow = function (o, value, isEnd) {
if (o.type == "path") {
var values = Str(value).toLowerCase().split("-"),
p = o.paper,
se = isEnd ? "end" : "start",
node = o.node,
attrs = o.attrs,
stroke = attrs["stroke-width"],
i = values.length,
type = "classic",
from,
to,
dx,
refX,
attr,
w = 3,
h = 3,
t = 5;
while (i--) {
switch (values[i]) {
case "block":
case "classic":
case "oval":
case "diamond":
case "open":
case "none":
type = values[i];
break;
case "wide": h = 5; break;
case "narrow": h = 2; break;
case "long": w = 5; break;
case "short": w = 2; break;
}
}
if (type == "open") {
w += 2;
h += 2;
t += 2;
dx = 1;
refX = isEnd ? 4 : 1;
attr = {
fill: "none",
stroke: attrs.stroke
};
} else {
refX = dx = w / 2;
attr = {
fill: attrs.stroke,
stroke: "none"
};
}
if (o._.arrows) {
if (isEnd) {
o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
} else {
o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
}
} else {
o._.arrows = {};
}
if (type != "none") {
var pathId = "raphael-marker-" + type,
markerId = "raphael-marker-" + se + type + w + h;
if (!g.doc.getElementById(pathId)) {
p.defs.appendChild($($("path"), {
"stroke-linecap": "round",
d: markers[type],
id: pathId
}));
markerCounter[pathId] = 1;
} else {
markerCounter[pathId]++;
}
var marker = g.doc.getElementById(markerId),
use;
if (!marker) {
marker = $($("marker"), {
id: markerId,
markerHeight: h,
markerWidth: w,
orient: "auto",
refX: refX,
refY: h / 2
});
use = $($("use"), {
"xlink:href": "#" + pathId,
transform: (isEnd ? " rotate(180 " + w / 2 + " " + h / 2 + ") " : S) + "scale(" + w / t + "," + h / t + ")",
"stroke-width": 1 / ((w / t + h / t) / 2)
});
marker.appendChild(use);
p.defs.appendChild(marker);
markerCounter[markerId] = 1;
} else {
markerCounter[markerId]++;
use = marker.getElementsByTagName("use")[0];
}
$(use, attr);
var delta = dx * (type != "diamond" && type != "oval");
if (isEnd) {
from = o._.arrows.startdx * stroke || 0;
to = R.getTotalLength(attrs.path) - delta * stroke;
} else {
from = delta * stroke;
to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
}
attr = {};
attr["marker-" + se] = "url(#" + markerId + ")";
if (to || from) {
attr.d = Raphael.getSubpath(attrs.path, from, to);
}
$(node, attr);
o._.arrows[se + "Path"] = pathId;
o._.arrows[se + "Marker"] = markerId;
o._.arrows[se + "dx"] = delta;
o._.arrows[se + "Type"] = type;
o._.arrows[se + "String"] = value;
} else {
if (isEnd) {
from = o._.arrows.startdx * stroke || 0;
to = R.getTotalLength(attrs.path) - from;
} else {
from = 0;
to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
}
o._.arrows[se + "Path"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)});
delete o._.arrows[se + "Path"];
delete o._.arrows[se + "Marker"];
delete o._.arrows[se + "dx"];
delete o._.arrows[se + "Type"];
delete o._.arrows[se + "String"];
}
for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {
var item = g.doc.getElementById(attr);
item && item.parentNode.removeChild(item);
}
}
},
setFillAndStroke = function (o, params) {
var dasharray = {
"": [0],
"none": [0],
"-": [3, 1],
".": [1, 1],
"-.": [3, 1, 1, 1],
"-..": [3, 1, 1, 1, 1, 1],
". ": [1, 3],
"- ": [4, 3],
"--": [8, 3],
"- .": [4, 3, 1, 3],
"--.": [8, 3, 1, 3],
"--..": [8, 3, 1, 3, 1, 3]
},
node = o.node,
attrs = o.attrs,
addDashes = function (o, value) {
value = dasharray[lowerCase.call(value)];
if (value) {
var width = o.attrs["stroke-width"] || "1",
butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
dashes = [],
i = value.length;
while (i--) {
dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
}
$(node, {"stroke-dasharray": dashes.join(",")});
}
};
for (var att in params) {
if (params[has](att)) {
if (!R._availableAttrs[has](att)) {
continue;
}
var value = params[att];
attrs[att] = value;
switch (att) {
case "blur":
o.blur(value);
break;
case "href":
case "title":
case "target":
var pn = node.parentNode;
if (lowerCase.call(pn.tagName) != "a") {
var hl = $("a");
pn.insertBefore(hl, node);
hl.appendChild(node);
pn = hl;
}
if (att == "target" && value == "blank") {
pn.setAttributeNS(xlink, "show", "new");
} else {
pn.setAttributeNS(xlink, att, value);
}
break;
case "cursor":
node.style.cursor = value;
break;
case "transform":
o.transform(value);
break;
case "arrow-start":
addArrow(o, value);
break;
case "arrow-end":
addArrow(o, value, 1);
break;
case "clip-rect":
var rect = Str(value).split(separator);
if (rect.length == 4) {
o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);
var el = $("clipPath"),
rc = $("rect");
el.id = R._createUUID();
$(rc, {
x: rect[0],
y: rect[1],
width: rect[2],
height: rect[3]
});
el.appendChild(rc);
o.paper.defs.appendChild(el);
$(node, {"clip-path": "url(#" + el.id + ")"});
o.clip = rc;
}
if (!value) {
var clip = g.doc.getElementById(node.getAttribute("clip-path").replace(/(^url\(#|\)$)/g, E));
clip && clip.parentNode.removeChild(clip);
$(node, {"clip-path": E});
delete o.clip;
}
break;
case "path":
if (o.type == "path") {
$(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"});
o._.dirty = 1;
if (o._.arrows) {
"startString" in o._.arrows && addArrow(o, o._.arrows.startString);
"endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
}
}
break;
case "width":
node.setAttribute(att, value);
o._.dirty = 1;
if (attrs.fx) {
att = "x";
value = attrs.x;
} else {
break;
}
case "x":
if (attrs.fx) {
value = -attrs.x - (attrs.width || 0);
}
case "rx":
if (att == "rx" && o.type == "rect") {
break;
}
case "cx":
node.setAttribute(att, value);
o.pattern && updatePosition(o);
o._.dirty = 1;
break;
case "height":
node.setAttribute(att, value);
o._.dirty = 1;
if (attrs.fy) {
att = "y";
value = attrs.y;
} else {
break;
}
case "y":
if (attrs.fy) {
value = -attrs.y - (attrs.height || 0);
}
case "ry":
if (att == "ry" && o.type == "rect") {
break;
}
case "cy":
node.setAttribute(att, value);
o.pattern && updatePosition(o);
o._.dirty = 1;
break;
case "r":
if (o.type == "rect") {
$(node, {rx: value, ry: value});
} else {
node.setAttribute(att, value);
}
o._.dirty = 1;
break;
case "src":
if (o.type == "image") {
node.setAttributeNS(xlink, "href", value);
}
break;
case "stroke-width":
if (o._.sx != 1 || o._.sy != 1) {
value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;
}
if (o.paper._vbSize) {
value *= o.paper._vbSize;
}
node.setAttribute(att, value);
if (attrs["stroke-dasharray"]) {
addDashes(o, attrs["stroke-dasharray"]);
}
if (o._.arrows) {
"startString" in o._.arrows && addArrow(o, o._.arrows.startString);
"endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
}
break;
case "stroke-dasharray":
addDashes(o, value);
break;
case "fill":
var isURL = Str(value).match(R._ISURL);
if (isURL) {
el = $("pattern");
var ig = $("image");
el.id = R._createUUID();
$(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});
$(ig, {x: 0, y: 0, "xlink:href": isURL[1]});
el.appendChild(ig);
(function (el) {
R._preload(isURL[1], function () {
var w = this.offsetWidth,
h = this.offsetHeight;
$(el, {width: w, height: h});
$(ig, {width: w, height: h});
o.paper.safari();
});
})(el);
o.paper.defs.appendChild(el);
node.style.fill = "url(#" + el.id + ")";
$(node, {fill: "url(#" + el.id + ")"});
o.pattern = el;
o.pattern && updatePosition(o);
break;
}
var clr = R.getRGB(value);
if (!clr.error) {
delete params.gradient;
delete attrs.gradient;
!R.is(attrs.opacity, "undefined") &&
R.is(params.opacity, "undefined") &&
$(node, {opacity: attrs.opacity});
!R.is(attrs["fill-opacity"], "undefined") &&
R.is(params["fill-opacity"], "undefined") &&
$(node, {"fill-opacity": attrs["fill-opacity"]});
} else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) {
if ("opacity" in attrs || "fill-opacity" in attrs) {
var gradient = g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
if (gradient) {
var stops = gradient.getElementsByTagName("stop");
$(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)});
}
}
attrs.gradient = value;
attrs.fill = "none";
break;
}
clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
case "stroke":
clr = R.getRGB(value);
node.setAttribute(att, clr.hex);
att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
if (att == "stroke" && o._.arrows) {
"startString" in o._.arrows && addArrow(o, o._.arrows.startString);
"endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
}
break;
case "gradient":
(o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value);
break;
case "opacity":
if (attrs.gradient && !attrs[has]("stroke-opacity")) {
$(node, {"stroke-opacity": value > 1 ? value / 100 : value});
}
// fall
case "fill-opacity":
if (attrs.gradient) {
gradient = g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
if (gradient) {
stops = gradient.getElementsByTagName("stop");
$(stops[stops.length - 1], {"stop-opacity": value});
}
break;
}
default:
att == "font-size" && (value = toInt(value, 10) + "px");
var cssrule = att.replace(/(\-.)/g, function (w) {
return w.substring(1).toUpperCase();
});
node.style[cssrule] = value;
o._.dirty = 1;
node.setAttribute(att, value);
break;
}
}
}
tuneText(o, params);
},
leading = 1.2,
tuneText = function (el, params) {
if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {
return;
}
var a = el.attrs,
node = el.node,
fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;
if (params[has]("text")) {
a.text = params.text;
while (node.firstChild) {
node.removeChild(node.firstChild);
}
var texts = Str(params.text).split("\n"),
tspans = [],
tspan;
for (var i = 0, ii = texts.length; i < ii; i++) {
tspan = $("tspan");
i && $(tspan, {dy: fontSize * leading, x: a.x});
tspan.appendChild(R._g.doc.createTextNode(texts[i]));
node.appendChild(tspan);
tspans[i] = tspan;
}
} else {
tspans = node.getElementsByTagName("tspan");
for (i = 0, ii = tspans.length; i < ii; i++) if (i) {
$(tspans[i], {dy: fontSize * leading, x: a.x});
} else {
$(tspans[0], {dy: 0});
}
}
$(node, {x: a.x, y: a.y});
el._.dirty = 1;
var bb = el._getBBox(),
dif = a.y - (bb.y + bb.height / 2);
dif && R.is(dif, "finite") && $(tspans[0], {dy: dif});
},
Element = function (node, svg) {
var X = 0,
Y = 0;
/*\
* Element.node
[ property (object) ]
**
* Gives you a reference to the DOM object, so you can assign event handlers or just mess around.
> Usage
| // draw a circle at coordinate 10,10 with radius of 10
| var c = paper.circle(10, 10, 10);
| c.node.onclick = function () {
| c.attr("fill", "red");
| };
\*/
this[0] = this.node = node;
/*\
* Element.raphael
[ property (object) ]
**
* Internal reference to @Raphael object. In case it is not available.
> Usage
| Raphael.el.red = function () {
| var hsb = this.paper.raphael.rgb2hsb(this.attr("fill"));
| hsb.h = 1;
| this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex});
| }
\*/
node.raphael = true;
/*\
* Element.id
[ property (number) ]
**
* Unique id of the element. Especially usesful when you want to listen to events of the element,
* because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method.
\*/
this.id = R._oid++;
node.raphaelid = this.id;
this.matrix = R.matrix();
this.realPath = null;
/*\
* Element.paper
[ property (object) ]
**
* Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions.
> Usage
| Raphael.el.cross = function () {
| this.attr({fill: "red"});
| this.paper.path("M10,10L50,50M50,10L10,50")
| .attr({stroke: "red"});
| }
\*/
this.paper = svg;
this.attrs = this.attrs || {};
this._ = {
transform: [],
sx: 1,
sy: 1,
deg: 0,
dx: 0,
dy: 0,
dirty: 1
};
!svg.bottom && (svg.bottom = this);
/*\
* Element.prev
[ property (object) ]
**
* Reference to the previous element in the hierarchy.
\*/
this.prev = svg.top;
svg.top && (svg.top.next = this);
svg.top = this;
/*\
* Element.next
[ property (object) ]
**
* Reference to the next element in the hierarchy.
\*/
this.next = null;
},
elproto = R.el;
Element.prototype = elproto;
elproto.constructor = Element;
R._engine.path = function (pathString, SVG) {
var el = $("path");
SVG.canvas && SVG.canvas.appendChild(el);
var p = new Element(el, SVG);
p.type = "path";
setFillAndStroke(p, {fill: "none", stroke: "#000", path: pathString});
return p;
};
/*\
* Element.rotate
[ method ]
**
* Adds rotation by given angle around given point to the list of
* transformations of the element.
> Parameters
- deg (number) angle in degrees
- cx (number) #optional x coordinate of the centre of rotation
- cy (number) #optional y coordinate of the centre of rotation
* If cx & cy aren’t specified centre of the shape is used as a point of rotation.
= (object) @Element
\*/
elproto.rotate = function (deg, cx, cy) {
if (this.removed) {
return this;
}
deg = Str(deg).split(separator);
if (deg.length - 1) {
cx = toFloat(deg[1]);
cy = toFloat(deg[2]);
}
deg = toFloat(deg[0]);
(cy == null) && (cx = cy);
if (cx == null || cy == null) {
var bbox = this.getBBox(1);
cx = bbox.x + bbox.width / 2;
cy = bbox.y + bbox.height / 2;
}
this.transform(this._.transform.concat([["r", deg, cx, cy]]));
return this;
};
/*\
* Element.scale
[ method ]
**
* Adds scale by given amount relative to given point to the list of
* transformations of the element.
> Parameters
- sx (number) horisontal scale amount
- sy (number) vertical scale amount
- cx (number) #optional x coordinate of the centre of scale
- cy (number) #optional y coordinate of the centre of scale
* If cx & cy aren’t specified centre of the shape is used instead.
= (object) @Element
\*/
elproto.scale = function (sx, sy, cx, cy) {
if (this.removed) {
return this;
}
sx = Str(sx).split(separator);
if (sx.length - 1) {
sy = toFloat(sx[1]);
cx = toFloat(sx[2]);
cy = toFloat(sx[3]);
}
sx = toFloat(sx[0]);
(sy == null) && (sy = sx);
(cy == null) && (cx = cy);
if (cx == null || cy == null) {
var bbox = this.getBBox(1);
}
cx = cx == null ? bbox.x + bbox.width / 2 : cx;
cy = cy == null ? bbox.y + bbox.height / 2 : cy;
this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
return this;
};
/*\
* Element.translate
[ method ]
**
* Adds translation by given amount to the list of transformations of the element.
> Parameters
- dx (number) horisontal shift
- dy (number) vertical shift
= (object) @Element
\*/
elproto.translate = function (dx, dy) {
if (this.removed) {
return this;
}
dx = Str(dx).split(separator);
if (dx.length - 1) {
dy = toFloat(dx[1]);
}
dx = toFloat(dx[0]) || 0;
dy = +dy || 0;
this.transform(this._.transform.concat([["t", dx, dy]]));
return this;
};
/*\
* Element.transform
[ method ]
**
* Adds transformation to the element which is separate to other attributes,
* i.e. translation doesn’t change `x` or `y` of the rectange. The format
* of transformation string is similar to the path string syntax:
| "t100,100r30,100,100s2,2,100,100r45s1.5"
* Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for
* scale and `m` is for matrix.
*
* So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100;
* rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin
* coordinates as optional parameters, the default is the centre point of the element.
* Matrix accepts six parameters.
> Usage
| var el = paper.rect(10, 20, 300, 200);
| // translate 100, 100, rotate 45°, translate -100, 0
| el.transform("t100,100r45t-100,0");
| // if you want you can append or prepend transformations
| el.transform("...t50,50");
| el.transform("s2...");
| // or even wrap
| el.transform("t50,50...t-50-50");
| // to reset transformation call method with empty string
| el.transform("");
| // to get current value call it without parameters
| console.log(el.transform());
> Parameters
- tstr (string) #optional transformation string
* If tstr isn’t specified
= (string) current transformation string
* else
= (object) @Element
\*/
elproto.transform = function (tstr) {
var _ = this._;
if (tstr == null) {
return _.transform;
}
R._extractTransform(this, tstr);
this.clip && $(this.clip, {transform: this.matrix.invert()});
this.pattern && updatePosition(this);
this.node && $(this.node, {transform: this.matrix});
if (_.sx != 1 || _.sy != 1) {
var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1;
this.attr({"stroke-width": sw});
}
return this;
};
/*\
* Element.hide
[ method ]
**
* Makes element invisible. See @Element.show.
= (object) @Element
\*/
elproto.hide = function () {
!this.removed && this.paper.safari(this.node.style.display = "none");
return this;
};
/*\
* Element.show
[ method ]
**
* Makes element visible. See @Element.hide.
= (object) @Element
\*/
elproto.show = function () {
!this.removed && this.paper.safari(this.node.style.display = "");
return this;
};
/*\
* Element.remove
[ method ]
**
* Removes element form the paper.
\*/
elproto.remove = function () {
if (this.removed) {
return;
}
eve.unbind("*.*." + this.id);
R._tear(this, this.paper);
this.node.parentNode.removeChild(this.node);
for (var i in this) {
delete this[i];
}
this.removed = true;
};
elproto._getBBox = function () {
if (this.node.style.display == "none") {
this.show();
var hide = true;
}
var bbox = {};
try {
bbox = this.node.getBBox();
} catch(e) {
// Firefox 3.0.x plays badly here
} finally {
bbox = bbox || {};
}
hide && this.hide();
return bbox;
};
/*\
* Element.attr
[ method ]
**
* Sets the attributes of the element.
> Parameters
- attrName (string) attribute’s name
- value (string) value
* or
- params (object) object of name/value pairs
* or
- attrName (string) attribute’s name
* or
- attrNames (array) in this case method returns array of current values for given attribute names
= (object) @Element if attrsName & value or params are passed in.
= (...) value of the attribute if only attrsName is passed in.
= (array) array of values of the attribute if attrsNames is passed in.
= (object) object of attributes if nothing is passed in.
> Possible parameters
# <p>Please refer to the <a href="http://www.w3.org/TR/SVG/" title="The W3C Recommendation for the SVG language describes these properties in detail.">SVG specification</a> for an explanation of these parameters.</p>
o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `midium`, length: `long`, `short`, `midium`.
o clip-rect (string) comma or space separated values: x, y, width and height
o cursor (string) CSS type of the cursor
o cx (number)
o cy (number)
o fill (string) colour, gradient or image
o fill-opacity (number)
o font (string)
o font-family (string)
o font-size (number) font size in pixels
o font-weight (string)
o height (number)
o href (string) URL, if specified element behaves as hyperlink
o opacity (number)
o path (string) SVG path string format
o r (number)
o rx (number)
o ry (number)
o src (string) image URL, only works for @Element.image element
o stroke (string) stroke colour
o stroke-dasharray (string) [“”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”]
o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”]
o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”]
o stroke-miterlimit (number)
o stroke-opacity (number)
o stroke-width (number) stroke width in pixels, default is '1'
o target (string) used with href
o text (string) contents of the text element. Use `\n` for multiline text
o text-anchor (string) [“`start`”, “`middle`”, “`end`”], default is “`middle`”
o title (string) will create tooltip with a given text
o transform (string) see @Element.transform
o width (number)
o x (number)
o y (number)
> Gradients
* Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90°
* gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black.
*
* radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” –
* gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point
* at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses.
> Path String
# <p>Please refer to <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 documentation regarding path string</a>. Raphaël fully supports it.</p>
> Colour Parsing
# <ul>
# <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>
# <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>
# <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>
# <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>
# <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>
# <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(200,&nbsp;100,&nbsp;0, .5)</code>”)</li>
# <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%,&nbsp;175%,&nbsp;0%, 50%)</code>”)</li>
# <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>
# <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
# <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</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(•••%, •••%, •••%) — same as above, but in %</li>
# <li>hsla(•••, •••, •••) — same as above, but with opacity</li>
# <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg,&nbsp;1,&nbsp;.5)</code>” or, if you want to go fancy, “<code>hsl(240°,&nbsp;1,&nbsp;.5)</code>”</li>
# </ul>
\*/
elproto.attr = function (name, value) {
if (this.removed) {
return this;
}
if (name == null) {
var res = {};
for (var a in this.attrs) if (this.attrs[has](a)) {
res[a] = this.attrs[a];
}
res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
res.transform = this._.transform;
return res;
}
if (value == null && R.is(name, "string")) {
if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) {
return this.attrs.gradient;
}
if (name == "transform") {
return this._.transform;
}
var names = name.split(separator),
out = {};
for (var i = 0, ii = names.length; i < ii; i++) {
name = names[i];
if (name in this.attrs) {
out[name] = this.attrs[name];
} else if (R.is(this.paper.customAttributes[name], "function")) {
out[name] = this.paper.customAttributes[name].def;
} else {
out[name] = R._availableAttrs[name];
}
}
return ii - 1 ? out : out[names[0]];
}
if (value == null && R.is(name, "array")) {
out = {};
for (i = 0, ii = name.length; i < ii; i++) {
out[name[i]] = this.attr(name[i]);
}
return out;
}
if (value != null) {
var params = {};
params[name] = value;
} else if (name != null && R.is(name, "object")) {
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.toFront
[ method ]
**
* Moves the element so it is the closest to the viewer’s eyes, on top of other elements.
= (object) @Element
\*/
elproto.toFront = function () {
if (this.removed) {
return this;
}
this.node.parentNode.appendChild(this.node);
var svg = this.paper;
svg.top != this && R._tofront(this, svg);
return this;
};
/*\
* Element.toBack
[ method ]
**
* Moves the element so it is the furthest from the viewer’s eyes, behind other elements.
= (object) @Element
\*/
elproto.toBack = function () {
if (this.removed) {
return this;
}
if (this.node.parentNode.firstChild != this.node) {
this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
R._toback(this, this.paper);
var svg = this.paper;
}
return this;
};
/*\
* Element.insertAfter
[ method ]
**
* Inserts current object after the given one.
= (object) @Element
\*/
elproto.insertAfter = function (element) {
if (this.removed) {
return this;
}
var node = element.node || element[element.length - 1].node;
if (node.nextSibling) {
node.parentNode.insertBefore(this.node, node.nextSibling);
} else {
node.parentNode.appendChild(this.node);
}
R._insertafter(this, element, this.paper);
return this;
};
/*\
* Element.insertBefore
[ method ]
**
* Inserts current object before the given one.
= (object) @Element
\*/
elproto.insertBefore = function (element) {
if (this.removed) {
return this;
}
var node = element.node || element[0].node;
node.parentNode.insertBefore(this.node, node);
R._insertbefore(this, element, this.paper);
return this;
};
elproto.blur = function (size) {
// Experimental. No Safari support. Use it on your own risk.
var t = this;
if (+size !== 0) {
var fltr = $("filter"),
blur = $("feGaussianBlur");
t.attrs.blur = size;
fltr.id = R._createUUID();
$(blur, {stdDeviation: +size || 1.5});
fltr.appendChild(blur);
t.paper.defs.appendChild(fltr);
t._blur = fltr;
$(t.node, {filter: "url(#" + fltr.id + ")"});
} else {
if (t._blur) {
t._blur.parentNode.removeChild(t._blur);
delete t._blur;
delete t.attrs.blur;
}
t.node.removeAttribute("filter");
}
};
R._engine.circle = function (svg, x, y, r) {
var el = $("circle");
svg.canvas && svg.canvas.appendChild(el);
var res = new Element(el, svg);
res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};
res.type = "circle";
$(el, res.attrs);
return res;
};
R._engine.rect = function (svg, x, y, w, h, r) {
var el = $("rect");
svg.canvas && svg.canvas.appendChild(el);
var res = new Element(el, svg);
res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};
res.type = "rect";
$(el, res.attrs);
return res;
};
R._engine.ellipse = function (svg, x, y, rx, ry) {
var el = $("ellipse");
svg.canvas && svg.canvas.appendChild(el);
var res = new Element(el, svg);
res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};
res.type = "ellipse";
$(el, res.attrs);
return res;
};
R._engine.image = function (svg, src, x, y, w, h) {
var el = $("image");
$(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
el.setAttributeNS(xlink, "href", src);
svg.canvas && svg.canvas.appendChild(el);
var res = new Element(el, svg);
res.attrs = {x: x, y: y, width: w, height: h, src: src};
res.type = "image";
return res;
};
R._engine.text = function (svg, x, y, text) {
var el = $("text");
// $(el, {x: x, y: y, "text-anchor": "middle"});
svg.canvas && svg.canvas.appendChild(el);
var res = new Element(el, svg);
res.attrs = {
x: x,
y: y,
"text-anchor": "middle",
text: text,
font: R._availableAttrs.font,
stroke: "none",
fill: "#000"
};
res.type = "text";
setFillAndStroke(res, res.attrs);
return res;
};
R._engine.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);
if (this._viewBox) {
this.setViewBox.apply(this, this._viewBox);
}
return this;
};
R._engine.create = function () {
var con = R._getContainer.apply(0, arguments),
container = con && con.container,
x = con.x,
y = con.y,
width = con.width,
height = con.height;
if (!container) {
throw new Error("SVG container not found.");
}
var cnvs = $("svg"),
css = "overflow:hidden;",
isFloating;
x = x || 0;
y = y || 0;
width = width || 512;
height = height || 342;
$(cnvs, {
height: height,
version: 1.1,
width: width,
xmlns: "http://www.w3.org/2000/svg"
});
if (container == 1) {
cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px";
R._g.doc.body.appendChild(cnvs);
isFloating = 1;
} else {
cnvs.style.cssText = css + "position:relative";
if (container.firstChild) {
container.insertBefore(cnvs, container.firstChild);
} else {
container.appendChild(cnvs);
}
}
container = new R._Paper;
container.width = width;
container.height = height;
container.canvas = cnvs;
// plugins.call(container, container, R.fn);
container.clear();
container._left = container._top = 0;
isFloating && (container.renderfix = function () {});
container.renderfix();
return container;
};
R._engine.setViewBox = function (x, y, w, h, fit) {
eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]);
var size = mmax(w / this.width, h / this.height),
top = this.top,
aspectRatio = fit ? "meet" : "xMinYMin",
vb,
sw;
if (x == null) {
if (this._vbSize) {
size = 1;
}
delete this._vbSize;
vb = "0 0 " + this.width + S + this.height;
} else {
this._vbSize = size;
vb = x + S + y + S + w + S + h;
}
$(this.canvas, {
viewBox: vb,
preserveAspectRatio: aspectRatio
});
while (size && top) {
sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1;
top.attr({"stroke-width": sw});
top._.dirty = 1;
top._.dirtyT = 1;
top = top.prev;
}
this._viewBox = [x, y, w, h, !!fit];
return this;
};
/*\
* Paper.renderfix
[ method ]
**
* Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependant
* on other elements after reflow it could shift half pixel which cause for lines to lost their crispness.
* This method fixes the issue.
**
Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method.
\*/
R.prototype.renderfix = function () {
var cnvs = this.canvas,
s = cnvs.style,
pos = cnvs.getScreenCTM(),
left = -pos.e % 1,
top = -pos.f % 1;
if (left || top) {
if (left) {
this._left = (this._left + left) % 1;
s.left = this._left + "px";
}
if (top) {
this._top = (this._top + top) % 1;
s.top = this._top + "px";
}
}
};
/*\
* Paper.clear
[ method ]
**
* Clears the paper, i.e. removes all the elements.
\*/
R.prototype.clear = function () {
R.eve("clear", this);
var c = this.canvas;
while (c.firstChild) {
c.removeChild(c.firstChild);
}
this.bottom = this.top = null;
(this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version));
c.appendChild(this.desc);
c.appendChild(this.defs = $("defs"));
};
/*\
* Paper.remove
[ method ]
**
* Removes the paper from the DOM.
\*/
R.prototype.remove = function () {
eve("remove", this);
this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
for (var i in this) {
this[i] = removed(i);
}
};
var setproto = R.st;
for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
setproto[method] = (function (methodname) {
return function () {
var arg = arguments;
return this.forEach(function (el) {
el[methodname].apply(el, arg);
});
};
})(method);
}
}(window.Raphael);
\ No newline at end of file
// ┌─────────────────────────────────────────────────────────────────────┐ \\
// │ Raphaël 2 - JavaScript Vector Library │ \\
// ├─────────────────────────────────────────────────────────────────────┤ \\
// │ VML Module │ \\
// ├─────────────────────────────────────────────────────────────────────┤ \\
// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
// └─────────────────────────────────────────────────────────────────────┘ \\
window.Raphael.vml && function (R) {
var has = "hasOwnProperty",
Str = String,
toFloat = parseFloat,
math = Math,
round = math.round,
mmax = math.max,
mmin = math.min,
abs = math.abs,
fillString = "fill",
separator = /[, ]+/,
S = " ",
E = "";
// 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,
cssDot = "position:absolute;left:0;top:0;width:1px;height:1px",
zoom = 21600,
pathTypes = {path: 1, rect: 1},
ovalTypes = {circle: 1, ellipse: 1},
path2vml = function (path) {
var total = /[ahqstv]/ig,
command = R._pathToAbsolute;
Str(path).match(total) && (command = path2curve);
total = /[clmz]/g;
if (command == R._pathToAbsolute && !Str(path).match(total)) {
var res = Str(path).replace(bites, function (all, command, args) {
var vals = [],
isMove = lowerCase.call(command) == "m",
res = map[command];
args.replace(val, function (value) {
if (isMove && vals.length == 2) {
res += vals + map[command == "m" ? "l" : "L"];
vals = [];
}
vals.push(round(value * zoom));
});
return res + vals;
});
return res;
}
var pa = command(path), p, r;
res = [];
for (var i = 0, ii = pa.length; i < ii; i++) {
p = pa[i];
r = pa[i][0].toLowerCase();
r == "z" && (r = "x");
for (var j = 1, jj = p.length; j < jj; j++) {
r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
}
res.push(r);
}
return res.join(S);
},
compensation = function (deg, dx, dy) {
var m = R.matrix();
m.rotate(-deg, .5, .5);
return {
dx: m.x(dx, dy),
dy: m.y(dx, dy)
};
},
setCoords = function (p, sx, sy, dx, dy, deg) {
var _ = p._,
m = p.matrix,
fillpos = _.fillpos,
o = p.node,
s = o.style,
y = 1,
flip = "",
dxdy,
kx = zoom / sx,
ky = zoom / sy;
s.visibility = "hidden";
if (!sx || !sy) {
return;
}
o.coordsize = abs(kx) + S + abs(ky);
s.rotation = deg * (sx * sy < 0 ? -1 : 1);
if (deg) {
var c = compensation(deg, dx, dy);
dx = c.dx;
dy = c.dy;
}
sx < 0 && (flip += "x");
sy < 0 && (flip += " y") && (y = -1);
s.flip = flip;
o.coordorigin = (dx * -kx) + S + (dy * -ky);
if (fillpos || _.fillsize) {
var fill = o.getElementsByTagName(fillString);
fill = fill && fill[0];
o.removeChild(fill);
if (fillpos) {
c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));
fill.position = c.dx * y + S + c.dy * y;
}
if (_.fillsize) {
fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);
}
o.appendChild(fill);
}
s.visibility = "visible";
};
R.toString = function () {
return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
};
addArrow = function (o, value, isEnd) {
var values = Str(value).toLowerCase().split("-"),
se = isEnd ? "end" : "start",
i = values.length,
type = "classic",
w = "medium",
h = "medium";
while (i--) {
switch (values[i]) {
case "block":
case "classic":
case "oval":
case "diamond":
case "open":
case "none":
type = values[i];
break;
case "wide":
case "narrow": h = values[i]; break;
case "long":
case "short": w = values[i]; break;
}
}
var stroke = o.node.getElementsByTagName("stroke")[0];
stroke[se + "arrow"] = type;
stroke[se + "arrowlength"] = w;
stroke[se + "arrowwidth"] = h;
};
setFillAndStroke = function (o, params) {
// o.paper.canvas.style.display = "none";
o.attrs = o.attrs || {};
var node = o.node,
a = o.attrs,
s = node.style,
xy,
newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),
isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),
res = o;
for (var par in params) if (params[has](par)) {
a[par] = params[par];
}
if (newpath) {
a.path = R._getPath[o.type](o);
o._.dirty = 1;
}
params.href && (node.href = params.href);
params.title && (node.title = params.title);
params.target && (node.target = params.target);
params.cursor && (s.cursor = params.cursor);
"blur" in params && o.blur(params.blur);
"transform" in params && o.transform(params.transform);
if (params.path && o.type == "path" || newpath) {
node.path = path2vml(a.path);
}
if (isOval) {
var cx = a.cx,
cy = a.cy,
rx = a.rx || a.r || 0,
ry = a.ry || a.r || 0;
node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));
}
if ("clip-rect" in params) {
var rect = Str(params["clip-rect"]).split(separator);
if (rect.length == 4) {
rect[2] = +rect[2] + (+rect[0]);
rect[3] = +rect[3] + (+rect[1]);
var div = node.clipRect || g.doc.createElement("div"),
dstyle = div.style,
group = node.parentNode;
dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
if (!node.clipRect) {
dstyle.position = "absolute";
dstyle.top = 0;
dstyle.left = 0;
dstyle.width = o.paper.width + "px";
dstyle.height = o.paper.height + "px";
group.parentNode.insertBefore(div, group);
div.appendChild(group);
node.clipRect = div;
}
}
if (!params["clip-rect"]) {
node.clipRect && (node.clipRect.style.clip = E);
}
}
if (o.textpath) {
var textpathStyle = o.textpath.style;
params.font && (textpathStyle.font = params.font);
params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"');
params["font-size"] && (textpathStyle.fontSize = params["font-size"]);
params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]);
params["font-style"] && (textpathStyle.fontStyle = params["font-style"]);
}
if ("arrow-start" in params) {
addArrow(res, params["arrow-start"]);
}
if ("arrow-end" in params) {
addArrow(res, params["arrow-end"], 1);
}
if (params.opacity != null ||
params["stroke-width"] != null ||
params.fill != null ||
params.src != null ||
params.stroke != null ||
params["stroke-width"] != null ||
params["stroke-opacity"] != null ||
params["fill-opacity"] != null ||
params["stroke-dasharray"] != null ||
params["stroke-miterlimit"] != null ||
params["stroke-linejoin"] != null ||
params["stroke-linecap"] != null) {
var fill = node.getElementsByTagName(fillString),
newfill = false;
fill = fill && fill[0];
!fill && (newfill = fill = createNode(fillString));
if (o.type == "image" && params.src) {
fill.src = params.src;
}
params.fill && (fill.on = true);
if (fill.on == null || params.fill == "none" || params.fill === null) {
fill.on = false;
}
if (fill.on && params.fill) {
var isURL = Str(params.fill).match(R._ISURL);
if (isURL) {
fill.parentNode == node && node.removeChild(fill);
fill.rotate = true;
fill.src = isURL[1];
fill.type = "tile";
var bbox = o.getBBox(1);
fill.position = bbox.x + S + bbox.y;
o._.fillpos = [bbox.x, bbox.y];
R._preload(isURL[1], function () {
o._.fillsize = [this.offsetWidth, this.offsetHeight];
});
} else {
fill.color = R.getRGB(params.fill).hex;
fill.src = E;
fill.type = "solid";
if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) {
a.fill = "none";
a.gradient = params.fill;
fill.rotate = false;
}
}
}
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 = mmin(mmax(opacity, 0), 1);
fill.opacity = opacity;
if (fill.src) {
fill.color = "none";
}
}
node.appendChild(fill);
var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
newstroke = false;
!stroke && (newstroke = stroke = createNode("stroke"));
if ((params.stroke && params.stroke != "none") ||
params["stroke-width"] ||
params["stroke-opacity"] != null ||
params["stroke-dasharray"] ||
params["stroke-miterlimit"] ||
params["stroke-linejoin"] ||
params["stroke-linecap"]) {
stroke.on = true;
}
(params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
var strokeColor = R.getRGB(params.stroke);
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 = 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);
stroke.opacity = opacity;
params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
stroke.miterlimit = params["stroke-miterlimit"] || 8;
params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
if (params["stroke-dasharray"]) {
var dasharray = {
"-": "shortdash",
".": "shortdot",
"-.": "shortdashdot",
"-..": "shortdashdotdot",
". ": "dot",
"- ": "dash",
"--": "longdash",
"- .": "dashdot",
"--.": "longdashdot",
"--..": "longdashdotdot"
};
stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
}
newstroke && node.appendChild(stroke);
}
if (res.type == "text") {
res.paper.canvas.style.display = E;
var span = res.paper.span,
m = 100,
fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/);
s = span.style;
a.font && (s.font = a.font);
a["font-family"] && (s.fontFamily = a["font-family"]);
a["font-weight"] && (s.fontWeight = a["font-weight"]);
a["font-style"] && (s.fontStyle = a["font-style"]);
fontSize = toFloat(fontSize ? fontSize[0] : a["font-size"]);
s.fontSize = fontSize * m + "px";
res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>"));
var brect = span.getBoundingClientRect();
res.W = a.w = (brect.right - brect.left) / m;
res.H = a.h = (brect.bottom - brect.top) / m;
res.paper.canvas.style.display = "none";
res.X = a.x;
res.Y = a.y + res.H / 2;
("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));
var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {
res._.dirty = 1;
break;
}
// text-anchor emulation
switch (a["text-anchor"]) {
case "start":
res.textpath.style["v-text-align"] = "left";
res.bbx = res.W / 2;
break;
case "end":
res.textpath.style["v-text-align"] = "right";
res.bbx = -res.W / 2;
break;
default:
res.textpath.style["v-text-align"] = "center";
res.bbx = 0;
break;
}
res.textpath.style["v-text-kern"] = true;
}
// res.paper.canvas.style.display = E;
};
addGradientFill = function (o, gradient, fill) {
o.attrs = o.attrs || {};
var attrs = o.attrs,
opacity,
oindex,
type = "linear",
fxfy = ".5 .5";
o.attrs.gradient = gradient;
gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {
type = "radial";
if (fx && fy) {
fx = toFloat(fx);
fy = toFloat(fy);
pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
fxfy = fx + S + fy;
}
return E;
});
gradient = gradient.split(/\s*\-\s*/);
if (type == "linear") {
var angle = gradient.shift();
angle = -toFloat(angle);
if (isNaN(angle)) {
return null;
}
}
var dots = R._parseDots(gradient);
if (!dots) {
return null;
}
o = o.shape || o.node;
if (dots.length) {
o.removeChild(fill);
fill.on = true;
fill.method = "none";
fill.color = dots[0].color;
fill.color2 = dots[dots.length - 1].color;
var clrs = [];
for (var i = 0, ii = dots.length; i < ii; i++) {
dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);
}
fill.colors = clrs.length ? clrs.join() : "0% " + fill.color;
if (type == "radial") {
fill.type = "gradientTitle";
fill.focus = "100%";
fill.focussize = "0 0";
fill.focusposition = fxfy;
fill.angle = 0;
} else {
// fill.rotate= true;
fill.type = "gradient";
fill.angle = (270 - angle) % 360;
}
o.appendChild(fill);
}
return 1;
};
Element = function (node, vml) {
this[0] = this.node = node;
node.raphael = true;
this.id = R._oid++;
node.raphaelid = this.id;
this.X = 0;
this.Y = 0;
this.attrs = {};
this.paper = vml;
this.matrix = R.matrix();
this._ = {
transform: [],
sx: 1,
sy: 1,
dx: 0,
dy: 0,
deg: 0,
dirty: 1,
dirtyT: 1
};
!vml.bottom && (vml.bottom = this);
this.prev = vml.top;
vml.top && (vml.top.next = this);
vml.top = this;
this.next = null;
};
var elproto = R.el;
Element.prototype = elproto;
elproto.constructor = Element;
elproto.transform = function (tstr) {
if (tstr == null) {
return this._.transform;
}
R._extractTransform(this, tstr);
var matrix = this.matrix.clone(),
vbs = this.paper._viewBoxShift,
skew = this.skew,
o = this.node,
split,
isGrad = Str(this.attrs.fill).indexOf("-") + 1;
matrix.translate(-.5, -.5);
if (vbs) {
matrix.scale(vbs.scale, vbs.scale, -1, -1);
matrix.translate(vbs.dx, vbs.dy);
}
if (isGrad || this.type == "image") {
skew.matrix = "1 0 0 1";
skew.offset = "0 0";
split = matrix.split();
if ((isGrad && split.noRotation) || !split.isSimple) {
o.style.filter = matrix.toFilter();
var bb = this.getBBox(),
bbt = this.getBBox(1),
dx = bb.x - bbt.x,
dy = bb.y - bbt.y;
o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
setCoords(this, 1, 1, dx, dy, 0);
} else {
o.style.filter = E;
setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
}
} else {
o.style.filter = E;
skew.matrix = Str(matrix);
skew.offset = matrix.offset();
}
return this;
};
elproto.rotate = function (deg, cx, cy) {
if (this.removed) {
return this;
}
if (deg == null) {
return;
}
deg = Str(deg).split(separator);
if (deg.length - 1) {
cx = toFloat(deg[1]);
cy = toFloat(deg[2]);
}
deg = toFloat(deg[0]);
(cy == null) && (cx = cy);
if (cx == null || cy == null) {
var bbox = this.getBBox(1);
cx = bbox.x + bbox.width / 2;
cy = bbox.y + bbox.height / 2;
}
this._.dirtyT = 1;
this.transform(this._.transform.concat([["r", deg, cx, cy]]));
return this;
};
elproto.translate = function (dx, dy) {
if (this.removed) {
return this;
}
dx = Str(dx).split(separator);
if (dx.length - 1) {
dy = toFloat(dx[1]);
}
dx = toFloat(dx[0]) || 0;
dy = +dy || 0;
if (this._.bbox) {
this._.bbox.x += dx;
this._.bbox.y += dy;
}
this.transform(this._.transform.concat([["t", dx, dy]]));
return this;
};
elproto.scale = function (sx, sy, cx, cy) {
if (this.removed) {
return this;
}
sx = Str(sx).split(separator);
if (sx.length - 1) {
sy = toFloat(sx[1]);
cx = toFloat(sx[2]);
cy = toFloat(sx[3]);
isNaN(cx) && (cx = null);
isNaN(cy) && (cy = null);
}
sx = toFloat(sx[0]);
(sy == null) && (sy = sx);
(cy == null) && (cx = cy);
if (cx == null || cy == null) {
var bbox = this.getBBox(1);
}
cx = cx == null ? bbox.x + bbox.width / 2 : cx;
cy = cy == null ? bbox.y + bbox.height / 2 : cy;
this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
this._.dirtyT = 1;
return this;
};
elproto.hide = function () {
!this.removed && (this.node.style.display = "none");
return this;
};
elproto.show = function () {
!this.removed && (this.node.style.display = E);
return this;
};
elproto._getBBox = function () {
if (this.removed) {
return {};
}
if (this.type == "text") {
return {
x: this.X + (this.bbx || 0) - this.W / 2,
y: this.Y - this.H,
width: this.W,
height: this.H
};
} else {
return pathDimensions(this.attrs.path);
}
};
elproto.remove = function () {
if (this.removed) {
return;
}
R.eve.unbind("*.*." + this.id);
R._tear(this, this.paper);
this.node.parentNode.removeChild(this.node);
this.shape && this.shape.parentNode.removeChild(this.shape);
for (var i in this) {
delete this[i];
}
this.removed = true;
};
elproto.attr = function (name, value) {
if (this.removed) {
return this;
}
if (name == null) {
var res = {};
for (var a in this.attrs) if (this.attrs[has](a)) {
res[a] = this.attrs[a];
}
res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
res.transform = this._.transform;
return res;
}
if (value == null && R.is(name, "string")) {
if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
return this.attrs.gradient;
}
var names = name.split(separator),
out = {};
for (var i = 0, ii = names.length; i < ii; i++) {
name = names[i];
if (name in this.attrs) {
out[name] = this.attrs[name];
} else if (R.is(this.paper.customAttributes[name], "function")) {
out[name] = this.paper.customAttributes[name].def;
} else {
out[name] = R._availableAttrs[name];
}
}
return ii - 1 ? out : out[names[0]];
}
if (this.attrs && value == null && R.is(name, "array")) {
out = {};
for (i = 0, ii = name.length; i < ii; i++) {
out[name[i]] = this.attr(name[i]);
}
return out;
}
var params;
if (value != null) {
params = {};
params[name] = value;
}
value == null && R.is(name, "object") && (params = name);
for (var key in params) {
R.eve("attr." + key + "." + this.id, this, params[key]);
}
if (params) {
for (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];
}
}
// this.paper.canvas.style.display = "none";
if (params.text && this.type == "text") {
this.textpath.string = params.text;
}
setFillAndStroke(this, params);
// this.paper.canvas.style.display = E;
}
return this;
};
elproto.toFront = function () {
!this.removed && this.node.parentNode.appendChild(this.node);
this.paper && this.paper.top != this && tofront(this, this.paper);
return this;
};
elproto.toBack = function () {
if (this.removed) {
return this;
}
if (this.node.parentNode.firstChild != this.node) {
this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
toback(this, this.paper);
}
return this;
};
elproto.insertAfter = function (element) {
if (this.removed) {
return this;
}
if (element.constructor == Set) {
element = element[element.length - 1];
}
if (element.node.nextSibling) {
element.node.parentNode.insertBefore(this.node, element.node.nextSibling);
} else {
element.node.parentNode.appendChild(this.node);
}
R._insertafter(this, element, this.paper);
return this;
};
elproto.insertBefore = function (element) {
if (this.removed) {
return this;
}
if (element.constructor == Set) {
element = element[0];
}
element.node.parentNode.insertBefore(this.node, element.node);
R._insertbefore(this, element, this.paper);
return this;
};
elproto.blur = function (size) {
var s = this.node.runtimeStyle,
f = s.filter;
f = f.replace(blurregexp, E);
if (+size !== 0) {
this.attrs.blur = size;
s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
} else {
s.filter = f;
s.margin = 0;
delete this.attrs.blur;
}
};
R._engine.path = function (pathString, vml) {
var el = createNode("shape");
el.style.cssText = cssDot;
el.coordsize = zoom + S + zoom;
el.coordorigin = vml.coordorigin;
var p = new Element(el, vml),
attr = {fill: "none", stroke: "#000"};
pathString && (attr.path = pathString);
p.type = "path";
p.path = [];
p.Path = E;
setFillAndStroke(p, attr);
vml.canvas.appendChild(el);
var skew = createNode("skew");
skew.on = true;
el.appendChild(skew);
p.skew = skew;
p.transform(E);
return p;
};
R._engine.rect = function (vml, x, y, w, h, r) {
var path = R._rectPath(x, y, w, h, r),
res = vml.path(path),
a = res.attrs;
res.X = a.x = x;
res.Y = a.y = y;
res.W = a.width = w;
res.H = a.height = h;
a.r = r;
a.path = path;
res.type = "rect";
return res;
};
R._engine.ellipse = function (vml, x, y, rx, ry) {
var res = vml.path(),
a = res.attrs;
res.X = x - rx;
res.Y = y - ry;
res.W = rx * 2;
res.H = ry * 2;
res.type = "ellipse";
setFillAndStroke(res, {
cx: x,
cy: y,
rx: rx,
ry: ry
});
return res;
};
R._engine.circle = function (vml, x, y, r) {
var res = vml.path(),
a = res.attrs;
res.X = x - r;
res.Y = y - r;
res.W = res.H = r * 2;
res.type = "circle";
setFillAndStroke(res, {
cx: x,
cy: y,
r: r
});
return res;
};
R._engine.image = function (vml, src, x, y, w, h) {
var path = R._rectPath(x, y, w, h),
res = vml.path(path).attr({stroke: "none"}),
a = res.attrs,
node = res.node,
fill = node.getElementsByTagName(fillString)[0];
a.src = src;
res.X = a.x = x;
res.Y = a.y = y;
res.W = a.width = w;
res.H = a.height = h;
a.path = path;
res.type = "image";
fill.parentNode == node && node.removeChild(fill);
fill.rotate = true;
fill.src = src;
fill.type = "tile";
res._.fillpos = [x, y];
res._.fillsize = [w, h];
node.appendChild(fill);
setCoords(res, 1, 1, 0, 0, 0);
return res;
};
R._engine.text = function (vml, x, y, text) {
var el = createNode("shape"),
path = createNode("path"),
o = createNode("textpath");
x = x || 0;
y = y || 0;
text = text || "";
path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1);
path.textpathok = true;
o.string = Str(text);
o.on = true;
el.style.cssText = "position:absolute;left:0;top:0;width:1px;height:1px";
el.coordsize = zoom + S + zoom;
el.coordorigin = "0 0";
var p = new Element(el, vml),
attr = {fill: "#000", stroke: "none", font: availableAttrs.font, text: text};
p.shape = el;
p.path = path;
p.textpath = o;
p.type = "text";
p.attrs.text = Str(text);
p.attrs.x = x;
p.attrs.y = y;
p.attrs.w = 1;
p.attrs.h = 1;
setFillAndStroke(p, attr);
el.appendChild(o);
el.appendChild(path);
vml.canvas.appendChild(el);
var skew = createNode("skew");
skew.on = true;
el.appendChild(skew);
p.skew = skew;
p.transform(E);
return p;
};
R._engine.setSize = function (width, height) {
var cs = this.canvas.style;
this.width = width;
this.height = height;
width == +width && (width += "px");
height == +height && (height += "px");
cs.width = width;
cs.height = height;
cs.clip = "rect(0 " + width + " " + height + " 0)";
if (this._viewBox) {
setViewBox.apply(this, this._viewBox);
}
return this;
};
R._engine.setViewBox = function (x, y, w, h, fit) {
R.eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]);
var width = this.width,
height = this.height,
size = 1 / mmax(w / width, h / height),
H, W;
if (fit) {
H = height / h;
W = width / w;
if (w * H < width) {
x -= (width - w * H) / 2 / H;
}
if (h * W < height) {
y -= (height - h * W) / 2 / W;
}
}
this._viewBox = [x, y, w, h, !!fit];
this._viewBoxShift = {
dx: -x,
dy: -y,
scale: size
};
this.forEach(function (el) {
el.transform("...");
});
return this;
};
var createNode,
initWin = function (win) {
var doc = win.document;
doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
try {
!doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
createNode = function (tagName) {
return doc.createElement('<rvml:' + tagName + ' class="rvml">');
};
} catch (e) {
createNode = function (tagName) {
return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
};
}
};
initWin(R._g.win);
R._engine.create = function () {
var con = R._getContainer.apply(0, arguments),
container = con.container,
height = con.height,
s,
width = con.width,
x = con.x,
y = con.y;
if (!container) {
throw new Error("VML container not found.");
}
var res = new R._Paper,
c = res.canvas = R._g.doc.createElement("div"),
cs = c.style;
x = x || 0;
y = y || 0;
width = width || 512;
height = height || 342;
res.width = width;
res.height = height;
width == +width && (width += "px");
height == +height && (height += "px");
res.coordsize = zoom * 1e3 + S + zoom * 1e3;
res.coordorigin = "0 0";
res.span = R._g.doc.createElement("span");
res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
c.appendChild(res.span);
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) {
R._g.doc.body.appendChild(c);
cs.left = x + "px";
cs.top = y + "px";
cs.position = "absolute";
} else {
if (container.firstChild) {
container.insertBefore(c, container.firstChild);
} else {
container.appendChild(c);
}
}
// plugins.call(res, res, R.fn);
res.renderfix = function () {};
return res;
};
R.prototype.clear = function () {
R.eve("clear", this);
this.canvas.innerHTML = E;
this.span = g.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;
};
R.prototype.remove = function () {
R.eve("remove", this);
this.canvas.parentNode.removeChild(this.canvas);
for (var i in this) {
this[i] = removed(i);
}
return true;
};
}(window.Raphael);
\ No newline at end of file
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