// ┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐ \\
// │ Raphaël 2.2.0 - JavaScript Vector Library │ \\
// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
// │ Copyright © 2008-2016 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
// │ Copyright © 2008-2016 Sencha Labs (http://sencha.com) │ \\
// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
// │ Licensed under the MIT (https://github.com/DmitryBaranovskiy/raphael/blob/master/license.txt) license.│ \\
// └───────────────────────────────────────────────────────────────────────────────────────────────────────┘ \\
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["Raphael"] = factory();
else
root["Raphael"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(3), __webpack_require__(4)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
return R;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = function(eve) {
/*\
* Raphael
[ method ]
**
* Creates a canvas object on which to draw.
* You must do this first, as all future calls to drawing methods
* from this instance will be bound to this canvas.
> Parameters
**
- container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface
- width (number)
- height (number)
- callback (function) #optional callback function which is going to be executed in the context of newly created paper
* or
- x (number)
- y (number)
- width (number)
- height (number)
- callback (function) #optional callback function which is going to be executed in the context of newly created paper
* or
- all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, Here is short list of commands available, for more details see SVG path string format. See also Easing demo. Please refer to the SVG specification for an explanation of these parameters. Please refer to SVG documentation regarding path string. Raphaël fully supports it.
#
= (object) RGB object in format:
o {
o r (number) red,
o g (number) green,
o b (number) blue
o hex (string) color in HTML/CSS format: #••••••,
o error (boolean) true if string can’t be parsed
o }
\*/
R.getRGB = cacher(function (colour) {
if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {
return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
}
if (colour == "none") {
return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString};
}
!(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));
var res,
red,
green,
blue,
opacity,
t,
values,
rgb = colour.match(colourRegExp);
if (rgb) {
if (rgb[2]) {
blue = toInt(rgb[2].substring(5), 16);
green = toInt(rgb[2].substring(3, 5), 16);
red = toInt(rgb[2].substring(1, 3), 16);
}
if (rgb[3]) {
blue = toInt((t = rgb[3].charAt(3)) + t, 16);
green = toInt((t = rgb[3].charAt(2)) + t, 16);
red = toInt((t = rgb[3].charAt(1)) + t, 16);
}
if (rgb[4]) {
values = rgb[4][split](commaSpaces);
red = toFloat(values[0]);
values[0].slice(-1) == "%" && (red *= 2.55);
green = toFloat(values[1]);
values[1].slice(-1) == "%" && (green *= 2.55);
blue = toFloat(values[2]);
values[2].slice(-1) == "%" && (blue *= 2.55);
rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3]));
values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
}
if (rgb[5]) {
values = rgb[5][split](commaSpaces);
red = toFloat(values[0]);
values[0].slice(-1) == "%" && (red *= 2.55);
green = toFloat(values[1]);
values[1].slice(-1) == "%" && (green *= 2.55);
blue = toFloat(values[2]);
values[2].slice(-1) == "%" && (blue *= 2.55);
(values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3]));
values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
return R.hsb2rgb(red, green, blue, opacity);
}
if (rgb[6]) {
values = rgb[6][split](commaSpaces);
red = toFloat(values[0]);
values[0].slice(-1) == "%" && (red *= 2.55);
green = toFloat(values[1]);
values[1].slice(-1) == "%" && (green *= 2.55);
blue = toFloat(values[2]);
values[2].slice(-1) == "%" && (blue *= 2.55);
(values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3]));
values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
return R.hsl2rgb(red, green, blue, opacity);
}
rgb = {r: red, g: green, b: blue, toString: clrToString};
rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
R.is(opacity, "finite") && (rgb.opacity = opacity);
return rgb;
}
return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
}, R);
/*\
* Raphael.hsb
[ method ]
**
* Converts HSB values to hex representation of the colour.
> Parameters
- h (number) hue
- s (number) saturation
- b (number) value or brightness
= (string) hex representation of the colour.
\*/
R.hsb = cacher(function (h, s, b) {
return R.hsb2rgb(h, s, b).hex;
});
/*\
* Raphael.hsl
[ method ]
**
* Converts HSL values to hex representation of the colour.
> Parameters
- h (number) hue
- s (number) saturation
- l (number) luminosity
= (string) hex representation of the colour.
\*/
R.hsl = cacher(function (h, s, l) {
return R.hsl2rgb(h, s, l).hex;
});
/*\
* Raphael.rgb
[ method ]
**
* Converts RGB values to hex representation of the colour.
> Parameters
- r (number) red
- g (number) green
- b (number) blue
= (string) hex representation of the colour.
\*/
R.rgb = cacher(function (r, g, b) {
function round(x) { return (x + 0.5) | 0; }
return "#" + (16777216 | round(b) | (round(g) << 8) | (round(r) << 16)).toString(16).slice(1);
});
/*\
* Raphael.getColor
[ method ]
**
* On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset
> Parameters
- value (number) #optional brightness, default is `0.75`
= (string) hex representation of the colour.
\*/
R.getColor = function (value) {
var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},
rgb = this.hsb2rgb(start.h, start.s, start.b);
start.h += .075;
if (start.h > 1) {
start.h = 0;
start.s -= .2;
start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});
}
return rgb.hex;
};
/*\
* Raphael.getColor.reset
[ method ]
**
* Resets spectrum position for @Raphael.getColor back to red.
\*/
R.getColor.reset = function () {
delete this.start;
};
// http://schepers.cc/getting-to-the-point
function catmullRom2bezier(crp, z) {
var d = [];
for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
var p = [
{x: +crp[i - 2], y: +crp[i - 1]},
{x: +crp[i], y: +crp[i + 1]},
{x: +crp[i + 2], y: +crp[i + 3]},
{x: +crp[i + 4], y: +crp[i + 5]}
];
if (z) {
if (!i) {
p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};
} else if (iLen - 4 == i) {
p[3] = {x: +crp[0], y: +crp[1]};
} else if (iLen - 2 == i) {
p[2] = {x: +crp[0], y: +crp[1]};
p[3] = {x: +crp[2], y: +crp[3]};
}
} else {
if (iLen - 4 == i) {
p[3] = p[2];
} else if (!i) {
p[0] = {x: +crp[i], y: +crp[i + 1]};
}
}
d.push(["C",
(-p[0].x + 6 * p[1].x + p[2].x) / 6,
(-p[0].y + 6 * p[1].y + p[2].y) / 6,
(p[1].x + 6 * p[2].x - p[3].x) / 6,
(p[1].y + 6*p[2].y - p[3].y) / 6,
p[2].x,
p[2].y
]);
}
return d;
}
/*\
* Raphael.parsePathString
[ method ]
**
* Utility method
**
* Parses given path string into an array of arrays of path segments.
> Parameters
- pathString (string|array) path string or array of segments (in the last case it will be returned straight away)
= (array) array of segments.
\*/
R.parsePathString = function (pathString) {
if (!pathString) {
return null;
}
var pth = paths(pathString);
if (pth.arr) {
return pathClone(pth.arr);
}
var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},
data = [];
if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption
data = pathClone(pathString);
}
if (!data.length) {
Str(pathString).replace(pathCommand, function (a, b, c) {
var params = [],
name = b.toLowerCase();
c.replace(pathValues, function (a, b) {
b && params.push(+b);
});
if (name == "m" && params.length > 2) {
data.push([b][concat](params.splice(0, 2)));
name = "l";
b = b == "m" ? "l" : "L";
}
if (name == "r") {
data.push([b][concat](params));
} else while (params.length >= paramCounts[name]) {
data.push([b][concat](params.splice(0, paramCounts[name])));
if (!paramCounts[name]) {
break;
}
}
});
}
data.toString = R._path2string;
pth.arr = pathClone(data);
return data;
};
/*\
* Raphael.parseTransformString
[ method ]
**
* Utility method
**
* Parses given path string into an array of transformations.
> Parameters
- TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)
= (array) array of transformations.
\*/
R.parseTransformString = cacher(function (TString) {
if (!TString) {
return null;
}
var paramCounts = {r: 3, s: 4, t: 2, m: 6},
data = [];
if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption
data = pathClone(TString);
}
if (!data.length) {
Str(TString).replace(tCommand, function (a, b, c) {
var params = [],
name = lowerCase.call(b);
c.replace(pathValues, function (a, b) {
b && params.push(+b);
});
data.push([b][concat](params));
});
}
data.toString = R._path2string;
return data;
});
// PATHS
var paths = function (ps) {
var p = paths.ps = paths.ps || {};
if (p[ps]) {
p[ps].sleep = 100;
} else {
p[ps] = {
sleep: 100
};
}
setTimeout(function () {
for (var key in p) if (p[has](key) && key != ps) {
p[key].sleep--;
!p[key].sleep && delete p[key];
}
});
return p[ps];
};
/*\
* Raphael.findDotsAtSegment
[ method ]
**
* Utility method
**
* Find dot coordinates on the given cubic bezier curve at the given t.
> Parameters
- p1x (number) x of the first point of the curve
- p1y (number) y of the first point of the curve
- c1x (number) x of the first anchor of the curve
- c1y (number) y of the first anchor of the curve
- c2x (number) x of the second anchor of the curve
- c2y (number) y of the second anchor of the curve
- p2x (number) x of the second point of the curve
- p2y (number) y of the second point of the curve
- t (number) position on the curve (0..1)
= (object) point information in format:
o {
o x: (number) x coordinate of the point
o y: (number) y coordinate of the point
o m: {
o x: (number) x coordinate of the left anchor
o y: (number) y coordinate of the left anchor
o }
o n: {
o x: (number) x coordinate of the right anchor
o y: (number) y coordinate of the right anchor
o }
o start: {
o x: (number) x coordinate of the start of the curve
o y: (number) y coordinate of the start of the curve
o }
o end: {
o x: (number) x coordinate of the end of the curve
o y: (number) y coordinate of the end of the curve
o }
o alpha: (number) angle of the curve derivative at the point
o }
\*/
R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
var t1 = 1 - t,
t13 = pow(t1, 3),
t12 = pow(t1, 2),
t2 = t * t,
t3 = t2 * t,
x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
ax = t1 * p1x + t * c1x,
ay = t1 * p1y + t * c1y,
cx = t1 * c2x + t * p2x,
cy = t1 * c2y + t * p2y,
alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);
(mx > nx || my < ny) && (alpha += 180);
return {
x: x,
y: y,
m: {x: mx, y: my},
n: {x: nx, y: ny},
start: {x: ax, y: ay},
end: {x: cx, y: cy},
alpha: alpha
};
};
/*\
* Raphael.bezierBBox
[ method ]
**
* Utility method
**
* Return bounding box of a given cubic bezier curve
> Parameters
- p1x (number) x of the first point of the curve
- p1y (number) y of the first point of the curve
- c1x (number) x of the first anchor of the curve
- c1y (number) y of the first anchor of the curve
- c2x (number) x of the second anchor of the curve
- c2y (number) y of the second anchor of the curve
- p2x (number) x of the second point of the curve
- p2y (number) y of the second point of the curve
* or
- bez (array) array of six points for bezier curve
= (object) point information in format:
o {
o min: {
o x: (number) x coordinate of the left point
o y: (number) y coordinate of the top point
o }
o max: {
o x: (number) x coordinate of the right point
o y: (number) y coordinate of the bottom point
o }
o }
\*/
R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
if (!R.is(p1x, "array")) {
p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];
}
var bbox = curveDim.apply(null, p1x);
return {
x: bbox.min.x,
y: bbox.min.y,
x2: bbox.max.x,
y2: bbox.max.y,
width: bbox.max.x - bbox.min.x,
height: bbox.max.y - bbox.min.y
};
};
/*\
* Raphael.isPointInsideBBox
[ method ]
**
* Utility method
**
* Returns `true` if given point is inside bounding boxes.
> Parameters
- bbox (string) bounding box
- x (string) x coordinate of the point
- y (string) y coordinate of the point
= (boolean) `true` if point inside
\*/
R.isPointInsideBBox = function (bbox, x, y) {
return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;
};
/*\
* Raphael.isBBoxIntersect
[ method ]
**
* Utility method
**
* Returns `true` if two bounding boxes intersect
> Parameters
- bbox1 (string) first bounding box
- bbox2 (string) second bounding box
= (boolean) `true` if they intersect
\*/
R.isBBoxIntersect = function (bbox1, bbox2) {
var i = R.isPointInsideBBox;
return i(bbox2, bbox1.x, bbox1.y)
|| i(bbox2, bbox1.x2, bbox1.y)
|| i(bbox2, bbox1.x, bbox1.y2)
|| i(bbox2, bbox1.x2, bbox1.y2)
|| i(bbox1, bbox2.x, bbox2.y)
|| i(bbox1, bbox2.x2, bbox2.y)
|| i(bbox1, bbox2.x, bbox2.y2)
|| i(bbox1, bbox2.x2, bbox2.y2)
|| (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)
&& (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);
};
function base3(t, p1, p2, p3, p4) {
var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
return t * t2 - 3 * p1 + 3 * p2;
}
function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
if (z == null) {
z = 1;
}
z = z > 1 ? 1 : z < 0 ? 0 : z;
var z2 = z / 2,
n = 12,
Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],
Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],
sum = 0;
for (var i = 0; i < n; i++) {
var ct = z2 * Tvalues[i] + z2,
xbase = base3(ct, x1, x2, x3, x4),
ybase = base3(ct, y1, y2, y3, y4),
comb = xbase * xbase + ybase * ybase;
sum += Cvalues[i] * math.sqrt(comb);
}
return z2 * sum;
}
function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
return;
}
var t = 1,
step = t / 2,
t2 = t - step,
l,
e = .01;
l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
while (abs(l - ll) > e) {
step /= 2;
t2 += (l < ll ? 1 : -1) * step;
l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
}
return t2;
}
function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
if (
mmax(x1, x2) < mmin(x3, x4) ||
mmin(x1, x2) > mmax(x3, x4) ||
mmax(y1, y2) < mmin(y3, y4) ||
mmin(y1, y2) > mmax(y3, y4)
) {
return;
}
var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),
ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),
denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (!denominator) {
return;
}
var px = nx / denominator,
py = ny / denominator,
px2 = +px.toFixed(2),
py2 = +py.toFixed(2);
if (
px2 < +mmin(x1, x2).toFixed(2) ||
px2 > +mmax(x1, x2).toFixed(2) ||
px2 < +mmin(x3, x4).toFixed(2) ||
px2 > +mmax(x3, x4).toFixed(2) ||
py2 < +mmin(y1, y2).toFixed(2) ||
py2 > +mmax(y1, y2).toFixed(2) ||
py2 < +mmin(y3, y4).toFixed(2) ||
py2 > +mmax(y3, y4).toFixed(2)
) {
return;
}
return {x: px, y: py};
}
function inter(bez1, bez2) {
return interHelper(bez1, bez2);
}
function interCount(bez1, bez2) {
return interHelper(bez1, bez2, 1);
}
function interHelper(bez1, bez2, justCount) {
var bbox1 = R.bezierBBox(bez1),
bbox2 = R.bezierBBox(bez2);
if (!R.isBBoxIntersect(bbox1, bbox2)) {
return justCount ? 0 : [];
}
var l1 = bezlen.apply(0, bez1),
l2 = bezlen.apply(0, bez2),
n1 = mmax(~~(l1 / 5), 1),
n2 = mmax(~~(l2 / 5), 1),
dots1 = [],
dots2 = [],
xy = {},
res = justCount ? 0 : [];
for (var i = 0; i < n1 + 1; i++) {
var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));
dots1.push({x: p.x, y: p.y, t: i / n1});
}
for (i = 0; i < n2 + 1; i++) {
p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));
dots2.push({x: p.x, y: p.y, t: i / n2});
}
for (i = 0; i < n1; i++) {
for (var j = 0; j < n2; j++) {
var di = dots1[i],
di1 = dots1[i + 1],
dj = dots2[j],
dj1 = dots2[j + 1],
ci = abs(di1.x - di.x) < .001 ? "y" : "x",
cj = abs(dj1.x - dj.x) < .001 ? "y" : "x",
is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);
if (is) {
if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {
continue;
}
xy[is.x.toFixed(4)] = is.y.toFixed(4);
var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),
t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) {
if (justCount) {
res++;
} else {
res.push({
x: is.x,
y: is.y,
t1: mmin(t1, 1),
t2: mmin(t2, 1)
});
}
}
}
}
}
return res;
}
/*\
* Raphael.pathIntersection
[ method ]
**
* Utility method
**
* Finds intersections of two paths
> Parameters
- path1 (string) path string
- path2 (string) path string
= (array) dots of intersection
o [
o {
o x: (number) x coordinate of the point
o y: (number) y coordinate of the point
o t1: (number) t value for segment of path1
o t2: (number) t value for segment of path2
o segment1: (number) order number for segment of path1
o segment2: (number) order number for segment of path2
o bez1: (array) eight coordinates representing beziér curve for the segment of path1
o bez2: (array) eight coordinates representing beziér curve for the segment of path2
o }
o ]
\*/
R.pathIntersection = function (path1, path2) {
return interPathHelper(path1, path2);
};
R.pathIntersectionNumber = function (path1, path2) {
return interPathHelper(path1, path2, 1);
};
function interPathHelper(path1, path2, justCount) {
path1 = R._path2curve(path1);
path2 = R._path2curve(path2);
var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,
res = justCount ? 0 : [];
for (var i = 0, ii = path1.length; i < ii; i++) {
var pi = path1[i];
if (pi[0] == "M") {
x1 = x1m = pi[1];
y1 = y1m = pi[2];
} else {
if (pi[0] == "C") {
bez1 = [x1, y1].concat(pi.slice(1));
x1 = bez1[6];
y1 = bez1[7];
} else {
bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];
x1 = x1m;
y1 = y1m;
}
for (var j = 0, jj = path2.length; j < jj; j++) {
var pj = path2[j];
if (pj[0] == "M") {
x2 = x2m = pj[1];
y2 = y2m = pj[2];
} else {
if (pj[0] == "C") {
bez2 = [x2, y2].concat(pj.slice(1));
x2 = bez2[6];
y2 = bez2[7];
} else {
bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];
x2 = x2m;
y2 = y2m;
}
var intr = interHelper(bez1, bez2, justCount);
if (justCount) {
res += intr;
} else {
for (var k = 0, kk = intr.length; k < kk; k++) {
intr[k].segment1 = i;
intr[k].segment2 = j;
intr[k].bez1 = bez1;
intr[k].bez2 = bez2;
}
res = res.concat(intr);
}
}
}
}
}
return res;
}
/*\
* Raphael.isPointInsidePath
[ method ]
**
* Utility method
**
* Returns `true` if given point is inside a given closed path.
> Parameters
- path (string) path string
- x (number) x of the point
- y (number) y of the point
= (boolean) true, if point is inside the path
\*/
R.isPointInsidePath = function (path, x, y) {
var bbox = R.pathBBox(path);
return R.isPointInsideBBox(bbox, x, y) &&
interPathHelper(path, [["M", x, y], ["H", bbox.x2 + 10]], 1) % 2 == 1;
};
R._removedFactory = function (methodname) {
return function () {
eve("raphael.log", null, "Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object", methodname);
};
};
/*\
* Raphael.pathBBox
[ method ]
**
* Utility method
**
* Return bounding box of a given path
> Parameters
- path (string) path string
= (object) bounding box
o {
o x: (number) x coordinate of the left top point of the box
o y: (number) y coordinate of the left top point of the box
o x2: (number) x coordinate of the right bottom point of the box
o y2: (number) y coordinate of the right bottom point of the box
o width: (number) width of the box
o height: (number) height of the box
o cx: (number) x coordinate of the center of the box
o cy: (number) y coordinate of the center of the box
o }
\*/
var pathDimensions = R.pathBBox = function (path) {
var pth = paths(path);
if (pth.bbox) {
return clone(pth.bbox);
}
if (!path) {
return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};
}
path = path2curve(path);
var x = 0,
y = 0,
X = [],
Y = [],
p;
for (var i = 0, ii = path.length; i < ii; i++) {
p = path[i];
if (p[0] == "M") {
x = p[1];
y = p[2];
X.push(x);
Y.push(y);
} else {
var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
X = X[concat](dim.min.x, dim.max.x);
Y = Y[concat](dim.min.y, dim.max.y);
x = p[5];
y = p[6];
}
}
var xmin = mmin[apply](0, X),
ymin = mmin[apply](0, Y),
xmax = mmax[apply](0, X),
ymax = mmax[apply](0, Y),
width = xmax - xmin,
height = ymax - ymin,
bb = {
x: xmin,
y: ymin,
x2: xmax,
y2: ymax,
width: width,
height: height,
cx: xmin + width / 2,
cy: ymin + height / 2
};
pth.bbox = clone(bb);
return bb;
},
pathClone = function (pathArray) {
var res = clone(pathArray);
res.toString = R._path2string;
return res;
},
pathToRelative = R._pathToRelative = function (pathArray) {
var pth = paths(pathArray);
if (pth.rel) {
return pathClone(pth.rel);
}
if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
pathArray = R.parsePathString(pathArray);
}
var res = [],
x = 0,
y = 0,
mx = 0,
my = 0,
start = 0;
if (pathArray[0][0] == "M") {
x = pathArray[0][1];
y = pathArray[0][2];
mx = x;
my = y;
start++;
res.push(["M", x, y]);
}
for (var i = start, ii = pathArray.length; i < ii; i++) {
var r = res[i] = [],
pa = pathArray[i];
if (pa[0] != lowerCase.call(pa[0])) {
r[0] = lowerCase.call(pa[0]);
switch (r[0]) {
case "a":
r[1] = pa[1];
r[2] = pa[2];
r[3] = pa[3];
r[4] = pa[4];
r[5] = pa[5];
r[6] = +(pa[6] - x).toFixed(3);
r[7] = +(pa[7] - y).toFixed(3);
break;
case "v":
r[1] = +(pa[1] - y).toFixed(3);
break;
case "m":
mx = pa[1];
my = pa[2];
default:
for (var j = 1, jj = pa.length; j < jj; j++) {
r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
}
}
} else {
r = res[i] = [];
if (pa[0] == "m") {
mx = pa[1] + x;
my = pa[2] + y;
}
for (var k = 0, kk = pa.length; k < kk; k++) {
res[i][k] = pa[k];
}
}
var len = res[i].length;
switch (res[i][0]) {
case "z":
x = mx;
y = my;
break;
case "h":
x += +res[i][len - 1];
break;
case "v":
y += +res[i][len - 1];
break;
default:
x += +res[i][len - 2];
y += +res[i][len - 1];
}
}
res.toString = R._path2string;
pth.rel = pathClone(res);
return res;
},
pathToAbsolute = R._pathToAbsolute = function (pathArray) {
var pth = paths(pathArray);
if (pth.abs) {
return pathClone(pth.abs);
}
if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
pathArray = R.parsePathString(pathArray);
}
if (!pathArray || !pathArray.length) {
return [["M", 0, 0]];
}
var res = [],
x = 0,
y = 0,
mx = 0,
my = 0,
start = 0;
if (pathArray[0][0] == "M") {
x = +pathArray[0][1];
y = +pathArray[0][2];
mx = x;
my = y;
start++;
res[0] = ["M", x, y];
}
var crz = pathArray.length == 3 && pathArray[0][0] == "M" && pathArray[1][0].toUpperCase() == "R" && pathArray[2][0].toUpperCase() == "Z";
for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
res.push(r = []);
pa = pathArray[i];
if (pa[0] != upperCase.call(pa[0])) {
r[0] = upperCase.call(pa[0]);
switch (r[0]) {
case "A":
r[1] = pa[1];
r[2] = pa[2];
r[3] = pa[3];
r[4] = pa[4];
r[5] = pa[5];
r[6] = +(pa[6] + x);
r[7] = +(pa[7] + y);
break;
case "V":
r[1] = +pa[1] + y;
break;
case "H":
r[1] = +pa[1] + x;
break;
case "R":
var dots = [x, y][concat](pa.slice(1));
for (var j = 2, jj = dots.length; j < jj; j++) {
dots[j] = +dots[j] + x;
dots[++j] = +dots[j] + y;
}
res.pop();
res = res[concat](catmullRom2bezier(dots, crz));
break;
case "M":
mx = +pa[1] + x;
my = +pa[2] + y;
default:
for (j = 1, jj = pa.length; j < jj; j++) {
r[j] = +pa[j] + ((j % 2) ? x : y);
}
}
} else if (pa[0] == "R") {
dots = [x, y][concat](pa.slice(1));
res.pop();
res = res[concat](catmullRom2bezier(dots, crz));
r = ["R"][concat](pa.slice(-2));
} else {
for (var k = 0, kk = pa.length; k < kk; k++) {
r[k] = pa[k];
}
}
switch (r[0]) {
case "Z":
x = mx;
y = my;
break;
case "H":
x = r[1];
break;
case "V":
y = r[1];
break;
case "M":
mx = r[r.length - 2];
my = r[r.length - 1];
default:
x = r[r.length - 2];
y = r[r.length - 1];
}
}
res.toString = R._path2string;
pth.abs = pathClone(res);
return res;
},
l2c = function (x1, y1, x2, y2) {
return [x1, y1, x2, y2, x2, y2];
},
q2c = function (x1, y1, ax, ay, x2, y2) {
var _13 = 1 / 3,
_23 = 2 / 3;
return [
_13 * x1 + _23 * ax,
_13 * y1 + _23 * ay,
_13 * x2 + _23 * ax,
_13 * y2 + _23 * ay,
x2,
y2
];
},
a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
// for more information of where this math came from visit:
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
var _120 = PI * 120 / 180,
rad = PI / 180 * (+angle || 0),
res = [],
xy,
rotate = cacher(function (x, y, rad) {
var X = x * math.cos(rad) - y * math.sin(rad),
Y = x * math.sin(rad) + y * math.cos(rad);
return {x: X, y: Y};
});
if (!recursive) {
xy = rotate(x1, y1, -rad);
x1 = xy.x;
y1 = xy.y;
xy = rotate(x2, y2, -rad);
x2 = xy.x;
y2 = xy.y;
var cos = math.cos(PI / 180 * angle),
sin = math.sin(PI / 180 * angle),
x = (x1 - x2) / 2,
y = (y1 - y2) / 2;
var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
if (h > 1) {
h = math.sqrt(h);
rx = h * rx;
ry = h * ry;
}
var rx2 = rx * rx,
ry2 = ry * ry,
k = (large_arc_flag == sweep_flag ? -1 : 1) *
math.sqrt(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(9)),
f2 = math.asin(((y2 - cy) / ry).toFixed(9));
f1 = x1 < cx ? PI - f1 : f1;
f2 = x2 < cx ? PI - f2 : f2;
f1 < 0 && (f1 = PI * 2 + f1);
f2 < 0 && (f2 = PI * 2 + f2);
if (sweep_flag && f1 > f2) {
f1 = f1 - PI * 2;
}
if (!sweep_flag && f2 > f1) {
f2 = f2 - PI * 2;
}
} else {
f1 = recursive[0];
f2 = recursive[1];
cx = recursive[2];
cy = recursive[3];
}
var df = f2 - f1;
if (abs(df) > _120) {
var f2old = f2,
x2old = x2,
y2old = y2;
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
x2 = cx + rx * math.cos(f2);
y2 = cy + ry * math.sin(f2);
res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
}
df = f2 - f1;
var c1 = math.cos(f1),
s1 = math.sin(f1),
c2 = math.cos(f2),
s2 = math.sin(f2),
t = math.tan(df / 4),
hx = 4 / 3 * rx * t,
hy = 4 / 3 * ry * t,
m1 = [x1, y1],
m2 = [x1 + hx * s1, y1 - hy * c1],
m3 = [x2 + hx * s2, y2 - hy * c2],
m4 = [x2, y2];
m2[0] = 2 * m1[0] - m2[0];
m2[1] = 2 * m1[1] - m2[1];
if (recursive) {
return [m2, m3, m4][concat](res);
} else {
res = [m2, m3, m4][concat](res).join()[split](",");
var newres = [];
for (var i = 0, ii = res.length; i < ii; i++) {
newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
}
return newres;
}
},
findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
var t1 = 1 - t;
return {
x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
};
},
curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
c = p1x - c1x,
t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
y = [p1y, p2y],
x = [p1x, p2x],
dot;
abs(t1) > "1e12" && (t1 = .5);
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);
y.push(dot.y);
}
if (t2 > 0 && t2 < 1) {
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
x.push(dot.x);
y.push(dot.y);
}
a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
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;
abs(t1) > "1e12" && (t1 = .5);
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);
y.push(dot.y);
}
if (t2 > 0 && t2 < 1) {
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
x.push(dot.x);
y.push(dot.y);
}
return {
min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},
max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}
};
}),
path2curve = R._path2curve = cacher(function (path, path2) {
var pth = !path2 && paths(path);
if (!path2 && pth.curve) {
return pathClone(pth.curve);
}
var p = pathToAbsolute(path),
p2 = path2 && pathToAbsolute(path2),
attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
processPath = function (path, d, pcom) {
var nx, ny, tq = {T:1, Q:1};
if (!path) {
return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
}
!(path[0] in tq) && (d.qx = d.qy = null);
switch (path[0]) {
case "M":
d.X = path[1];
d.Y = path[2];
break;
case "A":
path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));
break;
case "S":
if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S.
nx = d.x * 2 - d.bx; // And reflect the previous
ny = d.y * 2 - d.by; // command's control point relative to the current point.
}
else { // or some else or nothing
nx = d.x;
ny = d.y;
}
path = ["C", nx, ny][concat](path.slice(1));
break;
case "T":
if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T.
d.qx = d.x * 2 - d.qx; // And make a reflection similar
d.qy = d.y * 2 - d.qy; // to case "S".
}
else { // or something else or nothing
d.qx = d.x;
d.qy = d.y;
}
path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
break;
case "Q":
d.qx = path[1];
d.qy = path[2];
path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
break;
case "L":
path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));
break;
case "H":
path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));
break;
case "V":
path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));
break;
case "Z":
path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));
break;
}
return path;
},
fixArc = function (pp, i) {
if (pp[i].length > 7) {
pp[i].shift();
var pi = pp[i];
while (pi.length) {
pcoms1[i]="A"; // if created multiple C:s, their original seg is saved
p2 && (pcoms2[i]="A"); // the same as above
pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));
}
pp.splice(i, 1);
ii = mmax(p.length, p2 && p2.length || 0);
}
},
fixM = function (path1, path2, a1, a2, i) {
if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
path2.splice(i, 0, ["M", a2.x, a2.y]);
a1.bx = 0;
a1.by = 0;
a1.x = path1[i][1];
a1.y = path1[i][2];
ii = mmax(p.length, p2 && p2.length || 0);
}
},
pcoms1 = [], // path commands of original path p
pcoms2 = [], // path commands of original path p2
pfirst = "", // temporary holder for original path command
pcom = ""; // holder for previous path command of original path
for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {
p[i] && (pfirst = p[i][0]); // save current path command
if (pfirst != "C") // C is not saved yet, because it may be result of conversion
{
pcoms1[i] = pfirst; // Save current path command
i && ( pcom = pcoms1[i-1]); // Get previous path command pcom
}
p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath
if (pcoms1[i] != "A" && pfirst == "C") pcoms1[i] = "C"; // A is the only command
// which may produce multiple C:s
// so we have to make sure that C is also C in original path
fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
if (p2) { // the same procedures is done to p2
p2[i] && (pfirst = p2[i][0]);
if (pfirst != "C")
{
pcoms2[i] = pfirst;
i && (pcom = pcoms2[i-1]);
}
p2[i] = processPath(p2[i], attrs2, pcom);
if (pcoms2[i]!="A" && pfirst=="C") pcoms2[i]="C";
fixArc(p2, i);
}
fixM(p, p2, attrs, attrs2, i);
fixM(p2, p, attrs2, attrs, i);
var seg = p[i],
seg2 = p2 && p2[i],
seglen = seg.length,
seg2len = p2 && seg2.length;
attrs.x = seg[seglen - 2];
attrs.y = seg[seglen - 1];
attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);
attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);
attrs2.x = p2 && seg2[seg2len - 2];
attrs2.y = p2 && seg2[seg2len - 1];
}
if (!p2) {
pth.curve = pathClone(p);
}
return p2 ? [p, p2] : p;
}, null, pathClone),
parseDots = R._parseDots = cacher(function (gradient) {
var dots = [];
for (var i = 0, ii = gradient.length; i < ii; i++) {
var dot = {},
par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
dot.color = R.getRGB(par[1]);
if (dot.color.error) {
return null;
}
dot.opacity = dot.color.opacity;
dot.color = dot.color.hex;
par[2] && (dot.offset = par[2] + "%");
dots.push(dot);
}
for (i = 1, ii = dots.length - 1; i < ii; i++) {
if (!dots[i].offset) {
var start = toFloat(dots[i - 1].offset || 0),
end = 0;
for (var j = i + 1; j < ii; j++) {
if (dots[j].offset) {
end = dots[j].offset;
break;
}
}
if (!end) {
end = 100;
j = ii;
}
end = toFloat(end);
var d = (end - start) / (j - i + 1);
for (; i < j; i++) {
start += d;
dots[i].offset = start + "%";
}
}
}
return dots;
}),
tear = R._tear = function (el, paper) {
el == paper.top && (paper.top = el.prev);
el == paper.bottom && (paper.bottom = el.next);
el.next && (el.next.prev = el.prev);
el.prev && (el.prev.next = el.next);
},
tofront = R._tofront = function (el, paper) {
if (paper.top === el) {
return;
}
tear(el, paper);
el.next = null;
el.prev = paper.top;
paper.top.next = el;
paper.top = el;
},
toback = R._toback = function (el, paper) {
if (paper.bottom === el) {
return;
}
tear(el, paper);
el.next = paper.bottom;
el.prev = null;
paper.bottom.prev = el;
paper.bottom = el;
},
insertafter = R._insertafter = function (el, el2, paper) {
tear(el, paper);
el2 == paper.top && (paper.top = el);
el2.next && (el2.next.prev = el);
el.next = el2.next;
el.prev = el2;
el2.next = el;
},
insertbefore = R._insertbefore = function (el, el2, paper) {
tear(el, paper);
el2 == paper.bottom && (paper.bottom = el);
el2.prev && (el2.prev.next = el);
el.prev = el2.prev;
el2.prev = el;
el.next = el2;
},
/*\
* Raphael.toMatrix
[ method ]
**
* Utility method
**
* Returns matrix of transformations applied to a given path
> Parameters
- path (string) path string
- transform (string|array) transformation string
= (object) @Matrix
\*/
toMatrix = R.toMatrix = function (path, transform) {
var bb = pathDimensions(path),
el = {
_: {
transform: E
},
getBBox: function () {
return bb;
}
};
extractTransform(el, transform);
return el.matrix;
},
/*\
* Raphael.transformPath
[ method ]
**
* Utility method
**
* Returns path transformed by a given transformation
> Parameters
- path (string) path string
- transform (string|array) transformation string
= (string) path
\*/
transformPath = R.transformPath = function (path, transform) {
return mapPath(path, toMatrix(path, transform));
},
extractTransform = R._extractTransform = function (el, tstr) {
if (tstr == null) {
return el._.transform;
}
tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E);
var tdata = R.parseTransformString(tstr),
deg = 0,
dx = 0,
dy = 0,
sx = 1,
sy = 1,
_ = el._,
m = new Matrix;
_.transform = tdata || [];
if (tdata) {
for (var i = 0, ii = tdata.length; i < ii; i++) {
var t = tdata[i],
tlen = t.length,
command = Str(t[0]).toLowerCase(),
absolute = t[0] != command,
inver = absolute ? m.invert() : 0,
x1,
y1,
x2,
y2,
bb;
if (command == "t" && tlen == 3) {
if (absolute) {
x1 = inver.x(0, 0);
y1 = inver.y(0, 0);
x2 = inver.x(t[1], t[2]);
y2 = inver.y(t[1], t[2]);
m.translate(x2 - x1, y2 - y1);
} else {
m.translate(t[1], t[2]);
}
} else if (command == "r") {
if (tlen == 2) {
bb = bb || el.getBBox(1);
m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);
deg += t[1];
} else if (tlen == 4) {
if (absolute) {
x2 = inver.x(t[2], t[3]);
y2 = inver.y(t[2], t[3]);
m.rotate(t[1], x2, y2);
} else {
m.rotate(t[1], t[2], t[3]);
}
deg += t[1];
}
} else if (command == "s") {
if (tlen == 2 || tlen == 3) {
bb = bb || el.getBBox(1);
m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);
sx *= t[1];
sy *= t[tlen - 1];
} else if (tlen == 5) {
if (absolute) {
x2 = inver.x(t[3], t[4]);
y2 = inver.y(t[3], t[4]);
m.scale(t[1], t[2], x2, y2);
} else {
m.scale(t[1], t[2], t[3], t[4]);
}
sx *= t[1];
sy *= t[2];
}
} else if (command == "m" && tlen == 7) {
m.add(t[1], t[2], t[3], t[4], t[5], t[6]);
}
_.dirtyT = 1;
el.matrix = m;
}
}
/*\
* Element.matrix
[ property (object) ]
**
* Keeps @Matrix object, which represents element transformation
\*/
el.matrix = m;
_.sx = sx;
_.sy = sy;
_.deg = deg;
_.dx = dx = m.e;
_.dy = dy = m.f;
if (sx == 1 && sy == 1 && !deg && _.bbox) {
_.bbox.x += +dx;
_.bbox.y += +dy;
} else {
_.dirtyT = 1;
}
},
getEmpty = function (item) {
var l = item[0];
switch (l.toLowerCase()) {
case "t": return [l, 0, 0];
case "m": return [l, 1, 0, 0, 1, 0, 0];
case "r": if (item.length == 4) {
return [l, 0, item[2], item[3]];
} else {
return [l, 0];
}
case "s": if (item.length == 5) {
return [l, 1, 1, item[3], item[4]];
} else if (item.length == 3) {
return [l, 1, 1];
} else {
return [l, 1];
}
}
},
equaliseTransform = R._equaliseTransform = function (t1, t2) {
t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
t1 = R.parseTransformString(t1) || [];
t2 = R.parseTransformString(t2) || [];
var maxlength = mmax(t1.length, t2.length),
from = [],
to = [],
i = 0, j, jj,
tt1, tt2;
for (; i < maxlength; i++) {
tt1 = t1[i] || getEmpty(t2[i]);
tt2 = t2[i] || getEmpty(tt1);
if ((tt1[0] != tt2[0]) ||
(tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
(tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
) {
return;
}
from[i] = [];
to[i] = [];
for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {
j in tt1 && (from[i][j] = tt1[j]);
j in tt2 && (to[i][j] = tt2[j]);
}
}
return {
from: from,
to: to
};
};
R._getContainer = function (x, y, w, h) {
var container;
container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x;
if (container == null) {
return;
}
if (container.tagName) {
if (y == null) {
return {
container: container,
width: container.style.pixelWidth || container.offsetWidth,
height: container.style.pixelHeight || container.offsetHeight
};
} else {
return {
container: container,
width: y,
height: w
};
}
}
return {
container: 1,
x: x,
y: y,
width: w,
height: h
};
};
/*\
* Raphael.pathToRelative
[ method ]
**
* Utility method
**
* Converts path to relative form
> Parameters
- pathString (string|array) path string or array of segments
= (array) array of segments.
\*/
R.pathToRelative = pathToRelative;
R._engine = {};
/*\
* Raphael.path2curve
[ method ]
**
* Utility method
**
* Converts path to a new path where all segments are cubic bezier curves.
> Parameters
- pathString (string|array) path string or array of segments
= (array) array of segments.
\*/
R.path2curve = path2curve;
/*\
* Raphael.matrix
[ method ]
**
* Utility method
**
* Returns matrix based on given parameters.
> Parameters
- a (number)
- b (number)
- c (number)
- d (number)
- e (number)
- f (number)
= (object) @Matrix
\*/
R.matrix = function (a, b, c, d, e, f) {
return new Matrix(a, b, c, d, e, f);
};
function Matrix(a, b, c, d, e, f) {
if (a != null) {
this.a = +a;
this.b = +b;
this.c = +c;
this.d = +d;
this.e = +e;
this.f = +f;
} else {
this.a = 1;
this.b = 0;
this.c = 0;
this.d = 1;
this.e = 0;
this.f = 0;
}
}
(function (matrixproto) {
/*\
* Matrix.add
[ method ]
**
* Adds given matrix to existing one.
> Parameters
- a (number)
- b (number)
- c (number)
- d (number)
- e (number)
- f (number)
or
- matrix (object) @Matrix
\*/
matrixproto.add = function (a, b, c, d, e, f) {
var out = [[], [], []],
m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
x, y, z, res;
if (a && a instanceof Matrix) {
matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];
}
for (x = 0; x < 3; x++) {
for (y = 0; y < 3; y++) {
res = 0;
for (z = 0; z < 3; z++) {
res += m[x][z] * matrix[z][y];
}
out[x][y] = res;
}
}
this.a = out[0][0];
this.b = out[1][0];
this.c = out[0][1];
this.d = out[1][1];
this.e = out[0][2];
this.f = out[1][2];
};
/*\
* Matrix.invert
[ method ]
**
* Returns inverted version of the matrix
= (object) @Matrix
\*/
matrixproto.invert = function () {
var me = this,
x = me.a * me.d - me.b * me.c;
return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
};
/*\
* Matrix.clone
[ method ]
**
* Returns copy of the matrix
= (object) @Matrix
\*/
matrixproto.clone = function () {
return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
};
/*\
* Matrix.translate
[ method ]
**
* Translate the matrix
> Parameters
- x (number)
- y (number)
\*/
matrixproto.translate = function (x, y) {
this.add(1, 0, 0, 1, x, y);
};
/*\
* Matrix.scale
[ method ]
**
* Scales the matrix
> Parameters
- x (number)
- y (number) #optional
- cx (number) #optional
- cy (number) #optional
\*/
matrixproto.scale = function (x, y, cx, cy) {
y == null && (y = x);
(cx || cy) && this.add(1, 0, 0, 1, cx, cy);
this.add(x, 0, 0, y, 0, 0);
(cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);
};
/*\
* Matrix.rotate
[ method ]
**
* Rotates the matrix
> Parameters
- a (number)
- x (number)
- y (number)
\*/
matrixproto.rotate = function (a, x, y) {
a = R.rad(a);
x = x || 0;
y = y || 0;
var cos = +math.cos(a).toFixed(9),
sin = +math.sin(a).toFixed(9);
this.add(cos, sin, -sin, cos, x, y);
this.add(1, 0, 0, 1, -x, -y);
};
/*\
* Matrix.x
[ method ]
**
* Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y
> Parameters
- x (number)
- y (number)
= (number) x
\*/
matrixproto.x = function (x, y) {
return x * this.a + y * this.c + this.e;
};
/*\
* Matrix.y
[ method ]
**
* Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x
> Parameters
- x (number)
- y (number)
= (number) y
\*/
matrixproto.y = function (x, y) {
return x * this.b + y * this.d + this.f;
};
matrixproto.get = function (i) {
return +this[Str.fromCharCode(97 + i)].toFixed(4);
};
matrixproto.toString = function () {
return R.svg ?
"matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" :
[this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();
};
matrixproto.toFilter = function () {
return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
};
matrixproto.offset = function () {
return [this.e.toFixed(4), this.f.toFixed(4)];
};
function norm(a) {
return a[0] * a[0] + a[1] * a[1];
}
function normalize(a) {
var mag = math.sqrt(norm(a));
a[0] && (a[0] /= mag);
a[1] && (a[1] /= mag);
}
/*\
* Matrix.split
[ method ]
**
* Splits matrix into primitive transformations
= (object) in format:
o dx (number) translation by x
o dy (number) translation by y
o scalex (number) scale by x
o scaley (number) scale by y
o shear (number) shear
o rotate (number) rotation in deg
o isSimple (boolean) could it be represented via simple transformations
\*/
matrixproto.split = function () {
var out = {};
// translation
out.dx = this.e;
out.dy = this.f;
// scale and shear
var row = [[this.a, this.c], [this.b, this.d]];
out.scalex = math.sqrt(norm(row[0]));
normalize(row[0]);
out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
out.scaley = math.sqrt(norm(row[1]));
normalize(row[1]);
out.shear /= out.scaley;
// rotation
var sin = -row[0][1],
cos = row[1][1];
if (cos < 0) {
out.rotate = R.deg(math.acos(cos));
if (sin < 0) {
out.rotate = 360 - out.rotate;
}
} else {
out.rotate = R.deg(math.asin(sin));
}
out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;
out.noRotation = !+out.shear.toFixed(9) && !out.rotate;
return out;
};
/*\
* Matrix.toTransformString
[ method ]
**
* Return transform string that represents given matrix
= (string) transform string
\*/
matrixproto.toTransformString = function (shorter) {
var s = shorter || this[split]();
if (s.isSimple) {
s.scalex = +s.scalex.toFixed(4);
s.scaley = +s.scaley.toFixed(4);
s.rotate = +s.rotate.toFixed(4);
return (s.dx || s.dy ? "t" + [s.dx, s.dy] : E) +
(s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) +
(s.rotate ? "r" + [s.rotate, 0, 0] : E);
} else {
return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
}
};
})(Matrix.prototype);
var preventDefault = function () {
this.returnValue = false;
},
preventTouch = function () {
return this.originalEvent.preventDefault();
},
stopPropagation = function () {
this.cancelBubble = true;
},
stopTouch = function () {
return this.originalEvent.stopPropagation();
},
getEventPosition = function (e) {
var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
return {
x: e.clientX + scrollX,
y: e.clientY + scrollY
};
},
addEvent = (function () {
if (g.doc.addEventListener) {
return function (obj, type, fn, element) {
var f = function (e) {
var pos = getEventPosition(e);
return fn.call(element, e, pos.x, pos.y);
};
obj.addEventListener(type, f, false);
if (supportsTouch && touchMap[type]) {
var _f = function (e) {
var pos = getEventPosition(e),
olde = e;
for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
if (e.targetTouches[i].target == obj) {
e = e.targetTouches[i];
e.originalEvent = olde;
e.preventDefault = preventTouch;
e.stopPropagation = stopTouch;
break;
}
}
return fn.call(element, e, pos.x, pos.y);
};
obj.addEventListener(touchMap[type], _f, false);
}
return function () {
obj.removeEventListener(type, f, false);
if (supportsTouch && touchMap[type])
obj.removeEventListener(touchMap[type], _f, false);
return true;
};
};
} else if (g.doc.attachEvent) {
return function (obj, type, fn, element) {
var f = function (e) {
e = e || g.win.event;
var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
x = e.clientX + scrollX,
y = e.clientY + scrollY;
e.preventDefault = e.preventDefault || preventDefault;
e.stopPropagation = e.stopPropagation || stopPropagation;
return fn.call(element, e, x, y);
};
obj.attachEvent("on" + type, f);
var detacher = function () {
obj.detachEvent("on" + type, f);
return true;
};
return detacher;
};
}
})(),
drag = [],
dragMove = function (e) {
var x = e.clientX,
y = e.clientY,
scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
dragi,
j = drag.length;
while (j--) {
dragi = drag[j];
if (supportsTouch && e.touches) {
var i = e.touches.length,
touch;
while (i--) {
touch = e.touches[i];
if (touch.identifier == dragi.el._drag.id) {
x = touch.clientX;
y = touch.clientY;
(e.originalEvent ? e.originalEvent : e).preventDefault();
break;
}
}
} else {
e.preventDefault();
}
var node = dragi.el.node,
o,
next = node.nextSibling,
parent = node.parentNode,
display = node.style.display;
g.win.opera && parent.removeChild(node);
node.style.display = "none";
o = dragi.el.paper.getElementByPoint(x, y);
node.style.display = display;
g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));
o && eve("raphael.drag.over." + dragi.el.id, dragi.el, o);
x += scrollX;
y += scrollY;
eve("raphael.drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);
}
},
dragUp = function (e) {
R.unmousemove(dragMove).unmouseup(dragUp);
var i = drag.length,
dragi;
while (i--) {
dragi = drag[i];
dragi.el._drag = {};
eve("raphael.drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);
}
drag = [];
},
/*\
* Raphael.el
[ property (object) ]
**
* You can add your own method to elements. This is useful when you want to hack default functionality or
* want to wrap some common transformation or attributes in one method. In difference to canvas methods,
* you can redefine element method at any time. Expending element methods wouldn’t affect set.
> Usage
| Raphael.el.red = function () {
| this.attr({fill: "#f00"});
| };
| // then use it
| paper.circle(100, 100, 20).red();
\*/
elproto = R.el = {};
/*\
* Element.click
[ method ]
**
* Adds event handler for click for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.unclick
[ method ]
**
* Removes event handler for click for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.dblclick
[ method ]
**
* Adds event handler for double click for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.undblclick
[ method ]
**
* Removes event handler for double click for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.mousedown
[ method ]
**
* Adds event handler for mousedown for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.unmousedown
[ method ]
**
* Removes event handler for mousedown for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.mousemove
[ method ]
**
* Adds event handler for mousemove for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.unmousemove
[ method ]
**
* Removes event handler for mousemove for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.mouseout
[ method ]
**
* Adds event handler for mouseout for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.unmouseout
[ method ]
**
* Removes event handler for mouseout for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.mouseover
[ method ]
**
* Adds event handler for mouseover for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.unmouseover
[ method ]
**
* Removes event handler for mouseover for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.mouseup
[ method ]
**
* Adds event handler for mouseup for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.unmouseup
[ method ]
**
* Removes event handler for mouseup for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.touchstart
[ method ]
**
* Adds event handler for touchstart for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.untouchstart
[ method ]
**
* Removes event handler for touchstart for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.touchmove
[ method ]
**
* Adds event handler for touchmove for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.untouchmove
[ method ]
**
* Removes event handler for touchmove for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.touchend
[ method ]
**
* Adds event handler for touchend for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.untouchend
[ method ]
**
* Removes event handler for touchend for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
/*\
* Element.touchcancel
[ method ]
**
* Adds event handler for touchcancel for the element.
> Parameters
- handler (function) handler for the event
= (object) @Element
\*/
/*\
* Element.untouchcancel
[ method ]
**
* Removes event handler for touchcancel for the element.
> Parameters
- handler (function) #optional handler for the event
= (object) @Element
\*/
for (var i = events.length; i--;) {
(function (eventName) {
R[eventName] = elproto[eventName] = function (fn, scope) {
if (R.is(fn, "function")) {
this.events = this.events || [];
this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});
}
return this;
};
R["un" + eventName] = elproto["un" + eventName] = function (fn) {
var events = this.events || [],
l = events.length;
while (l--){
if (events[l].name == eventName && (R.is(fn, "undefined") || events[l].f == fn)) {
events[l].unbind();
events.splice(l, 1);
!events.length && delete this.events;
}
}
return this;
};
})(events[i]);
}
/*\
* Element.data
[ method ]
**
* Adds or retrieves given value associated with given key.
**
* See also @Element.removeData
> Parameters
- key (string) key to store data
- value (any) #optional value to store
= (object) @Element
* or, if value is not specified:
= (any) value
* or, if key and value are not specified:
= (object) Key/value pairs for all the data associated with the element.
> Usage
| for (var i = 0, i < 5, i++) {
| paper.circle(10 + 15 * i, 10, 10)
| .attr({fill: "#000"})
| .data("i", i)
| .click(function () {
| alert(this.data("i"));
| });
| }
\*/
elproto.data = function (key, value) {
var data = eldata[this.id] = eldata[this.id] || {};
if (arguments.length == 0) {
return data;
}
if (arguments.length == 1) {
if (R.is(key, "object")) {
for (var i in key) if (key[has](i)) {
this.data(i, key[i]);
}
return this;
}
eve("raphael.data.get." + this.id, this, data[key], key);
return data[key];
}
data[key] = value;
eve("raphael.data.set." + this.id, this, value, key);
return this;
};
/*\
* Element.removeData
[ method ]
**
* Removes value associated with an element by given key.
* If key is not provided, removes all the data of the element.
> Parameters
- key (string) #optional key
= (object) @Element
\*/
elproto.removeData = function (key) {
if (key == null) {
eldata[this.id] = {};
} else {
eldata[this.id] && delete eldata[this.id][key];
}
return this;
};
/*\
* Element.getData
[ method ]
**
* Retrieves the element data
= (object) data
\*/
elproto.getData = function () {
return clone(eldata[this.id] || {});
};
/*\
* Element.hover
[ method ]
**
* Adds event handlers for hover for the element.
> Parameters
- f_in (function) handler for hover in
- f_out (function) handler for hover out
- icontext (object) #optional context for hover in handler
- ocontext (object) #optional context for hover out handler
= (object) @Element
\*/
elproto.hover = function (f_in, f_out, scope_in, scope_out) {
return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);
};
/*\
* Element.unhover
[ method ]
**
* Removes event handlers for hover for the element.
> Parameters
- f_in (function) handler for hover in
- f_out (function) handler for hover out
= (object) @Element
\*/
elproto.unhover = function (f_in, f_out) {
return this.unmouseover(f_in).unmouseout(f_out);
};
var draggable = [];
/*\
* Element.drag
[ method ]
**
* Adds event handlers for drag of the element.
> Parameters
- onmove (function) handler for moving
- onstart (function) handler for drag start
- onend (function) handler for drag end
- mcontext (object) #optional context for moving handler
- scontext (object) #optional context for drag start handler
- econtext (object) #optional context for drag end handler
* Additionally following `drag` events will be triggered: `drag.start.red
”, “green
”, “cornflowerblue
”, etc)#000
”, “#fc0
”, etc)#000000
”, “#bd2300
”)rgb(200, 100, 0)
”)rgb(100%, 175%, 0%)
”)hsb(0.5, 0.25, 1)
”)
* * “Catmull-Rom curveto” is a not standard SVG command and added in 2.0 to make life easier.
* Note: there is a special case when path consist of just three commands: “M10,10R…z”. In this case path will smoothly connects to its beginning.
> Usage
| var c = paper.path("M10 10L90 90");
| // draw a diagonal line:
| // move to 10,10, line to 90,90
* For example of path strings, check out these icons: http://raphaeljs.com/icons/
\*/
paperproto.path = function (pathString) {
pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
var out = R._engine.path(R.format[apply](R, arguments), this);
this.__set__ && this.__set__.push(out);
return out;
};
/*\
* Paper.image
[ method ]
**
* Embeds an image into the surface.
**
> Parameters
**
- src (string) URI of the source image
- x (number) x coordinate position
- y (number) y coordinate position
- width (number) width of the image
- height (number) height of the image
= (object) Raphaël element object with type “image”
**
> Usage
| var c = paper.image("apple.png", 10, 10, 80, 80);
\*/
paperproto.image = function (src, x, y, w, h) {
var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
this.__set__ && this.__set__.push(out);
return out;
};
/*\
* Paper.text
[ method ]
**
* Draws a text string. If you need line breaks, put “\n” in the string.
**
> Parameters
**
- x (number) x coordinate position
- y (number) y coordinate position
- text (string) The text string to draw
= (object) Raphaël element object with type “text”
**
> Usage
| var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!");
\*/
paperproto.text = function (x, y, text) {
var out = R._engine.text(this, x || 0, y || 0, Str(text));
this.__set__ && this.__set__.push(out);
return out;
};
/*\
* Paper.set
[ method ]
**
* Creates array-like object to keep and operate several elements at once.
* Warning: it doesn’t create any elements for itself in the page, it just groups existing elements.
* Sets act as pseudo elements — all methods available to an element can be used on a set.
= (object) array-like object that represents set of elements
**
> Usage
| var st = paper.set();
| st.push(
| paper.circle(10, 10, 5),
| paper.circle(30, 10, 5)
| );
| st.attr({fill: "red"}); // changes the fill of both circles
\*/
paperproto.set = function (itemsArray) {
!R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));
var out = new Set(itemsArray);
this.__set__ && this.__set__.push(out);
out["paper"] = this;
out["type"] = "set";
return out;
};
/*\
* Paper.setStart
[ method ]
**
* Creates @Paper.set. All elements that will be created after calling this method and before calling
* @Paper.setFinish will be added to the set.
**
> Usage
| paper.setStart();
| paper.circle(10, 10, 5),
| paper.circle(30, 10, 5)
| var st = paper.setFinish();
| st.attr({fill: "red"}); // changes the fill of both circles
\*/
paperproto.setStart = function (set) {
this.__set__ = set || this.set();
};
/*\
* Paper.setFinish
[ method ]
**
* See @Paper.setStart. This method finishes catching and returns resulting set.
**
= (object) set
\*/
paperproto.setFinish = function (set) {
var out = this.__set__;
delete this.__set__;
return out;
};
/*\
* Paper.getSize
[ method ]
**
* Obtains current paper actual size.
**
= (object)
\*/
paperproto.getSize = function () {
var container = this.canvas.parentNode;
return {
width: container.offsetWidth,
height: container.offsetHeight
};
};
/*\
* Paper.setSize
[ method ]
**
* If you need to change dimensions of the canvas call this method
**
> Parameters
**
- width (number) new width of the canvas
- height (number) new height of the canvas
\*/
paperproto.setSize = function (width, height) {
return R._engine.setSize.call(this, width, height);
};
/*\
* Paper.setViewBox
[ method ]
**
* Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by
* specifying new boundaries.
**
> Parameters
**
- x (number) new x position, default is `0`
- y (number) new y position, default is `0`
- w (number) new width of the canvas
- h (number) new height of the canvas
- fit (boolean) `true` if you want graphics to fit into new boundary box
\*/
paperproto.setViewBox = function (x, y, w, h, fit) {
return R._engine.setViewBox.call(this, x, y, w, h, fit);
};
/*\
* Paper.top
[ property ]
**
* Points to the topmost element on the paper
\*/
/*\
* Paper.bottom
[ property ]
**
* Points to the bottom element on the paper
\*/
paperproto.top = paperproto.bottom = null;
/*\
* Paper.raphael
[ property ]
**
* Points to the @Raphael object/function
\*/
paperproto.raphael = R;
var getOffset = function (elem) {
var box = elem.getBoundingClientRect(),
doc = elem.ownerDocument,
body = doc.body,
docElem = doc.documentElement,
clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,
left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;
return {
y: top,
x: left
};
};
/*\
* Paper.getElementByPoint
[ method ]
**
* Returns you topmost element under given point.
**
= (object) Raphaël element object
> Parameters
**
- x (number) x coordinate from the top left corner of the window
- y (number) y coordinate from the top left corner of the window
> Usage
| paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"});
\*/
paperproto.getElementByPoint = function (x, y) {
var paper = this,
svg = paper.canvas,
target = g.doc.elementFromPoint(x, y);
if (g.win.opera && target.tagName == "svg") {
var so = getOffset(svg),
sr = svg.createSVGRect();
sr.x = x - so.x;
sr.y = y - so.y;
sr.width = sr.height = 1;
var hits = svg.getIntersectionList(sr, null);
if (hits.length) {
target = hits[hits.length - 1];
}
}
if (!target) {
return null;
}
while (target.parentNode && target != svg.parentNode && !target.raphael) {
target = target.parentNode;
}
target == paper.canvas.parentNode && (target = svg);
target = target && target.raphael ? paper.getById(target.raphaelid) : null;
return target;
};
/*\
* Paper.getElementsByBBox
[ method ]
**
* Returns set of elements that have an intersecting bounding box
**
> Parameters
**
- bbox (object) bbox to check with
= (object) @Set
\*/
paperproto.getElementsByBBox = function (bbox) {
var set = this.set();
this.forEach(function (el) {
if (R.isBBoxIntersect(el.getBBox(), bbox)) {
set.push(el);
}
});
return set;
};
/*\
* Paper.getById
[ method ]
**
* Returns you element by its internal ID.
**
> Parameters
**
- id (number) id
= (object) Raphaël element object
\*/
paperproto.getById = function (id) {
var bot = this.bottom;
while (bot) {
if (bot.id == id) {
return bot;
}
bot = bot.next;
}
return null;
};
/*\
* Paper.forEach
[ method ]
**
* Executes given function for each element on the paper
*
* If callback function returns `false` it will stop loop running.
**
> Parameters
**
- callback (function) function to run
- thisArg (object) context object for the callback
= (object) Paper object
> Usage
| paper.forEach(function (el) {
| el.attr({ stroke: "blue" });
| });
\*/
paperproto.forEach = function (callback, thisArg) {
var bot = this.bottom;
while (bot) {
if (callback.call(thisArg, bot) === false) {
return this;
}
bot = bot.next;
}
return this;
};
/*\
* Paper.getElementsByPoint
[ method ]
**
* Returns set of elements that have common point inside
**
> Parameters
**
- x (number) x coordinate of the point
- y (number) y coordinate of the point
= (object) @Set
\*/
paperproto.getElementsByPoint = function (x, y) {
var set = this.set();
this.forEach(function (el) {
if (el.isPointInside(x, y)) {
set.push(el);
}
});
return set;
};
function x_y() {
return this.x + S + this.y;
}
function x_y_w_h() {
return this.x + S + this.y + S + this.width + " \xd7 " + this.height;
}
/*\
* Element.isPointInside
[ method ]
**
* Determine if given point is inside this element’s shape
**
> Parameters
**
- x (number) x coordinate of the point
- y (number) y coordinate of the point
= (boolean) `true` if point inside the shape
\*/
elproto.isPointInside = function (x, y) {
var rp = this.realPath = getPath[this.type](this);
if (this.attr('transform') && this.attr('transform').length) {
rp = R.transformPath(rp, this.attr('transform'));
}
return R.isPointInsidePath(rp, x, y);
};
/*\
* Element.getBBox
[ method ]
**
* Return bounding box for a given element
**
> Parameters
**
- isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`.
= (object) Bounding box object:
o {
o x: (number) top left corner x
o y: (number) top left corner y
o x2: (number) bottom right corner x
o y2: (number) bottom right corner y
o width: (number) width
o height: (number) height
o }
\*/
elproto.getBBox = function (isWithoutTransform) {
if (this.removed) {
return {};
}
var _ = this._;
if (isWithoutTransform) {
if (_.dirty || !_.bboxwt) {
this.realPath = getPath[this.type](this);
_.bboxwt = pathDimensions(this.realPath);
_.bboxwt.toString = x_y_w_h;
_.dirty = 0;
}
return _.bboxwt;
}
if (_.dirty || _.dirtyT || !_.bbox) {
if (_.dirty || !this.realPath) {
_.bboxwt = 0;
this.realPath = getPath[this.type](this);
}
_.bbox = pathDimensions(mapPath(this.realPath, this.matrix));
_.bbox.toString = x_y_w_h;
_.dirty = _.dirtyT = 0;
}
return _.bbox;
};
/*\
* Element.clone
[ method ]
**
= (object) clone of a given element
**
\*/
elproto.clone = function () {
if (this.removed) {
return null;
}
var out = this.paper[this.type]().attr(this.attr());
this.__set__ && this.__set__.push(out);
return out;
};
/*\
* Element.glow
[ method ]
**
* Return set of elements that create glow-like effect around given element. See @Paper.set.
*
* Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself.
**
> Parameters
**
- glow (object) #optional parameters object with all properties optional:
o {
o width (number) size of the glow, default is `10`
o fill (boolean) will it be filled, default is `false`
o opacity (number) opacity, default is `0.5`
o offsetx (number) horizontal offset, default is `0`
o offsety (number) vertical offset, default is `0`
o color (string) glow colour, default is `black`
o }
= (object) @Paper.set of elements that represents glow
\*/
elproto.glow = function (glow) {
if (this.type == "text") {
return null;
}
glow = glow || {};
var s = {
width: (glow.width || 10) + (+this.attr("stroke-width") || 1),
fill: glow.fill || false,
opacity: glow.opacity == null ? .5 : glow.opacity,
offsetx: glow.offsetx || 0,
offsety: glow.offsety || 0,
color: glow.color || "#000"
},
c = s.width / 2,
r = this.paper,
out = r.set(),
path = this.realPath || getPath[this.type](this);
path = this.matrix ? mapPath(path, this.matrix) : path;
for (var i = 1; i < c + 1; i++) {
out.push(r.path(path).attr({
stroke: s.color,
fill: s.fill ? s.color : "none",
"stroke-linejoin": "round",
"stroke-linecap": "round",
"stroke-width": +(s.width / c * i).toFixed(3),
opacity: +(s.opacity / c).toFixed(3)
}));
}
return out.insertBefore(this).translate(s.offsetx, s.offsety);
};
var curveslengths = {},
getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
if (length == null) {
return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
} else {
return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));
}
},
getLengthFactory = function (istotal, subpath) {
return function (path, length, onlystart) {
path = path2curve(path);
var x, y, p, l, sp = "", subpaths = {}, point,
len = 0;
for (var i = 0, ii = path.length; i < ii; i++) {
p = path[i];
if (p[0] == "M") {
x = +p[1];
y = +p[2];
} else {
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);
sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
if (onlystart) {return sp;}
subpaths.start = sp;
sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();
len += l;
x = +p[5];
y = +p[6];
continue;
}
if (!istotal && !subpath) {
point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
return {x: point.x, y: point.y, alpha: point.alpha};
}
}
len += l;
x = +p[5];
y = +p[6];
}
sp += p.shift() + p;
}
subpaths.end = sp;
point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
return point;
};
};
var getTotalLength = getLengthFactory(1),
getPointAtLength = getLengthFactory(),
getSubpathsAtLength = getLengthFactory(0, 1);
/*\
* Raphael.getTotalLength
[ method ]
**
* Returns length of the given path in pixels.
**
> Parameters
**
- path (string) SVG path string.
**
= (number) length.
\*/
R.getTotalLength = getTotalLength;
/*\
* Raphael.getPointAtLength
[ method ]
**
* Return coordinates of the point located at the given length on the given path.
**
> Parameters
**
- path (string) SVG path string
- length (number)
**
= (object) representation of the point:
o {
o x: (number) x coordinate
o y: (number) y coordinate
o alpha: (number) angle of derivative
o }
\*/
R.getPointAtLength = getPointAtLength;
/*\
* Raphael.getSubpath
[ method ]
**
* Return subpath of a given path from given length to given length.
**
> Parameters
**
- path (string) SVG path string
- from (number) position of the start of the segment
- to (number) position of the end of the segment
**
= (string) pathstring for the segment
\*/
R.getSubpath = function (path, from, to) {
if (this.getTotalLength(path) - to < 1e-6) {
return getSubpathsAtLength(path, from).end;
}
var a = getSubpathsAtLength(path, to, 1);
return from ? getSubpathsAtLength(a, from).end : a;
};
/*\
* Element.getTotalLength
[ method ]
**
* Returns length of the path in pixels. Only works for element of “path” type.
= (number) length.
\*/
elproto.getTotalLength = function () {
var path = this.getPath();
if (!path) {
return;
}
if (this.node.getTotalLength) {
return this.node.getTotalLength();
}
return getTotalLength(path);
};
/*\
* Element.getPointAtLength
[ method ]
**
* Return coordinates of the point located at the given length on the given path. Only works for element of “path” type.
**
> Parameters
**
- length (number)
**
= (object) representation of the point:
o {
o x: (number) x coordinate
o y: (number) y coordinate
o alpha: (number) angle of derivative
o }
\*/
elproto.getPointAtLength = function (length) {
var path = this.getPath();
if (!path) {
return;
}
return getPointAtLength(path, length);
};
/*\
* Element.getPath
[ method ]
**
* Returns path of the element. Only works for elements of “path” type and simple elements like circle.
= (object) path
**
\*/
elproto.getPath = function () {
var path,
getPath = R._getPath[this.type];
if (this.type == "text" || this.type == "set") {
return;
}
if (getPath) {
path = getPath(this);
}
return path;
};
/*\
* Element.getSubpath
[ method ]
**
* Return subpath of a given element from given length to given length. Only works for element of “path” type.
**
> Parameters
**
- from (number) position of the start of the segment
- to (number) position of the end of the segment
**
= (string) pathstring for the segment
\*/
elproto.getSubpath = function (from, to) {
var path = this.getPath();
if (!path) {
return;
}
return R.getSubpath(path, from, to);
};
/*\
* Raphael.easing_formulas
[ property ]
**
* Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:
#
# Command Name Parameters
# M moveto (x y)+
# Z closepath (none)
# L lineto (x y)+
# H horizontal lineto x+
# V vertical lineto y+
# C curveto (x1 y1 x2 y2 x y)+
# S smooth curveto (x2 y2 x y)+
# Q quadratic Bézier curveto (x1 y1 x y)+
# T smooth quadratic Bézier curveto (x y)+
# A elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ R Catmull-Rom curveto* x1 y1 (x y)+
#
#
#
\*/
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 params) {
eve("raphael.attr." + key + "." + this.id, this, params[key]);
}
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];
}
}
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;
}
var node = getRealNode(this.node);
node.parentNode.appendChild(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;
}
var node = getRealNode(this.node);
var parentNode = node.parentNode;
parentNode.insertBefore(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 || !element) {
return this;
}
var node = getRealNode(this.node);
var afterNode = getRealNode(element.node || element[element.length - 1].node);
if (afterNode.nextSibling) {
afterNode.parentNode.insertBefore(node, afterNode.nextSibling);
} else {
afterNode.parentNode.appendChild(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 || !element) {
return this;
}
var node = getRealNode(this.node);
var beforeNode = getRealNode(element.node || element[0].node);
beforeNode.parentNode.insertBefore(node, beforeNode);
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");
}
return t;
};
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, 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");
svg.canvas && svg.canvas.appendChild(el);
var res = new Element(el, svg);
res.attrs = {
x: x,
y: y,
"text-anchor": "middle",
text: text,
"font-family": R._availableAttrs["font-family"],
"font-size": R._availableAttrs["font-size"],
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",
"xmlns:xlink": "http://www.w3.org/1999/xlink"
});
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;
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("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
var paperSize = this.getSize(),
size = mmax(w / paperSize.width, h / paperSize.height),
top = this.top,
aspectRatio = fit ? "xMidYMid 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 dependent
* 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;
try {
pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();
} catch (e) {
pos = cnvs.createSVGMatrix();
}
var 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("raphael.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("raphael.remove", this);
this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
for (var i in this) {
this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
}
};
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);
}
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
if (R && !R.vml) {
return;
}
var has = "hasOwnProperty",
Str = String,
toFloat = parseFloat,
math = Math,
round = math.round,
mmax = math.max,
mmin = math.min,
abs = math.abs,
fillString = "fill",
separator = /[, ]+/,
eve = R.eve,
ms = " progid:DXImageTransform.Microsoft",
S = " ",
E = "",
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;behavior:url(#default#VML)",
zoom = 21600,
pathTypes = {path: 1, rect: 1, image: 1},
ovalTypes = {circle: 1, ellipse: 1},
path2vml = function (path) {
var total = /[ahqstv]/ig,
command = R._pathToAbsolute;
Str(path).match(total) && (command = R._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 = command.toLowerCase() == "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;
};
var 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);
if (params.path && o.type == "path" || newpath) {
node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path);
o._.dirty = 1;
if (o.type == "image") {
o._.fillpos = [a.x, a.y];
o._.fillsize = [a.width, a.height];
setCoords(o, 1, 1, 0, 0, 0);
}
}
"transform" in params && o.transform(params.transform);
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));
o._.dirty = 1;
}
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 || R._g.doc.createElement("div"),
dstyle = div.style;
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";
node.parentNode.insertBefore(div, node);
div.appendChild(node);
node.clipRect = div;
}
}
if (!params["clip-rect"]) {
node.clipRect && (node.clipRect.style.clip = "auto");
}
}
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.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 ("stroke-dasharray" in params) {
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(a["font-size"] || fontSize && fontSize[0]) || 10;
s.fontSize = fontSize * m + "px";
res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/"));
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,
pow = Math.pow,
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;
}
var vbs = this.paper._viewBoxShift,
vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E,
oldt;
if (vbs) {
oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E);
}
R._extractTransform(this, vbt + tstr);
var matrix = this.matrix.clone(),
skew = this.skew,
o = this.node,
split,
isGrad = ~Str(this.attrs.fill).indexOf("-"),
isPatt = !Str(this.attrs.fill).indexOf("url(");
matrix.translate(1, 1);
if (isPatt || 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();
}
if (oldt !== null) { // empty string value is true as well
this._.transform = oldt;
R._extractTransform(this, oldt);
}
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;
};
// Needed to fix the vml setViewBox issues
elproto.auxGetBBox = R.el.getBBox;
elproto.getBBox = function(){
var b = this.auxGetBBox();
if (this.paper && this.paper._viewBoxShift)
{
var c = {};
var z = 1/this.paper._viewBoxShift.scale;
c.x = b.x - this.paper._viewBoxShift.dx;
c.x *= z;
c.y = b.y - this.paper._viewBoxShift.dy;
c.y *= z;
c.width = b.width * z;
c.height = b.height * z;
c.x2 = c.x + c.width;
c.y2 = c.y + c.height;
return c;
}
return b;
};
elproto._getBBox = function () {
if (this.removed) {
return {};
}
return {
x: this.X + (this.bbx || 0) - this.W / 2,
y: this.Y - this.H,
width: this.W,
height: this.H
};
};
elproto.remove = function () {
if (this.removed || !this.node.parentNode) {
return;
}
this.paper.__set__ && this.paper.__set__.exclude(this);
R.eve.unbind("raphael.*.*." + 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) {
this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
}
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) {
eve("raphael.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 && R._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);
R._toback(this, this.paper);
}
return this;
};
elproto.insertAfter = function (element) {
if (this.removed) {
return this;
}
if (element.constructor == R.st.constructor) {
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 == R.st.constructor) {
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;
}
return this;
};
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 && 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 = cssDot;
el.coordsize = zoom + S + zoom;
el.coordorigin = "0 0";
var p = new Element(el, vml),
attr = {
fill: "#000",
stroke: "none",
font: R._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) {
R._engine.setViewBox.apply(this, this._viewBox);
}
return this;
};
R._engine.setViewBox = function (x, y, w, h, fit) {
R.eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
var paperSize = this.getSize(),
width = paperSize.width,
height = paperSize.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: paperSize
};
this.forEach(function (el) {
el.transform("...");
});
return this;
};
var createNode;
R._engine.initWin = function (win) {
var doc = win.document;
if (doc.styleSheets.length < 31) {
doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
} else {
// no more room, add to the existing one
// http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
doc.styleSheets[0].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('red
”, “green
”, “cornflowerblue
”, etc)#000
”, “#fc0
”, etc)#000000
”, “#bd2300
”)rgb(200, 100, 0)
”)rgb(100%, 175%, 0%)
”)rgba(200, 100, 0, .5)
”)rgba(100%, 175%, 0%, 50%)
”)hsb(0.5, 0.25, 1)
”)hsl(240deg, 1, .5)
” or, if you want to go fancy, “hsl(240°, 1, .5)
”