raphael.vml.js 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. // ┌─────────────────────────────────────────────────────────────────────┐ \\
  2. // │ Raphaël @@VERSION - JavaScript Vector Library │ \\
  3. // ├─────────────────────────────────────────────────────────────────────┤ \\
  4. // │ VML Module │ \\
  5. // ├─────────────────────────────────────────────────────────────────────┤ \\
  6. // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
  7. // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
  8. // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
  9. // └─────────────────────────────────────────────────────────────────────┘ \\
  10. define(["./raphael.core"], function(R) {
  11. if (R && !R.vml) {
  12. return;
  13. }
  14. var has = "hasOwnProperty",
  15. Str = String,
  16. toFloat = parseFloat,
  17. math = Math,
  18. round = math.round,
  19. mmax = math.max,
  20. mmin = math.min,
  21. abs = math.abs,
  22. fillString = "fill",
  23. separator = /[, ]+/,
  24. eve = R.eve,
  25. ms = " progid:DXImageTransform.Microsoft",
  26. S = " ",
  27. E = "",
  28. map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
  29. bites = /([clmz]),?([^clmz]*)/gi,
  30. blurregexp = / progid:\S+Blur\([^\)]+\)/g,
  31. val = /-?[^,\s-]+/g,
  32. cssDot = "position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)",
  33. zoom = 21600,
  34. pathTypes = {path: 1, rect: 1, image: 1},
  35. ovalTypes = {circle: 1, ellipse: 1},
  36. path2vml = function (path) {
  37. var total = /[ahqstv]/ig,
  38. command = R._pathToAbsolute;
  39. Str(path).match(total) && (command = R._path2curve);
  40. total = /[clmz]/g;
  41. if (command == R._pathToAbsolute && !Str(path).match(total)) {
  42. var res = Str(path).replace(bites, function (all, command, args) {
  43. var vals = [],
  44. isMove = command.toLowerCase() == "m",
  45. res = map[command];
  46. args.replace(val, function (value) {
  47. if (isMove && vals.length == 2) {
  48. res += vals + map[command == "m" ? "l" : "L"];
  49. vals = [];
  50. }
  51. vals.push(round(value * zoom));
  52. });
  53. return res + vals;
  54. });
  55. return res;
  56. }
  57. var pa = command(path), p, r;
  58. res = [];
  59. for (var i = 0, ii = pa.length; i < ii; i++) {
  60. p = pa[i];
  61. r = pa[i][0].toLowerCase();
  62. r == "z" && (r = "x");
  63. for (var j = 1, jj = p.length; j < jj; j++) {
  64. r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
  65. }
  66. res.push(r);
  67. }
  68. return res.join(S);
  69. },
  70. compensation = function (deg, dx, dy) {
  71. var m = R.matrix();
  72. m.rotate(-deg, .5, .5);
  73. return {
  74. dx: m.x(dx, dy),
  75. dy: m.y(dx, dy)
  76. };
  77. },
  78. setCoords = function (p, sx, sy, dx, dy, deg) {
  79. var _ = p._,
  80. m = p.matrix,
  81. fillpos = _.fillpos,
  82. o = p.node,
  83. s = o.style,
  84. y = 1,
  85. flip = "",
  86. dxdy,
  87. kx = zoom / sx,
  88. ky = zoom / sy;
  89. s.visibility = "hidden";
  90. if (!sx || !sy) {
  91. return;
  92. }
  93. o.coordsize = abs(kx) + S + abs(ky);
  94. s.rotation = deg * (sx * sy < 0 ? -1 : 1);
  95. if (deg) {
  96. var c = compensation(deg, dx, dy);
  97. dx = c.dx;
  98. dy = c.dy;
  99. }
  100. sx < 0 && (flip += "x");
  101. sy < 0 && (flip += " y") && (y = -1);
  102. s.flip = flip;
  103. o.coordorigin = (dx * -kx) + S + (dy * -ky);
  104. if (fillpos || _.fillsize) {
  105. var fill = o.getElementsByTagName(fillString);
  106. fill = fill && fill[0];
  107. o.removeChild(fill);
  108. if (fillpos) {
  109. c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));
  110. fill.position = c.dx * y + S + c.dy * y;
  111. }
  112. if (_.fillsize) {
  113. fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);
  114. }
  115. o.appendChild(fill);
  116. }
  117. s.visibility = "visible";
  118. };
  119. R.toString = function () {
  120. return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
  121. };
  122. var addArrow = function (o, value, isEnd) {
  123. var values = Str(value).toLowerCase().split("-"),
  124. se = isEnd ? "end" : "start",
  125. i = values.length,
  126. type = "classic",
  127. w = "medium",
  128. h = "medium";
  129. while (i--) {
  130. switch (values[i]) {
  131. case "block":
  132. case "classic":
  133. case "oval":
  134. case "diamond":
  135. case "open":
  136. case "none":
  137. type = values[i];
  138. break;
  139. case "wide":
  140. case "narrow": h = values[i]; break;
  141. case "long":
  142. case "short": w = values[i]; break;
  143. }
  144. }
  145. var stroke = o.node.getElementsByTagName("stroke")[0];
  146. stroke[se + "arrow"] = type;
  147. stroke[se + "arrowlength"] = w;
  148. stroke[se + "arrowwidth"] = h;
  149. },
  150. setFillAndStroke = function (o, params) {
  151. // o.paper.canvas.style.display = "none";
  152. o.attrs = o.attrs || {};
  153. var node = o.node,
  154. a = o.attrs,
  155. s = node.style,
  156. xy,
  157. 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),
  158. isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),
  159. res = o;
  160. for (var par in params) if (params[has](par)) {
  161. a[par] = params[par];
  162. }
  163. if (newpath) {
  164. a.path = R._getPath[o.type](o);
  165. o._.dirty = 1;
  166. }
  167. params.href && (node.href = params.href);
  168. params.title && (node.title = params.title);
  169. params.target && (node.target = params.target);
  170. params.cursor && (s.cursor = params.cursor);
  171. "blur" in params && o.blur(params.blur);
  172. if (params.path && o.type == "path" || newpath) {
  173. node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path);
  174. o._.dirty = 1;
  175. if (o.type == "image") {
  176. o._.fillpos = [a.x, a.y];
  177. o._.fillsize = [a.width, a.height];
  178. setCoords(o, 1, 1, 0, 0, 0);
  179. }
  180. }
  181. "transform" in params && o.transform(params.transform);
  182. if (isOval) {
  183. var cx = +a.cx,
  184. cy = +a.cy,
  185. rx = +a.rx || +a.r || 0,
  186. ry = +a.ry || +a.r || 0;
  187. 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));
  188. o._.dirty = 1;
  189. }
  190. if ("clip-rect" in params) {
  191. var rect = Str(params["clip-rect"]).split(separator);
  192. if (rect.length == 4) {
  193. rect[2] = +rect[2] + (+rect[0]);
  194. rect[3] = +rect[3] + (+rect[1]);
  195. var div = node.clipRect || R._g.doc.createElement("div"),
  196. dstyle = div.style;
  197. dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
  198. if (!node.clipRect) {
  199. dstyle.position = "absolute";
  200. dstyle.top = 0;
  201. dstyle.left = 0;
  202. dstyle.width = o.paper.width + "px";
  203. dstyle.height = o.paper.height + "px";
  204. node.parentNode.insertBefore(div, node);
  205. div.appendChild(node);
  206. node.clipRect = div;
  207. }
  208. }
  209. if (!params["clip-rect"]) {
  210. node.clipRect && (node.clipRect.style.clip = "auto");
  211. }
  212. }
  213. if (o.textpath) {
  214. var textpathStyle = o.textpath.style;
  215. params.font && (textpathStyle.font = params.font);
  216. params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"');
  217. params["font-size"] && (textpathStyle.fontSize = params["font-size"]);
  218. params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]);
  219. params["font-style"] && (textpathStyle.fontStyle = params["font-style"]);
  220. }
  221. if ("arrow-start" in params) {
  222. addArrow(res, params["arrow-start"]);
  223. }
  224. if ("arrow-end" in params) {
  225. addArrow(res, params["arrow-end"], 1);
  226. }
  227. if (params.opacity != null ||
  228. params["stroke-width"] != null ||
  229. params.fill != null ||
  230. params.src != null ||
  231. params.stroke != null ||
  232. params["stroke-width"] != null ||
  233. params["stroke-opacity"] != null ||
  234. params["fill-opacity"] != null ||
  235. params["stroke-dasharray"] != null ||
  236. params["stroke-miterlimit"] != null ||
  237. params["stroke-linejoin"] != null ||
  238. params["stroke-linecap"] != null) {
  239. var fill = node.getElementsByTagName(fillString),
  240. newfill = false;
  241. fill = fill && fill[0];
  242. !fill && (newfill = fill = createNode(fillString));
  243. if (o.type == "image" && params.src) {
  244. fill.src = params.src;
  245. }
  246. params.fill && (fill.on = true);
  247. if (fill.on == null || params.fill == "none" || params.fill === null) {
  248. fill.on = false;
  249. }
  250. if (fill.on && params.fill) {
  251. var isURL = Str(params.fill).match(R._ISURL);
  252. if (isURL) {
  253. fill.parentNode == node && node.removeChild(fill);
  254. fill.rotate = true;
  255. fill.src = isURL[1];
  256. fill.type = "tile";
  257. var bbox = o.getBBox(1);
  258. fill.position = bbox.x + S + bbox.y;
  259. o._.fillpos = [bbox.x, bbox.y];
  260. R._preload(isURL[1], function () {
  261. o._.fillsize = [this.offsetWidth, this.offsetHeight];
  262. });
  263. } else {
  264. fill.color = R.getRGB(params.fill).hex;
  265. fill.src = E;
  266. fill.type = "solid";
  267. if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) {
  268. a.fill = "none";
  269. a.gradient = params.fill;
  270. fill.rotate = false;
  271. }
  272. }
  273. }
  274. if ("fill-opacity" in params || "opacity" in params) {
  275. var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
  276. opacity = mmin(mmax(opacity, 0), 1);
  277. fill.opacity = opacity;
  278. if (fill.src) {
  279. fill.color = "none";
  280. }
  281. }
  282. node.appendChild(fill);
  283. var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
  284. newstroke = false;
  285. !stroke && (newstroke = stroke = createNode("stroke"));
  286. if ((params.stroke && params.stroke != "none") ||
  287. params["stroke-width"] ||
  288. params["stroke-opacity"] != null ||
  289. params["stroke-dasharray"] ||
  290. params["stroke-miterlimit"] ||
  291. params["stroke-linejoin"] ||
  292. params["stroke-linecap"]) {
  293. stroke.on = true;
  294. }
  295. (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
  296. var strokeColor = R.getRGB(params.stroke);
  297. stroke.on && params.stroke && (stroke.color = strokeColor.hex);
  298. opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
  299. var width = (toFloat(params["stroke-width"]) || 1) * .75;
  300. opacity = mmin(mmax(opacity, 0), 1);
  301. params["stroke-width"] == null && (width = a["stroke-width"]);
  302. params["stroke-width"] && (stroke.weight = width);
  303. width && width < 1 && (opacity *= width) && (stroke.weight = 1);
  304. stroke.opacity = opacity;
  305. params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
  306. stroke.miterlimit = params["stroke-miterlimit"] || 8;
  307. params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
  308. if ("stroke-dasharray" in params) {
  309. var dasharray = {
  310. "-": "shortdash",
  311. ".": "shortdot",
  312. "-.": "shortdashdot",
  313. "-..": "shortdashdotdot",
  314. ". ": "dot",
  315. "- ": "dash",
  316. "--": "longdash",
  317. "- .": "dashdot",
  318. "--.": "longdashdot",
  319. "--..": "longdashdotdot"
  320. };
  321. stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
  322. }
  323. newstroke && node.appendChild(stroke);
  324. }
  325. if (res.type == "text") {
  326. res.paper.canvas.style.display = E;
  327. var span = res.paper.span,
  328. m = 100,
  329. fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/);
  330. s = span.style;
  331. a.font && (s.font = a.font);
  332. a["font-family"] && (s.fontFamily = a["font-family"]);
  333. a["font-weight"] && (s.fontWeight = a["font-weight"]);
  334. a["font-style"] && (s.fontStyle = a["font-style"]);
  335. fontSize = toFloat(a["font-size"] || fontSize && fontSize[0]) || 10;
  336. s.fontSize = fontSize * m + "px";
  337. res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>"));
  338. var brect = span.getBoundingClientRect();
  339. res.W = a.w = (brect.right - brect.left) / m;
  340. res.H = a.h = (brect.bottom - brect.top) / m;
  341. // res.paper.canvas.style.display = "none";
  342. res.X = a.x;
  343. res.Y = a.y + res.H / 2;
  344. ("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));
  345. var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
  346. for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {
  347. res._.dirty = 1;
  348. break;
  349. }
  350. // text-anchor emulation
  351. switch (a["text-anchor"]) {
  352. case "start":
  353. res.textpath.style["v-text-align"] = "left";
  354. res.bbx = res.W / 2;
  355. break;
  356. case "end":
  357. res.textpath.style["v-text-align"] = "right";
  358. res.bbx = -res.W / 2;
  359. break;
  360. default:
  361. res.textpath.style["v-text-align"] = "center";
  362. res.bbx = 0;
  363. break;
  364. }
  365. res.textpath.style["v-text-kern"] = true;
  366. }
  367. // res.paper.canvas.style.display = E;
  368. },
  369. addGradientFill = function (o, gradient, fill) {
  370. o.attrs = o.attrs || {};
  371. var attrs = o.attrs,
  372. pow = Math.pow,
  373. opacity,
  374. oindex,
  375. type = "linear",
  376. fxfy = ".5 .5";
  377. o.attrs.gradient = gradient;
  378. gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {
  379. type = "radial";
  380. if (fx && fy) {
  381. fx = toFloat(fx);
  382. fy = toFloat(fy);
  383. pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
  384. fxfy = fx + S + fy;
  385. }
  386. return E;
  387. });
  388. gradient = gradient.split(/\s*\-\s*/);
  389. if (type == "linear") {
  390. var angle = gradient.shift();
  391. angle = -toFloat(angle);
  392. if (isNaN(angle)) {
  393. return null;
  394. }
  395. }
  396. var dots = R._parseDots(gradient);
  397. if (!dots) {
  398. return null;
  399. }
  400. o = o.shape || o.node;
  401. if (dots.length) {
  402. o.removeChild(fill);
  403. fill.on = true;
  404. fill.method = "none";
  405. fill.color = dots[0].color;
  406. fill.color2 = dots[dots.length - 1].color;
  407. var clrs = [];
  408. for (var i = 0, ii = dots.length; i < ii; i++) {
  409. dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);
  410. }
  411. fill.colors = clrs.length ? clrs.join() : "0% " + fill.color;
  412. if (type == "radial") {
  413. fill.type = "gradientTitle";
  414. fill.focus = "100%";
  415. fill.focussize = "0 0";
  416. fill.focusposition = fxfy;
  417. fill.angle = 0;
  418. } else {
  419. // fill.rotate= true;
  420. fill.type = "gradient";
  421. fill.angle = (270 - angle) % 360;
  422. }
  423. o.appendChild(fill);
  424. }
  425. return 1;
  426. },
  427. Element = function (node, vml) {
  428. this[0] = this.node = node;
  429. node.raphael = true;
  430. this.id = R._oid++;
  431. node.raphaelid = this.id;
  432. this.X = 0;
  433. this.Y = 0;
  434. this.attrs = {};
  435. this.paper = vml;
  436. this.matrix = R.matrix();
  437. this._ = {
  438. transform: [],
  439. sx: 1,
  440. sy: 1,
  441. dx: 0,
  442. dy: 0,
  443. deg: 0,
  444. dirty: 1,
  445. dirtyT: 1
  446. };
  447. !vml.bottom && (vml.bottom = this);
  448. this.prev = vml.top;
  449. vml.top && (vml.top.next = this);
  450. vml.top = this;
  451. this.next = null;
  452. };
  453. var elproto = R.el;
  454. Element.prototype = elproto;
  455. elproto.constructor = Element;
  456. elproto.transform = function (tstr) {
  457. if (tstr == null) {
  458. return this._.transform;
  459. }
  460. var vbs = this.paper._viewBoxShift,
  461. vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E,
  462. oldt;
  463. if (vbs) {
  464. oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E);
  465. }
  466. R._extractTransform(this, vbt + tstr);
  467. var matrix = this.matrix.clone(),
  468. skew = this.skew,
  469. o = this.node,
  470. split,
  471. isGrad = ~Str(this.attrs.fill).indexOf("-"),
  472. isPatt = !Str(this.attrs.fill).indexOf("url(");
  473. matrix.translate(1, 1);
  474. if (isPatt || isGrad || this.type == "image") {
  475. skew.matrix = "1 0 0 1";
  476. skew.offset = "0 0";
  477. split = matrix.split();
  478. if ((isGrad && split.noRotation) || !split.isSimple) {
  479. o.style.filter = matrix.toFilter();
  480. var bb = this.getBBox(),
  481. bbt = this.getBBox(1),
  482. dx = bb.x - bbt.x,
  483. dy = bb.y - bbt.y;
  484. o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
  485. setCoords(this, 1, 1, dx, dy, 0);
  486. } else {
  487. o.style.filter = E;
  488. setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
  489. }
  490. } else {
  491. o.style.filter = E;
  492. skew.matrix = Str(matrix);
  493. skew.offset = matrix.offset();
  494. }
  495. if (oldt !== null) { // empty string value is true as well
  496. this._.transform = oldt;
  497. R._extractTransform(this, oldt);
  498. }
  499. return this;
  500. };
  501. elproto.rotate = function (deg, cx, cy) {
  502. if (this.removed) {
  503. return this;
  504. }
  505. if (deg == null) {
  506. return;
  507. }
  508. deg = Str(deg).split(separator);
  509. if (deg.length - 1) {
  510. cx = toFloat(deg[1]);
  511. cy = toFloat(deg[2]);
  512. }
  513. deg = toFloat(deg[0]);
  514. (cy == null) && (cx = cy);
  515. if (cx == null || cy == null) {
  516. var bbox = this.getBBox(1);
  517. cx = bbox.x + bbox.width / 2;
  518. cy = bbox.y + bbox.height / 2;
  519. }
  520. this._.dirtyT = 1;
  521. this.transform(this._.transform.concat([["r", deg, cx, cy]]));
  522. return this;
  523. };
  524. elproto.translate = function (dx, dy) {
  525. if (this.removed) {
  526. return this;
  527. }
  528. dx = Str(dx).split(separator);
  529. if (dx.length - 1) {
  530. dy = toFloat(dx[1]);
  531. }
  532. dx = toFloat(dx[0]) || 0;
  533. dy = +dy || 0;
  534. if (this._.bbox) {
  535. this._.bbox.x += dx;
  536. this._.bbox.y += dy;
  537. }
  538. this.transform(this._.transform.concat([["t", dx, dy]]));
  539. return this;
  540. };
  541. elproto.scale = function (sx, sy, cx, cy) {
  542. if (this.removed) {
  543. return this;
  544. }
  545. sx = Str(sx).split(separator);
  546. if (sx.length - 1) {
  547. sy = toFloat(sx[1]);
  548. cx = toFloat(sx[2]);
  549. cy = toFloat(sx[3]);
  550. isNaN(cx) && (cx = null);
  551. isNaN(cy) && (cy = null);
  552. }
  553. sx = toFloat(sx[0]);
  554. (sy == null) && (sy = sx);
  555. (cy == null) && (cx = cy);
  556. if (cx == null || cy == null) {
  557. var bbox = this.getBBox(1);
  558. }
  559. cx = cx == null ? bbox.x + bbox.width / 2 : cx;
  560. cy = cy == null ? bbox.y + bbox.height / 2 : cy;
  561. this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
  562. this._.dirtyT = 1;
  563. return this;
  564. };
  565. elproto.hide = function () {
  566. !this.removed && (this.node.style.display = "none");
  567. return this;
  568. };
  569. elproto.show = function () {
  570. !this.removed && (this.node.style.display = E);
  571. return this;
  572. };
  573. // Needed to fix the vml setViewBox issues
  574. elproto.auxGetBBox = R.el.getBBox;
  575. elproto.getBBox = function(){
  576. var b = this.auxGetBBox();
  577. if (this.paper && this.paper._viewBoxShift)
  578. {
  579. var c = {};
  580. var z = 1/this.paper._viewBoxShift.scale;
  581. c.x = b.x - this.paper._viewBoxShift.dx;
  582. c.x *= z;
  583. c.y = b.y - this.paper._viewBoxShift.dy;
  584. c.y *= z;
  585. c.width = b.width * z;
  586. c.height = b.height * z;
  587. c.x2 = c.x + c.width;
  588. c.y2 = c.y + c.height;
  589. return c;
  590. }
  591. return b;
  592. };
  593. elproto._getBBox = function () {
  594. if (this.removed) {
  595. return {};
  596. }
  597. return {
  598. x: this.X + (this.bbx || 0) - this.W / 2,
  599. y: this.Y - this.H,
  600. width: this.W,
  601. height: this.H
  602. };
  603. };
  604. elproto.remove = function () {
  605. if (this.removed || !this.node.parentNode) {
  606. return;
  607. }
  608. this.paper.__set__ && this.paper.__set__.exclude(this);
  609. R.eve.unbind("raphael.*.*." + this.id);
  610. R._tear(this, this.paper);
  611. this.node.parentNode.removeChild(this.node);
  612. this.shape && this.shape.parentNode.removeChild(this.shape);
  613. for (var i in this) {
  614. this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
  615. }
  616. this.removed = true;
  617. };
  618. elproto.attr = function (name, value) {
  619. if (this.removed) {
  620. return this;
  621. }
  622. if (name == null) {
  623. var res = {};
  624. for (var a in this.attrs) if (this.attrs[has](a)) {
  625. res[a] = this.attrs[a];
  626. }
  627. res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
  628. res.transform = this._.transform;
  629. return res;
  630. }
  631. if (value == null && R.is(name, "string")) {
  632. if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
  633. return this.attrs.gradient;
  634. }
  635. var names = name.split(separator),
  636. out = {};
  637. for (var i = 0, ii = names.length; i < ii; i++) {
  638. name = names[i];
  639. if (name in this.attrs) {
  640. out[name] = this.attrs[name];
  641. } else if (R.is(this.paper.customAttributes[name], "function")) {
  642. out[name] = this.paper.customAttributes[name].def;
  643. } else {
  644. out[name] = R._availableAttrs[name];
  645. }
  646. }
  647. return ii - 1 ? out : out[names[0]];
  648. }
  649. if (this.attrs && value == null && R.is(name, "array")) {
  650. out = {};
  651. for (i = 0, ii = name.length; i < ii; i++) {
  652. out[name[i]] = this.attr(name[i]);
  653. }
  654. return out;
  655. }
  656. var params;
  657. if (value != null) {
  658. params = {};
  659. params[name] = value;
  660. }
  661. value == null && R.is(name, "object") && (params = name);
  662. for (var key in params) {
  663. eve("raphael.attr." + key + "." + this.id, this, params[key]);
  664. }
  665. if (params) {
  666. for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
  667. var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
  668. this.attrs[key] = params[key];
  669. for (var subkey in par) if (par[has](subkey)) {
  670. params[subkey] = par[subkey];
  671. }
  672. }
  673. // this.paper.canvas.style.display = "none";
  674. if (params.text && this.type == "text") {
  675. this.textpath.string = params.text;
  676. }
  677. setFillAndStroke(this, params);
  678. // this.paper.canvas.style.display = E;
  679. }
  680. return this;
  681. };
  682. elproto.toFront = function () {
  683. !this.removed && this.node.parentNode.appendChild(this.node);
  684. this.paper && this.paper.top != this && R._tofront(this, this.paper);
  685. return this;
  686. };
  687. elproto.toBack = function () {
  688. if (this.removed) {
  689. return this;
  690. }
  691. if (this.node.parentNode.firstChild != this.node) {
  692. this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
  693. R._toback(this, this.paper);
  694. }
  695. return this;
  696. };
  697. elproto.insertAfter = function (element) {
  698. if (this.removed) {
  699. return this;
  700. }
  701. if (element.constructor == R.st.constructor) {
  702. element = element[element.length - 1];
  703. }
  704. if (element.node.nextSibling) {
  705. element.node.parentNode.insertBefore(this.node, element.node.nextSibling);
  706. } else {
  707. element.node.parentNode.appendChild(this.node);
  708. }
  709. R._insertafter(this, element, this.paper);
  710. return this;
  711. };
  712. elproto.insertBefore = function (element) {
  713. if (this.removed) {
  714. return this;
  715. }
  716. if (element.constructor == R.st.constructor) {
  717. element = element[0];
  718. }
  719. element.node.parentNode.insertBefore(this.node, element.node);
  720. R._insertbefore(this, element, this.paper);
  721. return this;
  722. };
  723. elproto.blur = function (size) {
  724. var s = this.node.runtimeStyle,
  725. f = s.filter;
  726. f = f.replace(blurregexp, E);
  727. if (+size !== 0) {
  728. this.attrs.blur = size;
  729. s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
  730. s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
  731. } else {
  732. s.filter = f;
  733. s.margin = 0;
  734. delete this.attrs.blur;
  735. }
  736. return this;
  737. };
  738. R._engine.path = function (pathString, vml) {
  739. var el = createNode("shape");
  740. el.style.cssText = cssDot;
  741. el.coordsize = zoom + S + zoom;
  742. el.coordorigin = vml.coordorigin;
  743. var p = new Element(el, vml),
  744. attr = {fill: "none", stroke: "#000"};
  745. pathString && (attr.path = pathString);
  746. p.type = "path";
  747. p.path = [];
  748. p.Path = E;
  749. setFillAndStroke(p, attr);
  750. vml.canvas && vml.canvas.appendChild(el);
  751. var skew = createNode("skew");
  752. skew.on = true;
  753. el.appendChild(skew);
  754. p.skew = skew;
  755. p.transform(E);
  756. return p;
  757. };
  758. R._engine.rect = function (vml, x, y, w, h, r) {
  759. var path = R._rectPath(x, y, w, h, r),
  760. res = vml.path(path),
  761. a = res.attrs;
  762. res.X = a.x = x;
  763. res.Y = a.y = y;
  764. res.W = a.width = w;
  765. res.H = a.height = h;
  766. a.r = r;
  767. a.path = path;
  768. res.type = "rect";
  769. return res;
  770. };
  771. R._engine.ellipse = function (vml, x, y, rx, ry) {
  772. var res = vml.path(),
  773. a = res.attrs;
  774. res.X = x - rx;
  775. res.Y = y - ry;
  776. res.W = rx * 2;
  777. res.H = ry * 2;
  778. res.type = "ellipse";
  779. setFillAndStroke(res, {
  780. cx: x,
  781. cy: y,
  782. rx: rx,
  783. ry: ry
  784. });
  785. return res;
  786. };
  787. R._engine.circle = function (vml, x, y, r) {
  788. var res = vml.path(),
  789. a = res.attrs;
  790. res.X = x - r;
  791. res.Y = y - r;
  792. res.W = res.H = r * 2;
  793. res.type = "circle";
  794. setFillAndStroke(res, {
  795. cx: x,
  796. cy: y,
  797. r: r
  798. });
  799. return res;
  800. };
  801. R._engine.image = function (vml, src, x, y, w, h) {
  802. var path = R._rectPath(x, y, w, h),
  803. res = vml.path(path).attr({stroke: "none"}),
  804. a = res.attrs,
  805. node = res.node,
  806. fill = node.getElementsByTagName(fillString)[0];
  807. a.src = src;
  808. res.X = a.x = x;
  809. res.Y = a.y = y;
  810. res.W = a.width = w;
  811. res.H = a.height = h;
  812. a.path = path;
  813. res.type = "image";
  814. fill.parentNode == node && node.removeChild(fill);
  815. fill.rotate = true;
  816. fill.src = src;
  817. fill.type = "tile";
  818. res._.fillpos = [x, y];
  819. res._.fillsize = [w, h];
  820. node.appendChild(fill);
  821. setCoords(res, 1, 1, 0, 0, 0);
  822. return res;
  823. };
  824. R._engine.text = function (vml, x, y, text) {
  825. var el = createNode("shape"),
  826. path = createNode("path"),
  827. o = createNode("textpath");
  828. x = x || 0;
  829. y = y || 0;
  830. text = text || "";
  831. path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1);
  832. path.textpathok = true;
  833. o.string = Str(text);
  834. o.on = true;
  835. el.style.cssText = cssDot;
  836. el.coordsize = zoom + S + zoom;
  837. el.coordorigin = "0 0";
  838. var p = new Element(el, vml),
  839. attr = {
  840. fill: "#000",
  841. stroke: "none",
  842. font: R._availableAttrs.font,
  843. text: text
  844. };
  845. p.shape = el;
  846. p.path = path;
  847. p.textpath = o;
  848. p.type = "text";
  849. p.attrs.text = Str(text);
  850. p.attrs.x = x;
  851. p.attrs.y = y;
  852. p.attrs.w = 1;
  853. p.attrs.h = 1;
  854. setFillAndStroke(p, attr);
  855. el.appendChild(o);
  856. el.appendChild(path);
  857. vml.canvas.appendChild(el);
  858. var skew = createNode("skew");
  859. skew.on = true;
  860. el.appendChild(skew);
  861. p.skew = skew;
  862. p.transform(E);
  863. return p;
  864. };
  865. R._engine.setSize = function (width, height) {
  866. var cs = this.canvas.style;
  867. this.width = width;
  868. this.height = height;
  869. width == +width && (width += "px");
  870. height == +height && (height += "px");
  871. cs.width = width;
  872. cs.height = height;
  873. cs.clip = "rect(0 " + width + " " + height + " 0)";
  874. if (this._viewBox) {
  875. R._engine.setViewBox.apply(this, this._viewBox);
  876. }
  877. return this;
  878. };
  879. R._engine.setViewBox = function (x, y, w, h, fit) {
  880. R.eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
  881. var paperSize = this.getSize(),
  882. width = paperSize.width,
  883. height = paperSize.height,
  884. H, W;
  885. if (fit) {
  886. H = height / h;
  887. W = width / w;
  888. if (w * H < width) {
  889. x -= (width - w * H) / 2 / H;
  890. }
  891. if (h * W < height) {
  892. y -= (height - h * W) / 2 / W;
  893. }
  894. }
  895. this._viewBox = [x, y, w, h, !!fit];
  896. this._viewBoxShift = {
  897. dx: -x,
  898. dy: -y,
  899. scale: paperSize
  900. };
  901. this.forEach(function (el) {
  902. el.transform("...");
  903. });
  904. return this;
  905. };
  906. var createNode;
  907. R._engine.initWin = function (win) {
  908. var doc = win.document;
  909. if (doc.styleSheets.length < 31) {
  910. doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
  911. } else {
  912. // no more room, add to the existing one
  913. // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
  914. doc.styleSheets[0].addRule(".rvml", "behavior:url(#default#VML)");
  915. }
  916. try {
  917. !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
  918. createNode = function (tagName) {
  919. return doc.createElement('<rvml:' + tagName + ' class="rvml">');
  920. };
  921. } catch (e) {
  922. createNode = function (tagName) {
  923. return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
  924. };
  925. }
  926. };
  927. R._engine.initWin(R._g.win);
  928. R._engine.create = function () {
  929. var con = R._getContainer.apply(0, arguments),
  930. container = con.container,
  931. height = con.height,
  932. s,
  933. width = con.width,
  934. x = con.x,
  935. y = con.y;
  936. if (!container) {
  937. throw new Error("VML container not found.");
  938. }
  939. var res = new R._Paper,
  940. c = res.canvas = R._g.doc.createElement("div"),
  941. cs = c.style;
  942. x = x || 0;
  943. y = y || 0;
  944. width = width || 512;
  945. height = height || 342;
  946. res.width = width;
  947. res.height = height;
  948. width == +width && (width += "px");
  949. height == +height && (height += "px");
  950. res.coordsize = zoom * 1e3 + S + zoom * 1e3;
  951. res.coordorigin = "0 0";
  952. res.span = R._g.doc.createElement("span");
  953. res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
  954. c.appendChild(res.span);
  955. cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
  956. if (container == 1) {
  957. R._g.doc.body.appendChild(c);
  958. cs.left = x + "px";
  959. cs.top = y + "px";
  960. cs.position = "absolute";
  961. } else {
  962. if (container.firstChild) {
  963. container.insertBefore(c, container.firstChild);
  964. } else {
  965. container.appendChild(c);
  966. }
  967. }
  968. res.renderfix = function () {};
  969. return res;
  970. };
  971. R.prototype.clear = function () {
  972. R.eve("raphael.clear", this);
  973. this.canvas.innerHTML = E;
  974. this.span = R._g.doc.createElement("span");
  975. this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
  976. this.canvas.appendChild(this.span);
  977. this.bottom = this.top = null;
  978. };
  979. R.prototype.remove = function () {
  980. R.eve("raphael.remove", this);
  981. this.canvas.parentNode.removeChild(this.canvas);
  982. for (var i in this) {
  983. this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
  984. }
  985. return true;
  986. };
  987. var setproto = R.st;
  988. for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
  989. setproto[method] = (function (methodname) {
  990. return function () {
  991. var arg = arguments;
  992. return this.forEach(function (el) {
  993. el[methodname].apply(el, arg);
  994. });
  995. };
  996. })(method);
  997. }
  998. });