From: Dmitry Baranovskiy Date: Mon, 21 Mar 2011 11:36:31 +0000 (+1100) Subject: Documentation typo fixes. X-Git-Tag: v2.0.0~29 X-Git-Url: http://git.roojs.org/?p=raphael;a=commitdiff_plain;h=2711bdf6c8586f0dc6ae034d3376fe30bfcf034e Documentation typo fixes. --- diff --git a/dr.css b/dr.css index c189499..a4adc4c 100644 --- a/dr.css +++ b/dr.css @@ -18,16 +18,16 @@ html, body { background: #eee; border-right: solid #eee 3px; float: right; - font: 300 100.01%/1.4 "Myriad Pro", "Helvetica Neue", Helvetica, "Arial Unicode MS", Arial, sans-serif; + font: 300 16px/1.4 "Myriad Pro", "Helvetica Neue", Helvetica, "Arial Unicode MS", Arial, sans-serif; height: 100%; margin: 0; overflow: auto; - padding: 0 2em; - width: 60em; + padding: 0 30px; + width: 800px; } .dr-toc { margin: 0; - padding: 0 1em; + padding: 0 16px; background: #ddd; list-style: none; font-family: Menlo, Consolas, Monaco, "Lucida Console", monospace; @@ -35,11 +35,11 @@ html, body { border-right: solid #ddd 3px; height: 100%; float: right; - width: 15em; + width: 240px; } #dr { margin: 0 auto; - width: 82em; + width: 1152px; height: 100%; } ::-moz-selection { @@ -63,8 +63,8 @@ pre.code { background: #333; color: #fff; overflow-x: auto; - padding: 1em 2.5em; - margin: 0 -2.5em; + padding: 16px 30px; + margin: 0 -30px; } code b { color: #e9df8f; @@ -92,21 +92,21 @@ em.amp { font-style: italic; } dl.dr-parameters { - margin: .5em 0; + margin: 8px 0; } dt.dr-param { color: #666; font-weight: 400; float: left; - margin-right: 1em; - min-width: 10em; + margin-right: 16px; + min-width: 160px; } dd.dr-type { margin: 0; } dd.dr-description { display: table; - min-height: 1.5em; + min-height: 24px; border: solid 1px #eee; } .dr-type { @@ -115,46 +115,57 @@ dd.dr-description { .dr-type em, .dr-returns em, .dr-property em { - -moz-border-radius: .3em; - -webkit-border-radius: .3em; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; background: #ccc; - border-radius: .3em; - display: block; + border-radius: 5px; float: left; font-size: .75em; font-style: normal; font-weight: 700; - margin: .2em .5em .2em 0; - min-width: 5em; - padding: .1em .5em; + margin: 0 8px 0 0; + min-width: 80px; + padding: 2px 5px; text-align: center; } +.dr-type em.amp, +.dr-returns em.amp, +.dr-property em.amp { + float: none; + background: none; + font-size: 1em; + font-weight: 400; + font-style: italic; + margin: 0; + padding: 0; + min-width: 0; +} .dr-property em.dr-type { - margin: .23em 1em 0 0; + margin: 4px 16px 0 0; } em.dr-type-string { - background: #e5ff7f; - color: #667f00; + background: #e1edb1; + color: #3d4c00; } em.dr-type-object { - background: #ff7f7f; - color: #7f0000; + background: #edb1b1; + color: #4c0000; } em.dr-type-function { - background: #bf7fff; - color: #3f007f; + background: #cfb1ed; + color: #26004c; } em.dr-type-number { - background: #7fb2ff; - color: #00327f; + background: #b1c9ed; + color: #001e4c; } em.dr-type-boolean { - background: #7fffb2; - color: #007f32; + background: #b1edc9; + color: #004c1e; } em.dr-type-array { - background: #ffcc7f; - color: #7f4c00; + background: #edd5b1; + color: #4c2d00; } dd.dr-optional { display: none; @@ -162,20 +173,20 @@ dd.dr-optional { ol.dr-json { background: #ddd; list-style: none; - margin: 0 -2em; - padding: 1em 2em; + margin: 0 -30px; + padding: 16px 30px; } ol.dr-json .dr-json-key { float: left; - min-width: 3em; - margin-right: 1em; + min-width: 50px; + margin-right: 16px; } ol.dr-json .dr-json-description { display: table; } ol.dr-json ol.dr-json { margin: 0; - padding: 0 0 0 3em; + padding: 0 0 0 50px; } h1 { font-weight: 400; @@ -183,22 +194,22 @@ h1 { margin: 0; } h2, h3, h4, h5 { - margin: 1em 0; - padding: .4em 0 0; - font-weight: 100; + margin: 1em 0 .5em 0; + padding: 6px 0 0; + font-weight: 600; position: relative; } h5 { - font-size: 1.1em; + font-size: 18px; } h4 { - font-size: 1.2em; + font-size: 20px; } h3 { - font-size: 1.8em; + font-size: 28px; } h2 { - font-size: 2.4em; + font-size: 38px; } h2.dr-method, h3.dr-method, @@ -212,23 +223,35 @@ h4.dr-property, h5.dr-property { color: #009; } +i.dr-trixie { + border: solid 10px #eee; + border-left-color: #999; + height: 0; + margin-left: -30px; + margin-top: -10px; + overflow: hidden; + position: absolute; + top: 50%; + width: 0; +} p.header { - font-size: 1.2em; - font-weight: 200; + font-size: 19px; + font-weight: 600; + margin: 1em 0 .3em; } .dr-returns { - margin-top: 1em; + margin-top: 16px; } .dr-returns .dr-title { float: left; - margin-right: 1em; - width: 10em; + margin-right: 16px; + width: 160px; } .dr-toc a { display: block; text-decoration: none; color: #333; - padding-top: .5em; + padding-top: 8px; position: relative; z-index: 1000; } @@ -331,7 +354,6 @@ p { background: #333; } #src-dr-js code:hover .ln { -/* background: #666;*/ color: #fff; } #src-dr-js code .ln { diff --git a/raphael-src.html b/raphael-src.html index 8a100f1..a54e890 100644 --- a/raphael-src.html +++ b/raphael-src.html @@ -17,7 +17,7 @@ 15 * from this instance will be bound to this canvas. 16 > Parameters 17 ** -18 - container (HTMLElement|string) DOM element or it’s id which is going to be a parent for drawing surface +18 - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface 19 - width (number) 20 - height (number) 21 * or @@ -31,5901 +31,5899 @@ 29 - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`. 30 = (object) @Paper 31 > Usage -32 | // Each of the following examples create a canvas that is 320px wide by 200px high -33 | // Canvas is created at the viewport’s 10,50 coordinate -34 | var paper = Raphael(10, 50, 320, 200); -35 | // Canvas is created at the top left corner of the #notepad element -36 | // (or its top right corner in dir="rtl" elements) -37 | var paper = Raphael(document.getElementById("notepad"), 320, 200); -38 | // Same as above -39 | var paper = Raphael("notepad", 320, 200); -40 | // Image dump -41 | var set = Raphael(["notepad", 320, 200, { -42 | type: "rect", -43 | x: 10, -44 | y: 10, -45 | width: 25, -46 | height: 25, -47 | stroke: "#f00" -48 | }, { -49 | type: "text", -50 | x: 30, -51 | y: 40, -52 | text: "Dump" -53 | }]); -54 \*/ -55 function R(first) { -56 if (R.is(first, "function")) { -57 return eve.on("DOMload", first); -58 } else if (R.is(first, array)) { -59 var a = first, -60 cnv = create[apply](R, a.splice(0, 3 + R.is(a[0], nu))), -61 res = cnv.set(), -62 i = 0, -63 ii = a.length, -64 j; -65 for (; i < ii; i++) { -66 j = a[i] || {}; -67 elements[has](j.type) && res.push(cnv[j.type]().attr(j)); -68 } -69 return res; -70 } -71 return create[apply](R, arguments); -72 } -73 R.version = "2.0.0"; -74 var separator = /[, ]+/, -75 elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1}, -76 formatrg = /\{(\d+)\}/g, -77 proto = "prototype", -78 has = "hasOwnProperty", -79 g = { -80 doc: document, -81 win: window -82 }, -83 oldRaphael = { -84 was: Object.prototype[has].call(g.win, "Raphael"), -85 is: g.win.Raphael -86 }, -87 Paper = function () {}, -88 paperproto, -89 appendChild = "appendChild", -90 apply = "apply", -91 concat = "concat", -92 supportsTouch = "createTouch" in g.doc, -93 E = "", -94 S = " ", -95 Str = String, -96 split = "split", -97 events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend orientationchange touchcancel gesturestart gesturechange gestureend".split(S), -98 touchMap = { -99 mousedown: "touchstart", -100 mousemove: "touchmove", -101 mouseup: "touchend" -102 }, -103 lowerCase = Str.prototype.toLowerCase, -104 math = Math, -105 mmax = math.max, -106 mmin = math.min, -107 abs = math.abs, -108 pow = math.pow, -109 PI = math.PI, -110 nu = "number", -111 string = "string", -112 array = "array", -113 toString = "toString", -114 fillString = "fill", -115 objectToString = Object.prototype.toString, -116 paper = {}, -117 push = "push", -118 ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, -119 colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i, -120 isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1}, -121 bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, -122 round = math.round, -123 setAttribute = "setAttribute", -124 toFloat = parseFloat, -125 toInt = parseInt, -126 ms = " progid:DXImageTransform.Microsoft", -127 upperCase = Str.prototype.toUpperCase, -128 availableAttrs = {"arrow-end": "none", "arrow-start": "none", blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", opacity: 1, path: "M0,0", r: 0, rx: 0, ry: 0, src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", transform: "", width: 0, x: 0, y: 0}, -129 availableAnimAttrs = {blur: nu, "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rx: nu, ry: nu, stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, transform: "transform", width: nu, x: nu, y: nu}, -130 commaSpaces = /\s*,\s*/, -131 hsrg = {hs: 1, rg: 1}, -132 p2s = /,?([achlmqrstvxz]),?/gi, -133 pathCommand = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, -134 tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, -135 pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig, -136 radial_gradient = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/, -137 sortByKey = function (a, b) { -138 return a.key - b.key; -139 }, -140 sortByNumber = function (a, b) { -141 return a - b; -142 }, -143 fun = function () {}, -144 pipe = function (x) { -145 return x; -146 }, -147 rectPath = function (x, y, w, h, r) { -148 if (r) { -149 return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]]; -150 } -151 return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; -152 }, -153 ellipsePath = function (x, y, rx, ry) { -154 if (ry == null) { -155 ry = rx; -156 } -157 return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]]; -158 }, -159 getPath = { -160 path: function (el) { -161 return el.attr("path"); -162 }, -163 circle: function (el) { -164 var a = el.attrs; -165 return ellipsePath(a.cx, a.cy, a.r); -166 }, -167 ellipse: function (el) { -168 var a = el.attrs; -169 return ellipsePath(a.cx, a.cy, a.rx, a.ry); -170 }, -171 rect: function (el) { -172 var a = el.attrs; -173 return rectPath(a.x, a.y, a.width, a.height, a.r); -174 }, -175 image: function (el) { -176 var a = el.attrs; -177 return rectPath(a.x, a.y, a.width, a.height); -178 }, -179 text: function (el) { -180 var bbox = el._getBBox(); -181 return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); -182 } -183 }, -184 mapPath = function (path, matrix) { -185 if (!matrix) { -186 return path; -187 } -188 var x, y, i, j, pathi; -189 path = path2curve(path); -190 for (i = 0, ii = path.length; i < ii; i++) { -191 pathi = path[i]; -192 for (j = 1, jj = pathi.length; j < jj; j += 2) { -193 x = matrix.x(pathi[j], pathi[j + 1]); -194 y = matrix.y(pathi[j], pathi[j + 1]); -195 pathi[j] = x; -196 pathi[j + 1] = y; -197 } -198 } -199 return path; -200 }; -201 -202 /*\ -203 * Raphael.type -204 [ property (string) ] -205 ** -206 * Can be “SVG”, “VML” or empty, depending on browser support. -207 \*/ -208 R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"); -209 if (R.type == "VML") { -210 var d = g.doc.createElement("div"), -211 b; -212 d.innerHTML = '<v:shape adj="1"/>'; -213 b = d.firstChild; -214 b.style.behavior = "url(#default#VML)"; -215 if (!(b && typeof b.adj == "object")) { -216 return R.type = E; -217 } -218 d = null; -219 } -220 /*\ -221 * Raphael.svg -222 [ property (boolean) ] -223 ** -224 * `true` if browser supports SVG. -225 \*/ -226 /*\ -227 * Raphael.vml -228 [ property (boolean) ] -229 ** -230 * `true` if browser supports VML. -231 \*/ -232 R.svg = !(R.vml = R.type == "VML"); -233 paperproto = Paper.prototype = R.prototype; -234 /*\ -235 * Paper.customAttributes -236 [ property (object) ] -237 ** -238 * If you have a set of attributes that you would like to represent -239 * as a function of some number you can do it easily with custom attributes: -240 > Usage -241 | paper.customAttributes.hue = function (num) { -242 | num = num % 1; -243 | return {fill: "hsb(" + num + ", .75, 1)"}; -244 | }; -245 | // Custom attribute “hue” will change fill -246 | // to be given hue with fixed saturation and brightness. -247 | // Now you can use it like this: -248 | var c = paper.circle(10, 10, 10).attr({hue: .45}); -249 | // or even like this: -250 | c.animate({hue: 1}, 1e3); -251 | -252 | // You could also create custom attribute -253 | // with multiple parameters: -254 | paper.customAttributes.hsb = function (h, s, b) { -255 | return {fill: "hsb(" + [h, s, b].join(",") + ")"}; -256 | }; -257 | c.attr({hsb: ".5 .8 1"}); -258 | c.animate({hsb: "1 0 .5"}, 1e3); -259 \*/ -260 paperproto.customAttributes = {}; -261 R._id = 0; -262 R._oid = 0; -263 /*\ -264 * Raphael.fn -265 [ property (object) ] -266 ** -267 * You can add your own method to the canvas. For example if you want to draw pie chart, -268 * you can create your own pie chart function and ship it as a Raphaël plugin. To do this -269 * you need to extend `Raphael.fn` object. Please note that you can create your own namespaces -270 * inside `fn` object. Methods will be run in context of canvas anyway. You should alter `fn` -271 * object before Raphaël instance was created, otherwise it will take no effect. -272 > Usage -273 | Raphael.fn.arrow = function (x1, y1, x2, y2, size) { -274 | return this.path( ... ); -275 | }; -276 | // or create namespace -277 | Raphael.fn.mystuff = { -278 | arrow: function () {…}, -279 | star: function () {…}, -280 | // etc… -281 | }; -282 | var paper = Raphael(10, 10, 630, 480); -283 | // then use it -284 | paper.arrow(10, 10, 30, 30, 5).attr({fill: "#f00"}); -285 | paper.mystuff.arrow(); -286 | paper.mystuff.star(); -287 \*/ -288 R.fn = {}; -289 /*\ -290 * Raphael.is -291 [ method ] -292 ** -293 * Handfull replacement for `typeof` operator. -294 > Parameters -295 - o (…) any object or primitive -296 - type (string) name of the type, i.e. “string”, “function”, “number”, etc. -297 = (boolean) is given value is of given type -298 \*/ -299 R.is = function (o, type) { -300 type = lowerCase.call(type); -301 if (type == "finite") { -302 return !isnan[has](+o); -303 } -304 return (type == "null" && o === null) || -305 (type == typeof o) || -306 (type == "object" && o === Object(o)) || -307 (type == "array" && Array.isArray && Array.isArray(o)) || -308 objectToString.call(o).slice(8, -1).toLowerCase() == type; -309 }; -310 /*\ -311 * Raphael.angle -312 [ method ] -313 ** -314 * Returns angle between two or three points -315 > Parameters -316 - x1 (number) x coord of first point -317 - y1 (number) y coord of first point -318 - x2 (number) x coord of second point -319 - y2 (number) y coord of second point -320 - x3 (number) #optional x coord of third point -321 - y3 (number) #optional y coord of third point -322 = (number) angle in degrees. -323 \*/ -324 R.angle = function (x1, y1, x2, y2, x3, y3) { -325 if (x3 == null) { -326 var x = x1 - x2, -327 y = y1 - y2; -328 if (!x && !y) { -329 return 0; -330 } -331 return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; -332 } else { -333 return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3); -334 } -335 }; -336 /*\ -337 * Raphael.rad -338 [ method ] -339 ** -340 * Transform angle to radians -341 > Parameters -342 - deg (number) angle in degrees -343 = (number) angle in radians. -344 \*/ -345 R.rad = function (deg) { -346 return deg % 360 * PI / 180; -347 }; -348 /*\ -349 * Raphael.deg -350 [ method ] -351 ** -352 * Transform angle to degrees -353 > Parameters -354 - deg (number) angle in radians -355 = (number) angle in degrees. -356 \*/ -357 R.deg = function (rad) { -358 return rad * 180 / PI % 360; -359 }; -360 /*\ -361 * Raphael.snapTo -362 [ method ] -363 ** -364 * Snaps given value to given grid. -365 > Parameters -366 - values (array|number) given array of values or step of the grid -367 - value (number) value to adjust -368 - tolerance (number) #optional tolerance for snapping. Default is `10`. -369 = (number) adjusted value. -370 \*/ -371 R.snapTo = function (values, value, tolerance) { -372 tolerance = R.is(tolerance, "finite") ? tolerance : 10; -373 if (R.is(values, array)) { -374 var i = values.length; -375 while (i--) if (abs(values[i] - value) <= tolerance) { -376 return values[i]; -377 } -378 } else { -379 values = +values; -380 var rem = value % values; -381 if (rem < tolerance) { -382 return value - rem; -383 } -384 if (rem > values - tolerance) { -385 return value - rem + values; -386 } -387 } -388 return value; -389 }; -390 -391 var createUUID = (function (uuidRegEx, uuidReplacer) { -392 return function () { -393 return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase(); -394 }; -395 })(/[xy]/g, function (c) { -396 var r = math.random() * 16 | 0, -397 v = c == "x" ? r : (r & 3 | 8); -398 return v.toString(16); -399 }); -400 -401 /*\ -402 * Raphael.setWindow -403 [ method ] -404 ** -405 * Used when you need to draw in `<iframe>`. Switched window to the iframe one. -406 > Parameters -407 - newwin (window) new window object -408 \*/ -409 R.setWindow = function (newwin) { -410 eve("setWindow", R, g.win, newwin); -411 g.win = newwin; -412 g.doc = g.win.document; -413 if (initWin) { -414 initWin(g.win); -415 } -416 }; -417 // colour utilities -418 var toHex = function (color) { -419 if (R.vml) { -420 // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/ -421 var trim = /^\s+|\s+$/g; -422 var bod; -423 try { -424 var docum = new ActiveXObject("htmlfile"); -425 docum.write("<body>"); -426 docum.close(); -427 bod = docum.body; -428 } catch(e) { -429 bod = createPopup().document.body; -430 } -431 var range = bod.createTextRange(); -432 toHex = cacher(function (color) { -433 try { -434 bod.style.color = Str(color).replace(trim, E); -435 var value = range.queryCommandValue("ForeColor"); -436 value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16); -437 return "#" + ("000000" + value.toString(16)).slice(-6); -438 } catch(e) { -439 return "none"; -440 } -441 }); -442 } else { -443 var i = g.doc.createElement("i"); -444 i.title = "Rapha\xebl Colour Picker"; -445 i.style.display = "none"; -446 g.doc.body.appendChild(i); -447 toHex = cacher(function (color) { -448 i.style.color = color; -449 return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); -450 }); -451 } -452 return toHex(color); -453 }, -454 hsbtoString = function () { -455 return "hsb(" + [this.h, this.s, this.b] + ")"; -456 }, -457 hsltoString = function () { -458 return "hsl(" + [this.h, this.s, this.l] + ")"; -459 }, -460 rgbtoString = function () { -461 return this.hex; -462 }, -463 prepareRGB = function (r, g, b) { -464 if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) { -465 b = r.b; -466 g = r.g; -467 r = r.r; -468 } -469 if (g == null && R.is(r, string)) { -470 var clr = R.getRGB(r); -471 r = clr.r; -472 g = clr.g; -473 b = clr.b; -474 } -475 if (r > 1 || g > 1 || b > 1) { -476 r /= 255; -477 g /= 255; -478 b /= 255; -479 } -480 -481 return [r, g, b]; -482 }, -483 packageRGB = function (r, g, b, o) { -484 r *= 255; -485 g *= 255; -486 b *= 255; -487 var rgb = { -488 r: r, -489 g: g, -490 b: b, -491 hex: R.rgb(r, g, b), -492 toString: rgbtoString -493 }; -494 R.is(o, "finite") && (rgb.opacity = o); -495 return rgb; -496 }; -497 /*\ -498 * Raphael.hsb2rgb -499 [ method ] -500 ** -501 * Converts HSB values to RGB object. -502 > Parameters -503 - h (number) hue -504 - s (number) saturation -505 - v (number) value or brightness -506 = (object) RGB object in format: -507 o { -508 o r (number) red, -509 o g (number) green, -510 o b (number) blue, -511 o hex (string) color in HTML/CSS format: #•••••• -512 o } -513 \*/ -514 R.hsb2rgb = function (h, s, v, o) { -515 if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) { -516 v = h.b; -517 s = h.s; -518 h = h.h; -519 o = h.o; -520 } -521 h *= 360; -522 var R, G, B, X, C; -523 h = (h % 360) / 60; -524 C = v * s; -525 X = C * (1 - abs(h % 2 - 1)); -526 R = G = B = v - C; -527 -528 h = ~~h; -529 R += [C, X, 0, 0, X, C][h]; -530 G += [X, C, C, X, 0, 0][h]; -531 B += [0, 0, X, C, C, X][h]; -532 return packageRGB(R, G, B, o); -533 }; -534 /*\ -535 * Raphael.hsl2rgb -536 [ method ] -537 ** -538 * Converts HSL values to RGB object. -539 > Parameters -540 - h (number) hue -541 - s (number) saturation -542 - l (number) luminosity -543 = (object) RGB object in format: -544 o { -545 o r (number) red, -546 o g (number) green, -547 o b (number) blue, -548 o hex (string) color in HTML/CSS format: #•••••• -549 o } -550 \*/ -551 R.hsl2rgb = function (h, s, l, o) { -552 if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) { -553 l = h.l; -554 s = h.s; -555 h = h.h; -556 } -557 if (h > 1 || s > 1 || l > 1) { -558 h /= 360; -559 s /= 100; -560 l /= 100; -561 } -562 h *= 360; -563 var R, G, B, X, C; -564 h = (h % 360) / 60; -565 C = 2 * s * (l < .5 ? l : 1 - l); -566 X = C * (1 - abs(h % 2 - 1)); -567 R = G = B = l - C / 2; -568 -569 h = ~~h; -570 R += [C, X, 0, 0, X, C][h]; -571 G += [X, C, C, X, 0, 0][h]; -572 B += [0, 0, X, C, C, X][h]; -573 return packageRGB(R, G, B, o); -574 }; -575 /*\ -576 * Raphael.rgb2hsb -577 [ method ] -578 ** -579 * Converts RGB values to HSB object. -580 > Parameters -581 - r (number) red -582 - g (number) green -583 - b (number) blue -584 = (object) HSB object in format: -585 o { -586 o h (number) hue -587 o s (number) saturation -588 o b (number) brightness -589 o } -590 \*/ -591 R.rgb2hsb = function (r, g, b) { -592 b = prepareRGB(r, g, b); -593 r = b[0]; -594 g = b[1]; -595 b = b[2]; -596 -597 var H, S, V, C; -598 V = mmax(r, g, b); -599 C = V - mmin(r, g, b); -600 H = (C == 0 ? null : -601 V == r ? (g - b) / C : -602 V == g ? (b - r) / C + 2 : -603 (r - g) / C + 4); -604 H = (H % 6) * 60; -605 S = C == 0 ? 0 : C / V; -606 return {h: H, s: S, b: V, toString: hsbtoString}; -607 }; -608 /*\ -609 * Raphael.rgb2hsl -610 [ method ] -611 ** -612 * Converts RGB values to HSL object. -613 > Parameters -614 - r (number) red -615 - g (number) green -616 - b (number) blue -617 = (object) HSL object in format: -618 o { -619 o h (number) hue -620 o s (number) saturation -621 o l (number) luminosity -622 o } -623 \*/ -624 R.rgb2hsl = function (r, g, b) { -625 b = prepareRGB(r, g, b); -626 r = b[0]; -627 g = b[1]; -628 b = b[2]; -629 -630 var H, S, L, M, m, C; -631 M = mmax(r, g, b); -632 m = mmin(r, g, b); -633 C = M - m; -634 H = (C == 0 ? null : -635 M == r ? (g - b) / C : -636 M == g ? (b - r) / C + 2 : -637 (r - g) / C + 4); -638 H = (H % 6) * 60; -639 L = (M + m) / 2; -640 S = (C == 0 ? 0 : -641 L < .5 ? C / (2 * L) : -642 C / (2 - 2 * L)); -643 return {h: H, s: S, l: L, toString: hsltoString}; -644 }; -645 R._path2string = function () { -646 return this.join(",").replace(p2s, "$1"); -647 }; -648 function cacher(f, scope, postprocessor) { -649 function newf() { -650 var arg = Array.prototype.slice.call(arguments, 0), -651 args = arg.join("\u2400"), -652 cache = newf.cache = newf.cache || {}, -653 count = newf.count = newf.count || []; -654 if (cache[has](args)) { -655 return postprocessor ? postprocessor(cache[args]) : cache[args]; -656 } -657 count.length >= 1e3 && delete cache[count.shift()]; -658 count.push(args); -659 cache[args] = f[apply](scope, arg); -660 return postprocessor ? postprocessor(cache[args]) : cache[args]; -661 } -662 return newf; -663 } -664 -665 function preload(src, f) { -666 var img = g.doc.createElement("img"); -667 img.style.cssText = "position:absolute;left:-9999em;top-9999em"; -668 img.onload = function () { -669 f.call(this); -670 this.onload = null; -671 g.doc.body.removeChild(this); -672 }; -673 img.onerror = function () { -674 g.doc.body.removeChild(this); -675 }; -676 g.doc.body.appendChild(img); -677 img.src = src; -678 } -679 -680 /*\ -681 * Raphael.getRGB -682 [ method ] -683 ** -684 * Parses colour string as RGB object -685 > Parameters -686 - colour (string) colour string in one of formats: -687 <ul> -688 <li>Colour name (“<samp>red</samp>”, “<samp>green</samp>”, “<samp>cornflowerblue</samp>”, etc)</li> -689 <li>#••• — shortened HTML colour: (“<samp>#000</samp>”, “<samp>#fc0</samp>”, etc)</li> -690 <li>#•••••• — full length HTML colour: (“<samp>#000000</samp>”, “<samp>#bd2300</samp>”)</li> -691 <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<samp>rgb(2001000)</samp>”)</li> -692 <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<samp>rgb(100%, 175%, 0%)</samp>”)</li> -693 <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<samp>hsb(0.50.251)</samp>”)</li> -694 <li>hsb(•••%, •••%, •••%) — same as above, but in %</li> -695 <li>hsl(•••, •••, •••) — same as hsb</li> -696 <li>hsl(•••%, •••%, •••%) — same as hsb</li> -697 </ul> -698 = (object) RGB object in format: -699 o { -700 o r (number) red, -701 o g (number) green, -702 o b (number) blue -703 o hex (string) color in HTML/CSS format: #••••••, -704 o error (boolean) true if string can’t be parsed -705 o } -706 \*/ -707 R.getRGB = cacher(function (colour) { -708 if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { -709 return {r: -1, g: -1, b: -1, hex: "none", error: 1}; -710 } -711 if (colour == "none") { -712 return {r: -1, g: -1, b: -1, hex: "none"}; -713 } -714 !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); -715 var res, -716 red, -717 green, -718 blue, -719 opacity, -720 t, -721 values, -722 rgb = colour.match(colourRegExp); -723 if (rgb) { -724 if (rgb[2]) { -725 blue = toInt(rgb[2].substring(5), 16); -726 green = toInt(rgb[2].substring(3, 5), 16); -727 red = toInt(rgb[2].substring(1, 3), 16); -728 } -729 if (rgb[3]) { -730 blue = toInt((t = rgb[3].charAt(3)) + t, 16); -731 green = toInt((t = rgb[3].charAt(2)) + t, 16); -732 red = toInt((t = rgb[3].charAt(1)) + t, 16); -733 } -734 if (rgb[4]) { -735 values = rgb[4].split(commaSpaces); -736 red = toFloat(values[0]); -737 values[0].slice(-1) == "%" && (red *= 2.55); -738 green = toFloat(values[1]); -739 values[1].slice(-1) == "%" && (green *= 2.55); -740 blue = toFloat(values[2]); -741 values[2].slice(-1) == "%" && (blue *= 2.55); -742 rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); -743 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); -744 } -745 if (rgb[5]) { -746 values = rgb[5].split(commaSpaces); -747 red = toFloat(values[0]); -748 values[0].slice(-1) == "%" && (red *= 2.55); -749 green = toFloat(values[1]); -750 values[1].slice(-1) == "%" && (green *= 2.55); -751 blue = toFloat(values[2]); -752 values[2].slice(-1) == "%" && (blue *= 2.55); -753 (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); -754 rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); -755 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); -756 return R.hsb2rgb(red, green, blue, opacity); -757 } -758 if (rgb[6]) { -759 values = rgb[6].split(commaSpaces); -760 red = toFloat(values[0]); -761 values[0].slice(-1) == "%" && (red *= 2.55); -762 green = toFloat(values[1]); -763 values[1].slice(-1) == "%" && (green *= 2.55); -764 blue = toFloat(values[2]); -765 values[2].slice(-1) == "%" && (blue *= 2.55); -766 (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); -767 rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); -768 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); -769 return R.hsl2rgb(red, green, blue, opacity); -770 } -771 rgb = {r: red, g: green, b: blue}; -772 rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1); -773 R.is(opacity, "finite") && (rgb.opacity = opacity); -774 return rgb; -775 } -776 return {r: -1, g: -1, b: -1, hex: "none", error: 1}; -777 }, R); -778 /*\ -779 * Raphael.hsb -780 [ method ] -781 ** -782 * Converts HSB values to hex representation of the colour. -783 > Parameters -784 - h (number) hue -785 - s (number) saturation -786 - b (number) value or brightness -787 = (string) hex representation of the colour. -788 \*/ -789 R.hsb = cacher(function (h, s, b) { -790 return R.hsb2rgb(h, s, b).hex; -791 }); -792 /*\ -793 * Raphael.hsl -794 [ method ] -795 ** -796 * Converts HSL values to hex representation of the colour. -797 > Parameters -798 - h (number) hue -799 - s (number) saturation -800 - l (number) luminosity -801 = (string) hex representation of the colour. -802 \*/ -803 R.hsl = cacher(function (h, s, l) { -804 return R.hsl2rgb(h, s, l).hex; -805 }); -806 /*\ -807 * Raphael.rgb -808 [ method ] -809 ** -810 * Converts RGB values to hex representation of the colour. -811 > Parameters -812 - r (number) red -813 - g (number) green -814 - b (number) blue -815 = (string) hex representation of the colour. -816 \*/ -817 R.rgb = cacher(function (r, g, b) { -818 return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); -819 }); -820 /*\ -821 * Raphael.getColor -822 [ method ] -823 ** -824 * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset -825 > Parameters -826 - value (number) #optional brightness, default is `0.75` -827 = (string) hex representation of the colour. -828 \*/ -829 R.getColor = function (value) { -830 var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75}, -831 rgb = this.hsb2rgb(start.h, start.s, start.b); -832 start.h += .075; -833 if (start.h > 1) { -834 start.h = 0; -835 start.s -= .2; -836 start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b}); -837 } -838 return rgb.hex; -839 }; -840 /*\ -841 * Raphael.getColor.reset -842 [ method ] -843 ** -844 * Resets spectrum position for @Raphael.getColor back to red. -845 \*/ -846 R.getColor.reset = function () { -847 delete this.start; -848 }; -849 -850 /*\ -851 * Raphael.parsePathString -852 [ method ] -853 ** -854 * Utility method -855 ** -856 * Parses given path string into an array of arrays of path segments. -857 > Parameters -858 - pathString (string|array) path string or array of segments (in the last case it will be returned stright away) -859 = (array) array of segments. -860 \*/ -861 R.parsePathString = cacher(function (pathString) { -862 if (!pathString) { -863 return null; -864 } -865 var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}, -866 data = []; -867 if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption -868 data = pathClone(pathString); -869 } -870 if (!data.length) { -871 Str(pathString).replace(pathCommand, function (a, b, c) { -872 var params = [], -873 name = lowerCase.call(b); -874 c.replace(pathValues, function (a, b) { -875 b && params.push(+b); -876 }); -877 if (name == "m" && params.length > 2) { -878 data.push([b][concat](params.splice(0, 2))); -879 name = "l"; -880 b = b == "m" ? "l" : "L"; -881 } -882 while (params.length >= paramCounts[name]) { -883 data.push([b][concat](params.splice(0, paramCounts[name]))); -884 if (!paramCounts[name]) { -885 break; -886 } -887 } -888 }); -889 } -890 data.toString = R._path2string; -891 return data; -892 }); -893 /*\ -894 * Raphael.parseTransformString -895 [ method ] -896 ** -897 * Utility method -898 ** -899 * Parses given path string into an array of transformations. -900 > Parameters -901 - TString (string|array) transform string or array of transformations (in the last case it will be returned stright away) -902 = (array) array of transformations. -903 \*/ -904 R.parseTransformString = cacher(function (TString) { -905 if (!TString) { -906 return null; -907 } -908 var paramCounts = {r: 3, s: 4, t: 2, m: 6}, -909 data = []; -910 if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption -911 data = pathClone(TString); -912 } -913 if (!data.length) { -914 Str(TString).replace(tCommand, function (a, b, c) { -915 var params = [], -916 name = lowerCase.call(b); -917 c.replace(pathValues, function (a, b) { -918 b && params.push(+b); -919 }); -920 data.push([name][concat](params)); -921 }); -922 } -923 data.toString = R._path2string; -924 return data; -925 }); -926 /*\ -927 * Raphael.findDotsAtSegment -928 [ method ] -929 ** -930 * Utility method -931 ** -932 * Find dot coordinates on the given cubic bezier curve at the given t. -933 > Parameters -934 - p1x (number) x of the first point of the curve -935 - p1y (number) y of the first point of the curve -936 - c1x (number) x of the first anchor of the curve -937 - c1y (number) y of the first anchor of the curve -938 - c2x (number) x of the second anchor of the curve -939 - c2y (number) y of the second anchor of the curve -940 - p2x (number) x of the second point of the curve -941 - p2y (number) y of the second point of the curve -942 - t (number) position on the curve (0..1) -943 = (object) point information in format: -944 o { -945 o x: (number) x coordinate of the point -946 o y: (number) y coordinate of the point -947 o m: { -948 o x: (number) x coordinate of the left anchor -949 o y: (number) y coordinate of the left anchor -950 o } -951 o n: { -952 o x: (number) x coordinate of the right anchor -953 o y: (number) y coordinate of the right anchor -954 o } -955 o start: { -956 o x: (number) x coordinate of the start of the curve -957 o y: (number) y coordinate of the start of the curve -958 o } -959 o end: { -960 o x: (number) x coordinate of the end of the curve -961 o y: (number) y coordinate of the end of the curve -962 o } -963 o alpha: (number) angle of the curve derivative at the point -964 o } -965 \*/ -966 R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { -967 var t1 = 1 - t, -968 x = pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, -969 y = pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y, -970 mx = p1x + 2 * t * (c1x - p1x) + t * t * (c2x - 2 * c1x + p1x), -971 my = p1y + 2 * t * (c1y - p1y) + t * t * (c2y - 2 * c1y + p1y), -972 nx = c1x + 2 * t * (c2x - c1x) + t * t * (p2x - 2 * c2x + c1x), -973 ny = c1y + 2 * t * (c2y - c1y) + t * t * (p2y - 2 * c2y + c1y), -974 ax = (1 - t) * p1x + t * c1x, -975 ay = (1 - t) * p1y + t * c1y, -976 cx = (1 - t) * c2x + t * p2x, -977 cy = (1 - t) * c2y + t * p2y, -978 alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI); -979 (mx > nx || my < ny) && (alpha += 180); -980 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}; -981 }; -982 var pathDimensions = cacher(function (path) { -983 if (!path) { -984 return {x: 0, y: 0, width: 0, height: 0}; -985 } -986 path = path2curve(path); -987 var x = 0, -988 y = 0, -989 X = [], -990 Y = [], -991 p; -992 for (var i = 0, ii = path.length; i < ii; i++) { -993 p = path[i]; -994 if (p[0] == "M") { -995 x = p[1]; -996 y = p[2]; -997 X.push(x); -998 Y.push(y); -999 } else { -1000 var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); -1001 X = X[concat](dim.min.x, dim.max.x); -1002 Y = Y[concat](dim.min.y, dim.max.y); -1003 x = p[5]; -1004 y = p[6]; -1005 } -1006 } -1007 var xmin = mmin[apply](0, X), -1008 ymin = mmin[apply](0, Y); -1009 return { -1010 x: xmin, -1011 y: ymin, -1012 width: mmax[apply](0, X) - xmin, -1013 height: mmax[apply](0, Y) - ymin -1014 }; -1015 }), -1016 pathClone = function (pathArray) { -1017 var res = []; -1018 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption -1019 pathArray = R.parsePathString(pathArray); -1020 } -1021 for (var i = 0, ii = pathArray.length; i < ii; i++) { -1022 res[i] = []; -1023 for (var j = 0, jj = pathArray[i].length; j < jj; j++) { -1024 res[i][j] = pathArray[i][j]; -1025 } -1026 } -1027 res.toString = R._path2string; -1028 return res; -1029 }, -1030 pathToRelative = cacher(function (pathArray) { -1031 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption -1032 pathArray = R.parsePathString(pathArray); -1033 } -1034 var res = [], -1035 x = 0, -1036 y = 0, -1037 mx = 0, -1038 my = 0, -1039 start = 0; -1040 if (pathArray[0][0] == "M") { -1041 x = pathArray[0][1]; -1042 y = pathArray[0][2]; -1043 mx = x; -1044 my = y; -1045 start++; -1046 res.push(["M", x, y]); -1047 } -1048 for (var i = start, ii = pathArray.length; i < ii; i++) { -1049 var r = res[i] = [], -1050 pa = pathArray[i]; -1051 if (pa[0] != lowerCase.call(pa[0])) { -1052 r[0] = lowerCase.call(pa[0]); -1053 switch (r[0]) { -1054 case "a": -1055 r[1] = pa[1]; -1056 r[2] = pa[2]; -1057 r[3] = pa[3]; -1058 r[4] = pa[4]; -1059 r[5] = pa[5]; -1060 r[6] = +(pa[6] - x).toFixed(3); -1061 r[7] = +(pa[7] - y).toFixed(3); -1062 break; -1063 case "v": -1064 r[1] = +(pa[1] - y).toFixed(3); -1065 break; -1066 case "m": -1067 mx = pa[1]; -1068 my = pa[2]; -1069 default: -1070 for (var j = 1, jj = pa.length; j < jj; j++) { -1071 r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3); -1072 } -1073 } -1074 } else { -1075 r = res[i] = []; -1076 if (pa[0] == "m") { -1077 mx = pa[1] + x; -1078 my = pa[2] + y; -1079 } -1080 for (var k = 0, kk = pa.length; k < kk; k++) { -1081 res[i][k] = pa[k]; -1082 } -1083 } -1084 var len = res[i].length; -1085 switch (res[i][0]) { -1086 case "z": -1087 x = mx; -1088 y = my; -1089 break; -1090 case "h": -1091 x += +res[i][len - 1]; -1092 break; -1093 case "v": -1094 y += +res[i][len - 1]; -1095 break; -1096 default: -1097 x += +res[i][len - 2]; -1098 y += +res[i][len - 1]; -1099 } -1100 } -1101 res.toString = R._path2string; -1102 return res; -1103 }, 0, pathClone), -1104 pathToAbsolute = cacher(function (pathArray) { -1105 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption -1106 pathArray = R.parsePathString(pathArray); -1107 } -1108 var res = [], -1109 x = 0, -1110 y = 0, -1111 mx = 0, -1112 my = 0, -1113 start = 0; -1114 if (pathArray[0][0] == "M") { -1115 x = +pathArray[0][1]; -1116 y = +pathArray[0][2]; -1117 mx = x; -1118 my = y; -1119 start++; -1120 res[0] = ["M", x, y]; -1121 } -1122 for (var i = start, ii = pathArray.length; i < ii; i++) { -1123 var r = res[i] = [], -1124 pa = pathArray[i]; -1125 if (pa[0] != upperCase.call(pa[0])) { -1126 r[0] = upperCase.call(pa[0]); -1127 switch (r[0]) { -1128 case "A": -1129 r[1] = pa[1]; -1130 r[2] = pa[2]; -1131 r[3] = pa[3]; -1132 r[4] = pa[4]; -1133 r[5] = pa[5]; -1134 r[6] = +(pa[6] + x); -1135 r[7] = +(pa[7] + y); -1136 break; -1137 case "V": -1138 r[1] = +pa[1] + y; -1139 break; -1140 case "H": -1141 r[1] = +pa[1] + x; -1142 break; -1143 case "M": -1144 mx = +pa[1] + x; -1145 my = +pa[2] + y; -1146 default: -1147 for (var j = 1, jj = pa.length; j < jj; j++) { -1148 r[j] = +pa[j] + ((j % 2) ? x : y); -1149 } -1150 } -1151 } else { -1152 for (var k = 0, kk = pa.length; k < kk; k++) { -1153 res[i][k] = pa[k]; -1154 } -1155 } -1156 switch (r[0]) { -1157 case "Z": -1158 x = mx; -1159 y = my; -1160 break; -1161 case "H": -1162 x = r[1]; -1163 break; -1164 case "V": -1165 y = r[1]; -1166 break; -1167 case "M": -1168 mx = res[i][res[i].length - 2]; -1169 my = res[i][res[i].length - 1]; -1170 default: -1171 x = res[i][res[i].length - 2]; -1172 y = res[i][res[i].length - 1]; -1173 } -1174 } -1175 res.toString = R._path2string; -1176 return res; -1177 }, null, pathClone), -1178 l2c = function (x1, y1, x2, y2) { -1179 return [x1, y1, x2, y2, x2, y2]; -1180 }, -1181 q2c = function (x1, y1, ax, ay, x2, y2) { -1182 var _13 = 1 / 3, -1183 _23 = 2 / 3; -1184 return [ -1185 _13 * x1 + _23 * ax, -1186 _13 * y1 + _23 * ay, -1187 _13 * x2 + _23 * ax, -1188 _13 * y2 + _23 * ay, -1189 x2, -1190 y2 -1191 ]; -1192 }, -1193 a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { -1194 // for more information of where this math came from visit: -1195 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes -1196 var _120 = PI * 120 / 180, -1197 rad = PI / 180 * (+angle || 0), -1198 res = [], -1199 xy, -1200 rotate = cacher(function (x, y, rad) { -1201 var X = x * math.cos(rad) - y * math.sin(rad), -1202 Y = x * math.sin(rad) + y * math.cos(rad); -1203 return {x: X, y: Y}; -1204 }); -1205 if (!recursive) { -1206 xy = rotate(x1, y1, -rad); -1207 x1 = xy.x; -1208 y1 = xy.y; -1209 xy = rotate(x2, y2, -rad); -1210 x2 = xy.x; -1211 y2 = xy.y; -1212 var cos = math.cos(PI / 180 * angle), -1213 sin = math.sin(PI / 180 * angle), -1214 x = (x1 - x2) / 2, -1215 y = (y1 - y2) / 2; -1216 var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); -1217 if (h > 1) { -1218 h = math.sqrt(h); -1219 rx = h * rx; -1220 ry = h * ry; -1221 } -1222 var rx2 = rx * rx, -1223 ry2 = ry * ry, -1224 k = (large_arc_flag == sweep_flag ? -1 : 1) * -1225 math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), -1226 cx = k * rx * y / ry + (x1 + x2) / 2, -1227 cy = k * -ry * x / rx + (y1 + y2) / 2, -1228 f1 = math.asin(((y1 - cy) / ry).toFixed(9)), -1229 f2 = math.asin(((y2 - cy) / ry).toFixed(9)); -1230 -1231 f1 = x1 < cx ? PI - f1 : f1; -1232 f2 = x2 < cx ? PI - f2 : f2; -1233 f1 < 0 && (f1 = PI * 2 + f1); -1234 f2 < 0 && (f2 = PI * 2 + f2); -1235 if (sweep_flag && f1 > f2) { -1236 f1 = f1 - PI * 2; -1237 } -1238 if (!sweep_flag && f2 > f1) { -1239 f2 = f2 - PI * 2; -1240 } -1241 } else { -1242 f1 = recursive[0]; -1243 f2 = recursive[1]; -1244 cx = recursive[2]; -1245 cy = recursive[3]; -1246 } -1247 var df = f2 - f1; -1248 if (abs(df) > _120) { -1249 var f2old = f2, -1250 x2old = x2, -1251 y2old = y2; -1252 f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); -1253 x2 = cx + rx * math.cos(f2); -1254 y2 = cy + ry * math.sin(f2); -1255 res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); -1256 } -1257 df = f2 - f1; -1258 var c1 = math.cos(f1), -1259 s1 = math.sin(f1), -1260 c2 = math.cos(f2), -1261 s2 = math.sin(f2), -1262 t = math.tan(df / 4), -1263 hx = 4 / 3 * rx * t, -1264 hy = 4 / 3 * ry * t, -1265 m1 = [x1, y1], -1266 m2 = [x1 + hx * s1, y1 - hy * c1], -1267 m3 = [x2 + hx * s2, y2 - hy * c2], -1268 m4 = [x2, y2]; -1269 m2[0] = 2 * m1[0] - m2[0]; -1270 m2[1] = 2 * m1[1] - m2[1]; -1271 if (recursive) { -1272 return [m2, m3, m4][concat](res); -1273 } else { -1274 res = [m2, m3, m4][concat](res).join().split(","); -1275 var newres = []; -1276 for (var i = 0, ii = res.length; i < ii; i++) { -1277 newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; -1278 } -1279 return newres; -1280 } -1281 }, -1282 findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { -1283 var t1 = 1 - t; -1284 return { -1285 x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, -1286 y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y -1287 }; -1288 }, -1289 curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { -1290 var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x), -1291 b = 2 * (c1x - p1x) - 2 * (c2x - c1x), -1292 c = p1x - c1x, -1293 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a, -1294 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a, -1295 y = [p1y, p2y], -1296 x = [p1x, p2x], -1297 dot; -1298 abs(t1) > "1e12" && (t1 = .5); -1299 abs(t2) > "1e12" && (t2 = .5); -1300 if (t1 > 0 && t1 < 1) { -1301 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); -1302 x.push(dot.x); -1303 y.push(dot.y); -1304 } -1305 if (t2 > 0 && t2 < 1) { -1306 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); -1307 x.push(dot.x); -1308 y.push(dot.y); -1309 } -1310 a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y); -1311 b = 2 * (c1y - p1y) - 2 * (c2y - c1y); -1312 c = p1y - c1y; -1313 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a; -1314 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a; -1315 abs(t1) > "1e12" && (t1 = .5); -1316 abs(t2) > "1e12" && (t2 = .5); -1317 if (t1 > 0 && t1 < 1) { -1318 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); -1319 x.push(dot.x); -1320 y.push(dot.y); -1321 } -1322 if (t2 > 0 && t2 < 1) { -1323 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); -1324 x.push(dot.x); -1325 y.push(dot.y); -1326 } -1327 return { -1328 min: {x: mmin[apply](0, x), y: mmin[apply](0, y)}, -1329 max: {x: mmax[apply](0, x), y: mmax[apply](0, y)} -1330 }; -1331 }), -1332 path2curve = cacher(function (path, path2) { -1333 var p = pathToAbsolute(path), -1334 p2 = path2 && pathToAbsolute(path2), -1335 attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, -1336 attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, -1337 processPath = function (path, d) { -1338 var nx, ny; -1339 if (!path) { -1340 return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; -1341 } -1342 !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null); -1343 switch (path[0]) { -1344 case "M": -1345 d.X = path[1]; -1346 d.Y = path[2]; -1347 break; -1348 case "A": -1349 path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1)))); -1350 break; -1351 case "S": -1352 nx = d.x + (d.x - (d.bx || d.x)); -1353 ny = d.y + (d.y - (d.by || d.y)); -1354 path = ["C", nx, ny][concat](path.slice(1)); -1355 break; -1356 case "T": -1357 d.qx = d.x + (d.x - (d.qx || d.x)); -1358 d.qy = d.y + (d.y - (d.qy || d.y)); -1359 path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); -1360 break; -1361 case "Q": -1362 d.qx = path[1]; -1363 d.qy = path[2]; -1364 path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4])); -1365 break; -1366 case "L": -1367 path = ["C"][concat](l2c(d.x, d.y, path[1], path[2])); -1368 break; -1369 case "H": -1370 path = ["C"][concat](l2c(d.x, d.y, path[1], d.y)); -1371 break; -1372 case "V": -1373 path = ["C"][concat](l2c(d.x, d.y, d.x, path[1])); -1374 break; -1375 case "Z": -1376 path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y)); -1377 break; -1378 } -1379 return path; -1380 }, -1381 fixArc = function (pp, i) { -1382 if (pp[i].length > 7) { -1383 pp[i].shift(); -1384 var pi = pp[i]; -1385 while (pi.length) { -1386 pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6))); -1387 } -1388 pp.splice(i, 1); -1389 ii = mmax(p.length, p2 && p2.length || 0); -1390 } -1391 }, -1392 fixM = function (path1, path2, a1, a2, i) { -1393 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { -1394 path2.splice(i, 0, ["M", a2.x, a2.y]); -1395 a1.bx = 0; -1396 a1.by = 0; -1397 a1.x = path1[i][1]; -1398 a1.y = path1[i][2]; -1399 ii = mmax(p.length, p2 && p2.length || 0); -1400 } -1401 }; -1402 for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) { -1403 p[i] = processPath(p[i], attrs); -1404 fixArc(p, i); -1405 p2 && (p2[i] = processPath(p2[i], attrs2)); -1406 p2 && fixArc(p2, i); -1407 fixM(p, p2, attrs, attrs2, i); -1408 fixM(p2, p, attrs2, attrs, i); -1409 var seg = p[i], -1410 seg2 = p2 && p2[i], -1411 seglen = seg.length, -1412 seg2len = p2 && seg2.length; -1413 attrs.x = seg[seglen - 2]; -1414 attrs.y = seg[seglen - 1]; -1415 attrs.bx = toFloat(seg[seglen - 4]) || attrs.x; -1416 attrs.by = toFloat(seg[seglen - 3]) || attrs.y; -1417 attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x); -1418 attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y); -1419 attrs2.x = p2 && seg2[seg2len - 2]; -1420 attrs2.y = p2 && seg2[seg2len - 1]; -1421 } -1422 return p2 ? [p, p2] : p; -1423 }, null, pathClone), -1424 parseDots = cacher(function (gradient) { -1425 var dots = []; -1426 for (var i = 0, ii = gradient.length; i < ii; i++) { -1427 var dot = {}, -1428 par = gradient[i].match(/^([^:]*):?([\d\.]*)/); -1429 dot.color = R.getRGB(par[1]); -1430 if (dot.color.error) { -1431 return null; -1432 } -1433 dot.color = dot.color.hex; -1434 par[2] && (dot.offset = par[2] + "%"); -1435 dots.push(dot); -1436 } -1437 for (i = 1, ii = dots.length - 1; i < ii; i++) { -1438 if (!dots[i].offset) { -1439 var start = toFloat(dots[i - 1].offset || 0), -1440 end = 0; -1441 for (var j = i + 1; j < ii; j++) { -1442 if (dots[j].offset) { -1443 end = dots[j].offset; -1444 break; -1445 } -1446 } -1447 if (!end) { -1448 end = 100; -1449 j = ii; -1450 } -1451 end = toFloat(end); -1452 var d = (end - start) / (j - i + 1); -1453 for (; i < j; i++) { -1454 start += d; -1455 dots[i].offset = start + "%"; -1456 } -1457 } -1458 } -1459 return dots; -1460 }), -1461 getContainer = function (x, y, w, h) { -1462 var container; -1463 container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x; -1464 if (container == null) { -1465 return; -1466 } -1467 if (container.tagName) { -1468 if (y == null) { -1469 return { -1470 container: container, -1471 width: container.style.pixelWidth || container.offsetWidth, -1472 height: container.style.pixelHeight || container.offsetHeight -1473 }; -1474 } else { -1475 return {container: container, width: y, height: w}; -1476 } -1477 } -1478 return {container: 1, x: x, y: y, width: w, height: h}; -1479 }, -1480 plugins = function (con, add) { -1481 var that = this; -1482 for (var prop in add) { -1483 if (add[has](prop) && !(prop in con)) { -1484 switch (typeof add[prop]) { -1485 case "function": -1486 (function (f) { -1487 con[prop] = con === that ? f : function () { return f[apply](that, arguments); }; -1488 })(add[prop]); -1489 break; -1490 case "object": -1491 con[prop] = con[prop] || {}; -1492 plugins.call(this, con[prop], add[prop]); -1493 break; -1494 default: -1495 con[prop] = add[prop]; -1496 break; -1497 } -1498 } -1499 } -1500 }, -1501 tear = function (el, paper) { -1502 el == paper.top && (paper.top = el.prev); -1503 el == paper.bottom && (paper.bottom = el.next); -1504 el.next && (el.next.prev = el.prev); -1505 el.prev && (el.prev.next = el.next); -1506 }, -1507 tofront = function (el, paper) { -1508 if (paper.top === el) { -1509 return; -1510 } -1511 tear(el, paper); -1512 el.next = null; -1513 el.prev = paper.top; -1514 paper.top.next = el; -1515 paper.top = el; -1516 }, -1517 toback = function (el, paper) { -1518 if (paper.bottom === el) { -1519 return; -1520 } -1521 tear(el, paper); -1522 el.next = paper.bottom; -1523 el.prev = null; -1524 paper.bottom.prev = el; -1525 paper.bottom = el; -1526 }, -1527 insertafter = function (el, el2, paper) { -1528 tear(el, paper); -1529 el2 == paper.top && (paper.top = el); -1530 el2.next && (el2.next.prev = el); -1531 el.next = el2.next; -1532 el.prev = el2; -1533 el2.next = el; -1534 }, -1535 insertbefore = function (el, el2, paper) { -1536 tear(el, paper); -1537 el2 == paper.bottom && (paper.bottom = el); -1538 el2.prev && (el2.prev.next = el); -1539 el.prev = el2.prev; -1540 el2.prev = el; -1541 el.next = el2; -1542 }, -1543 removed = function (methodname) { -1544 return function () { -1545 throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object"); -1546 }; -1547 }, -1548 extractTransform = function (el, tstr) { -1549 if (tstr == null) { -1550 return el._.transform; -1551 } -1552 tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E); -1553 var tdata = R.parseTransformString(tstr), -1554 deg = 0, -1555 dx = 0, -1556 dy = 0, -1557 sx = 1, -1558 sy = 1, -1559 _ = el._, -1560 m = new Matrix; -1561 _.transform = tdata || []; -1562 if (tdata) { -1563 for (var i = 0, ii = tdata.length; i < ii; i++) { -1564 var t = tdata[i], -1565 tlen = t.length, -1566 bb; -1567 t[0] = Str(t[0]).toLowerCase(); -1568 if (t[0] == "t" && tlen == 3) { -1569 m.translate(t[1], t[2]); -1570 } else if (t[0] == "r") { -1571 if (tlen == 2) { -1572 bb = bb || el.getBBox(1); -1573 m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2); -1574 deg += t[1]; -1575 } else if (tlen == 4) { -1576 m.rotate(t[1], t[2], t[3]); -1577 deg += t[1]; -1578 } -1579 } else if (t[0] == "s") { -1580 if (tlen == 2 || tlen == 3) { -1581 bb = bb || el.getBBox(1); -1582 m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2); -1583 sx *= t[1]; -1584 sy *= t[tlen - 1]; -1585 } else if (tlen == 5) { -1586 m.scale(t[1], t[2], t[3], t[4]); -1587 sx *= t[1]; -1588 sy *= t[2]; -1589 } -1590 } else if (t[0] == "m" && tlen == 7) { -1591 m.add(t[1], t[2], t[3], t[4], t[5], t[6]); -1592 } -1593 _.dirtyT = 1; -1594 el.matrix = m; -1595 } -1596 } -1597 -1598 el.matrix = m; -1599 -1600 _.sx = sx; -1601 _.sy = sy; -1602 _.deg = deg; -1603 _.dx = dx = m.m[0][2]; -1604 _.dy = dy = m.m[1][2]; -1605 -1606 if (sx == 1 && sy == 1 && !deg && _.bbox) { -1607 _.bbox.x += +dx; -1608 _.bbox.y += +dy; -1609 } else { -1610 _.dirtyT = 1; -1611 } -1612 }, -1613 getEmpty = function (item) { -1614 switch (item[0]) { -1615 case "t": return ["t", 0, 0]; -1616 case "m": return ["m", 1, 0, 0, 1, 0, 0]; -1617 case "r": if (item.length == 4) { -1618 return ["r", 0, item[2], item[3]]; -1619 } else { -1620 return ["r", 0]; -1621 } -1622 case "s": if (item.length == 5) { -1623 return ["s", 1, 1, item[3], item[4]]; -1624 } else if (item.length == 3) { -1625 return ["s", 1, 1]; -1626 } else { -1627 return ["s", 1]; -1628 } -1629 } -1630 }, -1631 equaliseTransform = function (t1, t2) { -1632 t1 = R.parseTransformString(t1) || []; -1633 t2 = R.parseTransformString(t2) || []; -1634 var maxlength = mmax(t1.length, t2.length), -1635 from = [], -1636 to = [], -1637 i = 0, j, jj, -1638 tt1, tt2; -1639 for (; i < maxlength; i++) { -1640 tt1 = t1[i] || getEmpty(t2[i]); -1641 tt2 = t2[i] || getEmpty(tt1); -1642 if ( (tt1[0] != tt2[0]) || -1643 (tt1[0] == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || -1644 (tt1[0] == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) -1645 ) { -1646 return; -1647 } -1648 from[i] = []; -1649 to[i] = []; -1650 for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) { -1651 j in tt1 && (from[i][j] = tt1[j]); -1652 j in tt2 && (to[i][j] = tt2[j]); -1653 } -1654 } -1655 return { -1656 from: from, -1657 to: to -1658 }; -1659 }; -1660 /*\ -1661 * Raphael.pathToRelative -1662 [ method ] -1663 ** -1664 * Utility method -1665 ** -1666 * Converts path to relative form -1667 > Parameters -1668 - pathString (string|array) path string or array of segments -1669 = (array) array of segments. -1670 \*/ -1671 R.pathToRelative = pathToRelative; -1672 /*\ -1673 * Raphael.path2curve -1674 [ method ] -1675 ** -1676 * Utility method -1677 ** -1678 * Converts path to path where all segments are cubic bezier curves. -1679 > Parameters -1680 - pathString (string|array) path string or array of segments -1681 = (array) array of segments. -1682 \*/ -1683 R.path2curve = path2curve; -1684 // Matrix -1685 // var m = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix(); -1686 function Matrix(a, b, c, d, e, f) { -1687 if (a != null) { -1688 this.m = [[a, c, e], [b, d, f], [0, 0, 1]]; -1689 } else { -1690 this.m = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; -1691 } -1692 } -1693 var matrixproto = Matrix.prototype; -1694 matrixproto.add = function (a, b, c, d, e, f) { -1695 var out = [[], [], []], -1696 matrix = [[a, c, e], [b, d, f], [0, 0, 1]], -1697 x, y, z, res; -1698 -1699 for (x = 0; x < 3; x++) { -1700 for (y = 0; y < 3; y++) { -1701 res = 0; -1702 for (z = 0; z < 3; z++) { -1703 res += this.m[x][z] * matrix[z][y]; -1704 } -1705 out[x][y] = res; -1706 } -1707 } -1708 this.m = out; -1709 }; -1710 matrixproto.invert = function () { -1711 var a = this.m[0][0], -1712 b = this.m[1][0], -1713 c = this.m[0][1], -1714 d = this.m[1][1], -1715 e = this.m[0][2], -1716 f = this.m[1][2], -1717 x = a * d - b * c; -1718 return new Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x); -1719 }; -1720 matrixproto.clone = function () { -1721 var a = this.m[0][0], -1722 b = this.m[1][0], -1723 c = this.m[0][1], -1724 d = this.m[1][1], -1725 e = this.m[0][2], -1726 f = this.m[1][2]; -1727 return new Matrix(a, b, c, d, e, f); -1728 }; -1729 matrixproto.translate = function (x, y) { -1730 this.add(1, 0, 0, 1, x, y); -1731 }; -1732 matrixproto.scale = function (x, y, cx, cy) { -1733 y == null && (y = x); -1734 this.add(1, 0, 0, 1, cx, cy); -1735 this.add(x, 0, 0, y, 0, 0); -1736 this.add(1, 0, 0, 1, -cx, -cy); -1737 }; -1738 matrixproto.rotate = function (a, x, y) { -1739 a = R.rad(a); -1740 var cos = +math.cos(a).toFixed(9), -1741 sin = +math.sin(a).toFixed(9); -1742 this.add(cos, sin, -sin, cos, x, y); -1743 this.add(1, 0, 0, 1, -x, -y); -1744 }; -1745 matrixproto.x = function (x, y) { -1746 return x * this.m[0][0] + y * this.m[0][1] + this.m[0][2]; -1747 }; -1748 matrixproto.y = function (x, y) { -1749 return x * this.m[1][0] + y * this.m[1][1] + this.m[1][2]; -1750 }; -1751 matrixproto.get = function (i, j) { -1752 return +this.m[i][j].toFixed(4); -1753 }; -1754 matrixproto.toString = function () { -1755 return R.svg ? -1756 "matrix(" + [this.get(0, 0), this.get(1, 0), this.get(0, 1), this.get(1, 1), this.get(0, 2), this.get(1, 2)].join() + ")" : -1757 [this.get(0, 0), this.get(0, 1), this.get(1, 0), this.get(1, 1), 0, 0].join(); -1758 }; -1759 matrixproto.toFilter = function () { -1760 return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0, 0) + -1761 ", M12=" + this.get(0, 1) + ", M21=" + this.get(1, 0) + ", M22=" + this.get(1, 1) + -1762 ", Dx=" + this.get(0, 2) + ", Dy=" + this.get(1, 2) + ", sizingmedthod='auto expand')"; -1763 }; -1764 matrixproto.offset = function () { -1765 return [this.m[0][2].toFixed(4), this.m[1][2].toFixed(4)]; -1766 }; -1767 -1768 R.Matrix = Matrix; -1769 -1770 // SVG -1771 if (R.svg) { -1772 var xlink = "http://www.w3.org/1999/xlink", -1773 markers = { -1774 block: "M5,0 0,2.5 5,5z", -1775 classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z", -1776 diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z", -1777 open: "M6,1 1,3.5 6,6", -1778 oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z" -1779 }, -1780 markerCounter = {}; -1781 R.toString = function () { -1782 return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version; -1783 }; -1784 var $ = function (el, attr) { -1785 if (attr) { -1786 if (typeof el == "string") { -1787 el = $(el); -1788 } -1789 for (var key in attr) if (attr[has](key)) { -1790 if (key.substring(0, 6) == "xlink:") { -1791 el.setAttributeNS(xlink, key.substring(6), Str(attr[key])); -1792 } else { -1793 el[setAttribute](key, Str(attr[key])); -1794 } -1795 } -1796 } else { -1797 el = g.doc.createElementNS("http://www.w3.org/2000/svg", el); -1798 el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)"); -1799 } -1800 return el; -1801 }, -1802 thePath = function (pathString, SVG) { -1803 var el = $("path"); -1804 SVG.canvas && SVG.canvas.appendChild(el); -1805 var p = new Element(el, SVG); -1806 p.type = "path"; -1807 setFillAndStroke(p, {fill: "none", stroke: "#000", path: pathString}); -1808 return p; -1809 }, -1810 gradients = {}, -1811 rgGrad = /^url\(#(.*)\)$/, -1812 removeGradientFill = function (node, paper) { -1813 var oid = node.getAttribute(fillString); -1814 oid = oid && oid.match(rgGrad); -1815 if (oid && !--gradients[oid[1]]) { -1816 delete gradients[oid[1]]; -1817 paper.defs.removeChild(g.doc.getElementById(oid[1])); -1818 } -1819 }, -1820 addGradientFill = function (element, gradient) { -1821 var type = "linear", -1822 id = element.id + gradient, -1823 fx = .5, fy = .5, -1824 o = element.node, -1825 SVG = element.paper, -1826 s = o.style, -1827 el = g.doc.getElementById(id); -1828 if (!el) { -1829 gradient = Str(gradient).replace(radial_gradient, function (all, _fx, _fy) { -1830 type = "radial"; -1831 if (_fx && _fy) { -1832 fx = toFloat(_fx); -1833 fy = toFloat(_fy); -1834 var dir = ((fy > .5) * 2 - 1); -1835 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && -1836 (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) && -1837 fy != .5 && -1838 (fy = fy.toFixed(5) - 1e-5 * dir); -1839 } -1840 return E; -1841 }); -1842 gradient = gradient.split(/\s*\-\s*/); -1843 if (type == "linear") { -1844 var angle = gradient.shift(); -1845 angle = -toFloat(angle); -1846 if (isNaN(angle)) { -1847 return null; -1848 } -1849 var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))], -1850 max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1); -1851 vector[2] *= max; -1852 vector[3] *= max; -1853 if (vector[2] < 0) { -1854 vector[0] = -vector[2]; -1855 vector[2] = 0; -1856 } -1857 if (vector[3] < 0) { -1858 vector[1] = -vector[3]; -1859 vector[3] = 0; -1860 } -1861 } -1862 var dots = parseDots(gradient); -1863 if (!dots) { -1864 return null; -1865 } -1866 if (element.gradient) { -1867 SVG.defs.removeChild(element.gradient); -1868 delete element.gradient; -1869 } -1870 -1871 el = $(type + "Gradient", {id: id}); -1872 element.gradient = el; -1873 $(el, type == "radial" ? { -1874 fx: fx, -1875 fy: fy -1876 } : { -1877 x1: vector[0], -1878 y1: vector[1], -1879 x2: vector[2], -1880 y2: vector[3], -1881 gradientTransform: element.matrix.invert() -1882 }); -1883 SVG.defs.appendChild(el); -1884 for (var i = 0, ii = dots.length; i < ii; i++) { -1885 el.appendChild($("stop", { -1886 offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%", -1887 "stop-color": dots[i].color || "#fff" -1888 })); -1889 } -1890 } -1891 $(o, { -1892 fill: "url(#" + id + ")", -1893 opacity: 1, -1894 "fill-opacity": 1 -1895 }); -1896 s.fill = E; -1897 s.opacity = 1; -1898 s.fillOpacity = 1; -1899 return 1; -1900 }, -1901 updatePosition = function (o) { -1902 var bbox = o.getBBox(1); -1903 $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"}); -1904 }, -1905 addArrow = function (o, value, isEnd) { -1906 if (o.type == "path") { -1907 var values = Str(value).toLowerCase().split("-"), -1908 p = o.paper, -1909 se = isEnd ? "end" : "start", -1910 node = o.node, -1911 attrs = o.attrs, -1912 stroke = attrs["stroke-width"], -1913 i = values.length, -1914 type = "classic", -1915 from, -1916 to, -1917 dx, -1918 refX, -1919 attr, -1920 w = 3, -1921 h = 3, -1922 t = 5; -1923 while (i--) { -1924 switch (values[i]) { -1925 case "block": -1926 case "classic": -1927 case "oval": -1928 case "diamond": -1929 case "open": -1930 case "none": -1931 type = values[i]; -1932 break; -1933 case "wide": h = 5; break; -1934 case "narrow": h = 2; break; -1935 case "long": w = 5; break; -1936 case "short": w = 2; break; -1937 } -1938 } -1939 if (type == "open") { -1940 w += 2; -1941 h += 2; -1942 t += 2; -1943 dx = 1; -1944 refX = isEnd ? 4 : 1; -1945 attr = { -1946 fill: "none", -1947 stroke: attrs.stroke -1948 }; -1949 } else { -1950 refX = dx = w / 2; -1951 attr = { -1952 fill: attrs.stroke, -1953 stroke: "none" -1954 }; -1955 } -1956 if (o._.arrows) { -1957 if (isEnd) { -1958 o._.arrows.endPath && markerCounter[o._.arrows.endPath]--; -1959 o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--; -1960 } else { -1961 o._.arrows.startPath && markerCounter[o._.arrows.startPath]--; -1962 o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--; -1963 } -1964 } else { -1965 o._.arrows = {}; -1966 } -1967 if (type != "none") { -1968 var pathId = "raphael-marker-" + type, -1969 markerId = "raphael-marker-" + se + type + w + h; -1970 if (!g.doc.getElementById(pathId)) { -1971 p.defs.appendChild($($("path"), { -1972 "stroke-linecap": "round", -1973 d: markers[type], -1974 id: pathId -1975 })); -1976 markerCounter[pathId] = 1; -1977 } else { -1978 markerCounter[pathId]++; -1979 } -1980 var marker = g.doc.getElementById(markerId), -1981 use; -1982 if (!marker) { -1983 marker = $($("marker"), { -1984 id: markerId, -1985 markerHeight: h, -1986 markerWidth: w, -1987 orient: "auto", -1988 refX: refX, -1989 refY: h / 2 -1990 }); -1991 use = $($("use"), { -1992 "xlink:href": "#" + pathId, -1993 transform: (isEnd ? " rotate(180 " + w / 2 + " " + h / 2 + ") " : S) + "scale(" + w / t + "," + h / t + ")", -1994 "stroke-width": 1 / ((w / t + h / t) / 2) -1995 }); -1996 marker.appendChild(use); -1997 p.defs.appendChild(marker); -1998 markerCounter[markerId] = 1; -1999 } else { -2000 markerCounter[markerId]++; -2001 use = marker.getElementsByTagName("use")[0]; -2002 } -2003 $(use, attr); -2004 var delta = dx * (type != "diamond" && type != "oval"); -2005 if (isEnd) { -2006 from = o._.arrows.startdx * stroke || 0; -2007 to = R.getTotalLength(attrs.path) - delta * stroke; -2008 } else { -2009 from = delta * stroke; -2010 to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); -2011 } -2012 attr = {}; -2013 attr["marker-" + se] = "url(#" + markerId + ")"; -2014 if (to || from) { -2015 attr.d = Raphael.getSubpath(attrs.path, from, to); -2016 } -2017 $(node, attr); -2018 o._.arrows[se + "Path"] = pathId; -2019 o._.arrows[se + "Marker"] = markerId; -2020 o._.arrows[se + "dx"] = delta; -2021 o._.arrows[se + "Type"] = type; -2022 o._.arrows[se + "String"] = value; -2023 } else { -2024 if (isEnd) { -2025 from = o._.arrows.startdx * stroke || 0; -2026 to = R.getTotalLength(attrs.path) - from; -2027 } else { -2028 from = 0; -2029 to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); -2030 } -2031 o._.arrows[se + "Path"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)}); -2032 delete o._.arrows[se + "Path"]; -2033 delete o._.arrows[se + "Marker"]; -2034 delete o._.arrows[se + "dx"]; -2035 delete o._.arrows[se + "Type"]; -2036 delete o._.arrows[se + "String"]; -2037 } -2038 for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) { -2039 var item = g.doc.getElementById(attr); -2040 item && item.parentNode.removeChild(item); -2041 } -2042 } -2043 }, -2044 setFillAndStroke = function (o, params) { -2045 var dasharray = { -2046 "": [0], -2047 "none": [0], -2048 "-": [3, 1], -2049 ".": [1, 1], -2050 "-.": [3, 1, 1, 1], -2051 "-..": [3, 1, 1, 1, 1, 1], -2052 ". ": [1, 3], -2053 "- ": [4, 3], -2054 "--": [8, 3], -2055 "- .": [4, 3, 1, 3], -2056 "--.": [8, 3, 1, 3], -2057 "--..": [8, 3, 1, 3, 1, 3] -2058 }, -2059 node = o.node, -2060 attrs = o.attrs, -2061 addDashes = function (o, value) { -2062 value = dasharray[lowerCase.call(value)]; -2063 if (value) { -2064 var width = o.attrs["stroke-width"] || "1", -2065 butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0, -2066 dashes = [], -2067 i = value.length; -2068 while (i--) { -2069 dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt; -2070 } -2071 $(node, {"stroke-dasharray": dashes.join(",")}); -2072 } -2073 }; -2074 for (var att in params) { -2075 if (params[has](att)) { -2076 if (!availableAttrs[has](att)) { -2077 continue; -2078 } -2079 var value = params[att]; -2080 attrs[att] = value; -2081 switch (att) { -2082 case "blur": -2083 o.blur(value); -2084 break; -2085 case "href": -2086 case "title": -2087 case "target": -2088 var pn = node.parentNode; -2089 if (lowerCase.call(pn.tagName) != "a") { -2090 var hl = $("a"); -2091 pn.insertBefore(hl, node); -2092 hl.appendChild(node); -2093 pn = hl; -2094 } -2095 if (att == "target" && value == "blank") { -2096 pn.setAttributeNS(xlink, "show", "new"); -2097 } else { -2098 pn.setAttributeNS(xlink, att, value); -2099 } -2100 break; -2101 case "cursor": -2102 node.style.cursor = value; -2103 break; -2104 case "transform": -2105 o.transform(value); -2106 break; -2107 case "arrow-start": -2108 addArrow(o, value); -2109 break; -2110 case "arrow-end": -2111 addArrow(o, value, 1); -2112 break; -2113 case "clip-rect": -2114 var rect = Str(value).split(separator); -2115 if (rect.length == 4) { -2116 o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode); -2117 var el = $("clipPath"), -2118 rc = $("rect"); -2119 el.id = createUUID(); -2120 $(rc, { -2121 x: rect[0], -2122 y: rect[1], -2123 width: rect[2], -2124 height: rect[3] -2125 }); -2126 el.appendChild(rc); -2127 o.paper.defs.appendChild(el); -2128 $(node, {"clip-path": "url(#" + el.id + ")"}); -2129 o.clip = rc; -2130 } -2131 if (!value) { -2132 var clip = g.doc.getElementById(node.getAttribute("clip-path").replace(/(^url\(#|\)$)/g, E)); -2133 clip && clip.parentNode.removeChild(clip); -2134 $(node, {"clip-path": E}); -2135 delete o.clip; -2136 } -2137 break; -2138 case "path": -2139 if (o.type == "path") { -2140 $(node, {d: value ? attrs.path = pathToAbsolute(value) : "M0,0"}); -2141 o._.dirty = 1; -2142 if (o._.arrows) { -2143 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); -2144 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); -2145 } -2146 } -2147 break; -2148 case "width": -2149 node[setAttribute](att, value); -2150 o._.dirty = 1; -2151 if (attrs.fx) { -2152 att = "x"; -2153 value = attrs.x; -2154 } else { -2155 break; -2156 } -2157 case "x": -2158 if (attrs.fx) { -2159 value = -attrs.x - (attrs.width || 0); -2160 } -2161 case "rx": -2162 if (att == "rx" && o.type == "rect") { -2163 break; -2164 } -2165 case "cx": -2166 node[setAttribute](att, value); -2167 o.pattern && updatePosition(o); -2168 o._.dirty = 1; -2169 break; -2170 case "height": -2171 node[setAttribute](att, value); -2172 o._.dirty = 1; -2173 if (attrs.fy) { -2174 att = "y"; -2175 value = attrs.y; -2176 } else { -2177 break; -2178 } -2179 case "y": -2180 if (attrs.fy) { -2181 value = -attrs.y - (attrs.height || 0); -2182 } -2183 case "ry": -2184 if (att == "ry" && o.type == "rect") { -2185 break; -2186 } -2187 case "cy": -2188 node[setAttribute](att, value); -2189 o.pattern && updatePosition(o); -2190 o._.dirty = 1; -2191 break; -2192 case "r": -2193 if (o.type == "rect") { -2194 $(node, {rx: value, ry: value}); -2195 } else { -2196 node[setAttribute](att, value); -2197 } -2198 o._.dirty = 1; -2199 break; -2200 case "src": -2201 if (o.type == "image") { -2202 node.setAttributeNS(xlink, "href", value); -2203 } -2204 break; -2205 case "stroke-width": -2206 if (o._.sx != 1 || o._.sy != 1) { -2207 value /= mmax(abs(o._.sx), abs(o._.sy)) || 1; -2208 } -2209 if (o.paper._vbSize) { -2210 value *= o.paper._vbSize; -2211 } -2212 node[setAttribute](att, value); -2213 if (attrs["stroke-dasharray"]) { -2214 addDashes(o, attrs["stroke-dasharray"]); -2215 } -2216 if (o._.arrows) { -2217 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); -2218 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); -2219 } -2220 break; -2221 case "stroke-dasharray": -2222 addDashes(o, value); -2223 break; -2224 case fillString: -2225 var isURL = Str(value).match(ISURL); -2226 if (isURL) { -2227 el = $("pattern"); -2228 var ig = $("image"); -2229 el.id = createUUID(); -2230 $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1}); -2231 $(ig, {x: 0, y: 0, "xlink:href": isURL[1]}); -2232 el.appendChild(ig); -2233 -2234 (function (el) { -2235 preload(isURL[1], function () { -2236 var w = this.offsetWidth, -2237 h = this.offsetHeight; -2238 $(el, {width: w, height: h}); -2239 $(ig, {width: w, height: h}); -2240 o.paper.safari(); -2241 }); -2242 })(el); -2243 o.paper.defs.appendChild(el); -2244 node.style.fill = "url(#" + el.id + ")"; -2245 $(node, {fill: "url(#" + el.id + ")"}); -2246 o.pattern = el; -2247 o.pattern && updatePosition(o); -2248 break; -2249 } -2250 var clr = R.getRGB(value); -2251 if (!clr.error) { -2252 delete params.gradient; -2253 delete attrs.gradient; -2254 !R.is(attrs.opacity, "undefined") && -2255 R.is(params.opacity, "undefined") && -2256 $(node, {opacity: attrs.opacity}); -2257 !R.is(attrs["fill-opacity"], "undefined") && -2258 R.is(params["fill-opacity"], "undefined") && -2259 $(node, {"fill-opacity": attrs["fill-opacity"]}); -2260 } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) { -2261 if ("opacity" in attrs || "fill-opacity" in attrs) { -2262 var gradient = g.doc.getElementById(node.getAttribute(fillString).replace(/^url\(#|\)$/g, E)); -2263 if (gradient) { -2264 var stops = gradient.getElementsByTagName("stop"); -2265 $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)}); -2266 } -2267 } -2268 attrs.gradient = value; -2269 attrs.fill = "none"; -2270 break; -2271 } -2272 clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); -2273 case "stroke": -2274 clr = R.getRGB(value); -2275 node[setAttribute](att, clr.hex); -2276 att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); -2277 if (att == "stroke" && o._.arrows) { -2278 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); -2279 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); -2280 } -2281 break; -2282 case "gradient": -2283 (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value); -2284 break; -2285 case "opacity": -2286 if (attrs.gradient && !attrs[has]("stroke-opacity")) { -2287 $(node, {"stroke-opacity": value > 1 ? value / 100 : value}); -2288 } -2289 // fall -2290 case "fill-opacity": -2291 if (attrs.gradient) { -2292 gradient = g.doc.getElementById(node.getAttribute(fillString).replace(/^url\(#|\)$/g, E)); -2293 if (gradient) { -2294 stops = gradient.getElementsByTagName("stop"); -2295 $(stops[stops.length - 1], {"stop-opacity": value}); -2296 } -2297 break; -2298 } -2299 default: -2300 att == "font-size" && (value = toInt(value, 10) + "px"); -2301 var cssrule = att.replace(/(\-.)/g, function (w) { -2302 return upperCase.call(w.substring(1)); -2303 }); -2304 node.style[cssrule] = value; -2305 o._.dirty = 1; -2306 node[setAttribute](att, value); -2307 break; -2308 } -2309 } -2310 } -2311 -2312 tuneText(o, params); -2313 }, -2314 leading = 1.2, -2315 tuneText = function (el, params) { -2316 if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) { -2317 return; -2318 } -2319 var a = el.attrs, -2320 node = el.node, -2321 fontSize = node.firstChild ? toInt(g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10; -2322 -2323 if (params[has]("text")) { -2324 a.text = params.text; -2325 while (node.firstChild) { -2326 node.removeChild(node.firstChild); -2327 } -2328 var texts = Str(params.text).split("\n"), -2329 tspans = [], -2330 tspan; -2331 for (var i = 0, ii = texts.length; i < ii; i++) if (texts[i]) { -2332 tspan = $("tspan"); -2333 i && $(tspan, {dy: fontSize * leading, x: a.x}); -2334 tspan.appendChild(g.doc.createTextNode(texts[i])); -2335 node.appendChild(tspan); -2336 tspans[i] = tspan; -2337 } -2338 } else { -2339 tspans = node.getElementsByTagName("tspan"); -2340 for (i = 0, ii = tspans.length; i < ii; i++) { -2341 i && $(tspans[i], {dy: fontSize * leading, x: a.x}); -2342 } -2343 } -2344 $(node, {y: a.y}); -2345 el._.dirty = 1; -2346 var bb = el._getBBox(), -2347 dif = a.y - (bb.y + bb.height / 2); -2348 dif && R.is(dif, "finite") && $(tspans[0], {dy: a.y + dif}); -2349 }, -2350 Element = function (node, svg) { -2351 var X = 0, -2352 Y = 0; -2353 /*\ -2354 * Element.node -2355 [ property (object) ] -2356 ** -2357 * Gives you a reference to the DOM object, so you can assign event handlers or just mess around. -2358 > Usage -2359 | // draw a circle at coordinate 10,10 with radius of 10 -2360 | var c = paper.circle(10, 10, 10); -2361 | c.node.onclick = function () { -2362 | c.attr("fill", "red"); -2363 | }; -2364 \*/ -2365 this[0] = this.node = node; -2366 /*\ -2367 * Element.raphael -2368 [ property (object) ] -2369 ** -2370 * Internal reference to @Raphael object. In case it is not available. -2371 > Usage -2372 | Raphael.el.red = function () { -2373 | var hsb = this.paper.raphael.rgb2hsb(this.attr("fill")); -2374 | hsb.h = 1; -2375 | this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex}); -2376 | } -2377 \*/ -2378 node.raphael = true; -2379 /*\ -2380 * Element.id -2381 [ property (number) ] -2382 ** -2383 * Unique id of the element. Especially usesful when you want to listen to events of the element, -2384 * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method. -2385 \*/ -2386 this.id = R._oid++; -2387 node.raphaelid = this.id; -2388 this.matrix = new Matrix; -2389 this.realPath = null; -2390 /*\ -2391 * Element.paper -2392 [ property (object) ] -2393 ** -2394 * Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions. -2395 > Usage -2396 | Raphael.el.cross = function () { -2397 | this.attr({fill: "red"}); -2398 | this.paper.path("M10,10L50,50M50,10L10,50") -2399 | .attr({stroke: "red"}); -2400 | } -2401 \*/ -2402 this.paper = svg; -2403 this.attrs = this.attrs || {}; -2404 this._ = { -2405 transform: [], -2406 sx: 1, -2407 sy: 1, -2408 deg: 0, -2409 dx: 0, -2410 dy: 0, -2411 dirty: 1 -2412 }; -2413 !svg.bottom && (svg.bottom = this); -2414 /*\ -2415 * Element.prev -2416 [ property (object) ] -2417 ** -2418 * Reference to the previous element in the hierarchy. -2419 \*/ -2420 this.prev = svg.top; -2421 svg.top && (svg.top.next = this); -2422 svg.top = this; -2423 /*\ -2424 * Element.next -2425 [ property (object) ] -2426 ** -2427 * Reference to the next element in the hierarchy. -2428 \*/ -2429 this.next = null; -2430 }, -2431 elproto = Element.prototype; -2432 /*\ -2433 * Element.rotate -2434 [ method ] -2435 ** -2436 * Adds rotation by given angle around given point to the list of -2437 * transformations of the element. -2438 > Parameters -2439 - deg (number) angle in degrees -2440 - cx (number) #optional x coordinate of the centre of rotation -2441 - cy (number) #optional y coordinate of the centre of rotation -2442 * If cx & cy aren’t specified centre of the shape is used as a point of rotation. -2443 = (object) @Element -2444 \*/ -2445 elproto.rotate = function (deg, cx, cy) { -2446 if (this.removed) { -2447 return this; -2448 } -2449 deg = Str(deg).split(separator); -2450 if (deg.length - 1) { -2451 cx = toFloat(deg[1]); -2452 cy = toFloat(deg[2]); -2453 } -2454 deg = toFloat(deg[0]); -2455 (cy == null) && (cx = cy); -2456 if (cx == null || cy == null) { -2457 var bbox = this.getBBox(1); -2458 cx = bbox.x + bbox.width / 2; -2459 cy = bbox.y + bbox.height / 2; -2460 } -2461 this.transform(this._.transform.concat([["r", deg, cx, cy]])); -2462 return this; -2463 }; -2464 /*\ -2465 * Element.scale -2466 [ method ] -2467 ** -2468 * Adds scale by given amount relative to given point to the list of -2469 * transformations of the element. -2470 > Parameters -2471 - sx (number) horisontal scale amount -2472 - sy (number) vertical scale amount -2473 - cx (number) #optional x coordinate of the centre of scale -2474 - cy (number) #optional y coordinate of the centre of scale -2475 * If cx & cy aren’t specified centre of the shape is used instead. -2476 = (object) @Element -2477 \*/ -2478 elproto.scale = function (sx, sy, cx, cy) { -2479 if (this.removed) { -2480 return this; -2481 } -2482 sx = Str(sx).split(separator); -2483 if (sx.length - 1) { -2484 sy = toFloat(sx[1]); -2485 cx = toFloat(sx[2]); -2486 cy = toFloat(sx[3]); -2487 } -2488 sx = toFloat(sx[0]); -2489 (sy == null) && (sy = sx); -2490 (cy == null) && (cx = cy); -2491 if (cx == null || cy == null) { -2492 var bbox = this.getBBox(1); -2493 } -2494 cx = cx == null ? bbox.x + bbox.width / 2 : cx; -2495 cy = cy == null ? bbox.y + bbox.height / 2 : cy; -2496 this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); -2497 return this; -2498 }; -2499 /*\ -2500 * Element.translate -2501 [ method ] -2502 ** -2503 * Adds translation by given amount to the list of transformations of the element. -2504 > Parameters -2505 - dx (number) horisontal shift -2506 - dy (number) vertical shift -2507 = (object) @Element -2508 \*/ -2509 elproto.translate = function (dx, dy) { -2510 if (this.removed) { -2511 return this; -2512 } -2513 dx = Str(dx).split(separator); -2514 if (dx.length - 1) { -2515 dy = toFloat(dx[1]); -2516 } -2517 dx = toFloat(dx[0]) || 0; -2518 dy = +dy || 0; -2519 this.transform(this._.transform.concat([["t", dx, dy]])); -2520 return this; -2521 }; -2522 /*\ -2523 * Element.transform -2524 [ method ] -2525 ** -2526 * Adds transformation to the element which is separate to other attributes, -2527 * i.e. translation doesn’t change `x` or `y` of the rectange. The format -2528 * of transformation string is similar to the path string syntax: -2529 | "t100,100r30,100,100s2,2,100,100r45s1.5" -2530 * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for -2531 * scale and `m` is for matrix. -2532 * -2533 * So, example line could be read like “translate by 100, 100, rotate 30° around 100, 100, scale twice around 100, 100 -2534 * rotate 45° around centre and scale 1.5 times relative to centre”. As you see rotate and scale commands has origin -2535 * coordinates as a optional parameters. -2536 * Matrix accepts six parameters. -2537 > Usage -2538 | var el = paper.rect(10, 20, 300, 200); -2539 | // translate 100, 100, rotate 45°, translate -100, 0 -2540 | el.transform("t100,100r45t-100,0"); -2541 | // if you want you can append or prepend transformations -2542 | el.transform("...t50,50"); -2543 | el.transform("s2..."); -2544 | // or even wrap -2545 | el.transform("t50,50...t-50-50"); -2546 | // to reset transformation call method with empty string -2547 | el.transform(""); -2548 | // to get current value call it without parameters -2549 | console.log(el.transform()); -2550 > Parameters -2551 - tstr (string) #optional transformation string -2552 * If tstr isn’t specified -2553 = (string) current transformation string -2554 * else -2555 = (object) @Element -2556 \*/ -2557 elproto.transform = function (tstr) { -2558 var _ = this._; -2559 if (!tstr) { -2560 return _.transform; -2561 } -2562 extractTransform(this, tstr); -2563 -2564 this.clip && $(this.clip, {transform: this.matrix.invert()}); -2565 // this.gradient && $(this.gradient, {gradientTransform: this.matrix.invert()}); -2566 this.pattern && updatePosition(this); -2567 this.node && $(this.node, {transform: this.matrix}); -2568 -2569 if (_.sx != 1 || _.sy != 1) { -2570 var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1; -2571 this.attr({"stroke-width": sw}); -2572 } -2573 -2574 return this; -2575 }; -2576 /*\ -2577 * Element.hide -2578 [ method ] -2579 ** -2580 * Makes element invisible. See @Element.show. -2581 = (object) @Element -2582 \*/ -2583 elproto.hide = function () { -2584 !this.removed && this.paper.safari(this.node.style.display = "none"); -2585 return this; -2586 }; -2587 /*\ -2588 * Element.show -2589 [ method ] -2590 ** -2591 * Makes element visible. See @Element.hide. -2592 = (object) @Element -2593 \*/ -2594 elproto.show = function () { -2595 !this.removed && this.paper.safari(this.node.style.display = ""); -2596 return this; -2597 }; -2598 /*\ -2599 * Element.remove -2600 [ method ] -2601 ** -2602 * Removes element form the paper. -2603 \*/ -2604 elproto.remove = function () { -2605 if (this.removed) { -2606 return; -2607 } -2608 eve.unbind("*.*." + this.id); -2609 tear(this, this.paper); -2610 this.node.parentNode.removeChild(this.node); -2611 for (var i in this) { -2612 delete this[i]; -2613 } -2614 this.removed = true; -2615 }; -2616 elproto._getBBox = function () { -2617 if (this.node.style.display == "none") { -2618 this.show(); -2619 var hide = true; -2620 } -2621 var bbox = {}; -2622 try { -2623 bbox = this.node.getBBox(); -2624 } catch(e) { -2625 // Firefox 3.0.x plays badly here -2626 } finally { -2627 bbox = bbox || {}; -2628 } -2629 hide && this.hide(); -2630 return bbox; -2631 }; -2632 /*\ -2633 * Element.attr -2634 [ method ] -2635 ** -2636 * Sets the attributes of the element. -2637 > Parameters -2638 - attrName (string) attribute’s name -2639 - value (string) value -2640 * or -2641 - params (object) object of name/value pairs -2642 * or -2643 - attrName (string) attribute’s name -2644 * or -2645 - attrNames (array) in this case method returns array of current values for given attribute names -2646 = (object) @Element if attrsName & value or params are passed in. -2647 = (...) value of the attribute if only attrsName is passed in. -2648 = (array) array of values of the attribute if attrsNames is passed in. -2649 = (object) object of attributes if nothing is passed in. -2650 > Possible parameters -2651 # <p>Please refer to the <a href="http://www.w3.org/TR/SVG/" title="The W3C Recommendation for the SVG language describes these properties in detail.">SVG specification</a> for an explanation of these parameters.</p> -2652 o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `midium`, length: `long`, `short`, `midium`. -2653 o clip-rect (string) comma or space separated values: x, y, width and height -2654 o cursor (string) CSS type of the cursor -2655 o cx (number) -2656 o cy (number) -2657 o fill (string) colour, gradient or image -2658 o fill-opacity (number) -2659 o font (string) -2660 o font-family (string) -2661 o font-size (number) font size in pixels -2662 o font-weight (string) -2663 o height (number) -2664 o href (string) URL, if specified element behaves as hyperlink -2665 o opacity (number) -2666 o path (string) SVG path string format -2667 o r (number) -2668 o rx (number) -2669 o ry (number) -2670 o src (string) image URL, only works for @Element.image element -2671 o stroke (string) stroke colour -2672 o stroke-dasharray (string) [“”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”] -2673 o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”] -2674 o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”] -2675 o stroke-miterlimit (number) -2676 o stroke-opacity (number) -2677 o stroke-width (number) stroke width in pixels, default is '1' -2678 o target (string) used with href -2679 o text (string) contents of the text element. Use `\n` for multiline text -2680 o text-anchor (string) [“`start`”, “`middle`”, “`end`”], default is “`middle`” -2681 o title (string) will create tooltip with a given text -2682 o transform (string) see @Element.transform -2683 o width (number) -2684 o x (number) -2685 o y (number) -2686 > Gradients -2687 * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90° -2688 * gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black. -2689 * -2690 * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” – -2691 * gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point -2692 * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses. -2693 > Path String -2694 # <p>Please refer to <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path’s data attribute’s format are described in the SVG specification.">SVG documentation regarding path string</a>. Raphaël fully supports it.</p> -2695 > Colour Parsing -2696 # <ul> -2697 # <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li> -2698 # <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li> -2699 # <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li> -2700 # <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(2001000)</code>”)</li> -2701 # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%, 175%, 0%)</code>”)</li> -2702 # <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(2001000, .5)</code>”)</li> -2703 # <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%, 175%, 0%, 50%)</code>”)</li> -2704 # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.50.251)</code>”)</li> -2705 # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li> -2706 # <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</li> -2707 # <li>hsl(•••, •••, •••) — almost the same as hsb, see <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV - Wikipedia, the free encyclopedia">Wikipedia page</a></li> -2708 # <li>hsl(•••%, •••%, •••%) — same as above, but in %</li> -2709 # <li>hsla(•••, •••, •••) — same as above, but with opacity</li> -2710 # <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg, 1.5)</code>” or, if you want to go fancy, “<code>hsl(240°, 1.5)</code>”</li> -2711 # </ul> -2712 \*/ -2713 elproto.attr = function (name, value) { -2714 if (this.removed) { -2715 return this; -2716 } -2717 if (name == null) { -2718 var res = {}; -2719 for (var i in this.attrs) if (this.attrs[has](i)) { -2720 res[i] = this.attrs[i]; -2721 } -2722 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; -2723 res.transform = this._.transform; -2724 return res; -2725 } -2726 if (value == null && R.is(name, string)) { -2727 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { -2728 return this.attrs.gradient; -2729 } -2730 if (name == "transform") { -2731 return this._.transform; -2732 } -2733 if (name in this.attrs) { -2734 return this.attrs[name]; -2735 } else if (R.is(this.paper.customAttributes[name], "function")) { -2736 return this.paper.customAttributes[name].def; -2737 } else { -2738 return availableAttrs[name]; -2739 } -2740 } -2741 if (value == null && R.is(name, array)) { -2742 var values = {}; -2743 for (var j = 0, jj = name.length; j < jj; j++) { -2744 values[name[j]] = this.attr(name[j]); -2745 } -2746 return values; -2747 } -2748 if (value != null) { -2749 var params = {}; -2750 params[name] = value; -2751 } else if (name != null && R.is(name, "object")) { -2752 params = name; -2753 } -2754 for (var key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { -2755 var par = this.paper.customAttributes[key].apply(this, [][concat](params[key])); -2756 this.attrs[key] = params[key]; -2757 for (var subkey in par) if (par[has](subkey)) { -2758 params[subkey] = par[subkey]; -2759 } -2760 } -2761 setFillAndStroke(this, params); -2762 return this; -2763 }; -2764 /*\ -2765 * Element.toFront -2766 [ method ] -2767 ** -2768 * Moves the element so it is the closest to the viewer’s eyes, on top of other elements. -2769 = (object) @Element -2770 \*/ -2771 elproto.toFront = function () { -2772 if (this.removed) { -2773 return this; -2774 } -2775 this.node.parentNode.appendChild(this.node); -2776 var svg = this.paper; -2777 svg.top != this && tofront(this, svg); -2778 return this; -2779 }; -2780 /*\ -2781 * Element.toBack -2782 [ method ] -2783 ** -2784 * Moves the element so it is the furthest from the viewer’s eyes, behind other elements. -2785 = (object) @Element -2786 \*/ -2787 elproto.toBack = function () { -2788 if (this.removed) { -2789 return this; -2790 } -2791 if (this.node.parentNode.firstChild != this.node) { -2792 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); -2793 toback(this, this.paper); -2794 var svg = this.paper; -2795 } -2796 return this; -2797 }; -2798 /*\ -2799 * Element.insertAfter -2800 [ method ] -2801 ** -2802 * Inserts current object after the given one. -2803 = (object) @Element -2804 \*/ -2805 elproto.insertAfter = function (element) { -2806 if (this.removed) { -2807 return this; -2808 } -2809 var node = element.node || element[element.length - 1].node; -2810 if (node.nextSibling) { -2811 node.parentNode.insertBefore(this.node, node.nextSibling); -2812 } else { -2813 node.parentNode.appendChild(this.node); -2814 } -2815 insertafter(this, element, this.paper); -2816 return this; -2817 }; -2818 /*\ -2819 * Element.insertBefore -2820 [ method ] -2821 ** -2822 * Inserts current object before the given one. -2823 = (object) @Element -2824 \*/ -2825 elproto.insertBefore = function (element) { -2826 if (this.removed) { -2827 return this; -2828 } -2829 var node = element.node || element[0].node; -2830 node.parentNode.insertBefore(this.node, node); -2831 insertbefore(this, element, this.paper); -2832 return this; -2833 }; -2834 elproto.blur = function (size) { -2835 // Experimental. No Safari support. Use it on your own risk. -2836 var t = this; -2837 if (+size !== 0) { -2838 var fltr = $("filter"), -2839 blur = $("feGaussianBlur"); -2840 t.attrs.blur = size; -2841 fltr.id = createUUID(); -2842 $(blur, {stdDeviation: +size || 1.5}); -2843 fltr.appendChild(blur); -2844 t.paper.defs.appendChild(fltr); -2845 t._blur = fltr; -2846 $(t.node, {filter: "url(#" + fltr.id + ")"}); -2847 } else { -2848 if (t._blur) { -2849 t._blur.parentNode.removeChild(t._blur); -2850 delete t._blur; -2851 delete t.attrs.blur; -2852 } -2853 t.node.removeAttribute("filter"); -2854 } -2855 }; -2856 var theCircle = function (svg, x, y, r) { -2857 var el = $("circle"); -2858 svg.canvas && svg.canvas.appendChild(el); -2859 var res = new Element(el, svg); -2860 res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"}; -2861 res.type = "circle"; -2862 $(el, res.attrs); -2863 return res; -2864 }, -2865 theRect = function (svg, x, y, w, h, r) { -2866 var el = $("rect"); -2867 svg.canvas && svg.canvas.appendChild(el); -2868 var res = new Element(el, svg); -2869 res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"}; -2870 res.type = "rect"; -2871 $(el, res.attrs); -2872 return res; -2873 }, -2874 theEllipse = function (svg, x, y, rx, ry) { -2875 var el = $("ellipse"); -2876 svg.canvas && svg.canvas.appendChild(el); -2877 var res = new Element(el, svg); -2878 res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"}; -2879 res.type = "ellipse"; -2880 $(el, res.attrs); -2881 return res; -2882 }, -2883 theImage = function (svg, src, x, y, w, h) { -2884 var el = $("image"); -2885 $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"}); -2886 el.setAttributeNS(xlink, "href", src); -2887 svg.canvas && svg.canvas.appendChild(el); -2888 var res = new Element(el, svg); -2889 res.attrs = {x: x, y: y, width: w, height: h, src: src}; -2890 res.type = "image"; -2891 return res; -2892 }, -2893 theText = function (svg, x, y, text) { -2894 var el = $("text"); -2895 $(el, {x: x, y: y, "text-anchor": "middle"}); -2896 svg.canvas && svg.canvas.appendChild(el); -2897 var res = new Element(el, svg); -2898 res.attrs = {x: x, y: y, "text-anchor": "middle", text: text, font: availableAttrs.font, stroke: "none", fill: "#000"}; -2899 res.type = "text"; -2900 setFillAndStroke(res, res.attrs); -2901 return res; -2902 }, -2903 setSize = function (width, height) { -2904 this.width = width || this.width; -2905 this.height = height || this.height; -2906 this.canvas[setAttribute]("width", this.width); -2907 this.canvas[setAttribute]("height", this.height); -2908 if (this._viewBox) { -2909 this.setViewBox.apply(this, this._viewBox); -2910 } -2911 return this; -2912 }, -2913 create = function () { -2914 var con = getContainer[apply](0, arguments), -2915 container = con && con.container, -2916 x = con.x, -2917 y = con.y, -2918 width = con.width, -2919 height = con.height; -2920 if (!container) { -2921 throw new Error("SVG container not found."); -2922 } -2923 var cnvs = $("svg"), -2924 css = "overflow:hidden;"; -2925 x = x || 0; -2926 y = y || 0; -2927 width = width || 512; -2928 height = height || 342; -2929 $(cnvs, { -2930 height: height, -2931 version: 1.1, -2932 width: width, -2933 xmlns: "http://www.w3.org/2000/svg" -2934 }); -2935 if (container == 1) { -2936 cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px"; -2937 g.doc.body.appendChild(cnvs); -2938 } else { -2939 cnvs.style.cssText = css; -2940 if (container.firstChild) { -2941 container.insertBefore(cnvs, container.firstChild); -2942 } else { -2943 container.appendChild(cnvs); -2944 } -2945 } -2946 container = new Paper; -2947 container.width = width; -2948 container.height = height; -2949 container.canvas = cnvs; -2950 plugins.call(container, container, R.fn); -2951 container.clear(); -2952 return container; -2953 }, -2954 setViewBox = function (x, y, w, h, fit) { -2955 eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); -2956 var size = mmax(w / this.width, h / this.height), -2957 top = this.top, -2958 aspectRatio = fit ? "meet" : "xMinYMin", -2959 vb, -2960 sw; -2961 if (x == null) { -2962 if (this._vbSize) { -2963 size = 1; -2964 } -2965 delete this._vbSize; -2966 vb = "0 0 " + this.width + S + this.height; -2967 } else { -2968 this._vbSize = size; -2969 vb = x + S + y + S + w + S + h; -2970 } -2971 $(this.canvas, { -2972 viewBox: vb, -2973 preserveAspectRatio: aspectRatio -2974 }); -2975 while (size && top) { -2976 sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1; -2977 top.attr({"stroke-width": sw}); -2978 top._.dirty = 1; -2979 top._.dirtyT = 1; -2980 top = top.prev; -2981 } -2982 this._viewBox = [x, y, w, h, !!fit]; -2983 return this; -2984 }; -2985 /*\ -2986 * Paper.clear -2987 [ method ] -2988 ** -2989 * Clears the paper, i.e. removes all the elements. -2990 \*/ -2991 paperproto.clear = function () { -2992 eve("clear", this); -2993 var c = this.canvas; -2994 while (c.firstChild) { -2995 c.removeChild(c.firstChild); -2996 } -2997 this.bottom = this.top = null; -2998 (this.desc = $("desc")).appendChild(g.doc.createTextNode("Created with Rapha\xebl " + R.version)); -2999 c.appendChild(this.desc); -3000 c.appendChild(this.defs = $("defs")); -3001 }; -3002 /*\ -3003 * Paper.remove -3004 [ method ] -3005 ** -3006 * Removes the paper from the DOM. -3007 \*/ -3008 paperproto.remove = function () { -3009 eve("remove", this); -3010 this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas); -3011 for (var i in this) { -3012 this[i] = removed(i); -3013 } -3014 }; -3015 } -3016 -3017 // VML -3018 if (R.vml) { -3019 var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, -3020 bites = /([clmz]),?([^clmz]*)/gi, -3021 blurregexp = / progid:\S+Blur\([^\)]+\)/g, -3022 val = /-?[^,\s-]+/g, -3023 cssDot = "position:absolute;left:0;top:0;width:1px;height:1px", -3024 zoom = 21600, -3025 pathTypes = {path: 1, rect: 1}, -3026 ovalTypes = {circle: 1, ellipse: 1}, -3027 path2vml = function (path) { -3028 var total = /[ahqstv]/ig, -3029 command = pathToAbsolute; -3030 Str(path).match(total) && (command = path2curve); -3031 total = /[clmz]/g; -3032 if (command == pathToAbsolute && !Str(path).match(total)) { -3033 var res = Str(path).replace(bites, function (all, command, args) { -3034 var vals = [], -3035 isMove = lowerCase.call(command) == "m", -3036 res = map[command]; -3037 args.replace(val, function (value) { -3038 if (isMove && vals.length == 2) { -3039 res += vals + map[command == "m" ? "l" : "L"]; -3040 vals = []; -3041 } -3042 vals.push(round(value * zoom)); -3043 }); -3044 return res + vals; -3045 }); -3046 return res; -3047 } -3048 var pa = command(path), p, r; -3049 res = []; -3050 for (var i = 0, ii = pa.length; i < ii; i++) { -3051 p = pa[i]; -3052 r = lowerCase.call(pa[i][0]); -3053 r == "z" && (r = "x"); -3054 for (var j = 1, jj = p.length; j < jj; j++) { -3055 r += round(p[j] * zoom) + (j != jj - 1 ? "," : E); -3056 } -3057 res.push(r); -3058 } -3059 return res.join(S); -3060 }, -3061 compensation = function (deg, dx, dy) { -3062 var m = new Matrix; -3063 m.rotate(-deg, .5, .5); -3064 return { -3065 dx: m.x(dx, dy), -3066 dy: m.y(dx, dy) -3067 }; -3068 }, -3069 setCoords = function (p) { -3070 var _ = p._, -3071 sx = _.sx, -3072 sy = _.sy, -3073 deg = _.deg, -3074 dx = _.dx, -3075 dy = _.dy, -3076 fillpos = _.fillpos, -3077 o = p.node, -3078 s = o.style, -3079 y = 1, -3080 m = p.matrix, -3081 flip = "", -3082 dxdy, -3083 kx = zoom / sx, -3084 ky = zoom / sy; -3085 s.visibility = "hidden"; -3086 o.coordsize = abs(kx) + S + abs(ky); -3087 s.rotation = deg * (sx * sy < 0 ? -1 : 1); -3088 if (deg) { -3089 var c = compensation(deg, dx, dy); -3090 dx = c.dx; -3091 dy = c.dy; -3092 } -3093 sx < 0 && (flip += "x"); -3094 sy < 0 && (flip += " y") && (y = -1); -3095 s.flip = flip; -3096 o.coordorigin = (dx * -kx) + S + (dy * -ky); -3097 if (fillpos || _.fillsize) { -3098 var fill = o.getElementsByTagName(fillString); -3099 fill = fill && fill[0]; -3100 o.removeChild(fill); -3101 if (fillpos) { -3102 c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1])); -3103 fill.position = c.dx * y + S + c.dy * y; -3104 } -3105 if (_.fillsize) { -3106 fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy); -3107 } -3108 o.appendChild(fill); -3109 } -3110 s.visibility = "visible"; -3111 }; -3112 R.toString = function () { -3113 return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version; -3114 }; -3115 addArrow = function (o, value, isEnd) { -3116 var values = Str(value).toLowerCase().split("-"), -3117 se = isEnd ? "end" : "start", -3118 i = values.length, -3119 type = "classic", -3120 w = "medium", -3121 h = "medium"; -3122 while (i--) { -3123 switch (values[i]) { -3124 case "block": -3125 case "classic": -3126 case "oval": -3127 case "diamond": -3128 case "open": -3129 case "none": -3130 type = values[i]; -3131 break; -3132 case "wide": -3133 case "narrow": h = values[i]; break; -3134 case "long": -3135 case "short": w = values[i]; break; -3136 } -3137 } -3138 var stroke = o.node.getElementsByTagName("stroke")[0]; -3139 stroke[se + "arrow"] = type; -3140 stroke[se + "arrowlength"] = w; -3141 stroke[se + "arrowwidth"] = h; -3142 }; -3143 setFillAndStroke = function (o, params) { -3144 o.paper.canvas.style.display = "none"; -3145 o.attrs = o.attrs || {}; -3146 var node = o.node, -3147 a = o.attrs, -3148 s = node.style, -3149 xy, -3150 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), -3151 isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry), -3152 res = o; -3153 +32 | // Each of the following examples create a canvas +33 | // that is 320px wide by 200px high. +34 | // Canvas is created at the viewport’s 10,50 coordinate. +35 | var paper = Raphael(10, 50, 320, 200); +36 | // Canvas is created at the top left corner of the #notepad element +37 | // (or its top right corner in dir="rtl" elements) +38 | var paper = Raphael(document.getElementById("notepad"), 320, 200); +39 | // Same as above +40 | var paper = Raphael("notepad", 320, 200); +41 | // Image dump +42 | var set = Raphael(["notepad", 320, 200, { +43 | type: "rect", +44 | x: 10, +45 | y: 10, +46 | width: 25, +47 | height: 25, +48 | stroke: "#f00" +49 | }, { +50 | type: "text", +51 | x: 30, +52 | y: 40, +53 | text: "Dump" +54 | }]); +55 \*/ +56 function R(first) { +57 if (R.is(first, "function")) { +58 return eve.on("DOMload", first); +59 } else if (R.is(first, array)) { +60 var a = first, +61 cnv = create[apply](R, a.splice(0, 3 + R.is(a[0], nu))), +62 res = cnv.set(), +63 i = 0, +64 ii = a.length, +65 j; +66 for (; i < ii; i++) { +67 j = a[i] || {}; +68 elements[has](j.type) && res.push(cnv[j.type]().attr(j)); +69 } +70 return res; +71 } +72 return create[apply](R, arguments); +73 } +74 R.version = "2.0.0"; +75 var separator = /[, ]+/, +76 elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1}, +77 formatrg = /\{(\d+)\}/g, +78 proto = "prototype", +79 has = "hasOwnProperty", +80 g = { +81 doc: document, +82 win: window +83 }, +84 oldRaphael = { +85 was: Object.prototype[has].call(g.win, "Raphael"), +86 is: g.win.Raphael +87 }, +88 Paper = function () {}, +89 paperproto, +90 appendChild = "appendChild", +91 apply = "apply", +92 concat = "concat", +93 supportsTouch = "createTouch" in g.doc, +94 E = "", +95 S = " ", +96 Str = String, +97 split = "split", +98 events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend orientationchange touchcancel gesturestart gesturechange gestureend".split(S), +99 touchMap = { +100 mousedown: "touchstart", +101 mousemove: "touchmove", +102 mouseup: "touchend" +103 }, +104 lowerCase = Str.prototype.toLowerCase, +105 math = Math, +106 mmax = math.max, +107 mmin = math.min, +108 abs = math.abs, +109 pow = math.pow, +110 PI = math.PI, +111 nu = "number", +112 string = "string", +113 array = "array", +114 toString = "toString", +115 fillString = "fill", +116 objectToString = Object.prototype.toString, +117 paper = {}, +118 push = "push", +119 ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, +120 colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i, +121 isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1}, +122 bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, +123 round = math.round, +124 setAttribute = "setAttribute", +125 toFloat = parseFloat, +126 toInt = parseInt, +127 ms = " progid:DXImageTransform.Microsoft", +128 upperCase = Str.prototype.toUpperCase, +129 availableAttrs = {"arrow-end": "none", "arrow-start": "none", blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", opacity: 1, path: "M0,0", r: 0, rx: 0, ry: 0, src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", transform: "", width: 0, x: 0, y: 0}, +130 availableAnimAttrs = {blur: nu, "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rx: nu, ry: nu, stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, transform: "transform", width: nu, x: nu, y: nu}, +131 commaSpaces = /\s*,\s*/, +132 hsrg = {hs: 1, rg: 1}, +133 p2s = /,?([achlmqrstvxz]),?/gi, +134 pathCommand = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, +135 tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, +136 pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig, +137 radial_gradient = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/, +138 sortByKey = function (a, b) { +139 return a.key - b.key; +140 }, +141 sortByNumber = function (a, b) { +142 return a - b; +143 }, +144 fun = function () {}, +145 pipe = function (x) { +146 return x; +147 }, +148 rectPath = function (x, y, w, h, r) { +149 if (r) { +150 return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]]; +151 } +152 return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; +153 }, +154 ellipsePath = function (x, y, rx, ry) { +155 if (ry == null) { +156 ry = rx; +157 } +158 return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]]; +159 }, +160 getPath = { +161 path: function (el) { +162 return el.attr("path"); +163 }, +164 circle: function (el) { +165 var a = el.attrs; +166 return ellipsePath(a.cx, a.cy, a.r); +167 }, +168 ellipse: function (el) { +169 var a = el.attrs; +170 return ellipsePath(a.cx, a.cy, a.rx, a.ry); +171 }, +172 rect: function (el) { +173 var a = el.attrs; +174 return rectPath(a.x, a.y, a.width, a.height, a.r); +175 }, +176 image: function (el) { +177 var a = el.attrs; +178 return rectPath(a.x, a.y, a.width, a.height); +179 }, +180 text: function (el) { +181 var bbox = el._getBBox(); +182 return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); +183 } +184 }, +185 mapPath = function (path, matrix) { +186 if (!matrix) { +187 return path; +188 } +189 var x, y, i, j, pathi; +190 path = path2curve(path); +191 for (i = 0, ii = path.length; i < ii; i++) { +192 pathi = path[i]; +193 for (j = 1, jj = pathi.length; j < jj; j += 2) { +194 x = matrix.x(pathi[j], pathi[j + 1]); +195 y = matrix.y(pathi[j], pathi[j + 1]); +196 pathi[j] = x; +197 pathi[j + 1] = y; +198 } +199 } +200 return path; +201 }; +202 +203 /*\ +204 * Raphael.type +205 [ property (string) ] +206 ** +207 * Can be “SVG”, “VML” or empty, depending on browser support. +208 \*/ +209 R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"); +210 if (R.type == "VML") { +211 var d = g.doc.createElement("div"), +212 b; +213 d.innerHTML = '<v:shape adj="1"/>'; +214 b = d.firstChild; +215 b.style.behavior = "url(#default#VML)"; +216 if (!(b && typeof b.adj == "object")) { +217 return R.type = E; +218 } +219 d = null; +220 } +221 /*\ +222 * Raphael.svg +223 [ property (boolean) ] +224 ** +225 * `true` if browser supports SVG. +226 \*/ +227 /*\ +228 * Raphael.vml +229 [ property (boolean) ] +230 ** +231 * `true` if browser supports VML. +232 \*/ +233 R.svg = !(R.vml = R.type == "VML"); +234 paperproto = Paper.prototype = R.prototype; +235 /*\ +236 * Paper.customAttributes +237 [ property (object) ] +238 ** +239 * If you have a set of attributes that you would like to represent +240 * as a function of some number you can do it easily with custom attributes: +241 > Usage +242 | paper.customAttributes.hue = function (num) { +243 | num = num % 1; +244 | return {fill: "hsb(" + num + ", .75, 1)"}; +245 | }; +246 | // Custom attribute “hue” will change fill +247 | // to be given hue with fixed saturation and brightness. +248 | // Now you can use it like this: +249 | var c = paper.circle(10, 10, 10).attr({hue: .45}); +250 | // or even like this: +251 | c.animate({hue: 1}, 1e3); +252 | +253 | // You could also create custom attribute +254 | // with multiple parameters: +255 | paper.customAttributes.hsb = function (h, s, b) { +256 | return {fill: "hsb(" + [h, s, b].join(",") + ")"}; +257 | }; +258 | c.attr({hsb: ".5 .8 1"}); +259 | c.animate({hsb: "1 0 .5"}, 1e3); +260 \*/ +261 paperproto.customAttributes = {}; +262 R._id = 0; +263 R._oid = 0; +264 /*\ +265 * Raphael.fn +266 [ property (object) ] +267 ** +268 * You can add your own method to the canvas. For example if you want to draw a pie chart, +269 * you can create your own pie chart function and ship it as a Raphaël plugin. To do this +270 * you need to extend the `Raphael.fn` object. Please note that you can create your own namespaces +271 * inside the `fn` object — methods will be run in the context of canvas anyway. You should alter +272 * the `fn` object before a Raphaël instance is created, otherwise it will take no effect. +273 > Usage +274 | Raphael.fn.arrow = function (x1, y1, x2, y2, size) { +275 | return this.path( ... ); +276 | }; +277 | // or create namespace +278 | Raphael.fn.mystuff = { +279 | arrow: function () {…}, +280 | star: function () {…}, +281 | // etc… +282 | }; +283 | var paper = Raphael(10, 10, 630, 480); +284 | // then use it +285 | paper.arrow(10, 10, 30, 30, 5).attr({fill: "#f00"}); +286 | paper.mystuff.arrow(); +287 | paper.mystuff.star(); +288 \*/ +289 R.fn = {}; +290 /*\ +291 * Raphael.is +292 [ method ] +293 ** +294 * Handfull replacement for `typeof` operator. +295 > Parameters +296 - o (…) any object or primitive +297 - type (string) name of the type, i.e. “string”, “function”, “number”, etc. +298 = (boolean) is given value is of given type +299 \*/ +300 R.is = function (o, type) { +301 type = lowerCase.call(type); +302 if (type == "finite") { +303 return !isnan[has](+o); +304 } +305 return (type == "null" && o === null) || +306 (type == typeof o) || +307 (type == "object" && o === Object(o)) || +308 (type == "array" && Array.isArray && Array.isArray(o)) || +309 objectToString.call(o).slice(8, -1).toLowerCase() == type; +310 }; +311 /*\ +312 * Raphael.angle +313 [ method ] +314 ** +315 * Returns angle between two or three points +316 > Parameters +317 - x1 (number) x coord of first point +318 - y1 (number) y coord of first point +319 - x2 (number) x coord of second point +320 - y2 (number) y coord of second point +321 - x3 (number) #optional x coord of third point +322 - y3 (number) #optional y coord of third point +323 = (number) angle in degrees. +324 \*/ +325 R.angle = function (x1, y1, x2, y2, x3, y3) { +326 if (x3 == null) { +327 var x = x1 - x2, +328 y = y1 - y2; +329 if (!x && !y) { +330 return 0; +331 } +332 return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; +333 } else { +334 return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3); +335 } +336 }; +337 /*\ +338 * Raphael.rad +339 [ method ] +340 ** +341 * Transform angle to radians +342 > Parameters +343 - deg (number) angle in degrees +344 = (number) angle in radians. +345 \*/ +346 R.rad = function (deg) { +347 return deg % 360 * PI / 180; +348 }; +349 /*\ +350 * Raphael.deg +351 [ method ] +352 ** +353 * Transform angle to degrees +354 > Parameters +355 - deg (number) angle in radians +356 = (number) angle in degrees. +357 \*/ +358 R.deg = function (rad) { +359 return rad * 180 / PI % 360; +360 }; +361 /*\ +362 * Raphael.snapTo +363 [ method ] +364 ** +365 * Snaps given value to given grid. +366 > Parameters +367 - values (array|number) given array of values or step of the grid +368 - value (number) value to adjust +369 - tolerance (number) #optional tolerance for snapping. Default is `10`. +370 = (number) adjusted value. +371 \*/ +372 R.snapTo = function (values, value, tolerance) { +373 tolerance = R.is(tolerance, "finite") ? tolerance : 10; +374 if (R.is(values, array)) { +375 var i = values.length; +376 while (i--) if (abs(values[i] - value) <= tolerance) { +377 return values[i]; +378 } +379 } else { +380 values = +values; +381 var rem = value % values; +382 if (rem < tolerance) { +383 return value - rem; +384 } +385 if (rem > values - tolerance) { +386 return value - rem + values; +387 } +388 } +389 return value; +390 }; +391 +392 var createUUID = (function (uuidRegEx, uuidReplacer) { +393 return function () { +394 return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase(); +395 }; +396 })(/[xy]/g, function (c) { +397 var r = math.random() * 16 | 0, +398 v = c == "x" ? r : (r & 3 | 8); +399 return v.toString(16); +400 }); +401 +402 /*\ +403 * Raphael.setWindow +404 [ method ] +405 ** +406 * Used when you need to draw in `<iframe>`. Switched window to the iframe one. +407 > Parameters +408 - newwin (window) new window object +409 \*/ +410 R.setWindow = function (newwin) { +411 eve("setWindow", R, g.win, newwin); +412 g.win = newwin; +413 g.doc = g.win.document; +414 if (initWin) { +415 initWin(g.win); +416 } +417 }; +418 // colour utilities +419 var toHex = function (color) { +420 if (R.vml) { +421 // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/ +422 var trim = /^\s+|\s+$/g; +423 var bod; +424 try { +425 var docum = new ActiveXObject("htmlfile"); +426 docum.write("<body>"); +427 docum.close(); +428 bod = docum.body; +429 } catch(e) { +430 bod = createPopup().document.body; +431 } +432 var range = bod.createTextRange(); +433 toHex = cacher(function (color) { +434 try { +435 bod.style.color = Str(color).replace(trim, E); +436 var value = range.queryCommandValue("ForeColor"); +437 value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16); +438 return "#" + ("000000" + value.toString(16)).slice(-6); +439 } catch(e) { +440 return "none"; +441 } +442 }); +443 } else { +444 var i = g.doc.createElement("i"); +445 i.title = "Rapha\xebl Colour Picker"; +446 i.style.display = "none"; +447 g.doc.body.appendChild(i); +448 toHex = cacher(function (color) { +449 i.style.color = color; +450 return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); +451 }); +452 } +453 return toHex(color); +454 }, +455 hsbtoString = function () { +456 return "hsb(" + [this.h, this.s, this.b] + ")"; +457 }, +458 hsltoString = function () { +459 return "hsl(" + [this.h, this.s, this.l] + ")"; +460 }, +461 rgbtoString = function () { +462 return this.hex; +463 }, +464 prepareRGB = function (r, g, b) { +465 if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) { +466 b = r.b; +467 g = r.g; +468 r = r.r; +469 } +470 if (g == null && R.is(r, string)) { +471 var clr = R.getRGB(r); +472 r = clr.r; +473 g = clr.g; +474 b = clr.b; +475 } +476 if (r > 1 || g > 1 || b > 1) { +477 r /= 255; +478 g /= 255; +479 b /= 255; +480 } +481 +482 return [r, g, b]; +483 }, +484 packageRGB = function (r, g, b, o) { +485 r *= 255; +486 g *= 255; +487 b *= 255; +488 var rgb = { +489 r: r, +490 g: g, +491 b: b, +492 hex: R.rgb(r, g, b), +493 toString: rgbtoString +494 }; +495 R.is(o, "finite") && (rgb.opacity = o); +496 return rgb; +497 }; +498 /*\ +499 * Raphael.hsb2rgb +500 [ method ] +501 ** +502 * Converts HSB values to RGB object. +503 > Parameters +504 - h (number) hue +505 - s (number) saturation +506 - v (number) value or brightness +507 = (object) RGB object in format: +508 o { +509 o r (number) red, +510 o g (number) green, +511 o b (number) blue, +512 o hex (string) color in HTML/CSS format: #•••••• +513 o } +514 \*/ +515 R.hsb2rgb = function (h, s, v, o) { +516 if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) { +517 v = h.b; +518 s = h.s; +519 h = h.h; +520 o = h.o; +521 } +522 h *= 360; +523 var R, G, B, X, C; +524 h = (h % 360) / 60; +525 C = v * s; +526 X = C * (1 - abs(h % 2 - 1)); +527 R = G = B = v - C; +528 +529 h = ~~h; +530 R += [C, X, 0, 0, X, C][h]; +531 G += [X, C, C, X, 0, 0][h]; +532 B += [0, 0, X, C, C, X][h]; +533 return packageRGB(R, G, B, o); +534 }; +535 /*\ +536 * Raphael.hsl2rgb +537 [ method ] +538 ** +539 * Converts HSL values to RGB object. +540 > Parameters +541 - h (number) hue +542 - s (number) saturation +543 - l (number) luminosity +544 = (object) RGB object in format: +545 o { +546 o r (number) red, +547 o g (number) green, +548 o b (number) blue, +549 o hex (string) color in HTML/CSS format: #•••••• +550 o } +551 \*/ +552 R.hsl2rgb = function (h, s, l, o) { +553 if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) { +554 l = h.l; +555 s = h.s; +556 h = h.h; +557 } +558 if (h > 1 || s > 1 || l > 1) { +559 h /= 360; +560 s /= 100; +561 l /= 100; +562 } +563 h *= 360; +564 var R, G, B, X, C; +565 h = (h % 360) / 60; +566 C = 2 * s * (l < .5 ? l : 1 - l); +567 X = C * (1 - abs(h % 2 - 1)); +568 R = G = B = l - C / 2; +569 +570 h = ~~h; +571 R += [C, X, 0, 0, X, C][h]; +572 G += [X, C, C, X, 0, 0][h]; +573 B += [0, 0, X, C, C, X][h]; +574 return packageRGB(R, G, B, o); +575 }; +576 /*\ +577 * Raphael.rgb2hsb +578 [ method ] +579 ** +580 * Converts RGB values to HSB object. +581 > Parameters +582 - r (number) red +583 - g (number) green +584 - b (number) blue +585 = (object) HSB object in format: +586 o { +587 o h (number) hue +588 o s (number) saturation +589 o b (number) brightness +590 o } +591 \*/ +592 R.rgb2hsb = function (r, g, b) { +593 b = prepareRGB(r, g, b); +594 r = b[0]; +595 g = b[1]; +596 b = b[2]; +597 +598 var H, S, V, C; +599 V = mmax(r, g, b); +600 C = V - mmin(r, g, b); +601 H = (C == 0 ? null : +602 V == r ? (g - b) / C : +603 V == g ? (b - r) / C + 2 : +604 (r - g) / C + 4); +605 H = (H % 6) * 60; +606 S = C == 0 ? 0 : C / V; +607 return {h: H, s: S, b: V, toString: hsbtoString}; +608 }; +609 /*\ +610 * Raphael.rgb2hsl +611 [ method ] +612 ** +613 * Converts RGB values to HSL object. +614 > Parameters +615 - r (number) red +616 - g (number) green +617 - b (number) blue +618 = (object) HSL object in format: +619 o { +620 o h (number) hue +621 o s (number) saturation +622 o l (number) luminosity +623 o } +624 \*/ +625 R.rgb2hsl = function (r, g, b) { +626 b = prepareRGB(r, g, b); +627 r = b[0]; +628 g = b[1]; +629 b = b[2]; +630 +631 var H, S, L, M, m, C; +632 M = mmax(r, g, b); +633 m = mmin(r, g, b); +634 C = M - m; +635 H = (C == 0 ? null : +636 M == r ? (g - b) / C : +637 M == g ? (b - r) / C + 2 : +638 (r - g) / C + 4); +639 H = (H % 6) * 60; +640 L = (M + m) / 2; +641 S = (C == 0 ? 0 : +642 L < .5 ? C / (2 * L) : +643 C / (2 - 2 * L)); +644 return {h: H, s: S, l: L, toString: hsltoString}; +645 }; +646 R._path2string = function () { +647 return this.join(",").replace(p2s, "$1"); +648 }; +649 function cacher(f, scope, postprocessor) { +650 function newf() { +651 var arg = Array.prototype.slice.call(arguments, 0), +652 args = arg.join("\u2400"), +653 cache = newf.cache = newf.cache || {}, +654 count = newf.count = newf.count || []; +655 if (cache[has](args)) { +656 return postprocessor ? postprocessor(cache[args]) : cache[args]; +657 } +658 count.length >= 1e3 && delete cache[count.shift()]; +659 count.push(args); +660 cache[args] = f[apply](scope, arg); +661 return postprocessor ? postprocessor(cache[args]) : cache[args]; +662 } +663 return newf; +664 } +665 +666 function preload(src, f) { +667 var img = g.doc.createElement("img"); +668 img.style.cssText = "position:absolute;left:-9999em;top-9999em"; +669 img.onload = function () { +670 f.call(this); +671 this.onload = null; +672 g.doc.body.removeChild(this); +673 }; +674 img.onerror = function () { +675 g.doc.body.removeChild(this); +676 }; +677 g.doc.body.appendChild(img); +678 img.src = src; +679 } +680 +681 /*\ +682 * Raphael.getRGB +683 [ method ] +684 ** +685 * Parses colour string as RGB object +686 > Parameters +687 - colour (string) colour string in one of formats: +688 # <ul> +689 # <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li> +690 # <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li> +691 # <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li> +692 # <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(2001000)</code>”)</li> +693 # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%, 175%, 0%)</code>”)</li> +694 # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.50.251)</code>”)</li> +695 # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li> +696 # <li>hsl(•••, •••, •••) — same as hsb</li> +697 # <li>hsl(•••%, •••%, •••%) — same as hsb</li> +698 # </ul> +699 = (object) RGB object in format: +700 o { +701 o r (number) red, +702 o g (number) green, +703 o b (number) blue +704 o hex (string) color in HTML/CSS format: #••••••, +705 o error (boolean) true if string can’t be parsed +706 o } +707 \*/ +708 R.getRGB = cacher(function (colour) { +709 if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { +710 return {r: -1, g: -1, b: -1, hex: "none", error: 1}; +711 } +712 if (colour == "none") { +713 return {r: -1, g: -1, b: -1, hex: "none"}; +714 } +715 !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); +716 var res, +717 red, +718 green, +719 blue, +720 opacity, +721 t, +722 values, +723 rgb = colour.match(colourRegExp); +724 if (rgb) { +725 if (rgb[2]) { +726 blue = toInt(rgb[2].substring(5), 16); +727 green = toInt(rgb[2].substring(3, 5), 16); +728 red = toInt(rgb[2].substring(1, 3), 16); +729 } +730 if (rgb[3]) { +731 blue = toInt((t = rgb[3].charAt(3)) + t, 16); +732 green = toInt((t = rgb[3].charAt(2)) + t, 16); +733 red = toInt((t = rgb[3].charAt(1)) + t, 16); +734 } +735 if (rgb[4]) { +736 values = rgb[4].split(commaSpaces); +737 red = toFloat(values[0]); +738 values[0].slice(-1) == "%" && (red *= 2.55); +739 green = toFloat(values[1]); +740 values[1].slice(-1) == "%" && (green *= 2.55); +741 blue = toFloat(values[2]); +742 values[2].slice(-1) == "%" && (blue *= 2.55); +743 rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); +744 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); +745 } +746 if (rgb[5]) { +747 values = rgb[5].split(commaSpaces); +748 red = toFloat(values[0]); +749 values[0].slice(-1) == "%" && (red *= 2.55); +750 green = toFloat(values[1]); +751 values[1].slice(-1) == "%" && (green *= 2.55); +752 blue = toFloat(values[2]); +753 values[2].slice(-1) == "%" && (blue *= 2.55); +754 (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); +755 rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); +756 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); +757 return R.hsb2rgb(red, green, blue, opacity); +758 } +759 if (rgb[6]) { +760 values = rgb[6].split(commaSpaces); +761 red = toFloat(values[0]); +762 values[0].slice(-1) == "%" && (red *= 2.55); +763 green = toFloat(values[1]); +764 values[1].slice(-1) == "%" && (green *= 2.55); +765 blue = toFloat(values[2]); +766 values[2].slice(-1) == "%" && (blue *= 2.55); +767 (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); +768 rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); +769 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); +770 return R.hsl2rgb(red, green, blue, opacity); +771 } +772 rgb = {r: red, g: green, b: blue}; +773 rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1); +774 R.is(opacity, "finite") && (rgb.opacity = opacity); +775 return rgb; +776 } +777 return {r: -1, g: -1, b: -1, hex: "none", error: 1}; +778 }, R); +779 /*\ +780 * Raphael.hsb +781 [ method ] +782 ** +783 * Converts HSB values to hex representation of the colour. +784 > Parameters +785 - h (number) hue +786 - s (number) saturation +787 - b (number) value or brightness +788 = (string) hex representation of the colour. +789 \*/ +790 R.hsb = cacher(function (h, s, b) { +791 return R.hsb2rgb(h, s, b).hex; +792 }); +793 /*\ +794 * Raphael.hsl +795 [ method ] +796 ** +797 * Converts HSL values to hex representation of the colour. +798 > Parameters +799 - h (number) hue +800 - s (number) saturation +801 - l (number) luminosity +802 = (string) hex representation of the colour. +803 \*/ +804 R.hsl = cacher(function (h, s, l) { +805 return R.hsl2rgb(h, s, l).hex; +806 }); +807 /*\ +808 * Raphael.rgb +809 [ method ] +810 ** +811 * Converts RGB values to hex representation of the colour. +812 > Parameters +813 - r (number) red +814 - g (number) green +815 - b (number) blue +816 = (string) hex representation of the colour. +817 \*/ +818 R.rgb = cacher(function (r, g, b) { +819 return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); +820 }); +821 /*\ +822 * Raphael.getColor +823 [ method ] +824 ** +825 * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset +826 > Parameters +827 - value (number) #optional brightness, default is `0.75` +828 = (string) hex representation of the colour. +829 \*/ +830 R.getColor = function (value) { +831 var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75}, +832 rgb = this.hsb2rgb(start.h, start.s, start.b); +833 start.h += .075; +834 if (start.h > 1) { +835 start.h = 0; +836 start.s -= .2; +837 start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b}); +838 } +839 return rgb.hex; +840 }; +841 /*\ +842 * Raphael.getColor.reset +843 [ method ] +844 ** +845 * Resets spectrum position for @Raphael.getColor back to red. +846 \*/ +847 R.getColor.reset = function () { +848 delete this.start; +849 }; +850 +851 /*\ +852 * Raphael.parsePathString +853 [ method ] +854 ** +855 * Utility method +856 ** +857 * Parses given path string into an array of arrays of path segments. +858 > Parameters +859 - pathString (string|array) path string or array of segments (in the last case it will be returned straight away) +860 = (array) array of segments. +861 \*/ +862 R.parsePathString = cacher(function (pathString) { +863 if (!pathString) { +864 return null; +865 } +866 var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}, +867 data = []; +868 if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption +869 data = pathClone(pathString); +870 } +871 if (!data.length) { +872 Str(pathString).replace(pathCommand, function (a, b, c) { +873 var params = [], +874 name = lowerCase.call(b); +875 c.replace(pathValues, function (a, b) { +876 b && params.push(+b); +877 }); +878 if (name == "m" && params.length > 2) { +879 data.push([b][concat](params.splice(0, 2))); +880 name = "l"; +881 b = b == "m" ? "l" : "L"; +882 } +883 while (params.length >= paramCounts[name]) { +884 data.push([b][concat](params.splice(0, paramCounts[name]))); +885 if (!paramCounts[name]) { +886 break; +887 } +888 } +889 }); +890 } +891 data.toString = R._path2string; +892 return data; +893 }); +894 /*\ +895 * Raphael.parseTransformString +896 [ method ] +897 ** +898 * Utility method +899 ** +900 * Parses given path string into an array of transformations. +901 > Parameters +902 - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away) +903 = (array) array of transformations. +904 \*/ +905 R.parseTransformString = cacher(function (TString) { +906 if (!TString) { +907 return null; +908 } +909 var paramCounts = {r: 3, s: 4, t: 2, m: 6}, +910 data = []; +911 if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption +912 data = pathClone(TString); +913 } +914 if (!data.length) { +915 Str(TString).replace(tCommand, function (a, b, c) { +916 var params = [], +917 name = lowerCase.call(b); +918 c.replace(pathValues, function (a, b) { +919 b && params.push(+b); +920 }); +921 data.push([name][concat](params)); +922 }); +923 } +924 data.toString = R._path2string; +925 return data; +926 }); +927 /*\ +928 * Raphael.findDotsAtSegment +929 [ method ] +930 ** +931 * Utility method +932 ** +933 * Find dot coordinates on the given cubic bezier curve at the given t. +934 > Parameters +935 - p1x (number) x of the first point of the curve +936 - p1y (number) y of the first point of the curve +937 - c1x (number) x of the first anchor of the curve +938 - c1y (number) y of the first anchor of the curve +939 - c2x (number) x of the second anchor of the curve +940 - c2y (number) y of the second anchor of the curve +941 - p2x (number) x of the second point of the curve +942 - p2y (number) y of the second point of the curve +943 - t (number) position on the curve (0..1) +944 = (object) point information in format: +945 o { +946 o x: (number) x coordinate of the point +947 o y: (number) y coordinate of the point +948 o m: { +949 o x: (number) x coordinate of the left anchor +950 o y: (number) y coordinate of the left anchor +951 o } +952 o n: { +953 o x: (number) x coordinate of the right anchor +954 o y: (number) y coordinate of the right anchor +955 o } +956 o start: { +957 o x: (number) x coordinate of the start of the curve +958 o y: (number) y coordinate of the start of the curve +959 o } +960 o end: { +961 o x: (number) x coordinate of the end of the curve +962 o y: (number) y coordinate of the end of the curve +963 o } +964 o alpha: (number) angle of the curve derivative at the point +965 o } +966 \*/ +967 R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { +968 var t1 = 1 - t, +969 x = pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, +970 y = pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y, +971 mx = p1x + 2 * t * (c1x - p1x) + t * t * (c2x - 2 * c1x + p1x), +972 my = p1y + 2 * t * (c1y - p1y) + t * t * (c2y - 2 * c1y + p1y), +973 nx = c1x + 2 * t * (c2x - c1x) + t * t * (p2x - 2 * c2x + c1x), +974 ny = c1y + 2 * t * (c2y - c1y) + t * t * (p2y - 2 * c2y + c1y), +975 ax = (1 - t) * p1x + t * c1x, +976 ay = (1 - t) * p1y + t * c1y, +977 cx = (1 - t) * c2x + t * p2x, +978 cy = (1 - t) * c2y + t * p2y, +979 alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI); +980 (mx > nx || my < ny) && (alpha += 180); +981 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}; +982 }; +983 var pathDimensions = cacher(function (path) { +984 if (!path) { +985 return {x: 0, y: 0, width: 0, height: 0}; +986 } +987 path = path2curve(path); +988 var x = 0, +989 y = 0, +990 X = [], +991 Y = [], +992 p; +993 for (var i = 0, ii = path.length; i < ii; i++) { +994 p = path[i]; +995 if (p[0] == "M") { +996 x = p[1]; +997 y = p[2]; +998 X.push(x); +999 Y.push(y); +1000 } else { +1001 var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); +1002 X = X[concat](dim.min.x, dim.max.x); +1003 Y = Y[concat](dim.min.y, dim.max.y); +1004 x = p[5]; +1005 y = p[6]; +1006 } +1007 } +1008 var xmin = mmin[apply](0, X), +1009 ymin = mmin[apply](0, Y); +1010 return { +1011 x: xmin, +1012 y: ymin, +1013 width: mmax[apply](0, X) - xmin, +1014 height: mmax[apply](0, Y) - ymin +1015 }; +1016 }), +1017 pathClone = function (pathArray) { +1018 var res = []; +1019 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption +1020 pathArray = R.parsePathString(pathArray); +1021 } +1022 for (var i = 0, ii = pathArray.length; i < ii; i++) { +1023 res[i] = []; +1024 for (var j = 0, jj = pathArray[i].length; j < jj; j++) { +1025 res[i][j] = pathArray[i][j]; +1026 } +1027 } +1028 res.toString = R._path2string; +1029 return res; +1030 }, +1031 pathToRelative = cacher(function (pathArray) { +1032 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption +1033 pathArray = R.parsePathString(pathArray); +1034 } +1035 var res = [], +1036 x = 0, +1037 y = 0, +1038 mx = 0, +1039 my = 0, +1040 start = 0; +1041 if (pathArray[0][0] == "M") { +1042 x = pathArray[0][1]; +1043 y = pathArray[0][2]; +1044 mx = x; +1045 my = y; +1046 start++; +1047 res.push(["M", x, y]); +1048 } +1049 for (var i = start, ii = pathArray.length; i < ii; i++) { +1050 var r = res[i] = [], +1051 pa = pathArray[i]; +1052 if (pa[0] != lowerCase.call(pa[0])) { +1053 r[0] = lowerCase.call(pa[0]); +1054 switch (r[0]) { +1055 case "a": +1056 r[1] = pa[1]; +1057 r[2] = pa[2]; +1058 r[3] = pa[3]; +1059 r[4] = pa[4]; +1060 r[5] = pa[5]; +1061 r[6] = +(pa[6] - x).toFixed(3); +1062 r[7] = +(pa[7] - y).toFixed(3); +1063 break; +1064 case "v": +1065 r[1] = +(pa[1] - y).toFixed(3); +1066 break; +1067 case "m": +1068 mx = pa[1]; +1069 my = pa[2]; +1070 default: +1071 for (var j = 1, jj = pa.length; j < jj; j++) { +1072 r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3); +1073 } +1074 } +1075 } else { +1076 r = res[i] = []; +1077 if (pa[0] == "m") { +1078 mx = pa[1] + x; +1079 my = pa[2] + y; +1080 } +1081 for (var k = 0, kk = pa.length; k < kk; k++) { +1082 res[i][k] = pa[k]; +1083 } +1084 } +1085 var len = res[i].length; +1086 switch (res[i][0]) { +1087 case "z": +1088 x = mx; +1089 y = my; +1090 break; +1091 case "h": +1092 x += +res[i][len - 1]; +1093 break; +1094 case "v": +1095 y += +res[i][len - 1]; +1096 break; +1097 default: +1098 x += +res[i][len - 2]; +1099 y += +res[i][len - 1]; +1100 } +1101 } +1102 res.toString = R._path2string; +1103 return res; +1104 }, 0, pathClone), +1105 pathToAbsolute = cacher(function (pathArray) { +1106 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption +1107 pathArray = R.parsePathString(pathArray); +1108 } +1109 var res = [], +1110 x = 0, +1111 y = 0, +1112 mx = 0, +1113 my = 0, +1114 start = 0; +1115 if (pathArray[0][0] == "M") { +1116 x = +pathArray[0][1]; +1117 y = +pathArray[0][2]; +1118 mx = x; +1119 my = y; +1120 start++; +1121 res[0] = ["M", x, y]; +1122 } +1123 for (var i = start, ii = pathArray.length; i < ii; i++) { +1124 var r = res[i] = [], +1125 pa = pathArray[i]; +1126 if (pa[0] != upperCase.call(pa[0])) { +1127 r[0] = upperCase.call(pa[0]); +1128 switch (r[0]) { +1129 case "A": +1130 r[1] = pa[1]; +1131 r[2] = pa[2]; +1132 r[3] = pa[3]; +1133 r[4] = pa[4]; +1134 r[5] = pa[5]; +1135 r[6] = +(pa[6] + x); +1136 r[7] = +(pa[7] + y); +1137 break; +1138 case "V": +1139 r[1] = +pa[1] + y; +1140 break; +1141 case "H": +1142 r[1] = +pa[1] + x; +1143 break; +1144 case "M": +1145 mx = +pa[1] + x; +1146 my = +pa[2] + y; +1147 default: +1148 for (var j = 1, jj = pa.length; j < jj; j++) { +1149 r[j] = +pa[j] + ((j % 2) ? x : y); +1150 } +1151 } +1152 } else { +1153 for (var k = 0, kk = pa.length; k < kk; k++) { +1154 res[i][k] = pa[k]; +1155 } +1156 } +1157 switch (r[0]) { +1158 case "Z": +1159 x = mx; +1160 y = my; +1161 break; +1162 case "H": +1163 x = r[1]; +1164 break; +1165 case "V": +1166 y = r[1]; +1167 break; +1168 case "M": +1169 mx = res[i][res[i].length - 2]; +1170 my = res[i][res[i].length - 1]; +1171 default: +1172 x = res[i][res[i].length - 2]; +1173 y = res[i][res[i].length - 1]; +1174 } +1175 } +1176 res.toString = R._path2string; +1177 return res; +1178 }, null, pathClone), +1179 l2c = function (x1, y1, x2, y2) { +1180 return [x1, y1, x2, y2, x2, y2]; +1181 }, +1182 q2c = function (x1, y1, ax, ay, x2, y2) { +1183 var _13 = 1 / 3, +1184 _23 = 2 / 3; +1185 return [ +1186 _13 * x1 + _23 * ax, +1187 _13 * y1 + _23 * ay, +1188 _13 * x2 + _23 * ax, +1189 _13 * y2 + _23 * ay, +1190 x2, +1191 y2 +1192 ]; +1193 }, +1194 a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { +1195 // for more information of where this math came from visit: +1196 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes +1197 var _120 = PI * 120 / 180, +1198 rad = PI / 180 * (+angle || 0), +1199 res = [], +1200 xy, +1201 rotate = cacher(function (x, y, rad) { +1202 var X = x * math.cos(rad) - y * math.sin(rad), +1203 Y = x * math.sin(rad) + y * math.cos(rad); +1204 return {x: X, y: Y}; +1205 }); +1206 if (!recursive) { +1207 xy = rotate(x1, y1, -rad); +1208 x1 = xy.x; +1209 y1 = xy.y; +1210 xy = rotate(x2, y2, -rad); +1211 x2 = xy.x; +1212 y2 = xy.y; +1213 var cos = math.cos(PI / 180 * angle), +1214 sin = math.sin(PI / 180 * angle), +1215 x = (x1 - x2) / 2, +1216 y = (y1 - y2) / 2; +1217 var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); +1218 if (h > 1) { +1219 h = math.sqrt(h); +1220 rx = h * rx; +1221 ry = h * ry; +1222 } +1223 var rx2 = rx * rx, +1224 ry2 = ry * ry, +1225 k = (large_arc_flag == sweep_flag ? -1 : 1) * +1226 math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), +1227 cx = k * rx * y / ry + (x1 + x2) / 2, +1228 cy = k * -ry * x / rx + (y1 + y2) / 2, +1229 f1 = math.asin(((y1 - cy) / ry).toFixed(9)), +1230 f2 = math.asin(((y2 - cy) / ry).toFixed(9)); +1231 +1232 f1 = x1 < cx ? PI - f1 : f1; +1233 f2 = x2 < cx ? PI - f2 : f2; +1234 f1 < 0 && (f1 = PI * 2 + f1); +1235 f2 < 0 && (f2 = PI * 2 + f2); +1236 if (sweep_flag && f1 > f2) { +1237 f1 = f1 - PI * 2; +1238 } +1239 if (!sweep_flag && f2 > f1) { +1240 f2 = f2 - PI * 2; +1241 } +1242 } else { +1243 f1 = recursive[0]; +1244 f2 = recursive[1]; +1245 cx = recursive[2]; +1246 cy = recursive[3]; +1247 } +1248 var df = f2 - f1; +1249 if (abs(df) > _120) { +1250 var f2old = f2, +1251 x2old = x2, +1252 y2old = y2; +1253 f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); +1254 x2 = cx + rx * math.cos(f2); +1255 y2 = cy + ry * math.sin(f2); +1256 res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); +1257 } +1258 df = f2 - f1; +1259 var c1 = math.cos(f1), +1260 s1 = math.sin(f1), +1261 c2 = math.cos(f2), +1262 s2 = math.sin(f2), +1263 t = math.tan(df / 4), +1264 hx = 4 / 3 * rx * t, +1265 hy = 4 / 3 * ry * t, +1266 m1 = [x1, y1], +1267 m2 = [x1 + hx * s1, y1 - hy * c1], +1268 m3 = [x2 + hx * s2, y2 - hy * c2], +1269 m4 = [x2, y2]; +1270 m2[0] = 2 * m1[0] - m2[0]; +1271 m2[1] = 2 * m1[1] - m2[1]; +1272 if (recursive) { +1273 return [m2, m3, m4][concat](res); +1274 } else { +1275 res = [m2, m3, m4][concat](res).join().split(","); +1276 var newres = []; +1277 for (var i = 0, ii = res.length; i < ii; i++) { +1278 newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; +1279 } +1280 return newres; +1281 } +1282 }, +1283 findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { +1284 var t1 = 1 - t; +1285 return { +1286 x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, +1287 y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y +1288 }; +1289 }, +1290 curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { +1291 var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x), +1292 b = 2 * (c1x - p1x) - 2 * (c2x - c1x), +1293 c = p1x - c1x, +1294 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a, +1295 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a, +1296 y = [p1y, p2y], +1297 x = [p1x, p2x], +1298 dot; +1299 abs(t1) > "1e12" && (t1 = .5); +1300 abs(t2) > "1e12" && (t2 = .5); +1301 if (t1 > 0 && t1 < 1) { +1302 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); +1303 x.push(dot.x); +1304 y.push(dot.y); +1305 } +1306 if (t2 > 0 && t2 < 1) { +1307 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); +1308 x.push(dot.x); +1309 y.push(dot.y); +1310 } +1311 a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y); +1312 b = 2 * (c1y - p1y) - 2 * (c2y - c1y); +1313 c = p1y - c1y; +1314 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a; +1315 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a; +1316 abs(t1) > "1e12" && (t1 = .5); +1317 abs(t2) > "1e12" && (t2 = .5); +1318 if (t1 > 0 && t1 < 1) { +1319 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); +1320 x.push(dot.x); +1321 y.push(dot.y); +1322 } +1323 if (t2 > 0 && t2 < 1) { +1324 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); +1325 x.push(dot.x); +1326 y.push(dot.y); +1327 } +1328 return { +1329 min: {x: mmin[apply](0, x), y: mmin[apply](0, y)}, +1330 max: {x: mmax[apply](0, x), y: mmax[apply](0, y)} +1331 }; +1332 }), +1333 path2curve = cacher(function (path, path2) { +1334 var p = pathToAbsolute(path), +1335 p2 = path2 && pathToAbsolute(path2), +1336 attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, +1337 attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, +1338 processPath = function (path, d) { +1339 var nx, ny; +1340 if (!path) { +1341 return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; +1342 } +1343 !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null); +1344 switch (path[0]) { +1345 case "M": +1346 d.X = path[1]; +1347 d.Y = path[2]; +1348 break; +1349 case "A": +1350 path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1)))); +1351 break; +1352 case "S": +1353 nx = d.x + (d.x - (d.bx || d.x)); +1354 ny = d.y + (d.y - (d.by || d.y)); +1355 path = ["C", nx, ny][concat](path.slice(1)); +1356 break; +1357 case "T": +1358 d.qx = d.x + (d.x - (d.qx || d.x)); +1359 d.qy = d.y + (d.y - (d.qy || d.y)); +1360 path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); +1361 break; +1362 case "Q": +1363 d.qx = path[1]; +1364 d.qy = path[2]; +1365 path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4])); +1366 break; +1367 case "L": +1368 path = ["C"][concat](l2c(d.x, d.y, path[1], path[2])); +1369 break; +1370 case "H": +1371 path = ["C"][concat](l2c(d.x, d.y, path[1], d.y)); +1372 break; +1373 case "V": +1374 path = ["C"][concat](l2c(d.x, d.y, d.x, path[1])); +1375 break; +1376 case "Z": +1377 path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y)); +1378 break; +1379 } +1380 return path; +1381 }, +1382 fixArc = function (pp, i) { +1383 if (pp[i].length > 7) { +1384 pp[i].shift(); +1385 var pi = pp[i]; +1386 while (pi.length) { +1387 pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6))); +1388 } +1389 pp.splice(i, 1); +1390 ii = mmax(p.length, p2 && p2.length || 0); +1391 } +1392 }, +1393 fixM = function (path1, path2, a1, a2, i) { +1394 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { +1395 path2.splice(i, 0, ["M", a2.x, a2.y]); +1396 a1.bx = 0; +1397 a1.by = 0; +1398 a1.x = path1[i][1]; +1399 a1.y = path1[i][2]; +1400 ii = mmax(p.length, p2 && p2.length || 0); +1401 } +1402 }; +1403 for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) { +1404 p[i] = processPath(p[i], attrs); +1405 fixArc(p, i); +1406 p2 && (p2[i] = processPath(p2[i], attrs2)); +1407 p2 && fixArc(p2, i); +1408 fixM(p, p2, attrs, attrs2, i); +1409 fixM(p2, p, attrs2, attrs, i); +1410 var seg = p[i], +1411 seg2 = p2 && p2[i], +1412 seglen = seg.length, +1413 seg2len = p2 && seg2.length; +1414 attrs.x = seg[seglen - 2]; +1415 attrs.y = seg[seglen - 1]; +1416 attrs.bx = toFloat(seg[seglen - 4]) || attrs.x; +1417 attrs.by = toFloat(seg[seglen - 3]) || attrs.y; +1418 attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x); +1419 attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y); +1420 attrs2.x = p2 && seg2[seg2len - 2]; +1421 attrs2.y = p2 && seg2[seg2len - 1]; +1422 } +1423 return p2 ? [p, p2] : p; +1424 }, null, pathClone), +1425 parseDots = cacher(function (gradient) { +1426 var dots = []; +1427 for (var i = 0, ii = gradient.length; i < ii; i++) { +1428 var dot = {}, +1429 par = gradient[i].match(/^([^:]*):?([\d\.]*)/); +1430 dot.color = R.getRGB(par[1]); +1431 if (dot.color.error) { +1432 return null; +1433 } +1434 dot.color = dot.color.hex; +1435 par[2] && (dot.offset = par[2] + "%"); +1436 dots.push(dot); +1437 } +1438 for (i = 1, ii = dots.length - 1; i < ii; i++) { +1439 if (!dots[i].offset) { +1440 var start = toFloat(dots[i - 1].offset || 0), +1441 end = 0; +1442 for (var j = i + 1; j < ii; j++) { +1443 if (dots[j].offset) { +1444 end = dots[j].offset; +1445 break; +1446 } +1447 } +1448 if (!end) { +1449 end = 100; +1450 j = ii; +1451 } +1452 end = toFloat(end); +1453 var d = (end - start) / (j - i + 1); +1454 for (; i < j; i++) { +1455 start += d; +1456 dots[i].offset = start + "%"; +1457 } +1458 } +1459 } +1460 return dots; +1461 }), +1462 getContainer = function (x, y, w, h) { +1463 var container; +1464 container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x; +1465 if (container == null) { +1466 return; +1467 } +1468 if (container.tagName) { +1469 if (y == null) { +1470 return { +1471 container: container, +1472 width: container.style.pixelWidth || container.offsetWidth, +1473 height: container.style.pixelHeight || container.offsetHeight +1474 }; +1475 } else { +1476 return {container: container, width: y, height: w}; +1477 } +1478 } +1479 return {container: 1, x: x, y: y, width: w, height: h}; +1480 }, +1481 plugins = function (con, add) { +1482 var that = this; +1483 for (var prop in add) { +1484 if (add[has](prop) && !(prop in con)) { +1485 switch (typeof add[prop]) { +1486 case "function": +1487 (function (f) { +1488 con[prop] = con === that ? f : function () { return f[apply](that, arguments); }; +1489 })(add[prop]); +1490 break; +1491 case "object": +1492 con[prop] = con[prop] || {}; +1493 plugins.call(this, con[prop], add[prop]); +1494 break; +1495 default: +1496 con[prop] = add[prop]; +1497 break; +1498 } +1499 } +1500 } +1501 }, +1502 tear = function (el, paper) { +1503 el == paper.top && (paper.top = el.prev); +1504 el == paper.bottom && (paper.bottom = el.next); +1505 el.next && (el.next.prev = el.prev); +1506 el.prev && (el.prev.next = el.next); +1507 }, +1508 tofront = function (el, paper) { +1509 if (paper.top === el) { +1510 return; +1511 } +1512 tear(el, paper); +1513 el.next = null; +1514 el.prev = paper.top; +1515 paper.top.next = el; +1516 paper.top = el; +1517 }, +1518 toback = function (el, paper) { +1519 if (paper.bottom === el) { +1520 return; +1521 } +1522 tear(el, paper); +1523 el.next = paper.bottom; +1524 el.prev = null; +1525 paper.bottom.prev = el; +1526 paper.bottom = el; +1527 }, +1528 insertafter = function (el, el2, paper) { +1529 tear(el, paper); +1530 el2 == paper.top && (paper.top = el); +1531 el2.next && (el2.next.prev = el); +1532 el.next = el2.next; +1533 el.prev = el2; +1534 el2.next = el; +1535 }, +1536 insertbefore = function (el, el2, paper) { +1537 tear(el, paper); +1538 el2 == paper.bottom && (paper.bottom = el); +1539 el2.prev && (el2.prev.next = el); +1540 el.prev = el2.prev; +1541 el2.prev = el; +1542 el.next = el2; +1543 }, +1544 removed = function (methodname) { +1545 return function () { +1546 throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object"); +1547 }; +1548 }, +1549 extractTransform = function (el, tstr) { +1550 if (tstr == null) { +1551 return el._.transform; +1552 } +1553 tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E); +1554 var tdata = R.parseTransformString(tstr), +1555 deg = 0, +1556 dx = 0, +1557 dy = 0, +1558 sx = 1, +1559 sy = 1, +1560 _ = el._, +1561 m = new Matrix; +1562 _.transform = tdata || []; +1563 if (tdata) { +1564 for (var i = 0, ii = tdata.length; i < ii; i++) { +1565 var t = tdata[i], +1566 tlen = t.length, +1567 bb; +1568 t[0] = Str(t[0]).toLowerCase(); +1569 if (t[0] == "t" && tlen == 3) { +1570 m.translate(t[1], t[2]); +1571 } else if (t[0] == "r") { +1572 if (tlen == 2) { +1573 bb = bb || el.getBBox(1); +1574 m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2); +1575 deg += t[1]; +1576 } else if (tlen == 4) { +1577 m.rotate(t[1], t[2], t[3]); +1578 deg += t[1]; +1579 } +1580 } else if (t[0] == "s") { +1581 if (tlen == 2 || tlen == 3) { +1582 bb = bb || el.getBBox(1); +1583 m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2); +1584 sx *= t[1]; +1585 sy *= t[tlen - 1]; +1586 } else if (tlen == 5) { +1587 m.scale(t[1], t[2], t[3], t[4]); +1588 sx *= t[1]; +1589 sy *= t[2]; +1590 } +1591 } else if (t[0] == "m" && tlen == 7) { +1592 m.add(t[1], t[2], t[3], t[4], t[5], t[6]); +1593 } +1594 _.dirtyT = 1; +1595 el.matrix = m; +1596 } +1597 } +1598 +1599 el.matrix = m; +1600 +1601 _.sx = sx; +1602 _.sy = sy; +1603 _.deg = deg; +1604 _.dx = dx = m.m[0][2]; +1605 _.dy = dy = m.m[1][2]; +1606 +1607 if (sx == 1 && sy == 1 && !deg && _.bbox) { +1608 _.bbox.x += +dx; +1609 _.bbox.y += +dy; +1610 } else { +1611 _.dirtyT = 1; +1612 } +1613 }, +1614 getEmpty = function (item) { +1615 switch (item[0]) { +1616 case "t": return ["t", 0, 0]; +1617 case "m": return ["m", 1, 0, 0, 1, 0, 0]; +1618 case "r": if (item.length == 4) { +1619 return ["r", 0, item[2], item[3]]; +1620 } else { +1621 return ["r", 0]; +1622 } +1623 case "s": if (item.length == 5) { +1624 return ["s", 1, 1, item[3], item[4]]; +1625 } else if (item.length == 3) { +1626 return ["s", 1, 1]; +1627 } else { +1628 return ["s", 1]; +1629 } +1630 } +1631 }, +1632 equaliseTransform = function (t1, t2) { +1633 t1 = R.parseTransformString(t1) || []; +1634 t2 = R.parseTransformString(t2) || []; +1635 var maxlength = mmax(t1.length, t2.length), +1636 from = [], +1637 to = [], +1638 i = 0, j, jj, +1639 tt1, tt2; +1640 for (; i < maxlength; i++) { +1641 tt1 = t1[i] || getEmpty(t2[i]); +1642 tt2 = t2[i] || getEmpty(tt1); +1643 if ( (tt1[0] != tt2[0]) || +1644 (tt1[0] == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || +1645 (tt1[0] == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) +1646 ) { +1647 return; +1648 } +1649 from[i] = []; +1650 to[i] = []; +1651 for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) { +1652 j in tt1 && (from[i][j] = tt1[j]); +1653 j in tt2 && (to[i][j] = tt2[j]); +1654 } +1655 } +1656 return { +1657 from: from, +1658 to: to +1659 }; +1660 }; +1661 /*\ +1662 * Raphael.pathToRelative +1663 [ method ] +1664 ** +1665 * Utility method +1666 ** +1667 * Converts path to relative form +1668 > Parameters +1669 - pathString (string|array) path string or array of segments +1670 = (array) array of segments. +1671 \*/ +1672 R.pathToRelative = pathToRelative; +1673 /*\ +1674 * Raphael.path2curve +1675 [ method ] +1676 ** +1677 * Utility method +1678 ** +1679 * Converts path to a new path where all segments are cubic bezier curves. +1680 > Parameters +1681 - pathString (string|array) path string or array of segments +1682 = (array) array of segments. +1683 \*/ +1684 R.path2curve = path2curve; +1685 // Matrix +1686 // var m = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix(); +1687 function Matrix(a, b, c, d, e, f) { +1688 if (a != null) { +1689 this.m = [[a, c, e], [b, d, f], [0, 0, 1]]; +1690 } else { +1691 this.m = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; +1692 } +1693 } +1694 var matrixproto = Matrix.prototype; +1695 matrixproto.add = function (a, b, c, d, e, f) { +1696 var out = [[], [], []], +1697 matrix = [[a, c, e], [b, d, f], [0, 0, 1]], +1698 x, y, z, res; +1699 +1700 for (x = 0; x < 3; x++) { +1701 for (y = 0; y < 3; y++) { +1702 res = 0; +1703 for (z = 0; z < 3; z++) { +1704 res += this.m[x][z] * matrix[z][y]; +1705 } +1706 out[x][y] = res; +1707 } +1708 } +1709 this.m = out; +1710 }; +1711 matrixproto.invert = function () { +1712 var a = this.m[0][0], +1713 b = this.m[1][0], +1714 c = this.m[0][1], +1715 d = this.m[1][1], +1716 e = this.m[0][2], +1717 f = this.m[1][2], +1718 x = a * d - b * c; +1719 return new Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x); +1720 }; +1721 matrixproto.clone = function () { +1722 var a = this.m[0][0], +1723 b = this.m[1][0], +1724 c = this.m[0][1], +1725 d = this.m[1][1], +1726 e = this.m[0][2], +1727 f = this.m[1][2]; +1728 return new Matrix(a, b, c, d, e, f); +1729 }; +1730 matrixproto.translate = function (x, y) { +1731 this.add(1, 0, 0, 1, x, y); +1732 }; +1733 matrixproto.scale = function (x, y, cx, cy) { +1734 y == null && (y = x); +1735 this.add(1, 0, 0, 1, cx, cy); +1736 this.add(x, 0, 0, y, 0, 0); +1737 this.add(1, 0, 0, 1, -cx, -cy); +1738 }; +1739 matrixproto.rotate = function (a, x, y) { +1740 a = R.rad(a); +1741 var cos = +math.cos(a).toFixed(9), +1742 sin = +math.sin(a).toFixed(9); +1743 this.add(cos, sin, -sin, cos, x, y); +1744 this.add(1, 0, 0, 1, -x, -y); +1745 }; +1746 matrixproto.x = function (x, y) { +1747 return x * this.m[0][0] + y * this.m[0][1] + this.m[0][2]; +1748 }; +1749 matrixproto.y = function (x, y) { +1750 return x * this.m[1][0] + y * this.m[1][1] + this.m[1][2]; +1751 }; +1752 matrixproto.get = function (i, j) { +1753 return +this.m[i][j].toFixed(4); +1754 }; +1755 matrixproto.toString = function () { +1756 return R.svg ? +1757 "matrix(" + [this.get(0, 0), this.get(1, 0), this.get(0, 1), this.get(1, 1), this.get(0, 2), this.get(1, 2)].join() + ")" : +1758 [this.get(0, 0), this.get(0, 1), this.get(1, 0), this.get(1, 1), 0, 0].join(); +1759 }; +1760 matrixproto.toFilter = function () { +1761 return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0, 0) + +1762 ", M12=" + this.get(0, 1) + ", M21=" + this.get(1, 0) + ", M22=" + this.get(1, 1) + +1763 ", Dx=" + this.get(0, 2) + ", Dy=" + this.get(1, 2) + ", sizingmedthod='auto expand')"; +1764 }; +1765 matrixproto.offset = function () { +1766 return [this.m[0][2].toFixed(4), this.m[1][2].toFixed(4)]; +1767 }; +1768 +1769 R.Matrix = Matrix; +1770 +1771 // SVG +1772 if (R.svg) { +1773 var xlink = "http://www.w3.org/1999/xlink", +1774 markers = { +1775 block: "M5,0 0,2.5 5,5z", +1776 classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z", +1777 diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z", +1778 open: "M6,1 1,3.5 6,6", +1779 oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z" +1780 }, +1781 markerCounter = {}; +1782 R.toString = function () { +1783 return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version; +1784 }; +1785 var $ = function (el, attr) { +1786 if (attr) { +1787 if (typeof el == "string") { +1788 el = $(el); +1789 } +1790 for (var key in attr) if (attr[has](key)) { +1791 if (key.substring(0, 6) == "xlink:") { +1792 el.setAttributeNS(xlink, key.substring(6), Str(attr[key])); +1793 } else { +1794 el[setAttribute](key, Str(attr[key])); +1795 } +1796 } +1797 } else { +1798 el = g.doc.createElementNS("http://www.w3.org/2000/svg", el); +1799 el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)"); +1800 } +1801 return el; +1802 }, +1803 thePath = function (pathString, SVG) { +1804 var el = $("path"); +1805 SVG.canvas && SVG.canvas.appendChild(el); +1806 var p = new Element(el, SVG); +1807 p.type = "path"; +1808 setFillAndStroke(p, {fill: "none", stroke: "#000", path: pathString}); +1809 return p; +1810 }, +1811 gradients = {}, +1812 rgGrad = /^url\(#(.*)\)$/, +1813 removeGradientFill = function (node, paper) { +1814 var oid = node.getAttribute(fillString); +1815 oid = oid && oid.match(rgGrad); +1816 if (oid && !--gradients[oid[1]]) { +1817 delete gradients[oid[1]]; +1818 paper.defs.removeChild(g.doc.getElementById(oid[1])); +1819 } +1820 }, +1821 addGradientFill = function (element, gradient) { +1822 var type = "linear", +1823 id = element.id + gradient, +1824 fx = .5, fy = .5, +1825 o = element.node, +1826 SVG = element.paper, +1827 s = o.style, +1828 el = g.doc.getElementById(id); +1829 if (!el) { +1830 gradient = Str(gradient).replace(radial_gradient, function (all, _fx, _fy) { +1831 type = "radial"; +1832 if (_fx && _fy) { +1833 fx = toFloat(_fx); +1834 fy = toFloat(_fy); +1835 var dir = ((fy > .5) * 2 - 1); +1836 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && +1837 (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) && +1838 fy != .5 && +1839 (fy = fy.toFixed(5) - 1e-5 * dir); +1840 } +1841 return E; +1842 }); +1843 gradient = gradient.split(/\s*\-\s*/); +1844 if (type == "linear") { +1845 var angle = gradient.shift(); +1846 angle = -toFloat(angle); +1847 if (isNaN(angle)) { +1848 return null; +1849 } +1850 var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))], +1851 max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1); +1852 vector[2] *= max; +1853 vector[3] *= max; +1854 if (vector[2] < 0) { +1855 vector[0] = -vector[2]; +1856 vector[2] = 0; +1857 } +1858 if (vector[3] < 0) { +1859 vector[1] = -vector[3]; +1860 vector[3] = 0; +1861 } +1862 } +1863 var dots = parseDots(gradient); +1864 if (!dots) { +1865 return null; +1866 } +1867 if (element.gradient) { +1868 SVG.defs.removeChild(element.gradient); +1869 delete element.gradient; +1870 } +1871 +1872 el = $(type + "Gradient", {id: id}); +1873 element.gradient = el; +1874 $(el, type == "radial" ? { +1875 fx: fx, +1876 fy: fy +1877 } : { +1878 x1: vector[0], +1879 y1: vector[1], +1880 x2: vector[2], +1881 y2: vector[3], +1882 gradientTransform: element.matrix.invert() +1883 }); +1884 SVG.defs.appendChild(el); +1885 for (var i = 0, ii = dots.length; i < ii; i++) { +1886 el.appendChild($("stop", { +1887 offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%", +1888 "stop-color": dots[i].color || "#fff" +1889 })); +1890 } +1891 } +1892 $(o, { +1893 fill: "url(#" + id + ")", +1894 opacity: 1, +1895 "fill-opacity": 1 +1896 }); +1897 s.fill = E; +1898 s.opacity = 1; +1899 s.fillOpacity = 1; +1900 return 1; +1901 }, +1902 updatePosition = function (o) { +1903 var bbox = o.getBBox(1); +1904 $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"}); +1905 }, +1906 addArrow = function (o, value, isEnd) { +1907 if (o.type == "path") { +1908 var values = Str(value).toLowerCase().split("-"), +1909 p = o.paper, +1910 se = isEnd ? "end" : "start", +1911 node = o.node, +1912 attrs = o.attrs, +1913 stroke = attrs["stroke-width"], +1914 i = values.length, +1915 type = "classic", +1916 from, +1917 to, +1918 dx, +1919 refX, +1920 attr, +1921 w = 3, +1922 h = 3, +1923 t = 5; +1924 while (i--) { +1925 switch (values[i]) { +1926 case "block": +1927 case "classic": +1928 case "oval": +1929 case "diamond": +1930 case "open": +1931 case "none": +1932 type = values[i]; +1933 break; +1934 case "wide": h = 5; break; +1935 case "narrow": h = 2; break; +1936 case "long": w = 5; break; +1937 case "short": w = 2; break; +1938 } +1939 } +1940 if (type == "open") { +1941 w += 2; +1942 h += 2; +1943 t += 2; +1944 dx = 1; +1945 refX = isEnd ? 4 : 1; +1946 attr = { +1947 fill: "none", +1948 stroke: attrs.stroke +1949 }; +1950 } else { +1951 refX = dx = w / 2; +1952 attr = { +1953 fill: attrs.stroke, +1954 stroke: "none" +1955 }; +1956 } +1957 if (o._.arrows) { +1958 if (isEnd) { +1959 o._.arrows.endPath && markerCounter[o._.arrows.endPath]--; +1960 o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--; +1961 } else { +1962 o._.arrows.startPath && markerCounter[o._.arrows.startPath]--; +1963 o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--; +1964 } +1965 } else { +1966 o._.arrows = {}; +1967 } +1968 if (type != "none") { +1969 var pathId = "raphael-marker-" + type, +1970 markerId = "raphael-marker-" + se + type + w + h; +1971 if (!g.doc.getElementById(pathId)) { +1972 p.defs.appendChild($($("path"), { +1973 "stroke-linecap": "round", +1974 d: markers[type], +1975 id: pathId +1976 })); +1977 markerCounter[pathId] = 1; +1978 } else { +1979 markerCounter[pathId]++; +1980 } +1981 var marker = g.doc.getElementById(markerId), +1982 use; +1983 if (!marker) { +1984 marker = $($("marker"), { +1985 id: markerId, +1986 markerHeight: h, +1987 markerWidth: w, +1988 orient: "auto", +1989 refX: refX, +1990 refY: h / 2 +1991 }); +1992 use = $($("use"), { +1993 "xlink:href": "#" + pathId, +1994 transform: (isEnd ? " rotate(180 " + w / 2 + " " + h / 2 + ") " : S) + "scale(" + w / t + "," + h / t + ")", +1995 "stroke-width": 1 / ((w / t + h / t) / 2) +1996 }); +1997 marker.appendChild(use); +1998 p.defs.appendChild(marker); +1999 markerCounter[markerId] = 1; +2000 } else { +2001 markerCounter[markerId]++; +2002 use = marker.getElementsByTagName("use")[0]; +2003 } +2004 $(use, attr); +2005 var delta = dx * (type != "diamond" && type != "oval"); +2006 if (isEnd) { +2007 from = o._.arrows.startdx * stroke || 0; +2008 to = R.getTotalLength(attrs.path) - delta * stroke; +2009 } else { +2010 from = delta * stroke; +2011 to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); +2012 } +2013 attr = {}; +2014 attr["marker-" + se] = "url(#" + markerId + ")"; +2015 if (to || from) { +2016 attr.d = Raphael.getSubpath(attrs.path, from, to); +2017 } +2018 $(node, attr); +2019 o._.arrows[se + "Path"] = pathId; +2020 o._.arrows[se + "Marker"] = markerId; +2021 o._.arrows[se + "dx"] = delta; +2022 o._.arrows[se + "Type"] = type; +2023 o._.arrows[se + "String"] = value; +2024 } else { +2025 if (isEnd) { +2026 from = o._.arrows.startdx * stroke || 0; +2027 to = R.getTotalLength(attrs.path) - from; +2028 } else { +2029 from = 0; +2030 to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); +2031 } +2032 o._.arrows[se + "Path"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)}); +2033 delete o._.arrows[se + "Path"]; +2034 delete o._.arrows[se + "Marker"]; +2035 delete o._.arrows[se + "dx"]; +2036 delete o._.arrows[se + "Type"]; +2037 delete o._.arrows[se + "String"]; +2038 } +2039 for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) { +2040 var item = g.doc.getElementById(attr); +2041 item && item.parentNode.removeChild(item); +2042 } +2043 } +2044 }, +2045 setFillAndStroke = function (o, params) { +2046 var dasharray = { +2047 "": [0], +2048 "none": [0], +2049 "-": [3, 1], +2050 ".": [1, 1], +2051 "-.": [3, 1, 1, 1], +2052 "-..": [3, 1, 1, 1, 1, 1], +2053 ". ": [1, 3], +2054 "- ": [4, 3], +2055 "--": [8, 3], +2056 "- .": [4, 3, 1, 3], +2057 "--.": [8, 3, 1, 3], +2058 "--..": [8, 3, 1, 3, 1, 3] +2059 }, +2060 node = o.node, +2061 attrs = o.attrs, +2062 addDashes = function (o, value) { +2063 value = dasharray[lowerCase.call(value)]; +2064 if (value) { +2065 var width = o.attrs["stroke-width"] || "1", +2066 butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0, +2067 dashes = [], +2068 i = value.length; +2069 while (i--) { +2070 dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt; +2071 } +2072 $(node, {"stroke-dasharray": dashes.join(",")}); +2073 } +2074 }; +2075 for (var att in params) { +2076 if (params[has](att)) { +2077 if (!availableAttrs[has](att)) { +2078 continue; +2079 } +2080 var value = params[att]; +2081 attrs[att] = value; +2082 switch (att) { +2083 case "blur": +2084 o.blur(value); +2085 break; +2086 case "href": +2087 case "title": +2088 case "target": +2089 var pn = node.parentNode; +2090 if (lowerCase.call(pn.tagName) != "a") { +2091 var hl = $("a"); +2092 pn.insertBefore(hl, node); +2093 hl.appendChild(node); +2094 pn = hl; +2095 } +2096 if (att == "target" && value == "blank") { +2097 pn.setAttributeNS(xlink, "show", "new"); +2098 } else { +2099 pn.setAttributeNS(xlink, att, value); +2100 } +2101 break; +2102 case "cursor": +2103 node.style.cursor = value; +2104 break; +2105 case "transform": +2106 o.transform(value); +2107 break; +2108 case "arrow-start": +2109 addArrow(o, value); +2110 break; +2111 case "arrow-end": +2112 addArrow(o, value, 1); +2113 break; +2114 case "clip-rect": +2115 var rect = Str(value).split(separator); +2116 if (rect.length == 4) { +2117 o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode); +2118 var el = $("clipPath"), +2119 rc = $("rect"); +2120 el.id = createUUID(); +2121 $(rc, { +2122 x: rect[0], +2123 y: rect[1], +2124 width: rect[2], +2125 height: rect[3] +2126 }); +2127 el.appendChild(rc); +2128 o.paper.defs.appendChild(el); +2129 $(node, {"clip-path": "url(#" + el.id + ")"}); +2130 o.clip = rc; +2131 } +2132 if (!value) { +2133 var clip = g.doc.getElementById(node.getAttribute("clip-path").replace(/(^url\(#|\)$)/g, E)); +2134 clip && clip.parentNode.removeChild(clip); +2135 $(node, {"clip-path": E}); +2136 delete o.clip; +2137 } +2138 break; +2139 case "path": +2140 if (o.type == "path") { +2141 $(node, {d: value ? attrs.path = pathToAbsolute(value) : "M0,0"}); +2142 o._.dirty = 1; +2143 if (o._.arrows) { +2144 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); +2145 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); +2146 } +2147 } +2148 break; +2149 case "width": +2150 node[setAttribute](att, value); +2151 o._.dirty = 1; +2152 if (attrs.fx) { +2153 att = "x"; +2154 value = attrs.x; +2155 } else { +2156 break; +2157 } +2158 case "x": +2159 if (attrs.fx) { +2160 value = -attrs.x - (attrs.width || 0); +2161 } +2162 case "rx": +2163 if (att == "rx" && o.type == "rect") { +2164 break; +2165 } +2166 case "cx": +2167 node[setAttribute](att, value); +2168 o.pattern && updatePosition(o); +2169 o._.dirty = 1; +2170 break; +2171 case "height": +2172 node[setAttribute](att, value); +2173 o._.dirty = 1; +2174 if (attrs.fy) { +2175 att = "y"; +2176 value = attrs.y; +2177 } else { +2178 break; +2179 } +2180 case "y": +2181 if (attrs.fy) { +2182 value = -attrs.y - (attrs.height || 0); +2183 } +2184 case "ry": +2185 if (att == "ry" && o.type == "rect") { +2186 break; +2187 } +2188 case "cy": +2189 node[setAttribute](att, value); +2190 o.pattern && updatePosition(o); +2191 o._.dirty = 1; +2192 break; +2193 case "r": +2194 if (o.type == "rect") { +2195 $(node, {rx: value, ry: value}); +2196 } else { +2197 node[setAttribute](att, value); +2198 } +2199 o._.dirty = 1; +2200 break; +2201 case "src": +2202 if (o.type == "image") { +2203 node.setAttributeNS(xlink, "href", value); +2204 } +2205 break; +2206 case "stroke-width": +2207 if (o._.sx != 1 || o._.sy != 1) { +2208 value /= mmax(abs(o._.sx), abs(o._.sy)) || 1; +2209 } +2210 if (o.paper._vbSize) { +2211 value *= o.paper._vbSize; +2212 } +2213 node[setAttribute](att, value); +2214 if (attrs["stroke-dasharray"]) { +2215 addDashes(o, attrs["stroke-dasharray"]); +2216 } +2217 if (o._.arrows) { +2218 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); +2219 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); +2220 } +2221 break; +2222 case "stroke-dasharray": +2223 addDashes(o, value); +2224 break; +2225 case fillString: +2226 var isURL = Str(value).match(ISURL); +2227 if (isURL) { +2228 el = $("pattern"); +2229 var ig = $("image"); +2230 el.id = createUUID(); +2231 $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1}); +2232 $(ig, {x: 0, y: 0, "xlink:href": isURL[1]}); +2233 el.appendChild(ig); +2234 +2235 (function (el) { +2236 preload(isURL[1], function () { +2237 var w = this.offsetWidth, +2238 h = this.offsetHeight; +2239 $(el, {width: w, height: h}); +2240 $(ig, {width: w, height: h}); +2241 o.paper.safari(); +2242 }); +2243 })(el); +2244 o.paper.defs.appendChild(el); +2245 node.style.fill = "url(#" + el.id + ")"; +2246 $(node, {fill: "url(#" + el.id + ")"}); +2247 o.pattern = el; +2248 o.pattern && updatePosition(o); +2249 break; +2250 } +2251 var clr = R.getRGB(value); +2252 if (!clr.error) { +2253 delete params.gradient; +2254 delete attrs.gradient; +2255 !R.is(attrs.opacity, "undefined") && +2256 R.is(params.opacity, "undefined") && +2257 $(node, {opacity: attrs.opacity}); +2258 !R.is(attrs["fill-opacity"], "undefined") && +2259 R.is(params["fill-opacity"], "undefined") && +2260 $(node, {"fill-opacity": attrs["fill-opacity"]}); +2261 } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) { +2262 if ("opacity" in attrs || "fill-opacity" in attrs) { +2263 var gradient = g.doc.getElementById(node.getAttribute(fillString).replace(/^url\(#|\)$/g, E)); +2264 if (gradient) { +2265 var stops = gradient.getElementsByTagName("stop"); +2266 $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)}); +2267 } +2268 } +2269 attrs.gradient = value; +2270 attrs.fill = "none"; +2271 break; +2272 } +2273 clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); +2274 case "stroke": +2275 clr = R.getRGB(value); +2276 node[setAttribute](att, clr.hex); +2277 att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); +2278 if (att == "stroke" && o._.arrows) { +2279 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); +2280 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); +2281 } +2282 break; +2283 case "gradient": +2284 (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value); +2285 break; +2286 case "opacity": +2287 if (attrs.gradient && !attrs[has]("stroke-opacity")) { +2288 $(node, {"stroke-opacity": value > 1 ? value / 100 : value}); +2289 } +2290 // fall +2291 case "fill-opacity": +2292 if (attrs.gradient) { +2293 gradient = g.doc.getElementById(node.getAttribute(fillString).replace(/^url\(#|\)$/g, E)); +2294 if (gradient) { +2295 stops = gradient.getElementsByTagName("stop"); +2296 $(stops[stops.length - 1], {"stop-opacity": value}); +2297 } +2298 break; +2299 } +2300 default: +2301 att == "font-size" && (value = toInt(value, 10) + "px"); +2302 var cssrule = att.replace(/(\-.)/g, function (w) { +2303 return upperCase.call(w.substring(1)); +2304 }); +2305 node.style[cssrule] = value; +2306 o._.dirty = 1; +2307 node[setAttribute](att, value); +2308 break; +2309 } +2310 } +2311 } +2312 +2313 tuneText(o, params); +2314 }, +2315 leading = 1.2, +2316 tuneText = function (el, params) { +2317 if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) { +2318 return; +2319 } +2320 var a = el.attrs, +2321 node = el.node, +2322 fontSize = node.firstChild ? toInt(g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10; +2323 +2324 if (params[has]("text")) { +2325 a.text = params.text; +2326 while (node.firstChild) { +2327 node.removeChild(node.firstChild); +2328 } +2329 var texts = Str(params.text).split("\n"), +2330 tspans = [], +2331 tspan; +2332 for (var i = 0, ii = texts.length; i < ii; i++) if (texts[i]) { +2333 tspan = $("tspan"); +2334 i && $(tspan, {dy: fontSize * leading, x: a.x}); +2335 tspan.appendChild(g.doc.createTextNode(texts[i])); +2336 node.appendChild(tspan); +2337 tspans[i] = tspan; +2338 } +2339 } else { +2340 tspans = node.getElementsByTagName("tspan"); +2341 for (i = 0, ii = tspans.length; i < ii; i++) { +2342 i && $(tspans[i], {dy: fontSize * leading, x: a.x}); +2343 } +2344 } +2345 $(node, {y: a.y}); +2346 el._.dirty = 1; +2347 var bb = el._getBBox(), +2348 dif = a.y - (bb.y + bb.height / 2); +2349 dif && R.is(dif, "finite") && $(tspans[0], {dy: a.y + dif}); +2350 }, +2351 Element = function (node, svg) { +2352 var X = 0, +2353 Y = 0; +2354 /*\ +2355 * Element.node +2356 [ property (object) ] +2357 ** +2358 * Gives you a reference to the DOM object, so you can assign event handlers or just mess around. +2359 > Usage +2360 | // draw a circle at coordinate 10,10 with radius of 10 +2361 | var c = paper.circle(10, 10, 10); +2362 | c.node.onclick = function () { +2363 | c.attr("fill", "red"); +2364 | }; +2365 \*/ +2366 this[0] = this.node = node; +2367 /*\ +2368 * Element.raphael +2369 [ property (object) ] +2370 ** +2371 * Internal reference to @Raphael object. In case it is not available. +2372 > Usage +2373 | Raphael.el.red = function () { +2374 | var hsb = this.paper.raphael.rgb2hsb(this.attr("fill")); +2375 | hsb.h = 1; +2376 | this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex}); +2377 | } +2378 \*/ +2379 node.raphael = true; +2380 /*\ +2381 * Element.id +2382 [ property (number) ] +2383 ** +2384 * Unique id of the element. Especially usesful when you want to listen to events of the element, +2385 * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method. +2386 \*/ +2387 this.id = R._oid++; +2388 node.raphaelid = this.id; +2389 this.matrix = new Matrix; +2390 this.realPath = null; +2391 /*\ +2392 * Element.paper +2393 [ property (object) ] +2394 ** +2395 * Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions. +2396 > Usage +2397 | Raphael.el.cross = function () { +2398 | this.attr({fill: "red"}); +2399 | this.paper.path("M10,10L50,50M50,10L10,50") +2400 | .attr({stroke: "red"}); +2401 | } +2402 \*/ +2403 this.paper = svg; +2404 this.attrs = this.attrs || {}; +2405 this._ = { +2406 transform: [], +2407 sx: 1, +2408 sy: 1, +2409 deg: 0, +2410 dx: 0, +2411 dy: 0, +2412 dirty: 1 +2413 }; +2414 !svg.bottom && (svg.bottom = this); +2415 /*\ +2416 * Element.prev +2417 [ property (object) ] +2418 ** +2419 * Reference to the previous element in the hierarchy. +2420 \*/ +2421 this.prev = svg.top; +2422 svg.top && (svg.top.next = this); +2423 svg.top = this; +2424 /*\ +2425 * Element.next +2426 [ property (object) ] +2427 ** +2428 * Reference to the next element in the hierarchy. +2429 \*/ +2430 this.next = null; +2431 }, +2432 elproto = Element.prototype; +2433 /*\ +2434 * Element.rotate +2435 [ method ] +2436 ** +2437 * Adds rotation by given angle around given point to the list of +2438 * transformations of the element. +2439 > Parameters +2440 - deg (number) angle in degrees +2441 - cx (number) #optional x coordinate of the centre of rotation +2442 - cy (number) #optional y coordinate of the centre of rotation +2443 * If cx & cy aren’t specified centre of the shape is used as a point of rotation. +2444 = (object) @Element +2445 \*/ +2446 elproto.rotate = function (deg, cx, cy) { +2447 if (this.removed) { +2448 return this; +2449 } +2450 deg = Str(deg).split(separator); +2451 if (deg.length - 1) { +2452 cx = toFloat(deg[1]); +2453 cy = toFloat(deg[2]); +2454 } +2455 deg = toFloat(deg[0]); +2456 (cy == null) && (cx = cy); +2457 if (cx == null || cy == null) { +2458 var bbox = this.getBBox(1); +2459 cx = bbox.x + bbox.width / 2; +2460 cy = bbox.y + bbox.height / 2; +2461 } +2462 this.transform(this._.transform.concat([["r", deg, cx, cy]])); +2463 return this; +2464 }; +2465 /*\ +2466 * Element.scale +2467 [ method ] +2468 ** +2469 * Adds scale by given amount relative to given point to the list of +2470 * transformations of the element. +2471 > Parameters +2472 - sx (number) horisontal scale amount +2473 - sy (number) vertical scale amount +2474 - cx (number) #optional x coordinate of the centre of scale +2475 - cy (number) #optional y coordinate of the centre of scale +2476 * If cx & cy aren’t specified centre of the shape is used instead. +2477 = (object) @Element +2478 \*/ +2479 elproto.scale = function (sx, sy, cx, cy) { +2480 if (this.removed) { +2481 return this; +2482 } +2483 sx = Str(sx).split(separator); +2484 if (sx.length - 1) { +2485 sy = toFloat(sx[1]); +2486 cx = toFloat(sx[2]); +2487 cy = toFloat(sx[3]); +2488 } +2489 sx = toFloat(sx[0]); +2490 (sy == null) && (sy = sx); +2491 (cy == null) && (cx = cy); +2492 if (cx == null || cy == null) { +2493 var bbox = this.getBBox(1); +2494 } +2495 cx = cx == null ? bbox.x + bbox.width / 2 : cx; +2496 cy = cy == null ? bbox.y + bbox.height / 2 : cy; +2497 this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); +2498 return this; +2499 }; +2500 /*\ +2501 * Element.translate +2502 [ method ] +2503 ** +2504 * Adds translation by given amount to the list of transformations of the element. +2505 > Parameters +2506 - dx (number) horisontal shift +2507 - dy (number) vertical shift +2508 = (object) @Element +2509 \*/ +2510 elproto.translate = function (dx, dy) { +2511 if (this.removed) { +2512 return this; +2513 } +2514 dx = Str(dx).split(separator); +2515 if (dx.length - 1) { +2516 dy = toFloat(dx[1]); +2517 } +2518 dx = toFloat(dx[0]) || 0; +2519 dy = +dy || 0; +2520 this.transform(this._.transform.concat([["t", dx, dy]])); +2521 return this; +2522 }; +2523 /*\ +2524 * Element.transform +2525 [ method ] +2526 ** +2527 * Adds transformation to the element which is separate to other attributes, +2528 * i.e. translation doesn’t change `x` or `y` of the rectange. The format +2529 * of transformation string is similar to the path string syntax: +2530 | "t100,100r30,100,100s2,2,100,100r45s1.5" +2531 * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for +2532 * scale and `m` is for matrix. +2533 * +2534 * So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100; +2535 * rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin +2536 * coordinates as optional parameters, the default is the centre point of the element. +2537 * Matrix accepts six parameters. +2538 > Usage +2539 | var el = paper.rect(10, 20, 300, 200); +2540 | // translate 100, 100, rotate 45°, translate -100, 0 +2541 | el.transform("t100,100r45t-100,0"); +2542 | // if you want you can append or prepend transformations +2543 | el.transform("...t50,50"); +2544 | el.transform("s2..."); +2545 | // or even wrap +2546 | el.transform("t50,50...t-50-50"); +2547 | // to reset transformation call method with empty string +2548 | el.transform(""); +2549 | // to get current value call it without parameters +2550 | console.log(el.transform()); +2551 > Parameters +2552 - tstr (string) #optional transformation string +2553 * If tstr isn’t specified +2554 = (string) current transformation string +2555 * else +2556 = (object) @Element +2557 \*/ +2558 elproto.transform = function (tstr) { +2559 var _ = this._; +2560 if (!tstr) { +2561 return _.transform; +2562 } +2563 extractTransform(this, tstr); +2564 +2565 this.clip && $(this.clip, {transform: this.matrix.invert()}); +2566 // this.gradient && $(this.gradient, {gradientTransform: this.matrix.invert()}); +2567 this.pattern && updatePosition(this); +2568 this.node && $(this.node, {transform: this.matrix}); +2569 +2570 if (_.sx != 1 || _.sy != 1) { +2571 var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1; +2572 this.attr({"stroke-width": sw}); +2573 } +2574 +2575 return this; +2576 }; +2577 /*\ +2578 * Element.hide +2579 [ method ] +2580 ** +2581 * Makes element invisible. See @Element.show. +2582 = (object) @Element +2583 \*/ +2584 elproto.hide = function () { +2585 !this.removed && this.paper.safari(this.node.style.display = "none"); +2586 return this; +2587 }; +2588 /*\ +2589 * Element.show +2590 [ method ] +2591 ** +2592 * Makes element visible. See @Element.hide. +2593 = (object) @Element +2594 \*/ +2595 elproto.show = function () { +2596 !this.removed && this.paper.safari(this.node.style.display = ""); +2597 return this; +2598 }; +2599 /*\ +2600 * Element.remove +2601 [ method ] +2602 ** +2603 * Removes element form the paper. +2604 \*/ +2605 elproto.remove = function () { +2606 if (this.removed) { +2607 return; +2608 } +2609 eve.unbind("*.*." + this.id); +2610 tear(this, this.paper); +2611 this.node.parentNode.removeChild(this.node); +2612 for (var i in this) { +2613 delete this[i]; +2614 } +2615 this.removed = true; +2616 }; +2617 elproto._getBBox = function () { +2618 if (this.node.style.display == "none") { +2619 this.show(); +2620 var hide = true; +2621 } +2622 var bbox = {}; +2623 try { +2624 bbox = this.node.getBBox(); +2625 } catch(e) { +2626 // Firefox 3.0.x plays badly here +2627 } finally { +2628 bbox = bbox || {}; +2629 } +2630 hide && this.hide(); +2631 return bbox; +2632 }; +2633 /*\ +2634 * Element.attr +2635 [ method ] +2636 ** +2637 * Sets the attributes of the element. +2638 > Parameters +2639 - attrName (string) attribute’s name +2640 - value (string) value +2641 * or +2642 - params (object) object of name/value pairs +2643 * or +2644 - attrName (string) attribute’s name +2645 * or +2646 - attrNames (array) in this case method returns array of current values for given attribute names +2647 = (object) @Element if attrsName & value or params are passed in. +2648 = (...) value of the attribute if only attrsName is passed in. +2649 = (array) array of values of the attribute if attrsNames is passed in. +2650 = (object) object of attributes if nothing is passed in. +2651 > Possible parameters +2652 # <p>Please refer to the <a href="http://www.w3.org/TR/SVG/" title="The W3C Recommendation for the SVG language describes these properties in detail.">SVG specification</a> for an explanation of these parameters.</p> +2653 o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `midium`, length: `long`, `short`, `midium`. +2654 o clip-rect (string) comma or space separated values: x, y, width and height +2655 o cursor (string) CSS type of the cursor +2656 o cx (number) +2657 o cy (number) +2658 o fill (string) colour, gradient or image +2659 o fill-opacity (number) +2660 o font (string) +2661 o font-family (string) +2662 o font-size (number) font size in pixels +2663 o font-weight (string) +2664 o height (number) +2665 o href (string) URL, if specified element behaves as hyperlink +2666 o opacity (number) +2667 o path (string) SVG path string format +2668 o r (number) +2669 o rx (number) +2670 o ry (number) +2671 o src (string) image URL, only works for @Element.image element +2672 o stroke (string) stroke colour +2673 o stroke-dasharray (string) [“”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”] +2674 o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”] +2675 o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”] +2676 o stroke-miterlimit (number) +2677 o stroke-opacity (number) +2678 o stroke-width (number) stroke width in pixels, default is '1' +2679 o target (string) used with href +2680 o text (string) contents of the text element. Use `\n` for multiline text +2681 o text-anchor (string) [“`start`”, “`middle`”, “`end`”], default is “`middle`” +2682 o title (string) will create tooltip with a given text +2683 o transform (string) see @Element.transform +2684 o width (number) +2685 o x (number) +2686 o y (number) +2687 > Gradients +2688 * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90° +2689 * gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black. +2690 * +2691 * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” – +2692 * gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point +2693 * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses. +2694 > Path String +2695 # <p>Please refer to <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path’s data attribute’s format are described in the SVG specification.">SVG documentation regarding path string</a>. Raphaël fully supports it.</p> +2696 > Colour Parsing +2697 # <ul> +2698 # <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li> +2699 # <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li> +2700 # <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li> +2701 # <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(2001000)</code>”)</li> +2702 # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%, 175%, 0%)</code>”)</li> +2703 # <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(2001000, .5)</code>”)</li> +2704 # <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%, 175%, 0%, 50%)</code>”)</li> +2705 # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.50.251)</code>”)</li> +2706 # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li> +2707 # <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</li> +2708 # <li>hsl(•••, •••, •••) — almost the same as hsb, see <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV - Wikipedia, the free encyclopedia">Wikipedia page</a></li> +2709 # <li>hsl(•••%, •••%, •••%) — same as above, but in %</li> +2710 # <li>hsla(•••, •••, •••) — same as above, but with opacity</li> +2711 # <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg, 1.5)</code>” or, if you want to go fancy, “<code>hsl(240°, 1.5)</code>”</li> +2712 # </ul> +2713 \*/ +2714 elproto.attr = function (name, value) { +2715 if (this.removed) { +2716 return this; +2717 } +2718 if (name == null) { +2719 var res = {}; +2720 for (var i in this.attrs) if (this.attrs[has](i)) { +2721 res[i] = this.attrs[i]; +2722 } +2723 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; +2724 res.transform = this._.transform; +2725 return res; +2726 } +2727 if (value == null && R.is(name, string)) { +2728 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { +2729 return this.attrs.gradient; +2730 } +2731 if (name == "transform") { +2732 return this._.transform; +2733 } +2734 if (name in this.attrs) { +2735 return this.attrs[name]; +2736 } else if (R.is(this.paper.customAttributes[name], "function")) { +2737 return this.paper.customAttributes[name].def; +2738 } else { +2739 return availableAttrs[name]; +2740 } +2741 } +2742 if (value == null && R.is(name, array)) { +2743 var values = {}; +2744 for (var j = 0, jj = name.length; j < jj; j++) { +2745 values[name[j]] = this.attr(name[j]); +2746 } +2747 return values; +2748 } +2749 if (value != null) { +2750 var params = {}; +2751 params[name] = value; +2752 } else if (name != null && R.is(name, "object")) { +2753 params = name; +2754 } +2755 for (var key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { +2756 var par = this.paper.customAttributes[key].apply(this, [][concat](params[key])); +2757 this.attrs[key] = params[key]; +2758 for (var subkey in par) if (par[has](subkey)) { +2759 params[subkey] = par[subkey]; +2760 } +2761 } +2762 setFillAndStroke(this, params); +2763 return this; +2764 }; +2765 /*\ +2766 * Element.toFront +2767 [ method ] +2768 ** +2769 * Moves the element so it is the closest to the viewer’s eyes, on top of other elements. +2770 = (object) @Element +2771 \*/ +2772 elproto.toFront = function () { +2773 if (this.removed) { +2774 return this; +2775 } +2776 this.node.parentNode.appendChild(this.node); +2777 var svg = this.paper; +2778 svg.top != this && tofront(this, svg); +2779 return this; +2780 }; +2781 /*\ +2782 * Element.toBack +2783 [ method ] +2784 ** +2785 * Moves the element so it is the furthest from the viewer’s eyes, behind other elements. +2786 = (object) @Element +2787 \*/ +2788 elproto.toBack = function () { +2789 if (this.removed) { +2790 return this; +2791 } +2792 if (this.node.parentNode.firstChild != this.node) { +2793 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); +2794 toback(this, this.paper); +2795 var svg = this.paper; +2796 } +2797 return this; +2798 }; +2799 /*\ +2800 * Element.insertAfter +2801 [ method ] +2802 ** +2803 * Inserts current object after the given one. +2804 = (object) @Element +2805 \*/ +2806 elproto.insertAfter = function (element) { +2807 if (this.removed) { +2808 return this; +2809 } +2810 var node = element.node || element[element.length - 1].node; +2811 if (node.nextSibling) { +2812 node.parentNode.insertBefore(this.node, node.nextSibling); +2813 } else { +2814 node.parentNode.appendChild(this.node); +2815 } +2816 insertafter(this, element, this.paper); +2817 return this; +2818 }; +2819 /*\ +2820 * Element.insertBefore +2821 [ method ] +2822 ** +2823 * Inserts current object before the given one. +2824 = (object) @Element +2825 \*/ +2826 elproto.insertBefore = function (element) { +2827 if (this.removed) { +2828 return this; +2829 } +2830 var node = element.node || element[0].node; +2831 node.parentNode.insertBefore(this.node, node); +2832 insertbefore(this, element, this.paper); +2833 return this; +2834 }; +2835 elproto.blur = function (size) { +2836 // Experimental. No Safari support. Use it on your own risk. +2837 var t = this; +2838 if (+size !== 0) { +2839 var fltr = $("filter"), +2840 blur = $("feGaussianBlur"); +2841 t.attrs.blur = size; +2842 fltr.id = createUUID(); +2843 $(blur, {stdDeviation: +size || 1.5}); +2844 fltr.appendChild(blur); +2845 t.paper.defs.appendChild(fltr); +2846 t._blur = fltr; +2847 $(t.node, {filter: "url(#" + fltr.id + ")"}); +2848 } else { +2849 if (t._blur) { +2850 t._blur.parentNode.removeChild(t._blur); +2851 delete t._blur; +2852 delete t.attrs.blur; +2853 } +2854 t.node.removeAttribute("filter"); +2855 } +2856 }; +2857 var theCircle = function (svg, x, y, r) { +2858 var el = $("circle"); +2859 svg.canvas && svg.canvas.appendChild(el); +2860 var res = new Element(el, svg); +2861 res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"}; +2862 res.type = "circle"; +2863 $(el, res.attrs); +2864 return res; +2865 }, +2866 theRect = function (svg, x, y, w, h, r) { +2867 var el = $("rect"); +2868 svg.canvas && svg.canvas.appendChild(el); +2869 var res = new Element(el, svg); +2870 res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"}; +2871 res.type = "rect"; +2872 $(el, res.attrs); +2873 return res; +2874 }, +2875 theEllipse = function (svg, x, y, rx, ry) { +2876 var el = $("ellipse"); +2877 svg.canvas && svg.canvas.appendChild(el); +2878 var res = new Element(el, svg); +2879 res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"}; +2880 res.type = "ellipse"; +2881 $(el, res.attrs); +2882 return res; +2883 }, +2884 theImage = function (svg, src, x, y, w, h) { +2885 var el = $("image"); +2886 $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"}); +2887 el.setAttributeNS(xlink, "href", src); +2888 svg.canvas && svg.canvas.appendChild(el); +2889 var res = new Element(el, svg); +2890 res.attrs = {x: x, y: y, width: w, height: h, src: src}; +2891 res.type = "image"; +2892 return res; +2893 }, +2894 theText = function (svg, x, y, text) { +2895 var el = $("text"); +2896 $(el, {x: x, y: y, "text-anchor": "middle"}); +2897 svg.canvas && svg.canvas.appendChild(el); +2898 var res = new Element(el, svg); +2899 res.attrs = {x: x, y: y, "text-anchor": "middle", text: text, font: availableAttrs.font, stroke: "none", fill: "#000"}; +2900 res.type = "text"; +2901 setFillAndStroke(res, res.attrs); +2902 return res; +2903 }, +2904 setSize = function (width, height) { +2905 this.width = width || this.width; +2906 this.height = height || this.height; +2907 this.canvas[setAttribute]("width", this.width); +2908 this.canvas[setAttribute]("height", this.height); +2909 if (this._viewBox) { +2910 this.setViewBox.apply(this, this._viewBox); +2911 } +2912 return this; +2913 }, +2914 create = function () { +2915 var con = getContainer[apply](0, arguments), +2916 container = con && con.container, +2917 x = con.x, +2918 y = con.y, +2919 width = con.width, +2920 height = con.height; +2921 if (!container) { +2922 throw new Error("SVG container not found."); +2923 } +2924 var cnvs = $("svg"), +2925 css = "overflow:hidden;"; +2926 x = x || 0; +2927 y = y || 0; +2928 width = width || 512; +2929 height = height || 342; +2930 $(cnvs, { +2931 height: height, +2932 version: 1.1, +2933 width: width, +2934 xmlns: "http://www.w3.org/2000/svg" +2935 }); +2936 if (container == 1) { +2937 cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px"; +2938 g.doc.body.appendChild(cnvs); +2939 } else { +2940 cnvs.style.cssText = css; +2941 if (container.firstChild) { +2942 container.insertBefore(cnvs, container.firstChild); +2943 } else { +2944 container.appendChild(cnvs); +2945 } +2946 } +2947 container = new Paper; +2948 container.width = width; +2949 container.height = height; +2950 container.canvas = cnvs; +2951 plugins.call(container, container, R.fn); +2952 container.clear(); +2953 return container; +2954 }, +2955 setViewBox = function (x, y, w, h, fit) { +2956 eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); +2957 var size = mmax(w / this.width, h / this.height), +2958 top = this.top, +2959 aspectRatio = fit ? "meet" : "xMinYMin", +2960 vb, +2961 sw; +2962 if (x == null) { +2963 if (this._vbSize) { +2964 size = 1; +2965 } +2966 delete this._vbSize; +2967 vb = "0 0 " + this.width + S + this.height; +2968 } else { +2969 this._vbSize = size; +2970 vb = x + S + y + S + w + S + h; +2971 } +2972 $(this.canvas, { +2973 viewBox: vb, +2974 preserveAspectRatio: aspectRatio +2975 }); +2976 while (size && top) { +2977 sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1; +2978 top.attr({"stroke-width": sw}); +2979 top._.dirty = 1; +2980 top._.dirtyT = 1; +2981 top = top.prev; +2982 } +2983 this._viewBox = [x, y, w, h, !!fit]; +2984 return this; +2985 }; +2986 /*\ +2987 * Paper.clear +2988 [ method ] +2989 ** +2990 * Clears the paper, i.e. removes all the elements. +2991 \*/ +2992 paperproto.clear = function () { +2993 eve("clear", this); +2994 var c = this.canvas; +2995 while (c.firstChild) { +2996 c.removeChild(c.firstChild); +2997 } +2998 this.bottom = this.top = null; +2999 (this.desc = $("desc")).appendChild(g.doc.createTextNode("Created with Rapha\xebl " + R.version)); +3000 c.appendChild(this.desc); +3001 c.appendChild(this.defs = $("defs")); +3002 }; +3003 /*\ +3004 * Paper.remove +3005 [ method ] +3006 ** +3007 * Removes the paper from the DOM. +3008 \*/ +3009 paperproto.remove = function () { +3010 eve("remove", this); +3011 this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas); +3012 for (var i in this) { +3013 this[i] = removed(i); +3014 } +3015 }; +3016 } +3017 +3018 // VML +3019 if (R.vml) { +3020 var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, +3021 bites = /([clmz]),?([^clmz]*)/gi, +3022 blurregexp = / progid:\S+Blur\([^\)]+\)/g, +3023 val = /-?[^,\s-]+/g, +3024 cssDot = "position:absolute;left:0;top:0;width:1px;height:1px", +3025 zoom = 21600, +3026 pathTypes = {path: 1, rect: 1}, +3027 ovalTypes = {circle: 1, ellipse: 1}, +3028 path2vml = function (path) { +3029 var total = /[ahqstv]/ig, +3030 command = pathToAbsolute; +3031 Str(path).match(total) && (command = path2curve); +3032 total = /[clmz]/g; +3033 if (command == pathToAbsolute && !Str(path).match(total)) { +3034 var res = Str(path).replace(bites, function (all, command, args) { +3035 var vals = [], +3036 isMove = lowerCase.call(command) == "m", +3037 res = map[command]; +3038 args.replace(val, function (value) { +3039 if (isMove && vals.length == 2) { +3040 res += vals + map[command == "m" ? "l" : "L"]; +3041 vals = []; +3042 } +3043 vals.push(round(value * zoom)); +3044 }); +3045 return res + vals; +3046 }); +3047 return res; +3048 } +3049 var pa = command(path), p, r; +3050 res = []; +3051 for (var i = 0, ii = pa.length; i < ii; i++) { +3052 p = pa[i]; +3053 r = lowerCase.call(pa[i][0]); +3054 r == "z" && (r = "x"); +3055 for (var j = 1, jj = p.length; j < jj; j++) { +3056 r += round(p[j] * zoom) + (j != jj - 1 ? "," : E); +3057 } +3058 res.push(r); +3059 } +3060 return res.join(S); +3061 }, +3062 compensation = function (deg, dx, dy) { +3063 var m = new Matrix; +3064 m.rotate(-deg, .5, .5); +3065 return { +3066 dx: m.x(dx, dy), +3067 dy: m.y(dx, dy) +3068 }; +3069 }, +3070 setCoords = function (p) { +3071 var _ = p._, +3072 sx = _.sx, +3073 sy = _.sy, +3074 deg = _.deg, +3075 dx = _.dx, +3076 dy = _.dy, +3077 fillpos = _.fillpos, +3078 o = p.node, +3079 s = o.style, +3080 y = 1, +3081 m = p.matrix, +3082 flip = "", +3083 dxdy, +3084 kx = zoom / sx, +3085 ky = zoom / sy; +3086 s.visibility = "hidden"; +3087 o.coordsize = abs(kx) + S + abs(ky); +3088 s.rotation = deg * (sx * sy < 0 ? -1 : 1); +3089 if (deg) { +3090 var c = compensation(deg, dx, dy); +3091 dx = c.dx; +3092 dy = c.dy; +3093 } +3094 sx < 0 && (flip += "x"); +3095 sy < 0 && (flip += " y") && (y = -1); +3096 s.flip = flip; +3097 o.coordorigin = (dx * -kx) + S + (dy * -ky); +3098 if (fillpos || _.fillsize) { +3099 var fill = o.getElementsByTagName(fillString); +3100 fill = fill && fill[0]; +3101 o.removeChild(fill); +3102 if (fillpos) { +3103 c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1])); +3104 fill.position = c.dx * y + S + c.dy * y; +3105 } +3106 if (_.fillsize) { +3107 fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy); +3108 } +3109 o.appendChild(fill); +3110 } +3111 s.visibility = "visible"; +3112 }; +3113 R.toString = function () { +3114 return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version; +3115 }; +3116 addArrow = function (o, value, isEnd) { +3117 var values = Str(value).toLowerCase().split("-"), +3118 se = isEnd ? "end" : "start", +3119 i = values.length, +3120 type = "classic", +3121 w = "medium", +3122 h = "medium"; +3123 while (i--) { +3124 switch (values[i]) { +3125 case "block": +3126 case "classic": +3127 case "oval": +3128 case "diamond": +3129 case "open": +3130 case "none": +3131 type = values[i]; +3132 break; +3133 case "wide": +3134 case "narrow": h = values[i]; break; +3135 case "long": +3136 case "short": w = values[i]; break; +3137 } +3138 } +3139 var stroke = o.node.getElementsByTagName("stroke")[0]; +3140 stroke[se + "arrow"] = type; +3141 stroke[se + "arrowlength"] = w; +3142 stroke[se + "arrowwidth"] = h; +3143 }; +3144 setFillAndStroke = function (o, params) { +3145 o.paper.canvas.style.display = "none"; +3146 o.attrs = o.attrs || {}; +3147 var node = o.node, +3148 a = o.attrs, +3149 s = node.style, +3150 xy, +3151 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), +3152 isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry), +3153 res = o; 3154 -3155 for (var par in params) if (params[has](par)) { -3156 a[par] = params[par]; -3157 } -3158 if (newpath) { -3159 a.path = getPath[o.type](o); -3160 o._.dirty = 1; -3161 } -3162 params.href && (node.href = params.href); -3163 params.title && (node.title = params.title); -3164 params.target && (node.target = params.target); -3165 params.cursor && (s.cursor = params.cursor); -3166 "blur" in params && o.blur(params.blur); -3167 "transform" in params && o.transform(params.transform); -3168 if (params.path && o.type == "path" || newpath) { -3169 node.path = path2vml(a.path); -3170 } -3171 if (isOval) { -3172 var cx = a.cx, -3173 cy = a.cy, -3174 rx = a.rx || a.r || 0, -3175 ry = a.ry || a.r || 0; -3176 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)); -3177 } -3178 if ("clip-rect" in params) { -3179 var rect = Str(params["clip-rect"]).split(separator); -3180 if (rect.length == 4) { -3181 rect[2] = +rect[2] + (+rect[0]); -3182 rect[3] = +rect[3] + (+rect[1]); -3183 var div = node.clipRect || g.doc.createElement("div"), -3184 dstyle = div.style, -3185 group = node.parentNode; -3186 dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect); -3187 if (!node.clipRect) { -3188 dstyle.position = "absolute"; -3189 dstyle.top = 0; -3190 dstyle.left = 0; -3191 dstyle.width = o.paper.width + "px"; -3192 dstyle.height = o.paper.height + "px"; -3193 group.parentNode.insertBefore(div, group); -3194 div.appendChild(group); -3195 node.clipRect = div; -3196 } -3197 } -3198 if (!params["clip-rect"]) { -3199 node.clipRect && (node.clipRect.style.clip = E); -3200 } -3201 } -3202 if (o.textpath) { -3203 var textpathStyle = o.textpath.style; -3204 params.font && (textpathStyle.font = params.font); -3205 params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"'); -3206 params["font-size"] && (textpathStyle.fontSize = params["font-size"]); -3207 params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]); -3208 params["font-style"] && (textpathStyle.fontStyle = params["font-style"]); -3209 } -3210 if ("arrow-start" in params) { -3211 addArrow(res, params["arrow-start"]); -3212 } -3213 if ("arrow-end" in params) { -3214 addArrow(res, params["arrow-end"], 1); -3215 } -3216 if (params.opacity != null || -3217 params["stroke-width"] != null || -3218 params.fill != null || -3219 params.src != null || -3220 params.stroke != null || -3221 params["stroke-width"] != null || -3222 params["stroke-opacity"] != null || -3223 params["fill-opacity"] != null || -3224 params["stroke-dasharray"] != null || -3225 params["stroke-miterlimit"] != null || -3226 params["stroke-linejoin"] != null || -3227 params["stroke-linecap"] != null) { -3228 var fill = node.getElementsByTagName(fillString), -3229 newfill = false; -3230 fill = fill && fill[0]; -3231 !fill && (newfill = fill = createNode(fillString)); -3232 if (o.type == "image" && params.src) { -3233 fill.src = params.src; -3234 } -3235 if ("fill-opacity" in params || "opacity" in params) { -3236 var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1); -3237 opacity = mmin(mmax(opacity, 0), 1); -3238 fill.opacity = opacity; -3239 } -3240 params.fill && (fill.on = true); -3241 if (fill.on == null || params.fill == "none" || params.fill === null) { -3242 fill.on = false; -3243 } -3244 if (fill.on && params.fill) { -3245 var isURL = params.fill.match(ISURL); -3246 if (isURL) { -3247 fill.parentNode == node && node.removeChild(fill); -3248 fill.rotate = true; -3249 fill.src = isURL[1]; -3250 fill.type = "tile"; -3251 var bbox = o.getBBox(1); -3252 fill.position = bbox.x + S + bbox.y; -3253 o._.fillpos = [bbox.x, bbox.y]; -3254 -3255 preload(isURL[1], function () { -3256 o._.fillsize = [this.offsetWidth, this.offsetHeight]; -3257 }); -3258 } else { -3259 fill.color = R.getRGB(params.fill).hex; -3260 fill.src = E; -3261 fill.type = "solid"; -3262 if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) { -3263 a.fill = "none"; -3264 a.gradient = params.fill; -3265 fill.rotate = false; -3266 } -3267 } -3268 } -3269 node.appendChild(fill); -3270 var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]), -3271 newstroke = false; -3272 !stroke && (newstroke = stroke = createNode("stroke")); -3273 if ((params.stroke && params.stroke != "none") || -3274 params["stroke-width"] || -3275 params["stroke-opacity"] != null || -3276 params["stroke-dasharray"] || -3277 params["stroke-miterlimit"] || -3278 params["stroke-linejoin"] || -3279 params["stroke-linecap"]) { -3280 stroke.on = true; -3281 } -3282 (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false); -3283 var strokeColor = R.getRGB(params.stroke); -3284 stroke.on && params.stroke && (stroke.color = strokeColor.hex); -3285 opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1); -3286 var width = (toFloat(params["stroke-width"]) || 1) * .75; -3287 opacity = mmin(mmax(opacity, 0), 1); -3288 params["stroke-width"] == null && (width = a["stroke-width"]); -3289 params["stroke-width"] && (stroke.weight = width); -3290 width && width < 1 && (opacity *= width) && (stroke.weight = 1); -3291 stroke.opacity = opacity; -3292 -3293 params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter"); -3294 stroke.miterlimit = params["stroke-miterlimit"] || 8; -3295 params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round"); -3296 if (params["stroke-dasharray"]) { -3297 var dasharray = { -3298 "-": "shortdash", -3299 ".": "shortdot", -3300 "-.": "shortdashdot", -3301 "-..": "shortdashdotdot", -3302 ". ": "dot", -3303 "- ": "dash", -3304 "--": "longdash", -3305 "- .": "dashdot", -3306 "--.": "longdashdot", -3307 "--..": "longdashdotdot" -3308 }; -3309 stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E; -3310 } -3311 newstroke && node.appendChild(stroke); -3312 } -3313 if (res.type == "text") { -3314 res.paper.canvas.style.display = E; -3315 var span = res.paper.span, -3316 m = 100, -3317 fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/); -3318 s = span.style; -3319 a.font && (s.font = a.font); -3320 a["font-family"] && (s.fontFamily = a["font-family"]); -3321 a["font-weight"] && (s.fontWeight = a["font-weight"]); -3322 a["font-style"] && (s.fontStyle = a["font-style"]); -3323 fontSize = toFloat(fontSize ? fontSize[0] : a["font-size"]); -3324 s.fontSize = fontSize * m + "px"; -3325 res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>")); -3326 var brect = span.getBoundingClientRect(); -3327 res.W = a.w = (brect.right - brect.left) / m; -3328 res.H = a.h = (brect.bottom - brect.top) / m; -3329 res.paper.canvas.style.display = "none"; -3330 res.X = a.x; -3331 res.Y = a.y + res.H / 2; -3332 -3333 ("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)); -3334 var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"]; -3335 for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) { -3336 res._.dirty = 1; -3337 break; -3338 } -3339 -3340 // text-anchor emulation -3341 switch (a["text-anchor"]) { -3342 case "start": -3343 res.textpath.style["v-text-align"] = "left"; -3344 res.bbx = res.W / 2; -3345 break; -3346 case "end": -3347 res.textpath.style["v-text-align"] = "right"; -3348 res.bbx = -res.W / 2; -3349 break; -3350 default: -3351 res.textpath.style["v-text-align"] = "center"; -3352 res.bbx = 0; -3353 break; -3354 } -3355 res.textpath.style["v-text-kern"] = true; -3356 } -3357 res.paper.canvas.style.display = E; -3358 }; -3359 addGradientFill = function (o, gradient, fill) { -3360 o.attrs = o.attrs || {}; -3361 var attrs = o.attrs, -3362 type = "linear", -3363 fxfy = ".5 .5"; -3364 o.attrs.gradient = gradient; -3365 gradient = Str(gradient).replace(radial_gradient, function (all, fx, fy) { -3366 type = "radial"; -3367 if (fx && fy) { -3368 fx = toFloat(fx); -3369 fy = toFloat(fy); -3370 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5); -3371 fxfy = fx + S + fy; -3372 } -3373 return E; -3374 }); -3375 gradient = gradient.split(/\s*\-\s*/); -3376 if (type == "linear") { -3377 var angle = gradient.shift(); -3378 angle = -toFloat(angle); -3379 if (isNaN(angle)) { -3380 return null; -3381 } -3382 } -3383 var dots = parseDots(gradient); -3384 if (!dots) { -3385 return null; -3386 } -3387 o = o.shape || o.node; -3388 if (dots.length) { -3389 o.removeChild(fill); -3390 fill.on = true; -3391 fill.method = "none"; -3392 fill.color = dots[0].color; -3393 fill.color2 = dots[dots.length - 1].color; -3394 var clrs = []; -3395 for (var i = 0, ii = dots.length; i < ii; i++) { -3396 dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color); -3397 } -3398 fill.colors && (fill.colors.value = clrs.length ? clrs.join() : "0% " + fill.color); -3399 if (type == "radial") { -3400 fill.type = "gradientTitle"; -3401 fill.focus = "100%"; -3402 fill.focussize = "0 0"; -3403 fill.focusposition = fxfy; -3404 fill.angle = 0; -3405 } else { -3406 // fill.rotate= true; -3407 fill.type = "gradient"; -3408 fill.angle = (270 - angle) % 360; -3409 } -3410 o.appendChild(fill); -3411 // alert(fill.outerHTML); -3412 } -3413 return 1; -3414 }; -3415 Element = function (node, vml) { -3416 this[0] = this.node = node; -3417 node.raphael = true; -3418 this.id = R._oid++; -3419 node.raphaelid = this.id; -3420 this.X = 0; -3421 this.Y = 0; -3422 this.attrs = {}; -3423 this.paper = vml; -3424 this.matrix = new Matrix; -3425 this._ = { -3426 transform: [], -3427 sx: 1, -3428 sy: 1, -3429 dx: 0, -3430 dy: 0, -3431 deg: 0, -3432 dirty: 1, -3433 dirtyT: 1 -3434 }; -3435 !vml.bottom && (vml.bottom = this); -3436 this.prev = vml.top; -3437 vml.top && (vml.top.next = this); -3438 vml.top = this; -3439 this.next = null; -3440 }; -3441 elproto = Element.prototype; -3442 elproto.transform = function (tstr) { -3443 if (tstr == null) { -3444 return this._.transform; -3445 } -3446 extractTransform(this, tstr); -3447 var matrix = this.matrix.clone(), -3448 skew = this.skew; -3449 matrix.translate(-.5, -.5); -3450 if (this.type == "image") { -3451 if (Str(tstr).indexOf("m") + 1) { -3452 this.node.style.filter = matrix.toFilter(); -3453 var bb = this.getBBox(), -3454 bbt = this.getBBox(1), -3455 im = matrix.invert(), -3456 dx = im.x(bb.x, bb.y) - im.x(bbt.x, bbt.y), -3457 dy = im.y(bb.x, bb.y) - im.y(bbt.x, bbt.y); -3458 // skew.offset = dx + S + dy; -3459 // this.node.getElementsByTagName(fillString)[0].position = skew.offset; -3460 } else { -3461 this.node.style.filter = E; -3462 setCoords(this); -3463 } -3464 } else { -3465 // o = this.node, -3466 // _ = this._, -3467 // fillpos = _.fillpos, -3468 // deg, -3469 // matrix = this.matrix; -3470 // fill = o.getElementsByTagName(fillString)[0], -3471 // angle = fill.angle; -3472 -3473 this.node.style.filter = E; -3474 skew.matrix = matrix; -3475 skew.offset = matrix.offset(); -3476 -3477 // if (0&&angle) { -3478 // angle = R.rad(270 - angle); -3479 // var dx = 100 * math.cos(angle), -3480 // dy = 100 * math.sin(angle), -3481 // zx = matrix.x(0, 0), -3482 // zy = matrix.y(0, 0), -3483 // mx = matrix.x(dx, dy), -3484 // my = matrix.y(dx, dy); -3485 // angle = R.angle(zx, zy, mx, my); -3486 // fill.angle = (270 - angle) % 360; -3487 // } -3488 } -3489 return this; -3490 }; -3491 elproto.rotate = function (deg, cx, cy) { -3492 if (this.removed) { -3493 return this; -3494 } -3495 if (deg == null) { -3496 return; -3497 } -3498 deg = Str(deg).split(separator); -3499 if (deg.length - 1) { -3500 cx = toFloat(deg[1]); -3501 cy = toFloat(deg[2]); -3502 } -3503 deg = toFloat(deg[0]); -3504 (cy == null) && (cx = cy); -3505 if (cx == null || cy == null) { -3506 var bbox = this.getBBox(1); -3507 cx = bbox.x + bbox.width / 2; -3508 cy = bbox.y + bbox.height / 2; -3509 } -3510 this._.dirtyT = 1; -3511 this.transform(this._.transform.concat([["r", deg, cx, cy]])); -3512 return this; -3513 }; -3514 elproto.translate = function (dx, dy) { -3515 if (this.removed) { -3516 return this; -3517 } -3518 dx = Str(dx).split(separator); -3519 if (dx.length - 1) { -3520 dy = toFloat(dx[1]); -3521 } -3522 dx = toFloat(dx[0]) || 0; -3523 dy = +dy || 0; -3524 if (this._.bbox) { -3525 this._.bbox.x += dx; -3526 this._.bbox.y += dy; -3527 } -3528 this.transform(this._.transform.concat([["t", dx, dy]])); -3529 return this; -3530 }; -3531 elproto.scale = function (sx, sy, cx, cy) { -3532 if (this.removed) { -3533 return this; -3534 } -3535 sx = Str(sx).split(separator); -3536 if (sx.length - 1) { -3537 sy = toFloat(sx[1]); -3538 cx = toFloat(sx[2]); -3539 cy = toFloat(sx[3]); -3540 isNaN(cx) && (cx = null); -3541 isNaN(cy) && (cy = null); -3542 } -3543 sx = toFloat(sx[0]); -3544 (sy == null) && (sy = sx); -3545 (cy == null) && (cx = cy); -3546 if (cx == null || cy == null) { -3547 var bbox = this.getBBox(1); -3548 } -3549 cx = cx == null ? bbox.x + bbox.width / 2 : cx; -3550 cy = cy == null ? bbox.y + bbox.height / 2 : cy; -3551 -3552 this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); -3553 this._.dirtyT = 1; -3554 return this; -3555 }; -3556 elproto.hide = function () { -3557 !this.removed && (this.node.style.display = "none"); -3558 return this; -3559 }; -3560 elproto.show = function () { -3561 !this.removed && (this.node.style.display = E); -3562 return this; -3563 }; -3564 elproto._getBBox = function () { -3565 if (this.removed) { -3566 return {}; -3567 } -3568 if (this.type == "text") { -3569 return { -3570 x: this.X + (this.bbx || 0) - this.W / 2, -3571 y: this.Y - this.H, -3572 width: this.W, -3573 height: this.H -3574 }; -3575 } else { -3576 return pathDimensions(this.attrs.path); -3577 } -3578 }; -3579 elproto.remove = function () { -3580 if (this.removed) { -3581 return; -3582 } -3583 eve.unbind("*.*." + this.id); -3584 tear(this, this.paper); -3585 this.node.parentNode.removeChild(this.node); -3586 this.shape && this.shape.parentNode.removeChild(this.shape); -3587 for (var i in this) { -3588 delete this[i]; -3589 } -3590 this.removed = true; -3591 }; -3592 elproto.attr = function (name, value) { -3593 if (this.removed) { -3594 return this; -3595 } -3596 if (name == null) { -3597 var res = {}; -3598 for (var i in this.attrs) if (this.attrs[has](i)) { -3599 res[i] = this.attrs[i]; -3600 } -3601 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; -3602 return res; -3603 } -3604 if (value == null && R.is(name, "string")) { -3605 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { -3606 return this.attrs.gradient; -3607 } -3608 if (name in this.attrs) { -3609 return this.attrs[name]; -3610 } else if (R.is(this.paper.customAttributes[name], "function")) { -3611 return this.paper.customAttributes[name].def; -3612 } else { -3613 return availableAttrs[name]; -3614 } -3615 } -3616 if (this.attrs && value == null && R.is(name, array)) { -3617 var ii, values = {}; -3618 for (i = 0, ii = name.length; i < ii; i++) { -3619 values[name[i]] = this.attr(name[i]); -3620 } -3621 return values; -3622 } -3623 var params; -3624 if (value != null) { -3625 params = {}; -3626 params[name] = value; -3627 } -3628 value == null && R.is(name, "object") && (params = name); -3629 for (var key in params) { -3630 eve("attr." + key + "." + this.id, this, params[key]); -3631 } -3632 if (params) { -3633 for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { -3634 var par = this.paper.customAttributes[key].apply(this, [][concat](params[key])); -3635 this.attrs[key] = params[key]; -3636 for (var subkey in par) if (par[has](subkey)) { -3637 params[subkey] = par[subkey]; -3638 } -3639 } -3640 // this.paper.canvas.style.display = "none"; -3641 if (params.text && this.type == "text") { -3642 this.textpath.string = params.text; -3643 } -3644 setFillAndStroke(this, params); -3645 // this.paper.canvas.style.display = E; -3646 } -3647 return this; -3648 }; -3649 elproto.toFront = function () { -3650 !this.removed && this.node.parentNode.appendChild(this.node); -3651 this.paper.top != this && tofront(this, this.paper); -3652 return this; -3653 }; -3654 elproto.toBack = function () { -3655 if (this.removed) { -3656 return this; -3657 } -3658 if (this.node.parentNode.firstChild != this.node) { -3659 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); -3660 toback(this, this.paper); -3661 } -3662 return this; -3663 }; -3664 elproto.insertAfter = function (element) { -3665 if (this.removed) { -3666 return this; -3667 } -3668 if (element.constructor == Set) { -3669 element = element[element.length - 1]; -3670 } -3671 if (element.node.nextSibling) { -3672 element.node.parentNode.insertBefore(this.node, element.node.nextSibling); -3673 } else { -3674 element.node.parentNode.appendChild(this.node); -3675 } -3676 insertafter(this, element, this.paper); -3677 return this; -3678 }; -3679 elproto.insertBefore = function (element) { -3680 if (this.removed) { -3681 return this; -3682 } -3683 if (element.constructor == Set) { -3684 element = element[0]; -3685 } -3686 element.node.parentNode.insertBefore(this.node, element.node); -3687 insertbefore(this, element, this.paper); -3688 return this; -3689 }; -3690 elproto.blur = function (size) { -3691 var s = this.node.runtimeStyle, -3692 f = s.filter; -3693 f = f.replace(blurregexp, E); -3694 if (+size !== 0) { -3695 this.attrs.blur = size; -3696 s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")"; -3697 s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5)); -3698 } else { -3699 s.filter = f; -3700 s.margin = 0; -3701 delete this.attrs.blur; -3702 } -3703 }; -3704 -3705 thePath = function (pathString, vml) { -3706 var el = createNode("shape"); -3707 el.style.cssText = cssDot; -3708 el.coordsize = zoom + S + zoom; -3709 el.coordorigin = vml.coordorigin; -3710 var p = new Element(el, vml), -3711 attr = {fill: "none", stroke: "#000"}; -3712 pathString && (attr.path = pathString); -3713 p.type = "path"; -3714 p.path = []; -3715 p.Path = E; -3716 setFillAndStroke(p, attr); -3717 vml.canvas.appendChild(el); -3718 var skew = createNode("skew"); -3719 skew.on = true; -3720 el.appendChild(skew); -3721 p.skew = skew; -3722 p.transform(E); -3723 return p; -3724 }; -3725 theRect = function (vml, x, y, w, h, r) { -3726 var path = rectPath(x, y, w, h, r), -3727 res = vml.path(path), -3728 a = res.attrs; -3729 res.X = a.x = x; -3730 res.Y = a.y = y; -3731 res.W = a.width = w; -3732 res.H = a.height = h; -3733 a.r = r; -3734 a.path = path; -3735 res.type = "rect"; -3736 return res; -3737 }; -3738 theEllipse = function (vml, x, y, rx, ry) { -3739 var res = vml.path(), -3740 a = res.attrs; -3741 res.X = x - rx; -3742 res.Y = y - ry; -3743 res.W = rx * 2; -3744 res.H = ry * 2; -3745 res.type = "ellipse"; -3746 setFillAndStroke(res, { -3747 cx: x, -3748 cy: y, -3749 rx: rx, -3750 ry: ry -3751 }); -3752 return res; -3753 }; -3754 theCircle = function (vml, x, y, r) { -3755 var res = vml.path(), -3756 a = res.attrs; -3757 res.X = x - r; -3758 res.Y = y - r; -3759 res.W = res.H = r * 2; -3760 res.type = "circle"; -3761 setFillAndStroke(res, { -3762 cx: x, -3763 cy: y, -3764 r: r -3765 }); -3766 return res; -3767 }; -3768 theImage = function (vml, src, x, y, w, h) { -3769 var path = rectPath(x, y, w, h), -3770 res = vml.path(path).attr({stroke: "none"}), -3771 a = res.attrs, -3772 node = res.node, -3773 fill = node.getElementsByTagName(fillString)[0]; -3774 a.src = src; -3775 res.X = a.x = x; -3776 res.Y = a.y = y; -3777 res.W = a.width = w; -3778 res.H = a.height = h; -3779 a.path = path; -3780 res.type = "image"; -3781 fill.parentNode == node && node.removeChild(fill); -3782 fill.rotate = true; -3783 fill.src = src; -3784 fill.type = "tile"; -3785 res._.fillpos = [x, y]; -3786 res._.fillsize = [w, h]; -3787 node.appendChild(fill); -3788 setCoords(res); -3789 return res; -3790 }; -3791 theText = function (vml, x, y, text) { -3792 var el = createNode("shape"), -3793 path = createNode("path"), -3794 o = createNode("textpath"); -3795 x = x || 0; -3796 y = y || 0; -3797 text = text || ""; -3798 path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1); -3799 path.textpathok = true; -3800 o.string = Str(text); -3801 o.on = true; -3802 el.style.cssText = "position:absolute;left:0;top:0;width:1;height:1"; -3803 el.coordsize = zoom + S + zoom; -3804 el.coordorigin = "0 0"; -3805 var p = new Element(el, vml), -3806 attr = {fill: "#000", stroke: "none", font: availableAttrs.font, text: text}; -3807 p.shape = el; -3808 p.path = path; -3809 p.textpath = o; -3810 p.type = "text"; -3811 p.attrs.text = Str(text); -3812 p.attrs.x = x; -3813 p.attrs.y = y; -3814 p.attrs.w = 1; -3815 p.attrs.h = 1; -3816 setFillAndStroke(p, attr); -3817 el.appendChild(o); -3818 el.appendChild(path); -3819 vml.canvas.appendChild(el); -3820 var skew = createNode("skew"); -3821 skew.on = true; -3822 el.appendChild(skew); -3823 p.skew = skew; -3824 p.transform(E); -3825 return p; -3826 }; -3827 setSize = function (width, height) { -3828 var cs = this.canvas.style; -3829 this.width = width; -3830 this.height = height; -3831 width == +width && (width += "px"); -3832 height == +height && (height += "px"); -3833 cs.width = width; -3834 cs.height = height; -3835 cs.clip = "rect(0 " + width + " " + height + " 0)"; -3836 if (this._viewBox) { -3837 setViewBox.apply(this, this._viewBox); -3838 } -3839 return this; -3840 }; -3841 setViewBox = function (x, y, w, h, fit) { -3842 eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); -3843 var width = this.width, -3844 height = this.height, -3845 size = 1e3 * mmax(w / width, h / height), -3846 H, W; -3847 if (fit) { -3848 H = height / h; -3849 W = width / w; -3850 if (w * H < width) { -3851 x -= (width - w * H) / 2 / H; -3852 } -3853 if (h * W < height) { -3854 y -= (height - h * W) / 2 / W; -3855 } -3856 } -3857 this._viewBox = [x, y, w, h, !!fit]; -3858 this.forEach(function (el) { -3859 el.transform("..."); -3860 }); -3861 return this; -3862 }; -3863 var createNode, -3864 initWin = function (win) { -3865 var doc = win.document; -3866 doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); -3867 try { -3868 !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); -3869 createNode = function (tagName) { -3870 return doc.createElement('<rvml:' + tagName + ' class="rvml">'); -3871 }; -3872 } catch (e) { -3873 createNode = function (tagName) { -3874 return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); -3875 }; -3876 } -3877 }; -3878 initWin(g.win); -3879 create = function () { -3880 var con = getContainer[apply](0, arguments), -3881 container = con.container, -3882 height = con.height, -3883 s, -3884 width = con.width, -3885 x = con.x, -3886 y = con.y; -3887 if (!container) { -3888 throw new Error("VML container not found."); -3889 } -3890 var res = new Paper, -3891 c = res.canvas = g.doc.createElement("div"), -3892 cs = c.style; -3893 x = x || 0; -3894 y = y || 0; -3895 width = width || 512; -3896 height = height || 342; -3897 res.width = width; -3898 res.height = height; -3899 width == +width && (width += "px"); -3900 height == +height && (height += "px"); -3901 res.coordsize = zoom * 1e3 + S + zoom * 1e3; -3902 res.coordorigin = "0 0"; -3903 res.span = g.doc.createElement("span"); -3904 res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;"; -3905 c.appendChild(res.span); -3906 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); -3907 if (container == 1) { -3908 g.doc.body.appendChild(c); -3909 cs.left = x + "px"; -3910 cs.top = y + "px"; -3911 cs.position = "absolute"; -3912 } else { -3913 if (container.firstChild) { -3914 container.insertBefore(c, container.firstChild); -3915 } else { -3916 container.appendChild(c); -3917 } -3918 } -3919 plugins.call(res, res, R.fn); -3920 return res; -3921 }; -3922 paperproto.clear = function () { -3923 eve("clear", this); -3924 this.canvas.innerHTML = E; -3925 this.span = g.doc.createElement("span"); -3926 this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;"; -3927 this.canvas.appendChild(this.span); -3928 this.bottom = this.top = null; -3929 }; -3930 paperproto.remove = function () { -3931 eve("remove", this); -3932 this.canvas.parentNode.removeChild(this.canvas); -3933 for (var i in this) { -3934 this[i] = removed(i); -3935 } -3936 return true; -3937 }; -3938 } -3939 -3940 // WebKit rendering bug workaround method -3941 var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/); -3942 if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") || -3943 (navigator.vendor == "Google Inc." && version && version[1] < 8)) { -3944 /*\ -3945 * Paper.safari -3946 [ method ] -3947 ** -3948 * Adds event handlers for hover for the element. -3949 > Parameters -3950 - f_in (function) handler for hover in -3951 - f_out (function) handler for hover out -3952 - icontext (object) #optional context for hover in handler -3953 - ocontext (object) #optional context for hover out handler -3954 = (object) @Element -3955 \*/ -3956 paperproto.safari = function () { -3957 var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"}); -3958 setTimeout(function () {rect.remove();}); -3959 }; -3960 } else { -3961 paperproto.safari = fun; -3962 } -3963 -3964 // Events -3965 var preventDefault = function () { -3966 this.returnValue = false; +3155 +3156 for (var par in params) if (params[has](par)) { +3157 a[par] = params[par]; +3158 } +3159 if (newpath) { +3160 a.path = getPath[o.type](o); +3161 o._.dirty = 1; +3162 } +3163 params.href && (node.href = params.href); +3164 params.title && (node.title = params.title); +3165 params.target && (node.target = params.target); +3166 params.cursor && (s.cursor = params.cursor); +3167 "blur" in params && o.blur(params.blur); +3168 "transform" in params && o.transform(params.transform); +3169 if (params.path && o.type == "path" || newpath) { +3170 node.path = path2vml(a.path); +3171 } +3172 if (isOval) { +3173 var cx = a.cx, +3174 cy = a.cy, +3175 rx = a.rx || a.r || 0, +3176 ry = a.ry || a.r || 0; +3177 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)); +3178 } +3179 if ("clip-rect" in params) { +3180 var rect = Str(params["clip-rect"]).split(separator); +3181 if (rect.length == 4) { +3182 rect[2] = +rect[2] + (+rect[0]); +3183 rect[3] = +rect[3] + (+rect[1]); +3184 var div = node.clipRect || g.doc.createElement("div"), +3185 dstyle = div.style, +3186 group = node.parentNode; +3187 dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect); +3188 if (!node.clipRect) { +3189 dstyle.position = "absolute"; +3190 dstyle.top = 0; +3191 dstyle.left = 0; +3192 dstyle.width = o.paper.width + "px"; +3193 dstyle.height = o.paper.height + "px"; +3194 group.parentNode.insertBefore(div, group); +3195 div.appendChild(group); +3196 node.clipRect = div; +3197 } +3198 } +3199 if (!params["clip-rect"]) { +3200 node.clipRect && (node.clipRect.style.clip = E); +3201 } +3202 } +3203 if (o.textpath) { +3204 var textpathStyle = o.textpath.style; +3205 params.font && (textpathStyle.font = params.font); +3206 params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"'); +3207 params["font-size"] && (textpathStyle.fontSize = params["font-size"]); +3208 params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]); +3209 params["font-style"] && (textpathStyle.fontStyle = params["font-style"]); +3210 } +3211 if ("arrow-start" in params) { +3212 addArrow(res, params["arrow-start"]); +3213 } +3214 if ("arrow-end" in params) { +3215 addArrow(res, params["arrow-end"], 1); +3216 } +3217 if (params.opacity != null || +3218 params["stroke-width"] != null || +3219 params.fill != null || +3220 params.src != null || +3221 params.stroke != null || +3222 params["stroke-width"] != null || +3223 params["stroke-opacity"] != null || +3224 params["fill-opacity"] != null || +3225 params["stroke-dasharray"] != null || +3226 params["stroke-miterlimit"] != null || +3227 params["stroke-linejoin"] != null || +3228 params["stroke-linecap"] != null) { +3229 var fill = node.getElementsByTagName(fillString), +3230 newfill = false; +3231 fill = fill && fill[0]; +3232 !fill && (newfill = fill = createNode(fillString)); +3233 if (o.type == "image" && params.src) { +3234 fill.src = params.src; +3235 } +3236 if ("fill-opacity" in params || "opacity" in params) { +3237 var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1); +3238 opacity = mmin(mmax(opacity, 0), 1); +3239 fill.opacity = opacity; +3240 } +3241 params.fill && (fill.on = true); +3242 if (fill.on == null || params.fill == "none" || params.fill === null) { +3243 fill.on = false; +3244 } +3245 if (fill.on && params.fill) { +3246 var isURL = params.fill.match(ISURL); +3247 if (isURL) { +3248 fill.parentNode == node && node.removeChild(fill); +3249 fill.rotate = true; +3250 fill.src = isURL[1]; +3251 fill.type = "tile"; +3252 var bbox = o.getBBox(1); +3253 fill.position = bbox.x + S + bbox.y; +3254 o._.fillpos = [bbox.x, bbox.y]; +3255 +3256 preload(isURL[1], function () { +3257 o._.fillsize = [this.offsetWidth, this.offsetHeight]; +3258 }); +3259 } else { +3260 fill.color = R.getRGB(params.fill).hex; +3261 fill.src = E; +3262 fill.type = "solid"; +3263 if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) { +3264 a.fill = "none"; +3265 a.gradient = params.fill; +3266 fill.rotate = false; +3267 } +3268 } +3269 } +3270 node.appendChild(fill); +3271 var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]), +3272 newstroke = false; +3273 !stroke && (newstroke = stroke = createNode("stroke")); +3274 if ((params.stroke && params.stroke != "none") || +3275 params["stroke-width"] || +3276 params["stroke-opacity"] != null || +3277 params["stroke-dasharray"] || +3278 params["stroke-miterlimit"] || +3279 params["stroke-linejoin"] || +3280 params["stroke-linecap"]) { +3281 stroke.on = true; +3282 } +3283 (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false); +3284 var strokeColor = R.getRGB(params.stroke); +3285 stroke.on && params.stroke && (stroke.color = strokeColor.hex); +3286 opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1); +3287 var width = (toFloat(params["stroke-width"]) || 1) * .75; +3288 opacity = mmin(mmax(opacity, 0), 1); +3289 params["stroke-width"] == null && (width = a["stroke-width"]); +3290 params["stroke-width"] && (stroke.weight = width); +3291 width && width < 1 && (opacity *= width) && (stroke.weight = 1); +3292 stroke.opacity = opacity; +3293 +3294 params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter"); +3295 stroke.miterlimit = params["stroke-miterlimit"] || 8; +3296 params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round"); +3297 if (params["stroke-dasharray"]) { +3298 var dasharray = { +3299 "-": "shortdash", +3300 ".": "shortdot", +3301 "-.": "shortdashdot", +3302 "-..": "shortdashdotdot", +3303 ". ": "dot", +3304 "- ": "dash", +3305 "--": "longdash", +3306 "- .": "dashdot", +3307 "--.": "longdashdot", +3308 "--..": "longdashdotdot" +3309 }; +3310 stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E; +3311 } +3312 newstroke && node.appendChild(stroke); +3313 } +3314 if (res.type == "text") { +3315 res.paper.canvas.style.display = E; +3316 var span = res.paper.span, +3317 m = 100, +3318 fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/); +3319 s = span.style; +3320 a.font && (s.font = a.font); +3321 a["font-family"] && (s.fontFamily = a["font-family"]); +3322 a["font-weight"] && (s.fontWeight = a["font-weight"]); +3323 a["font-style"] && (s.fontStyle = a["font-style"]); +3324 fontSize = toFloat(fontSize ? fontSize[0] : a["font-size"]); +3325 s.fontSize = fontSize * m + "px"; +3326 res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>")); +3327 var brect = span.getBoundingClientRect(); +3328 res.W = a.w = (brect.right - brect.left) / m; +3329 res.H = a.h = (brect.bottom - brect.top) / m; +3330 res.paper.canvas.style.display = "none"; +3331 res.X = a.x; +3332 res.Y = a.y + res.H / 2; +3333 +3334 ("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)); +3335 var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"]; +3336 for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) { +3337 res._.dirty = 1; +3338 break; +3339 } +3340 +3341 // text-anchor emulation +3342 switch (a["text-anchor"]) { +3343 case "start": +3344 res.textpath.style["v-text-align"] = "left"; +3345 res.bbx = res.W / 2; +3346 break; +3347 case "end": +3348 res.textpath.style["v-text-align"] = "right"; +3349 res.bbx = -res.W / 2; +3350 break; +3351 default: +3352 res.textpath.style["v-text-align"] = "center"; +3353 res.bbx = 0; +3354 break; +3355 } +3356 res.textpath.style["v-text-kern"] = true; +3357 } +3358 res.paper.canvas.style.display = E; +3359 }; +3360 addGradientFill = function (o, gradient, fill) { +3361 o.attrs = o.attrs || {}; +3362 var attrs = o.attrs, +3363 type = "linear", +3364 fxfy = ".5 .5"; +3365 o.attrs.gradient = gradient; +3366 gradient = Str(gradient).replace(radial_gradient, function (all, fx, fy) { +3367 type = "radial"; +3368 if (fx && fy) { +3369 fx = toFloat(fx); +3370 fy = toFloat(fy); +3371 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5); +3372 fxfy = fx + S + fy; +3373 } +3374 return E; +3375 }); +3376 gradient = gradient.split(/\s*\-\s*/); +3377 if (type == "linear") { +3378 var angle = gradient.shift(); +3379 angle = -toFloat(angle); +3380 if (isNaN(angle)) { +3381 return null; +3382 } +3383 } +3384 var dots = parseDots(gradient); +3385 if (!dots) { +3386 return null; +3387 } +3388 o = o.shape || o.node; +3389 if (dots.length) { +3390 o.removeChild(fill); +3391 fill.on = true; +3392 fill.method = "none"; +3393 fill.color = dots[0].color; +3394 fill.color2 = dots[dots.length - 1].color; +3395 var clrs = []; +3396 for (var i = 0, ii = dots.length; i < ii; i++) { +3397 dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color); +3398 } +3399 fill.colors && (fill.colors.value = clrs.length ? clrs.join() : "0% " + fill.color); +3400 if (type == "radial") { +3401 fill.type = "gradientTitle"; +3402 fill.focus = "100%"; +3403 fill.focussize = "0 0"; +3404 fill.focusposition = fxfy; +3405 fill.angle = 0; +3406 } else { +3407 // fill.rotate= true; +3408 fill.type = "gradient"; +3409 fill.angle = (270 - angle) % 360; +3410 } +3411 o.appendChild(fill); +3412 // alert(fill.outerHTML); +3413 } +3414 return 1; +3415 }; +3416 Element = function (node, vml) { +3417 this[0] = this.node = node; +3418 node.raphael = true; +3419 this.id = R._oid++; +3420 node.raphaelid = this.id; +3421 this.X = 0; +3422 this.Y = 0; +3423 this.attrs = {}; +3424 this.paper = vml; +3425 this.matrix = new Matrix; +3426 this._ = { +3427 transform: [], +3428 sx: 1, +3429 sy: 1, +3430 dx: 0, +3431 dy: 0, +3432 deg: 0, +3433 dirty: 1, +3434 dirtyT: 1 +3435 }; +3436 !vml.bottom && (vml.bottom = this); +3437 this.prev = vml.top; +3438 vml.top && (vml.top.next = this); +3439 vml.top = this; +3440 this.next = null; +3441 }; +3442 elproto = Element.prototype; +3443 elproto.transform = function (tstr) { +3444 if (tstr == null) { +3445 return this._.transform; +3446 } +3447 extractTransform(this, tstr); +3448 var matrix = this.matrix.clone(), +3449 skew = this.skew; +3450 matrix.translate(-.5, -.5); +3451 if (this.type == "image") { +3452 if (Str(tstr).indexOf("m") + 1) { +3453 this.node.style.filter = matrix.toFilter(); +3454 var bb = this.getBBox(), +3455 bbt = this.getBBox(1), +3456 im = matrix.invert(), +3457 dx = im.x(bb.x, bb.y) - im.x(bbt.x, bbt.y), +3458 dy = im.y(bb.x, bb.y) - im.y(bbt.x, bbt.y); +3459 // skew.offset = dx + S + dy; +3460 // this.node.getElementsByTagName(fillString)[0].position = skew.offset; +3461 } else { +3462 this.node.style.filter = E; +3463 setCoords(this); +3464 } +3465 } else { +3466 // o = this.node, +3467 // _ = this._, +3468 // fillpos = _.fillpos, +3469 // deg, +3470 // matrix = this.matrix; +3471 // fill = o.getElementsByTagName(fillString)[0], +3472 // angle = fill.angle; +3473 +3474 this.node.style.filter = E; +3475 skew.matrix = matrix; +3476 skew.offset = matrix.offset(); +3477 +3478 // if (0&&angle) { +3479 // angle = R.rad(270 - angle); +3480 // var dx = 100 * math.cos(angle), +3481 // dy = 100 * math.sin(angle), +3482 // zx = matrix.x(0, 0), +3483 // zy = matrix.y(0, 0), +3484 // mx = matrix.x(dx, dy), +3485 // my = matrix.y(dx, dy); +3486 // angle = R.angle(zx, zy, mx, my); +3487 // fill.angle = (270 - angle) % 360; +3488 // } +3489 } +3490 return this; +3491 }; +3492 elproto.rotate = function (deg, cx, cy) { +3493 if (this.removed) { +3494 return this; +3495 } +3496 if (deg == null) { +3497 return; +3498 } +3499 deg = Str(deg).split(separator); +3500 if (deg.length - 1) { +3501 cx = toFloat(deg[1]); +3502 cy = toFloat(deg[2]); +3503 } +3504 deg = toFloat(deg[0]); +3505 (cy == null) && (cx = cy); +3506 if (cx == null || cy == null) { +3507 var bbox = this.getBBox(1); +3508 cx = bbox.x + bbox.width / 2; +3509 cy = bbox.y + bbox.height / 2; +3510 } +3511 this._.dirtyT = 1; +3512 this.transform(this._.transform.concat([["r", deg, cx, cy]])); +3513 return this; +3514 }; +3515 elproto.translate = function (dx, dy) { +3516 if (this.removed) { +3517 return this; +3518 } +3519 dx = Str(dx).split(separator); +3520 if (dx.length - 1) { +3521 dy = toFloat(dx[1]); +3522 } +3523 dx = toFloat(dx[0]) || 0; +3524 dy = +dy || 0; +3525 if (this._.bbox) { +3526 this._.bbox.x += dx; +3527 this._.bbox.y += dy; +3528 } +3529 this.transform(this._.transform.concat([["t", dx, dy]])); +3530 return this; +3531 }; +3532 elproto.scale = function (sx, sy, cx, cy) { +3533 if (this.removed) { +3534 return this; +3535 } +3536 sx = Str(sx).split(separator); +3537 if (sx.length - 1) { +3538 sy = toFloat(sx[1]); +3539 cx = toFloat(sx[2]); +3540 cy = toFloat(sx[3]); +3541 isNaN(cx) && (cx = null); +3542 isNaN(cy) && (cy = null); +3543 } +3544 sx = toFloat(sx[0]); +3545 (sy == null) && (sy = sx); +3546 (cy == null) && (cx = cy); +3547 if (cx == null || cy == null) { +3548 var bbox = this.getBBox(1); +3549 } +3550 cx = cx == null ? bbox.x + bbox.width / 2 : cx; +3551 cy = cy == null ? bbox.y + bbox.height / 2 : cy; +3552 +3553 this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); +3554 this._.dirtyT = 1; +3555 return this; +3556 }; +3557 elproto.hide = function () { +3558 !this.removed && (this.node.style.display = "none"); +3559 return this; +3560 }; +3561 elproto.show = function () { +3562 !this.removed && (this.node.style.display = E); +3563 return this; +3564 }; +3565 elproto._getBBox = function () { +3566 if (this.removed) { +3567 return {}; +3568 } +3569 if (this.type == "text") { +3570 return { +3571 x: this.X + (this.bbx || 0) - this.W / 2, +3572 y: this.Y - this.H, +3573 width: this.W, +3574 height: this.H +3575 }; +3576 } else { +3577 return pathDimensions(this.attrs.path); +3578 } +3579 }; +3580 elproto.remove = function () { +3581 if (this.removed) { +3582 return; +3583 } +3584 eve.unbind("*.*." + this.id); +3585 tear(this, this.paper); +3586 this.node.parentNode.removeChild(this.node); +3587 this.shape && this.shape.parentNode.removeChild(this.shape); +3588 for (var i in this) { +3589 delete this[i]; +3590 } +3591 this.removed = true; +3592 }; +3593 elproto.attr = function (name, value) { +3594 if (this.removed) { +3595 return this; +3596 } +3597 if (name == null) { +3598 var res = {}; +3599 for (var i in this.attrs) if (this.attrs[has](i)) { +3600 res[i] = this.attrs[i]; +3601 } +3602 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; +3603 return res; +3604 } +3605 if (value == null && R.is(name, "string")) { +3606 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { +3607 return this.attrs.gradient; +3608 } +3609 if (name in this.attrs) { +3610 return this.attrs[name]; +3611 } else if (R.is(this.paper.customAttributes[name], "function")) { +3612 return this.paper.customAttributes[name].def; +3613 } else { +3614 return availableAttrs[name]; +3615 } +3616 } +3617 if (this.attrs && value == null && R.is(name, array)) { +3618 var ii, values = {}; +3619 for (i = 0, ii = name.length; i < ii; i++) { +3620 values[name[i]] = this.attr(name[i]); +3621 } +3622 return values; +3623 } +3624 var params; +3625 if (value != null) { +3626 params = {}; +3627 params[name] = value; +3628 } +3629 value == null && R.is(name, "object") && (params = name); +3630 for (var key in params) { +3631 eve("attr." + key + "." + this.id, this, params[key]); +3632 } +3633 if (params) { +3634 for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { +3635 var par = this.paper.customAttributes[key].apply(this, [][concat](params[key])); +3636 this.attrs[key] = params[key]; +3637 for (var subkey in par) if (par[has](subkey)) { +3638 params[subkey] = par[subkey]; +3639 } +3640 } +3641 // this.paper.canvas.style.display = "none"; +3642 if (params.text && this.type == "text") { +3643 this.textpath.string = params.text; +3644 } +3645 setFillAndStroke(this, params); +3646 // this.paper.canvas.style.display = E; +3647 } +3648 return this; +3649 }; +3650 elproto.toFront = function () { +3651 !this.removed && this.node.parentNode.appendChild(this.node); +3652 this.paper.top != this && tofront(this, this.paper); +3653 return this; +3654 }; +3655 elproto.toBack = function () { +3656 if (this.removed) { +3657 return this; +3658 } +3659 if (this.node.parentNode.firstChild != this.node) { +3660 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); +3661 toback(this, this.paper); +3662 } +3663 return this; +3664 }; +3665 elproto.insertAfter = function (element) { +3666 if (this.removed) { +3667 return this; +3668 } +3669 if (element.constructor == Set) { +3670 element = element[element.length - 1]; +3671 } +3672 if (element.node.nextSibling) { +3673 element.node.parentNode.insertBefore(this.node, element.node.nextSibling); +3674 } else { +3675 element.node.parentNode.appendChild(this.node); +3676 } +3677 insertafter(this, element, this.paper); +3678 return this; +3679 }; +3680 elproto.insertBefore = function (element) { +3681 if (this.removed) { +3682 return this; +3683 } +3684 if (element.constructor == Set) { +3685 element = element[0]; +3686 } +3687 element.node.parentNode.insertBefore(this.node, element.node); +3688 insertbefore(this, element, this.paper); +3689 return this; +3690 }; +3691 elproto.blur = function (size) { +3692 var s = this.node.runtimeStyle, +3693 f = s.filter; +3694 f = f.replace(blurregexp, E); +3695 if (+size !== 0) { +3696 this.attrs.blur = size; +3697 s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")"; +3698 s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5)); +3699 } else { +3700 s.filter = f; +3701 s.margin = 0; +3702 delete this.attrs.blur; +3703 } +3704 }; +3705 +3706 thePath = function (pathString, vml) { +3707 var el = createNode("shape"); +3708 el.style.cssText = cssDot; +3709 el.coordsize = zoom + S + zoom; +3710 el.coordorigin = vml.coordorigin; +3711 var p = new Element(el, vml), +3712 attr = {fill: "none", stroke: "#000"}; +3713 pathString && (attr.path = pathString); +3714 p.type = "path"; +3715 p.path = []; +3716 p.Path = E; +3717 setFillAndStroke(p, attr); +3718 vml.canvas.appendChild(el); +3719 var skew = createNode("skew"); +3720 skew.on = true; +3721 el.appendChild(skew); +3722 p.skew = skew; +3723 p.transform(E); +3724 return p; +3725 }; +3726 theRect = function (vml, x, y, w, h, r) { +3727 var path = rectPath(x, y, w, h, r), +3728 res = vml.path(path), +3729 a = res.attrs; +3730 res.X = a.x = x; +3731 res.Y = a.y = y; +3732 res.W = a.width = w; +3733 res.H = a.height = h; +3734 a.r = r; +3735 a.path = path; +3736 res.type = "rect"; +3737 return res; +3738 }; +3739 theEllipse = function (vml, x, y, rx, ry) { +3740 var res = vml.path(), +3741 a = res.attrs; +3742 res.X = x - rx; +3743 res.Y = y - ry; +3744 res.W = rx * 2; +3745 res.H = ry * 2; +3746 res.type = "ellipse"; +3747 setFillAndStroke(res, { +3748 cx: x, +3749 cy: y, +3750 rx: rx, +3751 ry: ry +3752 }); +3753 return res; +3754 }; +3755 theCircle = function (vml, x, y, r) { +3756 var res = vml.path(), +3757 a = res.attrs; +3758 res.X = x - r; +3759 res.Y = y - r; +3760 res.W = res.H = r * 2; +3761 res.type = "circle"; +3762 setFillAndStroke(res, { +3763 cx: x, +3764 cy: y, +3765 r: r +3766 }); +3767 return res; +3768 }; +3769 theImage = function (vml, src, x, y, w, h) { +3770 var path = rectPath(x, y, w, h), +3771 res = vml.path(path).attr({stroke: "none"}), +3772 a = res.attrs, +3773 node = res.node, +3774 fill = node.getElementsByTagName(fillString)[0]; +3775 a.src = src; +3776 res.X = a.x = x; +3777 res.Y = a.y = y; +3778 res.W = a.width = w; +3779 res.H = a.height = h; +3780 a.path = path; +3781 res.type = "image"; +3782 fill.parentNode == node && node.removeChild(fill); +3783 fill.rotate = true; +3784 fill.src = src; +3785 fill.type = "tile"; +3786 res._.fillpos = [x, y]; +3787 res._.fillsize = [w, h]; +3788 node.appendChild(fill); +3789 setCoords(res); +3790 return res; +3791 }; +3792 theText = function (vml, x, y, text) { +3793 var el = createNode("shape"), +3794 path = createNode("path"), +3795 o = createNode("textpath"); +3796 x = x || 0; +3797 y = y || 0; +3798 text = text || ""; +3799 path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1); +3800 path.textpathok = true; +3801 o.string = Str(text); +3802 o.on = true; +3803 el.style.cssText = "position:absolute;left:0;top:0;width:1;height:1"; +3804 el.coordsize = zoom + S + zoom; +3805 el.coordorigin = "0 0"; +3806 var p = new Element(el, vml), +3807 attr = {fill: "#000", stroke: "none", font: availableAttrs.font, text: text}; +3808 p.shape = el; +3809 p.path = path; +3810 p.textpath = o; +3811 p.type = "text"; +3812 p.attrs.text = Str(text); +3813 p.attrs.x = x; +3814 p.attrs.y = y; +3815 p.attrs.w = 1; +3816 p.attrs.h = 1; +3817 setFillAndStroke(p, attr); +3818 el.appendChild(o); +3819 el.appendChild(path); +3820 vml.canvas.appendChild(el); +3821 var skew = createNode("skew"); +3822 skew.on = true; +3823 el.appendChild(skew); +3824 p.skew = skew; +3825 p.transform(E); +3826 return p; +3827 }; +3828 setSize = function (width, height) { +3829 var cs = this.canvas.style; +3830 this.width = width; +3831 this.height = height; +3832 width == +width && (width += "px"); +3833 height == +height && (height += "px"); +3834 cs.width = width; +3835 cs.height = height; +3836 cs.clip = "rect(0 " + width + " " + height + " 0)"; +3837 if (this._viewBox) { +3838 setViewBox.apply(this, this._viewBox); +3839 } +3840 return this; +3841 }; +3842 setViewBox = function (x, y, w, h, fit) { +3843 eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); +3844 var width = this.width, +3845 height = this.height, +3846 size = 1e3 * mmax(w / width, h / height), +3847 H, W; +3848 if (fit) { +3849 H = height / h; +3850 W = width / w; +3851 if (w * H < width) { +3852 x -= (width - w * H) / 2 / H; +3853 } +3854 if (h * W < height) { +3855 y -= (height - h * W) / 2 / W; +3856 } +3857 } +3858 this._viewBox = [x, y, w, h, !!fit]; +3859 this.forEach(function (el) { +3860 el.transform("..."); +3861 }); +3862 return this; +3863 }; +3864 var createNode, +3865 initWin = function (win) { +3866 var doc = win.document; +3867 doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); +3868 try { +3869 !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); +3870 createNode = function (tagName) { +3871 return doc.createElement('<rvml:' + tagName + ' class="rvml">'); +3872 }; +3873 } catch (e) { +3874 createNode = function (tagName) { +3875 return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); +3876 }; +3877 } +3878 }; +3879 initWin(g.win); +3880 create = function () { +3881 var con = getContainer[apply](0, arguments), +3882 container = con.container, +3883 height = con.height, +3884 s, +3885 width = con.width, +3886 x = con.x, +3887 y = con.y; +3888 if (!container) { +3889 throw new Error("VML container not found."); +3890 } +3891 var res = new Paper, +3892 c = res.canvas = g.doc.createElement("div"), +3893 cs = c.style; +3894 x = x || 0; +3895 y = y || 0; +3896 width = width || 512; +3897 height = height || 342; +3898 res.width = width; +3899 res.height = height; +3900 width == +width && (width += "px"); +3901 height == +height && (height += "px"); +3902 res.coordsize = zoom * 1e3 + S + zoom * 1e3; +3903 res.coordorigin = "0 0"; +3904 res.span = g.doc.createElement("span"); +3905 res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;"; +3906 c.appendChild(res.span); +3907 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); +3908 if (container == 1) { +3909 g.doc.body.appendChild(c); +3910 cs.left = x + "px"; +3911 cs.top = y + "px"; +3912 cs.position = "absolute"; +3913 } else { +3914 if (container.firstChild) { +3915 container.insertBefore(c, container.firstChild); +3916 } else { +3917 container.appendChild(c); +3918 } +3919 } +3920 plugins.call(res, res, R.fn); +3921 return res; +3922 }; +3923 paperproto.clear = function () { +3924 eve("clear", this); +3925 this.canvas.innerHTML = E; +3926 this.span = g.doc.createElement("span"); +3927 this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;"; +3928 this.canvas.appendChild(this.span); +3929 this.bottom = this.top = null; +3930 }; +3931 paperproto.remove = function () { +3932 eve("remove", this); +3933 this.canvas.parentNode.removeChild(this.canvas); +3934 for (var i in this) { +3935 this[i] = removed(i); +3936 } +3937 return true; +3938 }; +3939 } +3940 +3941 // WebKit rendering bug workaround method +3942 var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/); +3943 if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") || +3944 (navigator.vendor == "Google Inc." && version && version[1] < 8)) { +3945 /*\ +3946 * Paper.safari +3947 [ method ] +3948 ** +3949 * There is an inconvenient rendering bug in Safari (WebKit): +3950 * sometimes the rendering should be forced. +3951 * This method should help with dealing with this bug. +3952 \*/ +3953 paperproto.safari = function () { +3954 var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"}); +3955 setTimeout(function () {rect.remove();}); +3956 }; +3957 } else { +3958 paperproto.safari = fun; +3959 } +3960 +3961 // Events +3962 var preventDefault = function () { +3963 this.returnValue = false; +3964 }, +3965 preventTouch = function () { +3966 return this.originalEvent.preventDefault(); 3967 }, -3968 preventTouch = function () { -3969 return this.originalEvent.preventDefault(); +3968 stopPropagation = function () { +3969 this.cancelBubble = true; 3970 }, -3971 stopPropagation = function () { -3972 this.cancelBubble = true; +3971 stopTouch = function () { +3972 return this.originalEvent.stopPropagation(); 3973 }, -3974 stopTouch = function () { -3975 return this.originalEvent.stopPropagation(); -3976 }, -3977 addEvent = (function () { -3978 if (g.doc.addEventListener) { -3979 return function (obj, type, fn, element) { -3980 var realName = supportsTouch && touchMap[type] ? touchMap[type] : type; -3981 var f = function (e) { -3982 if (supportsTouch && touchMap[has](type)) { -3983 for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { -3984 if (e.targetTouches[i].target == obj) { -3985 var olde = e; -3986 e = e.targetTouches[i]; -3987 e.originalEvent = olde; -3988 e.preventDefault = preventTouch; -3989 e.stopPropagation = stopTouch; -3990 break; -3991 } -3992 } -3993 } -3994 return fn.call(element, e); -3995 }; -3996 obj.addEventListener(realName, f, false); -3997 return function () { -3998 obj.removeEventListener(realName, f, false); -3999 return true; -4000 }; -4001 }; -4002 } else if (g.doc.attachEvent) { -4003 return function (obj, type, fn, element) { -4004 var f = function (e) { -4005 e = e || g.win.event; -4006 e.preventDefault = e.preventDefault || preventDefault; -4007 e.stopPropagation = e.stopPropagation || stopPropagation; -4008 return fn.call(element, e); -4009 }; -4010 obj.attachEvent("on" + type, f); -4011 var detacher = function () { -4012 obj.detachEvent("on" + type, f); -4013 return true; -4014 }; -4015 return detacher; -4016 }; -4017 } -4018 })(), -4019 drag = [], -4020 dragMove = function (e) { -4021 var x = e.clientX, -4022 y = e.clientY, -4023 scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, -4024 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, -4025 dragi, -4026 j = drag.length; -4027 while (j--) { -4028 dragi = drag[j]; -4029 if (supportsTouch) { -4030 var i = e.touches.length, -4031 touch; -4032 while (i--) { -4033 touch = e.touches[i]; -4034 if (touch.identifier == dragi.el._drag.id) { -4035 x = touch.clientX; -4036 y = touch.clientY; -4037 (e.originalEvent ? e.originalEvent : e).preventDefault(); -4038 break; -4039 } -4040 } -4041 } else { -4042 e.preventDefault(); -4043 } -4044 var node = dragi.el.node, -4045 o, -4046 next = node.nextSibling, -4047 parent = node.parentNode, -4048 display = node.style.display; -4049 g.win.opera && parent.removeChild(node); -4050 node.style.display = "none"; -4051 o = dragi.el.paper.getElementByPoint(x, y); -4052 node.style.display = display; -4053 g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node)); -4054 o && eve("drag.over." + dragi.el.id, dragi.el, o); -4055 x += scrollX; -4056 y += scrollY; -4057 eve("drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e); -4058 } -4059 }, -4060 dragUp = function (e) { -4061 R.unmousemove(dragMove).unmouseup(dragUp); -4062 var i = drag.length, -4063 dragi; -4064 while (i--) { -4065 dragi = drag[i]; -4066 dragi.el._drag = {}; -4067 eve("drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e); -4068 } -4069 drag = []; -4070 }; -4071 for (var i = events.length; i--;) { -4072 (function (eventName) { -4073 R[eventName] = Element.prototype[eventName] = function (fn, scope) { -4074 if (R.is(fn, "function")) { -4075 this.events = this.events || []; -4076 this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)}); -4077 } -4078 return this; -4079 }; -4080 R["un" + eventName] = Element.prototype["un" + eventName] = function (fn) { -4081 var events = this.events, -4082 l = events.length; -4083 while (l--) if (events[l].name == eventName && events[l].f == fn) { -4084 events[l].unbind(); -4085 events.splice(l, 1); -4086 !events.length && delete this.events; -4087 return this; -4088 } -4089 return this; -4090 }; -4091 })(events[i]); -4092 } -4093 /*\ -4094 * Element.hover -4095 [ method ] -4096 ** -4097 * Adds event handlers for hover for the element. -4098 > Parameters -4099 - f_in (function) handler for hover in -4100 - f_out (function) handler for hover out -4101 - icontext (object) #optional context for hover in handler -4102 - ocontext (object) #optional context for hover out handler -4103 = (object) @Element -4104 \*/ -4105 elproto.hover = function (f_in, f_out, scope_in, scope_out) { -4106 return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in); -4107 }; -4108 /*\ -4109 * Element.unhover -4110 [ method ] -4111 ** -4112 * Removes event handlers for hover for the element. -4113 > Parameters -4114 - f_in (function) handler for hover in -4115 - f_out (function) handler for hover out -4116 = (object) @Element -4117 \*/ -4118 elproto.unhover = function (f_in, f_out) { -4119 return this.unmouseover(f_in).unmouseout(f_out); -4120 }; -4121 /*\ -4122 * Element.drag -4123 [ method ] -4124 ** -4125 * Adds event handlers for drag of the element. -4126 > Parameters -4127 - onmove (function) handler for moving -4128 - onstart (function) handler for drag start -4129 - onend (function) handler for drag end -4130 - mcontext (object) #optional context for moving handler -4131 - scontext (object) #optional context for drag start handler -4132 - econtext (object) #optional context for drag end handler -4133 * Additionaly following `drag` events will be triggered: `drag.start.<id>` on start, -4134 * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element -4135 * `drag.over.<id>` will be fired as well. -4136 * -4137 * Start event and start handler will be called in specified context or in context of the element with following parameters: -4138 o x (number) x position of the mouse -4139 o y (number) y position of the mouse -4140 o event (object) DOM event object -4141 * Move event and move handler will be called in specified context or in context of the element with following parameters: -4142 o dx (number) shift by x from the start point -4143 o dy (number) shift by y from the start point -4144 o x (number) x position of the mouse -4145 o y (number) y position of the mouse -4146 o event (object) DOM event object -4147 * End event and end handler will be called in specified context or in context of the element with following parameters: -4148 o event (object) DOM event object -4149 = (object) @Element -4150 \*/ -4151 elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) { -4152 function start(e) { -4153 (e.originalEvent || e).preventDefault(); -4154 var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, -4155 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft; -4156 this._drag.x = e.clientX + scrollX; -4157 this._drag.y = e.clientY + scrollY; -4158 this._drag.id = e.identifier; -4159 !drag.length && R.mousemove(dragMove).mouseup(dragUp); -4160 drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope}); -4161 onstart && eve.on("drag.start." + this.id, onstart); -4162 onmove && eve.on("drag.move." + this.id, onmove); -4163 onend && eve.on("drag.end." + this.id, onend); -4164 eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e); -4165 } -4166 this._drag = {}; -4167 this.mousedown(start); -4168 return this; -4169 }; -4170 /*\ -4171 * Element.onDragOver -4172 [ method ] -4173 ** -4174 * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id). -4175 > Parameters -4176 - f (function) handler for event -4177 \*/ -4178 elproto.onDragOver = function (f) { -4179 f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id); -4180 }; -4181 /*\ -4182 * Element.undrag -4183 [ method ] -4184 ** -4185 * Removes all drag event handlers from given element. -4186 \*/ -4187 elproto.undrag = function () { -4188 var i = drag.length; -4189 while (i--) if (drag[i].el == this) { -4190 R.unmousedown(drag[i].start); -4191 drag.splice(i++, 1); -4192 eve.unbind("drag.*." + this.id); -4193 } -4194 !drag.length && R.unmousemove(dragMove).unmouseup(dragUp); -4195 }; -4196 /*\ -4197 * Paper.circle -4198 [ method ] -4199 ** -4200 * Draws a circle. -4201 ** -4202 > Parameters -4203 ** -4204 - x (number) x coordinate of the centre -4205 - y (number) y coordinate of the centre -4206 - r (number) radius -4207 = (object) Raphaël element object with type “circle” -4208 ** -4209 > Usage -4210 | var c = paper.circle(50, 50, 40); -4211 \*/ -4212 paperproto.circle = function (x, y, r) { -4213 return theCircle(this, x || 0, y || 0, r || 0); -4214 }; -4215 /*\ -4216 * Paper.rect -4217 [ method ] -4218 * -4219 * Draws a rectangle. -4220 ** -4221 > Parameters -4222 ** -4223 - x (number) x coordinate of the top left corner -4224 - y (number) y coordinate of the top left corner -4225 - width (number) width -4226 - height (number) height -4227 - r (number) @optional radius for rounded corners, default is 0 -4228 = (object) Raphaël element object with type “rect” -4229 ** -4230 > Usage -4231 | // regular rectangle -4232 | var c = paper.rect(10, 10, 50, 50); -4233 | // rectangle with rounded corners -4234 | var c = paper.rect(40, 40, 50, 50, 10); -4235 \*/ -4236 paperproto.rect = function (x, y, w, h, r) { -4237 return theRect(this, x || 0, y || 0, w || 0, h || 0, r || 0); -4238 }; -4239 /*\ -4240 * Paper.ellipse -4241 [ method ] -4242 ** -4243 * Draws an ellipse. -4244 ** -4245 > Parameters -4246 ** -4247 - x (number) x coordinate of the centre -4248 - y (number) y coordinate of the centre -4249 - rx (number) horisontal radius -4250 - ry (number) vertical radius -4251 = (object) Raphaël element object with type “ellipse” -4252 ** -4253 > Usage -4254 | var c = paper.ellipse(50, 50, 40, 20); -4255 \*/ -4256 paperproto.ellipse = function (x, y, rx, ry) { -4257 return theEllipse(this, x || 0, y || 0, rx || 0, ry || 0); -4258 }; -4259 /*\ -4260 * Paper.path -4261 [ method ] -4262 ** -4263 * Creates a path element by given path data string. -4264 ** -4265 > Parameters -4266 ** -4267 - pathString (string) path data in SVG path string format. -4268 = (object) Raphaël element object with type “ellipse” -4269 # Details of a path's data attribute's format are described in the <a href="http://www.w3.org/TR/SVG/paths.html#PathData">SVG specification</a>. -4270 ** -4271 > Usage -4272 | var c = paper.path("M10 10L90 90"); -4273 | // draw a diagonal line: -4274 | // move to 10,10, line to 90,90 -4275 \*/ -4276 paperproto.path = function (pathString) { -4277 pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E); -4278 return thePath(R.format[apply](R, arguments), this); -4279 }; -4280 /*\ -4281 * Paper.image -4282 [ method ] -4283 ** -4284 * Embeds an image into the surface. -4285 ** -4286 > Parameters -4287 ** -4288 - src (string) URI of the source image -4289 - x (number) x coordinate position -4290 - y (number) y coordinate position -4291 - width (number) width of the image -4292 - height (number) height of the image -4293 = (object) Raphaël element object with type “image” -4294 ** -4295 > Usage -4296 | var c = paper.image("apple.png", 10, 10, 80, 80); -4297 \*/ -4298 paperproto.image = function (src, x, y, w, h) { -4299 return theImage(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0); -4300 }; -4301 /*\ -4302 * Paper.text -4303 [ method ] -4304 ** -4305 * Draws a text string. If you need line breaks, put “\n” in the string. -4306 ** -4307 > Parameters -4308 ** -4309 - x (number) x coordinate position -4310 - y (number) y coordinate position -4311 - text (string) The text string to draw -4312 = (object) Raphaël element object with type “text” -4313 ** -4314 > Usage -4315 | var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!"); -4316 \*/ -4317 paperproto.text = function (x, y, text) { -4318 return theText(this, x || 0, y || 0, Str(text)); -4319 }; -4320 /*\ -4321 * Paper.set -4322 [ method ] -4323 ** -4324 * Creates array-like object to keep and operate couple of elements at once. -4325 * Warning: it doesn’t create any elements for itself in the page. -4326 = (object) array-like object that represents set of elements -4327 ** -4328 > Usage -4329 | var st = paper.set(); -4330 | st.push( -4331 | paper.circle(10, 10, 5), -4332 | paper.circle(30, 10, 5) -4333 | ); -4334 | st.attr({fill: "red"}); -4335 \*/ -4336 paperproto.set = function (itemsArray) { -4337 arguments.length > 1 && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length)); -4338 return new Set(itemsArray); -4339 }; -4340 /*\ -4341 * Paper.setSize -4342 [ method ] +3974 addEvent = (function () { +3975 if (g.doc.addEventListener) { +3976 return function (obj, type, fn, element) { +3977 var realName = supportsTouch && touchMap[type] ? touchMap[type] : type; +3978 var f = function (e) { +3979 if (supportsTouch && touchMap[has](type)) { +3980 for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { +3981 if (e.targetTouches[i].target == obj) { +3982 var olde = e; +3983 e = e.targetTouches[i]; +3984 e.originalEvent = olde; +3985 e.preventDefault = preventTouch; +3986 e.stopPropagation = stopTouch; +3987 break; +3988 } +3989 } +3990 } +3991 return fn.call(element, e); +3992 }; +3993 obj.addEventListener(realName, f, false); +3994 return function () { +3995 obj.removeEventListener(realName, f, false); +3996 return true; +3997 }; +3998 }; +3999 } else if (g.doc.attachEvent) { +4000 return function (obj, type, fn, element) { +4001 var f = function (e) { +4002 e = e || g.win.event; +4003 e.preventDefault = e.preventDefault || preventDefault; +4004 e.stopPropagation = e.stopPropagation || stopPropagation; +4005 return fn.call(element, e); +4006 }; +4007 obj.attachEvent("on" + type, f); +4008 var detacher = function () { +4009 obj.detachEvent("on" + type, f); +4010 return true; +4011 }; +4012 return detacher; +4013 }; +4014 } +4015 })(), +4016 drag = [], +4017 dragMove = function (e) { +4018 var x = e.clientX, +4019 y = e.clientY, +4020 scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, +4021 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, +4022 dragi, +4023 j = drag.length; +4024 while (j--) { +4025 dragi = drag[j]; +4026 if (supportsTouch) { +4027 var i = e.touches.length, +4028 touch; +4029 while (i--) { +4030 touch = e.touches[i]; +4031 if (touch.identifier == dragi.el._drag.id) { +4032 x = touch.clientX; +4033 y = touch.clientY; +4034 (e.originalEvent ? e.originalEvent : e).preventDefault(); +4035 break; +4036 } +4037 } +4038 } else { +4039 e.preventDefault(); +4040 } +4041 var node = dragi.el.node, +4042 o, +4043 next = node.nextSibling, +4044 parent = node.parentNode, +4045 display = node.style.display; +4046 g.win.opera && parent.removeChild(node); +4047 node.style.display = "none"; +4048 o = dragi.el.paper.getElementByPoint(x, y); +4049 node.style.display = display; +4050 g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node)); +4051 o && eve("drag.over." + dragi.el.id, dragi.el, o); +4052 x += scrollX; +4053 y += scrollY; +4054 eve("drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e); +4055 } +4056 }, +4057 dragUp = function (e) { +4058 R.unmousemove(dragMove).unmouseup(dragUp); +4059 var i = drag.length, +4060 dragi; +4061 while (i--) { +4062 dragi = drag[i]; +4063 dragi.el._drag = {}; +4064 eve("drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e); +4065 } +4066 drag = []; +4067 }; +4068 for (var i = events.length; i--;) { +4069 (function (eventName) { +4070 R[eventName] = Element.prototype[eventName] = function (fn, scope) { +4071 if (R.is(fn, "function")) { +4072 this.events = this.events || []; +4073 this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)}); +4074 } +4075 return this; +4076 }; +4077 R["un" + eventName] = Element.prototype["un" + eventName] = function (fn) { +4078 var events = this.events, +4079 l = events.length; +4080 while (l--) if (events[l].name == eventName && events[l].f == fn) { +4081 events[l].unbind(); +4082 events.splice(l, 1); +4083 !events.length && delete this.events; +4084 return this; +4085 } +4086 return this; +4087 }; +4088 })(events[i]); +4089 } +4090 /*\ +4091 * Element.hover +4092 [ method ] +4093 ** +4094 * Adds event handlers for hover for the element. +4095 > Parameters +4096 - f_in (function) handler for hover in +4097 - f_out (function) handler for hover out +4098 - icontext (object) #optional context for hover in handler +4099 - ocontext (object) #optional context for hover out handler +4100 = (object) @Element +4101 \*/ +4102 elproto.hover = function (f_in, f_out, scope_in, scope_out) { +4103 return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in); +4104 }; +4105 /*\ +4106 * Element.unhover +4107 [ method ] +4108 ** +4109 * Removes event handlers for hover for the element. +4110 > Parameters +4111 - f_in (function) handler for hover in +4112 - f_out (function) handler for hover out +4113 = (object) @Element +4114 \*/ +4115 elproto.unhover = function (f_in, f_out) { +4116 return this.unmouseover(f_in).unmouseout(f_out); +4117 }; +4118 /*\ +4119 * Element.drag +4120 [ method ] +4121 ** +4122 * Adds event handlers for drag of the element. +4123 > Parameters +4124 - onmove (function) handler for moving +4125 - onstart (function) handler for drag start +4126 - onend (function) handler for drag end +4127 - mcontext (object) #optional context for moving handler +4128 - scontext (object) #optional context for drag start handler +4129 - econtext (object) #optional context for drag end handler +4130 * Additionaly following `drag` events will be triggered: `drag.start.<id>` on start, +4131 * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element +4132 * `drag.over.<id>` will be fired as well. +4133 * +4134 * Start event and start handler will be called in specified context or in context of the element with following parameters: +4135 o x (number) x position of the mouse +4136 o y (number) y position of the mouse +4137 o event (object) DOM event object +4138 * Move event and move handler will be called in specified context or in context of the element with following parameters: +4139 o dx (number) shift by x from the start point +4140 o dy (number) shift by y from the start point +4141 o x (number) x position of the mouse +4142 o y (number) y position of the mouse +4143 o event (object) DOM event object +4144 * End event and end handler will be called in specified context or in context of the element with following parameters: +4145 o event (object) DOM event object +4146 = (object) @Element +4147 \*/ +4148 elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) { +4149 function start(e) { +4150 (e.originalEvent || e).preventDefault(); +4151 var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, +4152 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft; +4153 this._drag.x = e.clientX + scrollX; +4154 this._drag.y = e.clientY + scrollY; +4155 this._drag.id = e.identifier; +4156 !drag.length && R.mousemove(dragMove).mouseup(dragUp); +4157 drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope}); +4158 onstart && eve.on("drag.start." + this.id, onstart); +4159 onmove && eve.on("drag.move." + this.id, onmove); +4160 onend && eve.on("drag.end." + this.id, onend); +4161 eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e); +4162 } +4163 this._drag = {}; +4164 this.mousedown(start); +4165 return this; +4166 }; +4167 /*\ +4168 * Element.onDragOver +4169 [ method ] +4170 ** +4171 * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id). +4172 > Parameters +4173 - f (function) handler for event +4174 \*/ +4175 elproto.onDragOver = function (f) { +4176 f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id); +4177 }; +4178 /*\ +4179 * Element.undrag +4180 [ method ] +4181 ** +4182 * Removes all drag event handlers from given element. +4183 \*/ +4184 elproto.undrag = function () { +4185 var i = drag.length; +4186 while (i--) if (drag[i].el == this) { +4187 R.unmousedown(drag[i].start); +4188 drag.splice(i++, 1); +4189 eve.unbind("drag.*." + this.id); +4190 } +4191 !drag.length && R.unmousemove(dragMove).unmouseup(dragUp); +4192 }; +4193 /*\ +4194 * Paper.circle +4195 [ method ] +4196 ** +4197 * Draws a circle. +4198 ** +4199 > Parameters +4200 ** +4201 - x (number) x coordinate of the centre +4202 - y (number) y coordinate of the centre +4203 - r (number) radius +4204 = (object) Raphaël element object with type “circle” +4205 ** +4206 > Usage +4207 | var c = paper.circle(50, 50, 40); +4208 \*/ +4209 paperproto.circle = function (x, y, r) { +4210 return theCircle(this, x || 0, y || 0, r || 0); +4211 }; +4212 /*\ +4213 * Paper.rect +4214 [ method ] +4215 * +4216 * Draws a rectangle. +4217 ** +4218 > Parameters +4219 ** +4220 - x (number) x coordinate of the top left corner +4221 - y (number) y coordinate of the top left corner +4222 - width (number) width +4223 - height (number) height +4224 - r (number) #optional radius for rounded corners, default is 0 +4225 = (object) Raphaël element object with type “rect” +4226 ** +4227 > Usage +4228 | // regular rectangle +4229 | var c = paper.rect(10, 10, 50, 50); +4230 | // rectangle with rounded corners +4231 | var c = paper.rect(40, 40, 50, 50, 10); +4232 \*/ +4233 paperproto.rect = function (x, y, w, h, r) { +4234 return theRect(this, x || 0, y || 0, w || 0, h || 0, r || 0); +4235 }; +4236 /*\ +4237 * Paper.ellipse +4238 [ method ] +4239 ** +4240 * Draws an ellipse. +4241 ** +4242 > Parameters +4243 ** +4244 - x (number) x coordinate of the centre +4245 - y (number) y coordinate of the centre +4246 - rx (number) horizontal radius +4247 - ry (number) vertical radius +4248 = (object) Raphaël element object with type “ellipse” +4249 ** +4250 > Usage +4251 | var c = paper.ellipse(50, 50, 40, 20); +4252 \*/ +4253 paperproto.ellipse = function (x, y, rx, ry) { +4254 return theEllipse(this, x || 0, y || 0, rx || 0, ry || 0); +4255 }; +4256 /*\ +4257 * Paper.path +4258 [ method ] +4259 ** +4260 * Creates a path element by given path data string. +4261 ** +4262 > Parameters +4263 ** +4264 - pathString (string) path data in SVG path string format. +4265 = (object) Raphaël element object with type “ellipse” +4266 # Details of a path's data attribute's format are described in the <a href="http://www.w3.org/TR/SVG/paths.html#PathData">SVG specification</a>. +4267 ** +4268 > Usage +4269 | var c = paper.path("M10 10L90 90"); +4270 | // draw a diagonal line: +4271 | // move to 10,10, line to 90,90 +4272 \*/ +4273 paperproto.path = function (pathString) { +4274 pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E); +4275 return thePath(R.format[apply](R, arguments), this); +4276 }; +4277 /*\ +4278 * Paper.image +4279 [ method ] +4280 ** +4281 * Embeds an image into the surface. +4282 ** +4283 > Parameters +4284 ** +4285 - src (string) URI of the source image +4286 - x (number) x coordinate position +4287 - y (number) y coordinate position +4288 - width (number) width of the image +4289 - height (number) height of the image +4290 = (object) Raphaël element object with type “image” +4291 ** +4292 > Usage +4293 | var c = paper.image("apple.png", 10, 10, 80, 80); +4294 \*/ +4295 paperproto.image = function (src, x, y, w, h) { +4296 return theImage(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0); +4297 }; +4298 /*\ +4299 * Paper.text +4300 [ method ] +4301 ** +4302 * Draws a text string. If you need line breaks, put “\n” in the string. +4303 ** +4304 > Parameters +4305 ** +4306 - x (number) x coordinate position +4307 - y (number) y coordinate position +4308 - text (string) The text string to draw +4309 = (object) Raphaël element object with type “text” +4310 ** +4311 > Usage +4312 | var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!"); +4313 \*/ +4314 paperproto.text = function (x, y, text) { +4315 return theText(this, x || 0, y || 0, Str(text)); +4316 }; +4317 /*\ +4318 * Paper.set +4319 [ method ] +4320 ** +4321 * Creates array-like object to keep and operate several elements at once. +4322 * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements. +4323 * Sets act as pseudo elements — all methods available to an element can be used on a set. +4324 = (object) array-like object that represents set of elements +4325 ** +4326 > Usage +4327 | var st = paper.set(); +4328 | st.push( +4329 | paper.circle(10, 10, 5), +4330 | paper.circle(30, 10, 5) +4331 | ); +4332 | st.attr({fill: "red"}); +4333 \*/ +4334 paperproto.set = function (itemsArray) { +4335 arguments.length > 1 && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length)); +4336 return new Set(itemsArray); +4337 }; +4338 /*\ +4339 * Paper.setSize +4340 [ method ] +4341 ** +4342 * If you need to change dimensions of the canvas call this method 4343 ** -4344 * If you need to change dimensions of the canvas call this method +4344 > Parameters 4345 ** -4346 > Parameters -4347 ** -4348 - width (number) new width of the canvas -4349 - height (number) new height of the canvas -4350 > Usage -4351 | var st = paper.set(); -4352 | st.push( -4353 | paper.circle(10, 10, 5), -4354 | paper.circle(30, 10, 5) -4355 | ); -4356 | st.attr({fill: "red"}); -4357 \*/ -4358 paperproto.setSize = setSize; -4359 /*\ -4360 * Paper.setViewBox -4361 [ method ] -4362 ** -4363 * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by -4364 * specifying new boundaries. +4346 - width (number) new width of the canvas +4347 - height (number) new height of the canvas +4348 > Usage +4349 | var st = paper.set(); +4350 | st.push( +4351 | paper.circle(10, 10, 5), +4352 | paper.circle(30, 10, 5) +4353 | ); +4354 | st.attr({fill: "red"}); +4355 \*/ +4356 paperproto.setSize = setSize; +4357 /*\ +4358 * Paper.setViewBox +4359 [ method ] +4360 ** +4361 * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by +4362 * specifying new boundaries. +4363 ** +4364 > Parameters 4365 ** -4366 > Parameters -4367 ** -4368 x, y, w, h, fit -4369 - x (number) new x position, default is `0` -4370 - y (number) new y position, default is `0` -4371 - w (number) new width of the canvas -4372 - h (number) new height of the canvas -4373 - fit (boolean) `true` if you want graphics to fit into new boundary box -4374 \*/ -4375 paperproto.setViewBox = setViewBox; -4376 /*\ -4377 * Paper.top -4378 [ property ] -4379 ** -4380 * Points to the topmost element on the paper -4381 \*/ -4382 /*\ -4383 * Paper.bottom -4384 [ property ] -4385 ** -4386 * Points to the bottom element on the paper -4387 \*/ -4388 paperproto.top = paperproto.bottom = null; -4389 /*\ -4390 * Paper.raphael -4391 [ property ] -4392 ** -4393 * Points to the @Raphael object/function -4394 \*/ -4395 paperproto.raphael = R; -4396 var getOffset = function (elem) { -4397 var box = elem.getBoundingClientRect(), -4398 doc = elem.ownerDocument, -4399 body = doc.body, -4400 docElem = doc.documentElement, -4401 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, -4402 top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop, -4403 left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft; -4404 return { -4405 y: top, -4406 x: left -4407 }; -4408 }; -4409 /*\ -4410 * Paper.getElementByPoint -4411 [ method ] +4366 x, y, w, h, fit +4367 - x (number) new x position, default is `0` +4368 - y (number) new y position, default is `0` +4369 - w (number) new width of the canvas +4370 - h (number) new height of the canvas +4371 - fit (boolean) `true` if you want graphics to fit into new boundary box +4372 \*/ +4373 paperproto.setViewBox = setViewBox; +4374 /*\ +4375 * Paper.top +4376 [ property ] +4377 ** +4378 * Points to the topmost element on the paper +4379 \*/ +4380 /*\ +4381 * Paper.bottom +4382 [ property ] +4383 ** +4384 * Points to the bottom element on the paper +4385 \*/ +4386 paperproto.top = paperproto.bottom = null; +4387 /*\ +4388 * Paper.raphael +4389 [ property ] +4390 ** +4391 * Points to the @Raphael object/function +4392 \*/ +4393 paperproto.raphael = R; +4394 var getOffset = function (elem) { +4395 var box = elem.getBoundingClientRect(), +4396 doc = elem.ownerDocument, +4397 body = doc.body, +4398 docElem = doc.documentElement, +4399 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, +4400 top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop, +4401 left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft; +4402 return { +4403 y: top, +4404 x: left +4405 }; +4406 }; +4407 /*\ +4408 * Paper.getElementByPoint +4409 [ method ] +4410 ** +4411 * Returns you topmost element under given point. 4412 ** -4413 * Returns you topmost element under given point. -4414 ** -4415 = (object) Raphaël element object -4416 > Parameters -4417 ** -4418 - x (number) x coordinate from the top left corner of the window -4419 - y (number) y coordinate from the top left corner of the window -4420 > Usage -4421 | paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"}); -4422 \*/ -4423 paperproto.getElementByPoint = function (x, y) { -4424 var paper = this, -4425 svg = paper.canvas, -4426 target = g.doc.elementFromPoint(x, y); -4427 if (g.win.opera && target.tagName == "svg") { -4428 var so = getOffset(svg), -4429 sr = svg.createSVGRect(); -4430 sr.x = x - so.x; -4431 sr.y = y - so.y; -4432 sr.width = sr.height = 1; -4433 var hits = svg.getIntersectionList(sr, null); -4434 if (hits.length) { -4435 target = hits[hits.length - 1]; -4436 } -4437 } -4438 if (!target) { -4439 return null; -4440 } -4441 while (target.parentNode && target != svg.parentNode && !target.raphael) { -4442 target = target.parentNode; -4443 } -4444 target == paper.canvas.parentNode && (target = svg); -4445 target = target && target.raphael ? paper.getById(target.raphaelid) : null; -4446 return target; -4447 }; -4448 /*\ -4449 * Paper.getById -4450 [ method ] +4413 = (object) Raphaël element object +4414 > Parameters +4415 ** +4416 - x (number) x coordinate from the top left corner of the window +4417 - y (number) y coordinate from the top left corner of the window +4418 > Usage +4419 | paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"}); +4420 \*/ +4421 paperproto.getElementByPoint = function (x, y) { +4422 var paper = this, +4423 svg = paper.canvas, +4424 target = g.doc.elementFromPoint(x, y); +4425 if (g.win.opera && target.tagName == "svg") { +4426 var so = getOffset(svg), +4427 sr = svg.createSVGRect(); +4428 sr.x = x - so.x; +4429 sr.y = y - so.y; +4430 sr.width = sr.height = 1; +4431 var hits = svg.getIntersectionList(sr, null); +4432 if (hits.length) { +4433 target = hits[hits.length - 1]; +4434 } +4435 } +4436 if (!target) { +4437 return null; +4438 } +4439 while (target.parentNode && target != svg.parentNode && !target.raphael) { +4440 target = target.parentNode; +4441 } +4442 target == paper.canvas.parentNode && (target = svg); +4443 target = target && target.raphael ? paper.getById(target.raphaelid) : null; +4444 return target; +4445 }; +4446 /*\ +4447 * Paper.getById +4448 [ method ] +4449 ** +4450 * Returns you element by its internal ID. 4451 ** -4452 * Returns you element by it’s internal ID. +4452 > Parameters 4453 ** -4454 > Parameters -4455 ** -4456 - id (number) id -4457 = (object) Raphaël element object -4458 \*/ -4459 paperproto.getById = function (id) { -4460 var bot = this.bottom; -4461 while (bot) { -4462 if (bot.id == id) { -4463 return bot; -4464 } -4465 bot = bot.next; -4466 } -4467 return null; -4468 }; -4469 /*\ -4470 * Paper.forEach -4471 [ method ] -4472 ** -4473 * Executes given function for each element on the paper -4474 * -4475 * If function returns `false` it will stop loop running. +4454 - id (number) id +4455 = (object) Raphaël element object +4456 \*/ +4457 paperproto.getById = function (id) { +4458 var bot = this.bottom; +4459 while (bot) { +4460 if (bot.id == id) { +4461 return bot; +4462 } +4463 bot = bot.next; +4464 } +4465 return null; +4466 }; +4467 /*\ +4468 * Paper.forEach +4469 [ method ] +4470 ** +4471 * Executes given function for each element on the paper +4472 * +4473 * If callback function returns `false` it will stop loop running. +4474 ** +4475 > Parameters 4476 ** -4477 > Parameters -4478 ** -4479 - callback (function) function to run -4480 - thisArg (object) context object for the callback -4481 = (object) Paper object -4482 \*/ -4483 paperproto.forEach = function (callback, thisArg) { -4484 var bot = this.bottom; -4485 while (bot) { -4486 if (callback.call(thisArg, bot) === false) { -4487 return this; -4488 } -4489 bot = bot.next; -4490 } -4491 return this; -4492 }; -4493 function x_y() { -4494 return this.x + S + this.y; -4495 } -4496 function x_y_w_h() { -4497 return this.x + S + this.y + S + this.width + "\xd7" + this.height; -4498 } -4499 /*\ -4500 * Element.getBBox -4501 [ method ] +4477 - callback (function) function to run +4478 - thisArg (object) context object for the callback +4479 = (object) Paper object +4480 \*/ +4481 paperproto.forEach = function (callback, thisArg) { +4482 var bot = this.bottom; +4483 while (bot) { +4484 if (callback.call(thisArg, bot) === false) { +4485 return this; +4486 } +4487 bot = bot.next; +4488 } +4489 return this; +4490 }; +4491 function x_y() { +4492 return this.x + S + this.y; +4493 } +4494 function x_y_w_h() { +4495 return this.x + S + this.y + S + this.width + "\xd7" + this.height; +4496 } +4497 /*\ +4498 * Element.getBBox +4499 [ method ] +4500 ** +4501 * Return bounding box for a given element 4502 ** -4503 * Return bounding box for a given element +4503 > Parameters 4504 ** -4505 > Parameters -4506 ** -4507 - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`. -4508 = (object) Bounding box object: -4509 o { -4510 o x: (number) top left corner x -4511 o y: (number) top left corner y -4512 o width: (number) width -4513 o height: (number) height -4514 o } -4515 \*/ -4516 elproto.getBBox = function (isWithoutTransform) { -4517 if (this.removed) { -4518 return {}; -4519 } -4520 var _ = this._; -4521 if (isWithoutTransform) { -4522 if (_.dirty || !_.bboxwt) { -4523 this.realPath = getPath[this.type](this); -4524 _.bboxwt = pathDimensions(this.realPath); -4525 _.bboxwt.toString = x_y_w_h; -4526 _.dirty = 0; -4527 } -4528 return _.bboxwt; -4529 } -4530 if (_.dirty || _.dirtyT || !_.bbox) { -4531 if (_.dirty || !this.realPath) { -4532 _.bboxwt = 0; -4533 this.realPath = getPath[this.type](this); -4534 } -4535 _.bbox = pathDimensions(mapPath(this.realPath, this.matrix)); -4536 _.bbox.toString = x_y_w_h; -4537 _.dirty = _.dirtyT = 0; -4538 } -4539 return _.bbox; -4540 }; -4541 /*\ -4542 * Element.clone -4543 [ method ] +4505 - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`. +4506 = (object) Bounding box object: +4507 o { +4508 o x: (number) top left corner x +4509 o y: (number) top left corner y +4510 o width: (number) width +4511 o height: (number) height +4512 o } +4513 \*/ +4514 elproto.getBBox = function (isWithoutTransform) { +4515 if (this.removed) { +4516 return {}; +4517 } +4518 var _ = this._; +4519 if (isWithoutTransform) { +4520 if (_.dirty || !_.bboxwt) { +4521 this.realPath = getPath[this.type](this); +4522 _.bboxwt = pathDimensions(this.realPath); +4523 _.bboxwt.toString = x_y_w_h; +4524 _.dirty = 0; +4525 } +4526 return _.bboxwt; +4527 } +4528 if (_.dirty || _.dirtyT || !_.bbox) { +4529 if (_.dirty || !this.realPath) { +4530 _.bboxwt = 0; +4531 this.realPath = getPath[this.type](this); +4532 } +4533 _.bbox = pathDimensions(mapPath(this.realPath, this.matrix)); +4534 _.bbox.toString = x_y_w_h; +4535 _.dirty = _.dirtyT = 0; +4536 } +4537 return _.bbox; +4538 }; +4539 /*\ +4540 * Element.clone +4541 [ method ] +4542 ** +4543 = (object) clone of a given element 4544 ** -4545 = (object) clone of a given element -4546 ** -4547 \*/ -4548 elproto.clone = function () { -4549 if (this.removed) { -4550 return null; -4551 } -4552 var attr = this.attr(); -4553 delete attr.scale; -4554 delete attr.translation; -4555 return this.paper[this.type]().attr(attr); -4556 }; -4557 /*\ -4558 * Element.glow -4559 [ method ] -4560 ** -4561 * Return set of elements that create glow-like effect around given element. See @Paper.set. -4562 * -4563 * Note: Glow is not connected to the elment. If you change element attributes it won’t adjust itself. -4564 ** -4565 = (object) @Paper.set of elements that represents glow -4566 \*/ -4567 elproto.glow = function (glow) { -4568 if (this.type == "text") { -4569 return null; -4570 } -4571 glow = glow || {}; -4572 var s = { -4573 width: glow.width || 10, -4574 fill: glow.fill || false, -4575 opacity: glow.opacity || .5, -4576 offsetx: glow.offsetx || 0, -4577 offsety: glow.offsety || 0, -4578 color: glow.color || "#000" -4579 }, -4580 c = s.width / 2, -4581 r = this.paper, -4582 out = r.set(), -4583 path = this.realPath || getPath[this.type](this); -4584 path = this.matrix ? mapPath(path, this.matrix) : path; -4585 for (var i = 1; i < c + 1; i++) { -4586 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)})); -4587 } -4588 return out.insertBefore(this).translate(s.offsetx, s.offsety); -4589 }; -4590 var curveslengths = {}, -4591 getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { -4592 var len = 0, -4593 precision = 100, -4594 name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(), -4595 cache = curveslengths[name], -4596 old, dot; -4597 !cache && (curveslengths[name] = cache = {data: []}); -4598 cache.timer && clearTimeout(cache.timer); -4599 cache.timer = setTimeout(function () {delete curveslengths[name];}, 2e3); -4600 if (length != null && !cache.precision) { -4601 var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y); -4602 cache.precision = ~~total * 10; -4603 cache.data = []; -4604 } -4605 precision = cache.precision || precision; -4606 for (var i = 0; i < precision + 1; i++) { -4607 if (cache.data[i * precision]) { -4608 dot = cache.data[i * precision]; -4609 } else { -4610 dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision); -4611 cache.data[i * precision] = dot; -4612 } -4613 i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5)); -4614 if (length != null && len >= length) { -4615 return dot; -4616 } -4617 old = dot; -4618 } -4619 if (length == null) { -4620 return len; -4621 } -4622 }, -4623 getLengthFactory = function (istotal, subpath) { -4624 return function (path, length, onlystart) { -4625 path = path2curve(path); -4626 var x, y, p, l, sp = "", subpaths = {}, point, -4627 len = 0; -4628 for (var i = 0, ii = path.length; i < ii; i++) { -4629 p = path[i]; -4630 if (p[0] == "M") { -4631 x = +p[1]; -4632 y = +p[2]; -4633 } else { -4634 l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); -4635 if (len + l > length) { -4636 if (subpath && !subpaths.start) { -4637 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); -4638 sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y]; -4639 if (onlystart) {return sp;} -4640 subpaths.start = sp; -4641 sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join(); -4642 len += l; -4643 x = +p[5]; -4644 y = +p[6]; -4645 continue; -4646 } -4647 if (!istotal && !subpath) { -4648 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); -4649 return {x: point.x, y: point.y, alpha: point.alpha}; -4650 } -4651 } -4652 len += l; -4653 x = +p[5]; -4654 y = +p[6]; -4655 } -4656 sp += p.shift() + p; -4657 } -4658 subpaths.end = sp; -4659 point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], 1); -4660 point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha}); -4661 return point; -4662 }; -4663 }; -4664 var getTotalLength = getLengthFactory(1), -4665 getPointAtLength = getLengthFactory(), -4666 getSubpathsAtLength = getLengthFactory(0, 1); -4667 /*\ -4668 * Raphael.getTotalLength -4669 [ method ] +4545 \*/ +4546 elproto.clone = function () { +4547 if (this.removed) { +4548 return null; +4549 } +4550 var attr = this.attr(); +4551 delete attr.scale; +4552 delete attr.translation; +4553 return this.paper[this.type]().attr(attr); +4554 }; +4555 /*\ +4556 * Element.glow +4557 [ method ] +4558 ** +4559 * Return set of elements that create glow-like effect around given element. See @Paper.set. +4560 * +4561 * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself. +4562 ** +4563 = (object) @Paper.set of elements that represents glow +4564 \*/ +4565 elproto.glow = function (glow) { +4566 if (this.type == "text") { +4567 return null; +4568 } +4569 glow = glow || {}; +4570 var s = { +4571 width: glow.width || 10, +4572 fill: glow.fill || false, +4573 opacity: glow.opacity || .5, +4574 offsetx: glow.offsetx || 0, +4575 offsety: glow.offsety || 0, +4576 color: glow.color || "#000" +4577 }, +4578 c = s.width / 2, +4579 r = this.paper, +4580 out = r.set(), +4581 path = this.realPath || getPath[this.type](this); +4582 path = this.matrix ? mapPath(path, this.matrix) : path; +4583 for (var i = 1; i < c + 1; i++) { +4584 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)})); +4585 } +4586 return out.insertBefore(this).translate(s.offsetx, s.offsety); +4587 }; +4588 var curveslengths = {}, +4589 getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { +4590 var len = 0, +4591 precision = 100, +4592 name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(), +4593 cache = curveslengths[name], +4594 old, dot; +4595 !cache && (curveslengths[name] = cache = {data: []}); +4596 cache.timer && clearTimeout(cache.timer); +4597 cache.timer = setTimeout(function () {delete curveslengths[name];}, 2e3); +4598 if (length != null && !cache.precision) { +4599 var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y); +4600 cache.precision = ~~total * 10; +4601 cache.data = []; +4602 } +4603 precision = cache.precision || precision; +4604 for (var i = 0; i < precision + 1; i++) { +4605 if (cache.data[i * precision]) { +4606 dot = cache.data[i * precision]; +4607 } else { +4608 dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision); +4609 cache.data[i * precision] = dot; +4610 } +4611 i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5)); +4612 if (length != null && len >= length) { +4613 return dot; +4614 } +4615 old = dot; +4616 } +4617 if (length == null) { +4618 return len; +4619 } +4620 }, +4621 getLengthFactory = function (istotal, subpath) { +4622 return function (path, length, onlystart) { +4623 path = path2curve(path); +4624 var x, y, p, l, sp = "", subpaths = {}, point, +4625 len = 0; +4626 for (var i = 0, ii = path.length; i < ii; i++) { +4627 p = path[i]; +4628 if (p[0] == "M") { +4629 x = +p[1]; +4630 y = +p[2]; +4631 } else { +4632 l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); +4633 if (len + l > length) { +4634 if (subpath && !subpaths.start) { +4635 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); +4636 sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y]; +4637 if (onlystart) {return sp;} +4638 subpaths.start = sp; +4639 sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join(); +4640 len += l; +4641 x = +p[5]; +4642 y = +p[6]; +4643 continue; +4644 } +4645 if (!istotal && !subpath) { +4646 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); +4647 return {x: point.x, y: point.y, alpha: point.alpha}; +4648 } +4649 } +4650 len += l; +4651 x = +p[5]; +4652 y = +p[6]; +4653 } +4654 sp += p.shift() + p; +4655 } +4656 subpaths.end = sp; +4657 point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], 1); +4658 point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha}); +4659 return point; +4660 }; +4661 }; +4662 var getTotalLength = getLengthFactory(1), +4663 getPointAtLength = getLengthFactory(), +4664 getSubpathsAtLength = getLengthFactory(0, 1); +4665 /*\ +4666 * Raphael.getTotalLength +4667 [ method ] +4668 ** +4669 * Returns length of the given path in pixels. 4670 ** -4671 * Returns length of the given path in pixels. +4671 > Parameters 4672 ** -4673 > Parameters +4673 - path (string) SVG path string. 4674 ** -4675 - path (string) SVG path string. -4676 ** -4677 = (number) length. -4678 \*/ -4679 R.getTotalLength = getTotalLength; -4680 /*\ -4681 * Raphael.getPointAtLength -4682 [ method ] +4675 = (number) length. +4676 \*/ +4677 R.getTotalLength = getTotalLength; +4678 /*\ +4679 * Raphael.getPointAtLength +4680 [ method ] +4681 ** +4682 * Return coordinates of the point located at the given length on the given path. 4683 ** -4684 * Return coordinates of the point located at the given length on the given path. +4684 > Parameters 4685 ** -4686 > Parameters -4687 ** -4688 - path (string) SVG path string -4689 - length (number) -4690 ** -4691 = (object) representation of the point: -4692 o { -4693 o x: (number) x coordinate -4694 o y: (number) y coordinate -4695 o alpha: (number) angle of derivative -4696 o } -4697 \*/ -4698 R.getPointAtLength = getPointAtLength; -4699 /*\ -4700 * Raphael.getSubpath -4701 [ method ] +4686 - path (string) SVG path string +4687 - length (number) +4688 ** +4689 = (object) representation of the point: +4690 o { +4691 o x: (number) x coordinate +4692 o y: (number) y coordinate +4693 o alpha: (number) angle of derivative +4694 o } +4695 \*/ +4696 R.getPointAtLength = getPointAtLength; +4697 /*\ +4698 * Raphael.getSubpath +4699 [ method ] +4700 ** +4701 * Return subpath of a given path from given length to given length. 4702 ** -4703 * Return subpath of a given path from given length to given length. +4703 > Parameters 4704 ** -4705 > Parameters -4706 ** -4707 - path (string) SVG path string -4708 - from (number) position of the start of the segment -4709 - to (number) position of the end of the segment -4710 ** -4711 = (string) pathstring for the segment -4712 \*/ -4713 R.getSubpath = function (path, from, to) { -4714 if (abs(this.getTotalLength(path) - to) < 1e-6) { -4715 return getSubpathsAtLength(path, from).end; -4716 } -4717 var a = getSubpathsAtLength(path, to, 1); -4718 return from ? getSubpathsAtLength(a, from).end : a; -4719 }; -4720 /*\ -4721 * Element.getTotalLength -4722 [ method ] -4723 ** -4724 * Returns length of the path in pixels. Only works for element of “path” type. -4725 = (number) length. -4726 \*/ -4727 elproto.getTotalLength = function () { -4728 if (this.type != "path") {return;} -4729 if (this.node.getTotalLength) { -4730 return this.node.getTotalLength(); -4731 } -4732 return getTotalLength(this.attrs.path); -4733 }; -4734 /*\ -4735 * Element.getPointAtLength -4736 [ method ] +4705 - path (string) SVG path string +4706 - from (number) position of the start of the segment +4707 - to (number) position of the end of the segment +4708 ** +4709 = (string) pathstring for the segment +4710 \*/ +4711 R.getSubpath = function (path, from, to) { +4712 if (abs(this.getTotalLength(path) - to) < 1e-6) { +4713 return getSubpathsAtLength(path, from).end; +4714 } +4715 var a = getSubpathsAtLength(path, to, 1); +4716 return from ? getSubpathsAtLength(a, from).end : a; +4717 }; +4718 /*\ +4719 * Element.getTotalLength +4720 [ method ] +4721 ** +4722 * Returns length of the path in pixels. Only works for element of “path” type. +4723 = (number) length. +4724 \*/ +4725 elproto.getTotalLength = function () { +4726 if (this.type != "path") {return;} +4727 if (this.node.getTotalLength) { +4728 return this.node.getTotalLength(); +4729 } +4730 return getTotalLength(this.attrs.path); +4731 }; +4732 /*\ +4733 * Element.getPointAtLength +4734 [ method ] +4735 ** +4736 * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type. 4737 ** -4738 * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type. +4738 > Parameters 4739 ** -4740 > Parameters +4740 - length (number) 4741 ** -4742 - length (number) -4743 ** -4744 = (object) representation of the point: -4745 o { -4746 o x: (number) x coordinate -4747 o y: (number) y coordinate -4748 o alpha: (number) angle of derivative -4749 o } -4750 \*/ -4751 elproto.getPointAtLength = function (length) { -4752 if (this.type != "path") {return;} -4753 return getPointAtLength(this.attrs.path, length); -4754 }; -4755 /*\ -4756 * Element.getSubpath -4757 [ method ] +4742 = (object) representation of the point: +4743 o { +4744 o x: (number) x coordinate +4745 o y: (number) y coordinate +4746 o alpha: (number) angle of derivative +4747 o } +4748 \*/ +4749 elproto.getPointAtLength = function (length) { +4750 if (this.type != "path") {return;} +4751 return getPointAtLength(this.attrs.path, length); +4752 }; +4753 /*\ +4754 * Element.getSubpath +4755 [ method ] +4756 ** +4757 * Return subpath of a given element from given length to given length. Only works for element of “path” type. 4758 ** -4759 * Return subpath of a given element from given length to given length. Only works for element of “path” type. +4759 > Parameters 4760 ** -4761 > Parameters -4762 ** -4763 - from (number) position of the start of the segment -4764 - to (number) position of the end of the segment -4765 ** -4766 = (string) pathstring for the segment -4767 \*/ -4768 elproto.getSubpath = function (from, to) { -4769 if (this.type != "path") {return;} -4770 return R.getSubpath(this.attrs.path, from, to); -4771 }; -4772 /*\ -4773 * Raphael.easing_formulas -4774 [ property ] -4775 ** -4776 * Object that contains easing formulas for animation. You could extend it with your owns. By default it has following list of easing: -4777 # <ul> -4778 # <li>“linear”</li> -4779 # <li>“<” or “easeIn” or “ease-in”</li> -4780 # <li>“>” or “easeOut” or “ease-out”</li> -4781 # <li>“<>” or “easeInOut” or “ease-in-out”</li> -4782 # <li>“backIn” or “back-in”</li> -4783 # <li>“backOut” or “back-out”</li> -4784 # <li>“elastic”</li> -4785 # <li>“bounce”</li> -4786 # </ul> -4787 # <p>See also <a href="http://raphaeljs.com/easing.html">Easing demo</a>.</p> -4788 \*/ -4789 var ef = R.easing_formulas = { -4790 linear: function (n) { -4791 return n; -4792 }, -4793 "<": function (n) { -4794 return pow(n, 1.7); -4795 }, -4796 ">": function (n) { -4797 return pow(n, .48); -4798 }, -4799 "<>": function (n) { -4800 var q = .48 - n / 1.04, -4801 Q = math.sqrt(.1734 + q * q), -4802 x = Q - q, -4803 X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1), -4804 y = -Q - q, -4805 Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1), -4806 t = X + Y + .5; -4807 return (1 - t) * 3 * t * t + t * t * t; -4808 }, -4809 backIn: function (n) { -4810 var s = 1.70158; -4811 return n * n * ((s + 1) * n - s); -4812 }, -4813 backOut: function (n) { -4814 n = n - 1; -4815 var s = 1.70158; -4816 return n * n * ((s + 1) * n + s) + 1; -4817 }, -4818 elastic: function (n) { -4819 if (n == !!n) { -4820 return n; -4821 } -4822 return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1; -4823 }, -4824 bounce: function (n) { -4825 var s = 7.5625, -4826 p = 2.75, -4827 l; -4828 if (n < (1 / p)) { -4829 l = s * n * n; -4830 } else { -4831 if (n < (2 / p)) { -4832 n -= (1.5 / p); -4833 l = s * n * n + .75; -4834 } else { -4835 if (n < (2.5 / p)) { -4836 n -= (2.25 / p); -4837 l = s * n * n + .9375; -4838 } else { -4839 n -= (2.625 / p); -4840 l = s * n * n + .984375; -4841 } -4842 } -4843 } -4844 return l; -4845 } -4846 }; -4847 ef.easeIn = ef["ease-in"] = ef["<"]; -4848 ef.easeOut = ef["ease-out"] = ef[">"]; -4849 ef.easeInOut = ef["ease-in-out"] = ef["<>"]; -4850 ef["back-in"] = ef.backIn; -4851 ef["back-out"] = ef.backOut; -4852 -4853 var animationElements = [], -4854 requestAnimFrame = window.requestAnimationFrame || -4855 window.webkitRequestAnimationFrame || -4856 window.mozRequestAnimationFrame || -4857 window.oRequestAnimationFrame || -4858 window.msRequestAnimationFrame || -4859 function (callback) { -4860 setTimeout(callback, 16); -4861 }, -4862 animation = function () { -4863 var Now = +new Date, -4864 l = 0; -4865 for (; l < animationElements.length; l++) { -4866 var e = animationElements[l]; -4867 if (e.el.removed || e.paused) { -4868 continue; -4869 } -4870 var time = Now - e.start, -4871 ms = e.ms, -4872 easing = e.easing, -4873 from = e.from, -4874 diff = e.diff, -4875 to = e.to, -4876 t = e.t, -4877 that = e.el, -4878 set = {}, -4879 now; -4880 if (e.initstatus) { -4881 time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms; -4882 e.status = e.initstatus; -4883 delete e.initstatus; -4884 e.stop && animationElements.splice(l--, 1); -4885 } else { -4886 e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top; -4887 } -4888 if (time < 0) { -4889 continue; -4890 } -4891 if (time < ms) { -4892 var pos = easing(time / ms); -4893 for (var attr in from) if (from[has](attr)) { -4894 switch (availableAnimAttrs[attr]) { -4895 case nu: -4896 now = +from[attr] + pos * ms * diff[attr]; -4897 break; -4898 case "colour": -4899 now = "rgb(" + [ -4900 upto255(round(from[attr].r + pos * ms * diff[attr].r)), -4901 upto255(round(from[attr].g + pos * ms * diff[attr].g)), -4902 upto255(round(from[attr].b + pos * ms * diff[attr].b)) -4903 ].join(",") + ")"; -4904 break; -4905 case "path": -4906 now = []; -4907 for (var i = 0, ii = from[attr].length; i < ii; i++) { -4908 now[i] = [from[attr][i][0]]; -4909 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { -4910 now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j]; -4911 } -4912 now[i] = now[i].join(S); -4913 } -4914 now = now.join(S); -4915 break; -4916 case "transform": -4917 if (diff[attr].real) { -4918 now = []; -4919 for (i = 0, ii = from[attr].length; i < ii; i++) { -4920 now[i] = [from[attr][i][0]]; -4921 for (j = 1, jj = from[attr][i].length; j < jj; j++) { -4922 now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j]; -4923 } -4924 } -4925 } else { -4926 var get = function (i) { -4927 return +from[attr][i] + pos * ms * diff[attr][i]; -4928 }; -4929 // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]]; -4930 now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]]; -4931 } -4932 break; -4933 case "csv": -4934 if (attr == "clip-rect") { -4935 now = []; -4936 i = 4; -4937 while (i--) { -4938 now[i] = +from[attr][i] + pos * ms * diff[attr][i]; -4939 } -4940 } -4941 break; -4942 default: -4943 var from2 = [].concat(from[attr]); -4944 now = []; -4945 i = that.paper.customAttributes[attr].length; -4946 while (i--) { -4947 now[i] = +from2[i] + pos * ms * diff[attr][i]; -4948 } -4949 break; -4950 } -4951 set[attr] = now; -4952 } -4953 that.attr(set); -4954 (function (id, that, anim) { -4955 setTimeout(function () { -4956 eve("anim.frame." + id, that, anim); -4957 }); -4958 })(that.id, that, e.anim); -4959 } else { -4960 (function(f, el, a) { -4961 setTimeout(function() { -4962 eve("anim.finish." + el.id, el, a); -4963 R.is(f, "function") && f.call(el); -4964 }); -4965 })(e.callback, that, e.anim); -4966 if (--e.repeat) { -4967 that.attr(e.origin); -4968 e.start = Now; -4969 } else { -4970 that.attr(to); -4971 animationElements.splice(l--, 1); -4972 } -4973 if (e.next && !e.stop) { -4974 runAnimation(e.anim, e.el, e.next, null, e.totalOrigin); -4975 } -4976 } -4977 } -4978 R.svg && that && that.paper && that.paper.safari(); -4979 animationElements.length && requestAnimFrame(animation); -4980 }, -4981 upto255 = function (color) { -4982 return mmax(mmin(color, 255), 0); -4983 }; -4984 /*\ -4985 * Element.animateWith -4986 [ method ] +4761 - from (number) position of the start of the segment +4762 - to (number) position of the end of the segment +4763 ** +4764 = (string) pathstring for the segment +4765 \*/ +4766 elproto.getSubpath = function (from, to) { +4767 if (this.type != "path") {return;} +4768 return R.getSubpath(this.attrs.path, from, to); +4769 }; +4770 /*\ +4771 * Raphael.easing_formulas +4772 [ property ] +4773 ** +4774 * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing: +4775 # <ul> +4776 # <li>“linear”</li> +4777 # <li>“<” or “easeIn” or “ease-in”</li> +4778 # <li>“>” or “easeOut” or “ease-out”</li> +4779 # <li>“<>” or “easeInOut” or “ease-in-out”</li> +4780 # <li>“backIn” or “back-in”</li> +4781 # <li>“backOut” or “back-out”</li> +4782 # <li>“elastic”</li> +4783 # <li>“bounce”</li> +4784 # </ul> +4785 # <p>See also <a href="http://raphaeljs.com/easing.html">Easing demo</a>.</p> +4786 \*/ +4787 var ef = R.easing_formulas = { +4788 linear: function (n) { +4789 return n; +4790 }, +4791 "<": function (n) { +4792 return pow(n, 1.7); +4793 }, +4794 ">": function (n) { +4795 return pow(n, .48); +4796 }, +4797 "<>": function (n) { +4798 var q = .48 - n / 1.04, +4799 Q = math.sqrt(.1734 + q * q), +4800 x = Q - q, +4801 X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1), +4802 y = -Q - q, +4803 Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1), +4804 t = X + Y + .5; +4805 return (1 - t) * 3 * t * t + t * t * t; +4806 }, +4807 backIn: function (n) { +4808 var s = 1.70158; +4809 return n * n * ((s + 1) * n - s); +4810 }, +4811 backOut: function (n) { +4812 n = n - 1; +4813 var s = 1.70158; +4814 return n * n * ((s + 1) * n + s) + 1; +4815 }, +4816 elastic: function (n) { +4817 if (n == !!n) { +4818 return n; +4819 } +4820 return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1; +4821 }, +4822 bounce: function (n) { +4823 var s = 7.5625, +4824 p = 2.75, +4825 l; +4826 if (n < (1 / p)) { +4827 l = s * n * n; +4828 } else { +4829 if (n < (2 / p)) { +4830 n -= (1.5 / p); +4831 l = s * n * n + .75; +4832 } else { +4833 if (n < (2.5 / p)) { +4834 n -= (2.25 / p); +4835 l = s * n * n + .9375; +4836 } else { +4837 n -= (2.625 / p); +4838 l = s * n * n + .984375; +4839 } +4840 } +4841 } +4842 return l; +4843 } +4844 }; +4845 ef.easeIn = ef["ease-in"] = ef["<"]; +4846 ef.easeOut = ef["ease-out"] = ef[">"]; +4847 ef.easeInOut = ef["ease-in-out"] = ef["<>"]; +4848 ef["back-in"] = ef.backIn; +4849 ef["back-out"] = ef.backOut; +4850 +4851 var animationElements = [], +4852 requestAnimFrame = window.requestAnimationFrame || +4853 window.webkitRequestAnimationFrame || +4854 window.mozRequestAnimationFrame || +4855 window.oRequestAnimationFrame || +4856 window.msRequestAnimationFrame || +4857 function (callback) { +4858 setTimeout(callback, 16); +4859 }, +4860 animation = function () { +4861 var Now = +new Date, +4862 l = 0; +4863 for (; l < animationElements.length; l++) { +4864 var e = animationElements[l]; +4865 if (e.el.removed || e.paused) { +4866 continue; +4867 } +4868 var time = Now - e.start, +4869 ms = e.ms, +4870 easing = e.easing, +4871 from = e.from, +4872 diff = e.diff, +4873 to = e.to, +4874 t = e.t, +4875 that = e.el, +4876 set = {}, +4877 now; +4878 if (e.initstatus) { +4879 time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms; +4880 e.status = e.initstatus; +4881 delete e.initstatus; +4882 e.stop && animationElements.splice(l--, 1); +4883 } else { +4884 e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top; +4885 } +4886 if (time < 0) { +4887 continue; +4888 } +4889 if (time < ms) { +4890 var pos = easing(time / ms); +4891 for (var attr in from) if (from[has](attr)) { +4892 switch (availableAnimAttrs[attr]) { +4893 case nu: +4894 now = +from[attr] + pos * ms * diff[attr]; +4895 break; +4896 case "colour": +4897 now = "rgb(" + [ +4898 upto255(round(from[attr].r + pos * ms * diff[attr].r)), +4899 upto255(round(from[attr].g + pos * ms * diff[attr].g)), +4900 upto255(round(from[attr].b + pos * ms * diff[attr].b)) +4901 ].join(",") + ")"; +4902 break; +4903 case "path": +4904 now = []; +4905 for (var i = 0, ii = from[attr].length; i < ii; i++) { +4906 now[i] = [from[attr][i][0]]; +4907 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { +4908 now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j]; +4909 } +4910 now[i] = now[i].join(S); +4911 } +4912 now = now.join(S); +4913 break; +4914 case "transform": +4915 if (diff[attr].real) { +4916 now = []; +4917 for (i = 0, ii = from[attr].length; i < ii; i++) { +4918 now[i] = [from[attr][i][0]]; +4919 for (j = 1, jj = from[attr][i].length; j < jj; j++) { +4920 now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j]; +4921 } +4922 } +4923 } else { +4924 var get = function (i) { +4925 return +from[attr][i] + pos * ms * diff[attr][i]; +4926 }; +4927 // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]]; +4928 now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]]; +4929 } +4930 break; +4931 case "csv": +4932 if (attr == "clip-rect") { +4933 now = []; +4934 i = 4; +4935 while (i--) { +4936 now[i] = +from[attr][i] + pos * ms * diff[attr][i]; +4937 } +4938 } +4939 break; +4940 default: +4941 var from2 = [].concat(from[attr]); +4942 now = []; +4943 i = that.paper.customAttributes[attr].length; +4944 while (i--) { +4945 now[i] = +from2[i] + pos * ms * diff[attr][i]; +4946 } +4947 break; +4948 } +4949 set[attr] = now; +4950 } +4951 that.attr(set); +4952 (function (id, that, anim) { +4953 setTimeout(function () { +4954 eve("anim.frame." + id, that, anim); +4955 }); +4956 })(that.id, that, e.anim); +4957 } else { +4958 (function(f, el, a) { +4959 setTimeout(function() { +4960 eve("anim.finish." + el.id, el, a); +4961 R.is(f, "function") && f.call(el); +4962 }); +4963 })(e.callback, that, e.anim); +4964 if (--e.repeat) { +4965 that.attr(e.origin); +4966 e.start = Now; +4967 } else { +4968 that.attr(to); +4969 animationElements.splice(l--, 1); +4970 } +4971 if (e.next && !e.stop) { +4972 runAnimation(e.anim, e.el, e.next, null, e.totalOrigin); +4973 } +4974 } +4975 } +4976 R.svg && that && that.paper && that.paper.safari(); +4977 animationElements.length && requestAnimFrame(animation); +4978 }, +4979 upto255 = function (color) { +4980 return mmax(mmin(color, 255), 0); +4981 }; +4982 /*\ +4983 * Element.animateWith +4984 [ method ] +4985 ** +4986 * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element. 4987 ** -4988 * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element. +4988 > Parameters 4989 ** -4990 > Parameters -4991 ** -4992 - params (object) final attributes for the element, see also @Element.attr -4993 - ms (number) number of milliseconds for animation to run -4994 - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` -4995 - callback (function) #optional callback function. Will be called at the end of animation. -4996 * or -4997 - animation (object) animation object, see @Raphael.animation -4998 ** -4999 = (object) original element -5000 \*/ -5001 elproto.animateWith = function (element, params, ms, easing, callback) { -5002 for (var i = 0, ii = animationElements.length; i < ii; i++) { -5003 if (animationElements[i].el.id == element.id) { -5004 params.start = animationElements[i].timestamp; -5005 break; -5006 } -5007 } -5008 return this.animate(params, ms, easing, callback); -5009 }; -5010 function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) { -5011 var cx = 3 * p1x, -5012 bx = 3 * (p2x - p1x) - cx, -5013 ax = 1 - cx - bx, -5014 cy = 3 * p1y, -5015 by = 3 * (p2y - p1y) - cy, -5016 ay = 1 - cy - by; -5017 function sampleCurveX(t) { -5018 return ((ax * t + bx) * t + cx) * t; -5019 } -5020 function solve(x, epsilon) { -5021 var t = solveCurveX(x, epsilon); -5022 return ((ay * t + by) * t + cy) * t; -5023 } -5024 function solveCurveX(x, epsilon) { -5025 var t0, t1, t2, x2, d2, i; -5026 for(t2 = x, i = 0; i < 8; i++) { -5027 x2 = sampleCurveX(t2) - x; -5028 if (abs(x2) < epsilon) { -5029 return t2; -5030 } -5031 d2 = (3 * ax * t2 + 2 * bx) * t2 + cx; -5032 if (abs(d2) < 1e-6) { -5033 break; -5034 } -5035 t2 = t2 - x2 / d2; -5036 } -5037 t0 = 0; -5038 t1 = 1; -5039 t2 = x; -5040 if (t2 < t0) { -5041 return t0; -5042 } -5043 if (t2 > t1) { -5044 return t1; -5045 } -5046 while (t0 < t1) { -5047 x2 = sampleCurveX(t2); -5048 if (abs(x2 - x) < epsilon) { -5049 return t2; -5050 } -5051 if (x > x2) { -5052 t0 = t2; -5053 } else { -5054 t1 = t2; -5055 } -5056 t2 = (t1 - t0) / 2 + t0; -5057 } -5058 return t2; -5059 } -5060 return solve(t, 1 / (200 * duration)); -5061 } -5062 elproto.onAnimation = function (f) { -5063 f ? eve.on("anim.frame." + this.id, f) : eve.unbind("anim.frame." + this.id); -5064 return this; -5065 }; -5066 function Animation(anim, ms) { -5067 var percents = []; -5068 this.anim = anim; -5069 this.ms = ms; -5070 this.times = 1; -5071 if (this.anim) { -5072 for (var attr in this.anim) if (this.anim[has](attr)) { -5073 percents.push(+attr); -5074 } -5075 percents.sort(sortByNumber); -5076 } -5077 this.top = percents[percents.length - 1]; -5078 this.percents = percents; -5079 } -5080 /*\ -5081 * Animation.delay -5082 [ method ] +4990 - params (object) final attributes for the element, see also @Element.attr +4991 - ms (number) number of milliseconds for animation to run +4992 - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` +4993 - callback (function) #optional callback function. Will be called at the end of animation. +4994 * or +4995 - animation (object) animation object, see @Raphael.animation +4996 ** +4997 = (object) original element +4998 \*/ +4999 elproto.animateWith = function (element, params, ms, easing, callback) { +5000 for (var i = 0, ii = animationElements.length; i < ii; i++) { +5001 if (animationElements[i].el.id == element.id) { +5002 params.start = animationElements[i].timestamp; +5003 break; +5004 } +5005 } +5006 return this.animate(params, ms, easing, callback); +5007 }; +5008 function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) { +5009 var cx = 3 * p1x, +5010 bx = 3 * (p2x - p1x) - cx, +5011 ax = 1 - cx - bx, +5012 cy = 3 * p1y, +5013 by = 3 * (p2y - p1y) - cy, +5014 ay = 1 - cy - by; +5015 function sampleCurveX(t) { +5016 return ((ax * t + bx) * t + cx) * t; +5017 } +5018 function solve(x, epsilon) { +5019 var t = solveCurveX(x, epsilon); +5020 return ((ay * t + by) * t + cy) * t; +5021 } +5022 function solveCurveX(x, epsilon) { +5023 var t0, t1, t2, x2, d2, i; +5024 for(t2 = x, i = 0; i < 8; i++) { +5025 x2 = sampleCurveX(t2) - x; +5026 if (abs(x2) < epsilon) { +5027 return t2; +5028 } +5029 d2 = (3 * ax * t2 + 2 * bx) * t2 + cx; +5030 if (abs(d2) < 1e-6) { +5031 break; +5032 } +5033 t2 = t2 - x2 / d2; +5034 } +5035 t0 = 0; +5036 t1 = 1; +5037 t2 = x; +5038 if (t2 < t0) { +5039 return t0; +5040 } +5041 if (t2 > t1) { +5042 return t1; +5043 } +5044 while (t0 < t1) { +5045 x2 = sampleCurveX(t2); +5046 if (abs(x2 - x) < epsilon) { +5047 return t2; +5048 } +5049 if (x > x2) { +5050 t0 = t2; +5051 } else { +5052 t1 = t2; +5053 } +5054 t2 = (t1 - t0) / 2 + t0; +5055 } +5056 return t2; +5057 } +5058 return solve(t, 1 / (200 * duration)); +5059 } +5060 elproto.onAnimation = function (f) { +5061 f ? eve.on("anim.frame." + this.id, f) : eve.unbind("anim.frame." + this.id); +5062 return this; +5063 }; +5064 function Animation(anim, ms) { +5065 var percents = []; +5066 this.anim = anim; +5067 this.ms = ms; +5068 this.times = 1; +5069 if (this.anim) { +5070 for (var attr in this.anim) if (this.anim[has](attr)) { +5071 percents.push(+attr); +5072 } +5073 percents.sort(sortByNumber); +5074 } +5075 this.top = percents[percents.length - 1]; +5076 this.percents = percents; +5077 } +5078 /*\ +5079 * Animation.delay +5080 [ method ] +5081 ** +5082 * Creates a copy of existing animation object with given delay. 5083 ** -5084 * Creates copy of existing animation object with given delay. +5084 > Parameters 5085 ** -5086 > Parameters +5086 - delay (number) number of ms to pass between animation start and actual animation 5087 ** -5088 - delay (number) number of ms to pass between animation start and actual animation -5089 ** -5090 = (object) new altered Animation object -5091 \*/ -5092 Animation.prototype.delay = function (delay) { -5093 var a = new Animation(this.anim, this.ms); -5094 a.times = this.times; -5095 a.del = +delay || 0; -5096 return a; -5097 }; -5098 /*\ -5099 * Animation.repeat -5100 [ method ] +5088 = (object) new altered Animation object +5089 \*/ +5090 Animation.prototype.delay = function (delay) { +5091 var a = new Animation(this.anim, this.ms); +5092 a.times = this.times; +5093 a.del = +delay || 0; +5094 return a; +5095 }; +5096 /*\ +5097 * Animation.repeat +5098 [ method ] +5099 ** +5100 * Creates a copy of existing animation object with given repetition. 5101 ** -5102 * Creates copy of existing animation object with given repetition. +5102 > Parameters 5103 ** -5104 > Parameters +5104 - repeat (number) number iterations of animation. For infinite animation pass `Infinity` 5105 ** -5106 - repeat (number) number iterations of animation. For infinite animation pass `Infinity` -5107 ** -5108 = (object) new altered Animation object -5109 \*/ -5110 Animation.prototype.repeat = function (times) { -5111 var a = new Animation(this.anim, this.ms); -5112 a.del = this.del; -5113 a.times = math.floor(mmax(times, 0)) || 1; -5114 return a; -5115 }; -5116 function runAnimation(anim, element, percent, status, totalOrigin) { -5117 percent = toFloat(percent); -5118 var params, -5119 isInAnim, -5120 isInAnimSet, -5121 percents = [], -5122 next, -5123 prev, -5124 timestamp, -5125 ms = anim.ms, -5126 from = {}, -5127 to = {}, -5128 diff = {}; -5129 if (status) { -5130 for (i = 0, ii = animationElements.length; i < ii; i++) { -5131 var e = animationElements[i]; -5132 if (e.el.id == element.id && e.anim == anim) { -5133 if (e.percent != percent) { -5134 animationElements.splice(i, 1); -5135 isInAnimSet = 1; -5136 } else { -5137 isInAnim = e; -5138 } -5139 element.attr(e.totalOrigin); -5140 break; -5141 } -5142 } -5143 } else { -5144 status = 0 / 0; -5145 } -5146 for (var i = 0, ii = anim.percents.length; i < ii; i++) { -5147 if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) { -5148 percent = anim.percents[i]; -5149 prev = anim.percents[i - 1] || 0; -5150 ms = ms / anim.top * (percent - prev); -5151 next = anim.percents[i + 1]; -5152 params = anim.anim[percent]; -5153 break; -5154 } else if (status) { -5155 element.attr(anim.anim[anim.percents[i]]); -5156 } -5157 } -5158 if (!params) { -5159 return; -5160 } -5161 if (!isInAnim) { -5162 for (attr in params) if (params[has](attr)) { -5163 if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) { -5164 from[attr] = element.attr(attr); -5165 (from[attr] == null) && (from[attr] = availableAttrs[attr]); -5166 to[attr] = params[attr]; -5167 switch (availableAnimAttrs[attr]) { -5168 case nu: -5169 diff[attr] = (to[attr] - from[attr]) / ms; -5170 break; -5171 case "colour": -5172 from[attr] = R.getRGB(from[attr]); -5173 var toColour = R.getRGB(to[attr]); -5174 diff[attr] = { -5175 r: (toColour.r - from[attr].r) / ms, -5176 g: (toColour.g - from[attr].g) / ms, -5177 b: (toColour.b - from[attr].b) / ms -5178 }; -5179 break; -5180 case "path": -5181 var pathes = path2curve(from[attr], to[attr]), -5182 toPath = pathes[1]; -5183 from[attr] = pathes[0]; -5184 diff[attr] = []; -5185 for (i = 0, ii = from[attr].length; i < ii; i++) { -5186 diff[attr][i] = [0]; -5187 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { -5188 diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms; -5189 } -5190 } -5191 break; -5192 case "transform": -5193 var _ = element._, -5194 eq = equaliseTransform(_[attr], to[attr]); -5195 if (eq) { -5196 from[attr] = eq.from; -5197 to[attr] = eq.to; -5198 diff[attr] = []; -5199 diff[attr].real = true; -5200 for (i = 0, ii = from[attr].length; i < ii; i++) { -5201 diff[attr][i] = [from[attr][i][0]]; -5202 for (j = 1, jj = from[attr][i].length; j < jj; j++) { -5203 diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms; -5204 } -5205 } -5206 } else { -5207 var m = (element.matrix || new Matrix).m, -5208 to2 = {_:{transform: _.transform}, getBBox: function () { return element.getBBox(); }}; -5209 from[attr] = [ -5210 m[0][0], -5211 m[1][0], -5212 m[0][1], -5213 m[1][1], -5214 m[0][2], -5215 m[1][2] -5216 ]; -5217 extractTransform(to2, to[attr]); -5218 to[attr] = to2._.transform; -5219 diff[attr] = [ -5220 (to2.matrix.m[0][0] - m[0][0]) / ms, -5221 (to2.matrix.m[1][0] - m[1][0]) / ms, -5222 (to2.matrix.m[0][1] - m[0][1]) / ms, -5223 (to2.matrix.m[1][1] - m[1][1]) / ms, -5224 (to2.matrix.m[0][2] - m[0][2]) / ms, -5225 (to2.matrix.m[1][2] - m[1][2]) / ms -5226 ]; -5227 // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy]; -5228 // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }}; -5229 // extractTransform(to2, to[attr]); -5230 // diff[attr] = [ -5231 // (to2._.sx - _.sx) / ms, -5232 // (to2._.sy - _.sy) / ms, -5233 // (to2._.deg - _.deg) / ms, -5234 // (to2._.dx - _.dx) / ms, -5235 // (to2._.dy - _.dy) / ms -5236 // ]; -5237 } -5238 break; -5239 case "csv": -5240 var values = Str(params[attr]).split(separator), -5241 from2 = Str(from[attr]).split(separator); -5242 if (attr == "clip-rect") { -5243 from[attr] = from2; -5244 diff[attr] = []; -5245 i = from2.length; -5246 while (i--) { -5247 diff[attr][i] = (values[i] - from[attr][i]) / ms; -5248 } -5249 } -5250 to[attr] = values; -5251 break; -5252 default: -5253 values = [].concat(params[attr]); -5254 from2 = [].concat(from[attr]); -5255 diff[attr] = []; -5256 i = element.paper.customAttributes[attr].length; -5257 while (i--) { -5258 diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms; -5259 } -5260 break; -5261 } -5262 } -5263 } -5264 var easing = params.easing, -5265 easyeasy = R.easing_formulas[easing]; -5266 if (!easyeasy) { -5267 easyeasy = Str(easing).match(bezierrg); -5268 if (easyeasy && easyeasy.length == 5) { -5269 var curve = easyeasy; -5270 easyeasy = function (t) { -5271 return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms); -5272 }; -5273 } else { -5274 easyeasy = pipe; -5275 } -5276 } -5277 timestamp = params.start || anim.start || +new Date; -5278 e = { -5279 anim: anim, -5280 percent: percent, -5281 timestamp: timestamp, -5282 start: timestamp + (anim.del || 0), -5283 status: 0, -5284 initstatus: status || 0, -5285 stop: false, -5286 ms: ms, -5287 easing: easyeasy, -5288 from: from, -5289 diff: diff, -5290 to: to, -5291 el: element, -5292 callback: params.callback, -5293 prev: prev, -5294 next: next, -5295 repeat: anim.times, -5296 origin: element.attr(), -5297 totalOrigin: totalOrigin -5298 }; -5299 animationElements.push(e); -5300 if (status && !isInAnim) { -5301 e.stop = true; -5302 e.start = new Date - ms * status; -5303 if (animationElements.length == 1) { -5304 return animation(); -5305 } -5306 } -5307 animationElements.length == 1 && requestAnimFrame(animation); -5308 } else { -5309 isInAnim.initstatus = status; -5310 isInAnim.start = new Date - isInAnim.ms * status; -5311 } -5312 eve("anim.start." + element.id, element, anim); -5313 } -5314 /*\ -5315 * Raphael.animation -5316 [ method ] -5317 ** -5318 * Creates animation object. That later could be used for @Element.animate or @Element.animateWith methods. -5319 * See also @Animation.delay and @Animation.repeat methods. +5106 = (object) new altered Animation object +5107 \*/ +5108 Animation.prototype.repeat = function (times) { +5109 var a = new Animation(this.anim, this.ms); +5110 a.del = this.del; +5111 a.times = math.floor(mmax(times, 0)) || 1; +5112 return a; +5113 }; +5114 function runAnimation(anim, element, percent, status, totalOrigin) { +5115 percent = toFloat(percent); +5116 var params, +5117 isInAnim, +5118 isInAnimSet, +5119 percents = [], +5120 next, +5121 prev, +5122 timestamp, +5123 ms = anim.ms, +5124 from = {}, +5125 to = {}, +5126 diff = {}; +5127 if (status) { +5128 for (i = 0, ii = animationElements.length; i < ii; i++) { +5129 var e = animationElements[i]; +5130 if (e.el.id == element.id && e.anim == anim) { +5131 if (e.percent != percent) { +5132 animationElements.splice(i, 1); +5133 isInAnimSet = 1; +5134 } else { +5135 isInAnim = e; +5136 } +5137 element.attr(e.totalOrigin); +5138 break; +5139 } +5140 } +5141 } else { +5142 status = 0 / 0; +5143 } +5144 for (var i = 0, ii = anim.percents.length; i < ii; i++) { +5145 if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) { +5146 percent = anim.percents[i]; +5147 prev = anim.percents[i - 1] || 0; +5148 ms = ms / anim.top * (percent - prev); +5149 next = anim.percents[i + 1]; +5150 params = anim.anim[percent]; +5151 break; +5152 } else if (status) { +5153 element.attr(anim.anim[anim.percents[i]]); +5154 } +5155 } +5156 if (!params) { +5157 return; +5158 } +5159 if (!isInAnim) { +5160 for (attr in params) if (params[has](attr)) { +5161 if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) { +5162 from[attr] = element.attr(attr); +5163 (from[attr] == null) && (from[attr] = availableAttrs[attr]); +5164 to[attr] = params[attr]; +5165 switch (availableAnimAttrs[attr]) { +5166 case nu: +5167 diff[attr] = (to[attr] - from[attr]) / ms; +5168 break; +5169 case "colour": +5170 from[attr] = R.getRGB(from[attr]); +5171 var toColour = R.getRGB(to[attr]); +5172 diff[attr] = { +5173 r: (toColour.r - from[attr].r) / ms, +5174 g: (toColour.g - from[attr].g) / ms, +5175 b: (toColour.b - from[attr].b) / ms +5176 }; +5177 break; +5178 case "path": +5179 var pathes = path2curve(from[attr], to[attr]), +5180 toPath = pathes[1]; +5181 from[attr] = pathes[0]; +5182 diff[attr] = []; +5183 for (i = 0, ii = from[attr].length; i < ii; i++) { +5184 diff[attr][i] = [0]; +5185 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { +5186 diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms; +5187 } +5188 } +5189 break; +5190 case "transform": +5191 var _ = element._, +5192 eq = equaliseTransform(_[attr], to[attr]); +5193 if (eq) { +5194 from[attr] = eq.from; +5195 to[attr] = eq.to; +5196 diff[attr] = []; +5197 diff[attr].real = true; +5198 for (i = 0, ii = from[attr].length; i < ii; i++) { +5199 diff[attr][i] = [from[attr][i][0]]; +5200 for (j = 1, jj = from[attr][i].length; j < jj; j++) { +5201 diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms; +5202 } +5203 } +5204 } else { +5205 var m = (element.matrix || new Matrix).m, +5206 to2 = {_:{transform: _.transform}, getBBox: function () { return element.getBBox(); }}; +5207 from[attr] = [ +5208 m[0][0], +5209 m[1][0], +5210 m[0][1], +5211 m[1][1], +5212 m[0][2], +5213 m[1][2] +5214 ]; +5215 extractTransform(to2, to[attr]); +5216 to[attr] = to2._.transform; +5217 diff[attr] = [ +5218 (to2.matrix.m[0][0] - m[0][0]) / ms, +5219 (to2.matrix.m[1][0] - m[1][0]) / ms, +5220 (to2.matrix.m[0][1] - m[0][1]) / ms, +5221 (to2.matrix.m[1][1] - m[1][1]) / ms, +5222 (to2.matrix.m[0][2] - m[0][2]) / ms, +5223 (to2.matrix.m[1][2] - m[1][2]) / ms +5224 ]; +5225 // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy]; +5226 // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }}; +5227 // extractTransform(to2, to[attr]); +5228 // diff[attr] = [ +5229 // (to2._.sx - _.sx) / ms, +5230 // (to2._.sy - _.sy) / ms, +5231 // (to2._.deg - _.deg) / ms, +5232 // (to2._.dx - _.dx) / ms, +5233 // (to2._.dy - _.dy) / ms +5234 // ]; +5235 } +5236 break; +5237 case "csv": +5238 var values = Str(params[attr]).split(separator), +5239 from2 = Str(from[attr]).split(separator); +5240 if (attr == "clip-rect") { +5241 from[attr] = from2; +5242 diff[attr] = []; +5243 i = from2.length; +5244 while (i--) { +5245 diff[attr][i] = (values[i] - from[attr][i]) / ms; +5246 } +5247 } +5248 to[attr] = values; +5249 break; +5250 default: +5251 values = [].concat(params[attr]); +5252 from2 = [].concat(from[attr]); +5253 diff[attr] = []; +5254 i = element.paper.customAttributes[attr].length; +5255 while (i--) { +5256 diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms; +5257 } +5258 break; +5259 } +5260 } +5261 } +5262 var easing = params.easing, +5263 easyeasy = R.easing_formulas[easing]; +5264 if (!easyeasy) { +5265 easyeasy = Str(easing).match(bezierrg); +5266 if (easyeasy && easyeasy.length == 5) { +5267 var curve = easyeasy; +5268 easyeasy = function (t) { +5269 return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms); +5270 }; +5271 } else { +5272 easyeasy = pipe; +5273 } +5274 } +5275 timestamp = params.start || anim.start || +new Date; +5276 e = { +5277 anim: anim, +5278 percent: percent, +5279 timestamp: timestamp, +5280 start: timestamp + (anim.del || 0), +5281 status: 0, +5282 initstatus: status || 0, +5283 stop: false, +5284 ms: ms, +5285 easing: easyeasy, +5286 from: from, +5287 diff: diff, +5288 to: to, +5289 el: element, +5290 callback: params.callback, +5291 prev: prev, +5292 next: next, +5293 repeat: anim.times, +5294 origin: element.attr(), +5295 totalOrigin: totalOrigin +5296 }; +5297 animationElements.push(e); +5298 if (status && !isInAnim) { +5299 e.stop = true; +5300 e.start = new Date - ms * status; +5301 if (animationElements.length == 1) { +5302 return animation(); +5303 } +5304 } +5305 animationElements.length == 1 && requestAnimFrame(animation); +5306 } else { +5307 isInAnim.initstatus = status; +5308 isInAnim.start = new Date - isInAnim.ms * status; +5309 } +5310 eve("anim.start." + element.id, element, anim); +5311 } +5312 /*\ +5313 * Raphael.animation +5314 [ method ] +5315 ** +5316 * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods. +5317 * See also @Animation.delay and @Animation.repeat methods. +5318 ** +5319 > Parameters 5320 ** -5321 > Parameters -5322 ** -5323 - params (object) final attributes for the element, see also @Element.attr -5324 - ms (number) number of milliseconds for animation to run -5325 - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` -5326 - callback (function) #optional callback function. Will be called at the end of animation. -5327 ** -5328 = (object) @Animation -5329 \*/ -5330 R.animation = function (params, ms, easing, callback) { -5331 if (R.is(easing, "function") || !easing) { -5332 callback = callback || easing || null; -5333 easing = null; -5334 } -5335 params = Object(params); -5336 ms = +ms || 0; -5337 var p = {}, -5338 json, -5339 attr; -5340 for (attr in params) if (params[has](attr) && toFloat(attr) != attr) { -5341 json = true; -5342 p[attr] = params[attr]; -5343 } -5344 if (!json) { -5345 return new Animation(params, ms); -5346 } else { -5347 easing && (p.easing = easing); -5348 callback && (p.callback = callback); -5349 return new Animation({100: p}, ms); -5350 } -5351 }; -5352 /*\ -5353 * Element.animate -5354 [ method ] +5321 - params (object) final attributes for the element, see also @Element.attr +5322 - ms (number) number of milliseconds for animation to run +5323 - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` +5324 - callback (function) #optional callback function. Will be called at the end of animation. +5325 ** +5326 = (object) @Animation +5327 \*/ +5328 R.animation = function (params, ms, easing, callback) { +5329 if (R.is(easing, "function") || !easing) { +5330 callback = callback || easing || null; +5331 easing = null; +5332 } +5333 params = Object(params); +5334 ms = +ms || 0; +5335 var p = {}, +5336 json, +5337 attr; +5338 for (attr in params) if (params[has](attr) && toFloat(attr) != attr) { +5339 json = true; +5340 p[attr] = params[attr]; +5341 } +5342 if (!json) { +5343 return new Animation(params, ms); +5344 } else { +5345 easing && (p.easing = easing); +5346 callback && (p.callback = callback); +5347 return new Animation({100: p}, ms); +5348 } +5349 }; +5350 /*\ +5351 * Element.animate +5352 [ method ] +5353 ** +5354 * Creates and starts animation for given element. 5355 ** -5356 * Creates and starts animation for given element. +5356 > Parameters 5357 ** -5358 > Parameters -5359 ** -5360 - params (object) final attributes for the element, see also @Element.attr -5361 - ms (number) number of milliseconds for animation to run -5362 - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` -5363 - callback (function) #optional callback function. Will be called at the end of animation. -5364 * or -5365 - animation (object) animation object, see @Raphael.animation -5366 ** -5367 = (object) original element -5368 \*/ -5369 elproto.animate = function (params, ms, easing, callback) { -5370 var element = this; -5371 if (element.removed) { -5372 callback && callback.call(element); -5373 return element; -5374 } -5375 var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback); -5376 runAnimation(anim, element, anim.percents[0], null, element.attr()); -5377 return element; -5378 }; -5379 /*\ -5380 * Element.setTime -5381 [ method ] +5358 - params (object) final attributes for the element, see also @Element.attr +5359 - ms (number) number of milliseconds for animation to run +5360 - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` +5361 - callback (function) #optional callback function. Will be called at the end of animation. +5362 * or +5363 - animation (object) animation object, see @Raphael.animation +5364 ** +5365 = (object) original element +5366 \*/ +5367 elproto.animate = function (params, ms, easing, callback) { +5368 var element = this; +5369 if (element.removed) { +5370 callback && callback.call(element); +5371 return element; +5372 } +5373 var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback); +5374 runAnimation(anim, element, anim.percents[0], null, element.attr()); +5375 return element; +5376 }; +5377 /*\ +5378 * Element.setTime +5379 [ method ] +5380 ** +5381 * Sets the status of animation of the element in milliseconds. Similar to @Element.status method. 5382 ** -5383 * Sets the status of animation of the element in milliseconds. Similar to @Element.status method. +5383 > Parameters 5384 ** -5385 > Parameters -5386 ** -5387 - anim (object) animation object -5388 - value (number) number of milliseconds from the beginning of the animation -5389 ** -5390 = (object) original element if `value` is specified -5391 * Note, that during animation following events are triggered: -5392 * -5393 * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`. -5394 \*/ -5395 elproto.setTime = function (anim, value) { -5396 if (anim && value != null) { -5397 this.status(anim, mmin(value, anim.ms) / anim.ms); -5398 } -5399 return this; -5400 }; -5401 /*\ -5402 * Element.status -5403 [ method ] +5385 - anim (object) animation object +5386 - value (number) number of milliseconds from the beginning of the animation +5387 ** +5388 = (object) original element if `value` is specified +5389 * Note, that during animation following events are triggered: +5390 * +5391 * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`. +5392 \*/ +5393 elproto.setTime = function (anim, value) { +5394 if (anim && value != null) { +5395 this.status(anim, mmin(value, anim.ms) / anim.ms); +5396 } +5397 return this; +5398 }; +5399 /*\ +5400 * Element.status +5401 [ method ] +5402 ** +5403 * Gets or sets the status of animation of the element. 5404 ** -5405 * Gets or sets the status of animation of the element. +5405 > Parameters 5406 ** -5407 > Parameters -5408 ** -5409 - anim (object) #optional animation object -5410 - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position. -5411 ** -5412 = (number) status -5413 * or -5414 = (array) status if `anim` is not specified. Array of objects in format: -5415 o { -5416 o anim: (object) animation object -5417 o status: (number) status -5418 o } -5419 * or -5420 = (object) original element if `value` is specified -5421 \*/ -5422 elproto.status = function (anim, value) { -5423 var out = [], -5424 i = 0, -5425 len, -5426 e; -5427 if (value != null) { -5428 runAnimation(anim, this, -1, mmin(value, 1)); -5429 return this; -5430 } else { -5431 len = animationElements.length; -5432 for (; i < len; i++) { -5433 e = animationElements[i]; -5434 if (e.el.id == this.id && (!anim || e.anim == anim)) { -5435 if (anim) { -5436 return e.status; -5437 } -5438 out.push({anim: e.anim, status: e.status}); -5439 } -5440 } -5441 if (anim) { -5442 return 0; -5443 } -5444 return out; -5445 } -5446 }; -5447 /*\ -5448 * Element.pause -5449 [ method ] +5407 - anim (object) #optional animation object +5408 - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position. +5409 ** +5410 = (number) status +5411 * or +5412 = (array) status if `anim` is not specified. Array of objects in format: +5413 o { +5414 o anim: (object) animation object +5415 o status: (number) status +5416 o } +5417 * or +5418 = (object) original element if `value` is specified +5419 \*/ +5420 elproto.status = function (anim, value) { +5421 var out = [], +5422 i = 0, +5423 len, +5424 e; +5425 if (value != null) { +5426 runAnimation(anim, this, -1, mmin(value, 1)); +5427 return this; +5428 } else { +5429 len = animationElements.length; +5430 for (; i < len; i++) { +5431 e = animationElements[i]; +5432 if (e.el.id == this.id && (!anim || e.anim == anim)) { +5433 if (anim) { +5434 return e.status; +5435 } +5436 out.push({anim: e.anim, status: e.status}); +5437 } +5438 } +5439 if (anim) { +5440 return 0; +5441 } +5442 return out; +5443 } +5444 }; +5445 /*\ +5446 * Element.pause +5447 [ method ] +5448 ** +5449 * Stops animation of the element with ability to resume it later on. 5450 ** -5451 * Stops animation of the element with ability to resume it later on. +5451 > Parameters 5452 ** -5453 > Parameters +5453 - anim (object) #optional animation object 5454 ** -5455 - anim (object) #optional animation object -5456 ** -5457 = (object) original element -5458 \*/ -5459 elproto.pause = function (anim) { -5460 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { -5461 if (eve("anim.pause." + this.id, this, animationElements[i].anim) !== false) { -5462 animationElements[i].paused = true; -5463 } -5464 } -5465 return this; -5466 }; -5467 /*\ -5468 * Element.resume -5469 [ method ] +5455 = (object) original element +5456 \*/ +5457 elproto.pause = function (anim) { +5458 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { +5459 if (eve("anim.pause." + this.id, this, animationElements[i].anim) !== false) { +5460 animationElements[i].paused = true; +5461 } +5462 } +5463 return this; +5464 }; +5465 /*\ +5466 * Element.resume +5467 [ method ] +5468 ** +5469 * Resumes animation if it was paused with @Element.pause method. 5470 ** -5471 * Resumes animation if it was paused with @Element.pause method. +5471 > Parameters 5472 ** -5473 > Parameters +5473 - anim (object) #optional animation object 5474 ** -5475 - anim (object) #optional animation object -5476 ** -5477 = (object) original element -5478 \*/ -5479 elproto.resume = function (anim) { -5480 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { -5481 var e = animationElements[i]; -5482 if (eve("anim.resume." + this.id, this, e.anim) !== false) { -5483 delete e.paused; -5484 this.status(e.anim, e.status); -5485 } -5486 } -5487 return this; -5488 }; -5489 /*\ -5490 * Element.stop -5491 [ method ] +5475 = (object) original element +5476 \*/ +5477 elproto.resume = function (anim) { +5478 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { +5479 var e = animationElements[i]; +5480 if (eve("anim.resume." + this.id, this, e.anim) !== false) { +5481 delete e.paused; +5482 this.status(e.anim, e.status); +5483 } +5484 } +5485 return this; +5486 }; +5487 /*\ +5488 * Element.stop +5489 [ method ] +5490 ** +5491 * Stops animation of the element. 5492 ** -5493 * Stops animation of the element. +5493 > Parameters 5494 ** -5495 > Parameters +5495 - anim (object) #optional animation object 5496 ** -5497 - anim (object) #optional animation object -5498 ** -5499 = (object) original element -5500 \*/ -5501 elproto.stop = function (anim) { -5502 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { -5503 if (eve("anim.stop." + this.id, this, animationElements[i].anim) !== false) { -5504 animationElements.splice(i--, 1); -5505 } -5506 } -5507 return this; -5508 }; -5509 elproto.toString = function () { -5510 return "Rapha\xebl\u2019s object"; -5511 }; -5512 -5513 // Set -5514 var Set = function (items) { -5515 this.items = []; -5516 this.length = 0; -5517 this.type = "set"; -5518 if (items) { -5519 for (var i = 0, ii = items.length; i < ii; i++) { -5520 if (items[i] && (items[i].constructor == Element || items[i].constructor == Set)) { -5521 this[this.items.length] = this.items[this.items.length] = items[i]; -5522 this.length++; -5523 } -5524 } -5525 } -5526 }, -5527 setproto = Set.prototype; -5528 /*\ -5529 * Set.push -5530 [ method ] -5531 ** -5532 * Adds each argument to the current set. -5533 = (object) original element -5534 \*/ -5535 setproto.push = function () { -5536 var item, -5537 len; -5538 for (var i = 0, ii = arguments.length; i < ii; i++) { -5539 item = arguments[i]; -5540 if (item && (item.constructor == Element || item.constructor == Set)) { -5541 len = this.items.length; -5542 this[len] = this.items[len] = item; -5543 this.length++; -5544 } -5545 } -5546 return this; -5547 }; -5548 /*\ -5549 * Set.pop -5550 [ method ] -5551 ** -5552 * Removes last element and returns it. -5553 = (object) element -5554 \*/ -5555 setproto.pop = function () { -5556 this.length && delete this[this.length--]; -5557 return this.items.pop(); -5558 }; -5559 /*\ -5560 * Set.forEach -5561 [ method ] -5562 ** -5563 * Executes given function for each element in the set. -5564 * -5565 * If function returns `false` it will stop loop running. +5497 = (object) original element +5498 \*/ +5499 elproto.stop = function (anim) { +5500 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { +5501 if (eve("anim.stop." + this.id, this, animationElements[i].anim) !== false) { +5502 animationElements.splice(i--, 1); +5503 } +5504 } +5505 return this; +5506 }; +5507 elproto.toString = function () { +5508 return "Rapha\xebl\u2019s object"; +5509 }; +5510 +5511 // Set +5512 var Set = function (items) { +5513 this.items = []; +5514 this.length = 0; +5515 this.type = "set"; +5516 if (items) { +5517 for (var i = 0, ii = items.length; i < ii; i++) { +5518 if (items[i] && (items[i].constructor == Element || items[i].constructor == Set)) { +5519 this[this.items.length] = this.items[this.items.length] = items[i]; +5520 this.length++; +5521 } +5522 } +5523 } +5524 }, +5525 setproto = Set.prototype; +5526 /*\ +5527 * Set.push +5528 [ method ] +5529 ** +5530 * Adds each argument to the current set. +5531 = (object) original element +5532 \*/ +5533 setproto.push = function () { +5534 var item, +5535 len; +5536 for (var i = 0, ii = arguments.length; i < ii; i++) { +5537 item = arguments[i]; +5538 if (item && (item.constructor == Element || item.constructor == Set)) { +5539 len = this.items.length; +5540 this[len] = this.items[len] = item; +5541 this.length++; +5542 } +5543 } +5544 return this; +5545 }; +5546 /*\ +5547 * Set.pop +5548 [ method ] +5549 ** +5550 * Removes last element and returns it. +5551 = (object) element +5552 \*/ +5553 setproto.pop = function () { +5554 this.length && delete this[this.length--]; +5555 return this.items.pop(); +5556 }; +5557 /*\ +5558 * Set.forEach +5559 [ method ] +5560 ** +5561 * Executes given function for each element in the set. +5562 * +5563 * If function returns `false` it will stop loop running. +5564 ** +5565 > Parameters 5566 ** -5567 > Parameters -5568 ** -5569 - callback (function) function to run -5570 - thisArg (object) context object for the callback -5571 = (object) Set object -5572 \*/ -5573 setproto.forEach = function (callback, thisArg) { -5574 for (var i = 0, ii = this.items.length; i < ii; i++) { -5575 if (callback.call(thisArg, this.items[i]) === false) { -5576 return this; -5577 } -5578 } -5579 return this; -5580 }; -5581 for (var method in elproto) if (elproto[has](method)) { -5582 setproto[method] = (function (methodname) { -5583 return function () { -5584 var arg = arguments; -5585 return this.forEach(function (el) { -5586 el[methodname][apply](el, arg); -5587 }); -5588 }; -5589 })(method); -5590 } -5591 setproto.attr = function (name, value) { -5592 if (name && R.is(name, array) && R.is(name[0], "object")) { -5593 for (var j = 0, jj = name.length; j < jj; j++) { -5594 this.items[j].attr(name[j]); -5595 } -5596 } else { -5597 for (var i = 0, ii = this.items.length; i < ii; i++) { -5598 this.items[i].attr(name, value); -5599 } -5600 } -5601 return this; -5602 }; -5603 setproto.animate = function (params, ms, easing, callback) { -5604 (R.is(easing, "function") || !easing) && (callback = easing || null); -5605 var len = this.items.length, -5606 i = len, -5607 item, -5608 set = this, -5609 collector; -5610 callback && (collector = function () { -5611 !--len && callback.call(set); -5612 }); -5613 easing = R.is(easing, string) ? easing : collector; -5614 var anim = params instanceof Animation ? params : R.animation(params, ms, easing, collector); -5615 item = this.items[--i].animate(anim); -5616 while (i--) { -5617 this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim); -5618 } -5619 return this; -5620 }; -5621 setproto.insertAfter = function (el) { -5622 var i = this.items.length; -5623 while (i--) { -5624 this.items[i].insertAfter(el); -5625 } -5626 return this; -5627 }; -5628 setproto.getBBox = function () { -5629 var x = [], -5630 y = [], -5631 w = [], -5632 h = []; -5633 for (var i = this.items.length; i--;) if (!this.items[i].removed) { -5634 var box = this.items[i].getBBox(); -5635 x.push(box.x); -5636 y.push(box.y); -5637 w.push(box.x + box.width); -5638 h.push(box.y + box.height); -5639 } -5640 x = mmin[apply](0, x); -5641 y = mmin[apply](0, y); -5642 return { -5643 x: x, -5644 y: y, -5645 width: mmax[apply](0, w) - x, -5646 height: mmax[apply](0, h) - y -5647 }; -5648 }; -5649 setproto.clone = function (s) { -5650 s = new Set; -5651 for (var i = 0, ii = this.items.length; i < ii; i++) { -5652 s.push(this.items[i].clone()); -5653 } -5654 return s; -5655 }; -5656 setproto.toString = function () { -5657 return "Rapha\xebl\u2018s set"; -5658 }; -5659 -5660 R.registerFont = function (font) { -5661 if (!font.face) { -5662 return font; -5663 } -5664 this.fonts = this.fonts || {}; -5665 var fontcopy = { -5666 w: font.w, -5667 face: {}, -5668 glyphs: {} -5669 }, -5670 family = font.face["font-family"]; -5671 for (var prop in font.face) if (font.face[has](prop)) { -5672 fontcopy.face[prop] = font.face[prop]; -5673 } -5674 if (this.fonts[family]) { -5675 this.fonts[family].push(fontcopy); -5676 } else { -5677 this.fonts[family] = [fontcopy]; -5678 } -5679 if (!font.svg) { -5680 fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10); -5681 for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) { -5682 var path = font.glyphs[glyph]; -5683 fontcopy.glyphs[glyph] = { -5684 w: path.w, -5685 k: {}, -5686 d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) { -5687 return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M"; -5688 }) + "z" -5689 }; -5690 if (path.k) { -5691 for (var k in path.k) if (path[has](k)) { -5692 fontcopy.glyphs[glyph].k[k] = path.k[k]; -5693 } -5694 } -5695 } -5696 } -5697 return font; -5698 }; -5699 paperproto.getFont = function (family, weight, style, stretch) { -5700 stretch = stretch || "normal"; -5701 style = style || "normal"; -5702 weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400; -5703 if (!R.fonts) { -5704 return; -5705 } -5706 var font = R.fonts[family]; -5707 if (!font) { -5708 var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i"); -5709 for (var fontName in R.fonts) if (R.fonts[has](fontName)) { -5710 if (name.test(fontName)) { -5711 font = R.fonts[fontName]; -5712 break; -5713 } -5714 } -5715 } -5716 var thefont; -5717 if (font) { -5718 for (var i = 0, ii = font.length; i < ii; i++) { -5719 thefont = font[i]; -5720 if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) { -5721 break; -5722 } -5723 } -5724 } -5725 return thefont; -5726 }; -5727 paperproto.print = function (x, y, string, font, size, origin, letter_spacing) { -5728 origin = origin || "middle"; // baseline|middle -5729 letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1); -5730 var out = this.set(), -5731 letters = Str(string).split(E), -5732 shift = 0, -5733 path = E, -5734 scale; -5735 R.is(font, string) && (font = this.getFont(font)); -5736 if (font) { -5737 scale = (size || 16) / font.face["units-per-em"]; -5738 var bb = font.face.bbox.split(separator), -5739 top = +bb[0], -5740 height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2); -5741 for (var i = 0, ii = letters.length; i < ii; i++) { -5742 var prev = i && font.glyphs[letters[i - 1]] || {}, -5743 curr = font.glyphs[letters[i]]; -5744 shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0; -5745 curr && curr.d && out.push(this.path(curr.d).attr({fill: "#000", stroke: "none", transform: [["t", shift, 0]]})); -5746 } -5747 out.scale(scale, scale, top, height).translate(x - top, y - height); -5748 } -5749 return out; -5750 }; -5751 -5752 R.format = function (token, params) { -5753 var args = R.is(params, array) ? [0][concat](params) : arguments; -5754 token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) { -5755 return args[++i] == null ? E : args[i]; -5756 })); -5757 return token || E; -5758 }; -5759 R.ninja = function () { -5760 oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael; -5761 return R; -5762 }; -5763 /*\ -5764 * Raphael.el -5765 [ property (object) ] -5766 ** -5767 * You can add your own method to elements. This is usefull when you want to hack default functionality or -5768 * want to wrap some common transformation or attributes in one method. In difference to canvas methods, -5769 * you can redefine element method at any time. Expending element methods wouldn’t affect set -5770 > Usage -5771 | Raphael.el.red = function () { -5772 | this.attr({fill: "#f00"}); -5773 | }; -5774 | // then use it -5775 | paper.circle(100, 100, 20).red(); -5776 \*/ -5777 R.el = elproto; -5778 R.st = setproto; -5779 // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html -5780 (function (doc, loaded, f) { -5781 if (doc.readyState == null && doc.addEventListener){ -5782 doc.addEventListener(loaded, f = function () { -5783 doc.removeEventListener(loaded, f, false); -5784 doc.readyState = "complete"; -5785 }, false); -5786 doc.readyState = "loading"; -5787 } -5788 function isLoaded() { -5789 (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : eve("DOMload"); -5790 } -5791 isLoaded(); -5792 })(document, "DOMContentLoaded"); +5567 - callback (function) function to run +5568 - thisArg (object) context object for the callback +5569 = (object) Set object +5570 \*/ +5571 setproto.forEach = function (callback, thisArg) { +5572 for (var i = 0, ii = this.items.length; i < ii; i++) { +5573 if (callback.call(thisArg, this.items[i]) === false) { +5574 return this; +5575 } +5576 } +5577 return this; +5578 }; +5579 for (var method in elproto) if (elproto[has](method)) { +5580 setproto[method] = (function (methodname) { +5581 return function () { +5582 var arg = arguments; +5583 return this.forEach(function (el) { +5584 el[methodname][apply](el, arg); +5585 }); +5586 }; +5587 })(method); +5588 } +5589 setproto.attr = function (name, value) { +5590 if (name && R.is(name, array) && R.is(name[0], "object")) { +5591 for (var j = 0, jj = name.length; j < jj; j++) { +5592 this.items[j].attr(name[j]); +5593 } +5594 } else { +5595 for (var i = 0, ii = this.items.length; i < ii; i++) { +5596 this.items[i].attr(name, value); +5597 } +5598 } +5599 return this; +5600 }; +5601 setproto.animate = function (params, ms, easing, callback) { +5602 (R.is(easing, "function") || !easing) && (callback = easing || null); +5603 var len = this.items.length, +5604 i = len, +5605 item, +5606 set = this, +5607 collector; +5608 callback && (collector = function () { +5609 !--len && callback.call(set); +5610 }); +5611 easing = R.is(easing, string) ? easing : collector; +5612 var anim = params instanceof Animation ? params : R.animation(params, ms, easing, collector); +5613 item = this.items[--i].animate(anim); +5614 while (i--) { +5615 this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim); +5616 } +5617 return this; +5618 }; +5619 setproto.insertAfter = function (el) { +5620 var i = this.items.length; +5621 while (i--) { +5622 this.items[i].insertAfter(el); +5623 } +5624 return this; +5625 }; +5626 setproto.getBBox = function () { +5627 var x = [], +5628 y = [], +5629 w = [], +5630 h = []; +5631 for (var i = this.items.length; i--;) if (!this.items[i].removed) { +5632 var box = this.items[i].getBBox(); +5633 x.push(box.x); +5634 y.push(box.y); +5635 w.push(box.x + box.width); +5636 h.push(box.y + box.height); +5637 } +5638 x = mmin[apply](0, x); +5639 y = mmin[apply](0, y); +5640 return { +5641 x: x, +5642 y: y, +5643 width: mmax[apply](0, w) - x, +5644 height: mmax[apply](0, h) - y +5645 }; +5646 }; +5647 setproto.clone = function (s) { +5648 s = new Set; +5649 for (var i = 0, ii = this.items.length; i < ii; i++) { +5650 s.push(this.items[i].clone()); +5651 } +5652 return s; +5653 }; +5654 setproto.toString = function () { +5655 return "Rapha\xebl\u2018s set"; +5656 }; +5657 +5658 R.registerFont = function (font) { +5659 if (!font.face) { +5660 return font; +5661 } +5662 this.fonts = this.fonts || {}; +5663 var fontcopy = { +5664 w: font.w, +5665 face: {}, +5666 glyphs: {} +5667 }, +5668 family = font.face["font-family"]; +5669 for (var prop in font.face) if (font.face[has](prop)) { +5670 fontcopy.face[prop] = font.face[prop]; +5671 } +5672 if (this.fonts[family]) { +5673 this.fonts[family].push(fontcopy); +5674 } else { +5675 this.fonts[family] = [fontcopy]; +5676 } +5677 if (!font.svg) { +5678 fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10); +5679 for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) { +5680 var path = font.glyphs[glyph]; +5681 fontcopy.glyphs[glyph] = { +5682 w: path.w, +5683 k: {}, +5684 d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) { +5685 return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M"; +5686 }) + "z" +5687 }; +5688 if (path.k) { +5689 for (var k in path.k) if (path[has](k)) { +5690 fontcopy.glyphs[glyph].k[k] = path.k[k]; +5691 } +5692 } +5693 } +5694 } +5695 return font; +5696 }; +5697 paperproto.getFont = function (family, weight, style, stretch) { +5698 stretch = stretch || "normal"; +5699 style = style || "normal"; +5700 weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400; +5701 if (!R.fonts) { +5702 return; +5703 } +5704 var font = R.fonts[family]; +5705 if (!font) { +5706 var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i"); +5707 for (var fontName in R.fonts) if (R.fonts[has](fontName)) { +5708 if (name.test(fontName)) { +5709 font = R.fonts[fontName]; +5710 break; +5711 } +5712 } +5713 } +5714 var thefont; +5715 if (font) { +5716 for (var i = 0, ii = font.length; i < ii; i++) { +5717 thefont = font[i]; +5718 if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) { +5719 break; +5720 } +5721 } +5722 } +5723 return thefont; +5724 }; +5725 paperproto.print = function (x, y, string, font, size, origin, letter_spacing) { +5726 origin = origin || "middle"; // baseline|middle +5727 letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1); +5728 var out = this.set(), +5729 letters = Str(string).split(E), +5730 shift = 0, +5731 path = E, +5732 scale; +5733 R.is(font, string) && (font = this.getFont(font)); +5734 if (font) { +5735 scale = (size || 16) / font.face["units-per-em"]; +5736 var bb = font.face.bbox.split(separator), +5737 top = +bb[0], +5738 height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2); +5739 for (var i = 0, ii = letters.length; i < ii; i++) { +5740 var prev = i && font.glyphs[letters[i - 1]] || {}, +5741 curr = font.glyphs[letters[i]]; +5742 shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0; +5743 curr && curr.d && out.push(this.path(curr.d).attr({fill: "#000", stroke: "none", transform: [["t", shift, 0]]})); +5744 } +5745 out.scale(scale, scale, top, height).translate(x - top, y - height); +5746 } +5747 return out; +5748 }; +5749 +5750 R.format = function (token, params) { +5751 var args = R.is(params, array) ? [0][concat](params) : arguments; +5752 token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) { +5753 return args[++i] == null ? E : args[i]; +5754 })); +5755 return token || E; +5756 }; +5757 R.ninja = function () { +5758 oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael; +5759 return R; +5760 }; +5761 /*\ +5762 * Raphael.el +5763 [ property (object) ] +5764 ** +5765 * You can add your own method to elements. This is usefull when you want to hack default functionality or +5766 * want to wrap some common transformation or attributes in one method. In difference to canvas methods, +5767 * you can redefine element method at any time. Expending element methods wouldn’t affect set. +5768 > Usage +5769 | Raphael.el.red = function () { +5770 | this.attr({fill: "#f00"}); +5771 | }; +5772 | // then use it +5773 | paper.circle(100, 100, 20).red(); +5774 \*/ +5775 R.el = elproto; +5776 R.st = setproto; +5777 // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html +5778 (function (doc, loaded, f) { +5779 if (doc.readyState == null && doc.addEventListener){ +5780 doc.addEventListener(loaded, f = function () { +5781 doc.removeEventListener(loaded, f, false); +5782 doc.readyState = "complete"; +5783 }, false); +5784 doc.readyState = "loading"; +5785 } +5786 function isLoaded() { +5787 (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : eve("DOMload"); +5788 } +5789 isLoaded(); +5790 })(document, "DOMContentLoaded"); +5791 +5792 oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R); 5793 -5794 oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R); -5795 -5796 /* -5797 * Eve 0.2.1 - JavaScript Events Library -5798 * -5799 * Copyright (c) 2010 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) -5800 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. -5801 */ -5802 -5803 var eve = R.eve = (function () { -5804 var version = "0.2.1", -5805 has = "hasOwnProperty", -5806 separator = /[\.\/]/, -5807 wildcard = "*", -5808 events = {n: {}}, -5809 eve = function (name, scope) { -5810 var e = events, -5811 args = Array.prototype.slice.call(arguments, 2), -5812 listeners = eve.listeners(name), -5813 errors = []; -5814 for (var i = 0, ii = listeners.length; i < ii; i++) { -5815 try { -5816 listeners[i].apply(scope, args); -5817 } catch (ex) { -5818 errors.push({error: ex && ex.message || ex, func: listeners[i]}); -5819 } -5820 } -5821 if (errors.length) { -5822 return errors; -5823 } -5824 }; -5825 eve.listeners = function (name) { -5826 var names = name.split(separator), -5827 e = events, -5828 item, -5829 items, -5830 k, -5831 i, -5832 ii, -5833 j, -5834 jj, -5835 nes, -5836 es = [e], -5837 out = []; -5838 for (i = 0, ii = names.length; i < ii; i++) { -5839 nes = []; -5840 for (j = 0, jj = es.length; j < jj; j++) { -5841 e = es[j].n; -5842 items = [e[names[i]], e[wildcard]]; -5843 k = 2; -5844 while (k--) { -5845 item = items[k]; -5846 if (item) { -5847 nes.push(item); -5848 out = out.concat(item.f || []); -5849 } -5850 } -5851 } -5852 es = nes; -5853 } -5854 return out; -5855 }; -5856 eve.on = function (name, f) { -5857 var names = name.split(separator), -5858 e = events; -5859 for (var i = 0, ii = names.length; i < ii; i++) { -5860 e = e.n; -5861 !e[names[i]] && (e[names[i]] = {n: {}}); -5862 e = e[names[i]]; -5863 } -5864 e.f = e.f || []; -5865 for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { -5866 return false; -5867 } -5868 e.f.push(f); -5869 }; -5870 eve.unbind = function (name, f) { -5871 var names = name.split(separator), -5872 e, -5873 key, -5874 splice, -5875 cur = [events]; -5876 for (var i = 0, ii = names.length; i < ii; i++) { -5877 for (var j = 0; j < cur.length; j += splice.length - 2) { -5878 splice = [j, 1]; -5879 e = cur[j].n; -5880 if (names[i] != wildcard) { -5881 if (e[names[i]]) { -5882 splice.push(e[names[i]]); -5883 } -5884 } else { -5885 for (key in e) if (e[has](key)) { -5886 splice.push(e[key]); -5887 } -5888 } -5889 cur.splice.apply(cur, splice); -5890 } -5891 } -5892 for (i = 0, ii = cur.length; i < ii; i++) { -5893 e = cur[i]; -5894 while (e.n) { -5895 if (f) { -5896 if (e.f) { -5897 for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { -5898 e.f.splice(i, 1); -5899 break; -5900 } -5901 !e.f.length && delete e.f; -5902 } -5903 for (key in e.n) if (e.n[has](key) && e.n[key].f) { -5904 var funcs = e.n[key].f; -5905 for (i = 0, ii = funcs.length; i < ii; i++) if (funcs[i] == f) { -5906 funcs.splice(i, 1); -5907 break; -5908 } -5909 !funcs.length && delete e.n[key].f; -5910 } -5911 } else { -5912 delete e.f; -5913 for (key in e.n) if (e.n[has](key) && e.n[key].f) { -5914 delete e.n[key].f; -5915 } -5916 } -5917 e = e.n; -5918 } -5919 } -5920 return true; -5921 }; -5922 eve.version = version; -5923 eve.toString = function () { -5924 return "You are running Eve " + version; -5925 }; -5926 return eve; -5927 })(); -5928})(); +5794 /* +5795 * Eve 0.2.1 - JavaScript Events Library +5796 * +5797 * Copyright (c) 2010 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) +5798 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. +5799 */ +5800 +5801 var eve = R.eve = (function () { +5802 var version = "0.2.1", +5803 has = "hasOwnProperty", +5804 separator = /[\.\/]/, +5805 wildcard = "*", +5806 events = {n: {}}, +5807 eve = function (name, scope) { +5808 var e = events, +5809 args = Array.prototype.slice.call(arguments, 2), +5810 listeners = eve.listeners(name), +5811 errors = []; +5812 for (var i = 0, ii = listeners.length; i < ii; i++) { +5813 try { +5814 listeners[i].apply(scope, args); +5815 } catch (ex) { +5816 errors.push({error: ex && ex.message || ex, func: listeners[i]}); +5817 } +5818 } +5819 if (errors.length) { +5820 return errors; +5821 } +5822 }; +5823 eve.listeners = function (name) { +5824 var names = name.split(separator), +5825 e = events, +5826 item, +5827 items, +5828 k, +5829 i, +5830 ii, +5831 j, +5832 jj, +5833 nes, +5834 es = [e], +5835 out = []; +5836 for (i = 0, ii = names.length; i < ii; i++) { +5837 nes = []; +5838 for (j = 0, jj = es.length; j < jj; j++) { +5839 e = es[j].n; +5840 items = [e[names[i]], e[wildcard]]; +5841 k = 2; +5842 while (k--) { +5843 item = items[k]; +5844 if (item) { +5845 nes.push(item); +5846 out = out.concat(item.f || []); +5847 } +5848 } +5849 } +5850 es = nes; +5851 } +5852 return out; +5853 }; +5854 eve.on = function (name, f) { +5855 var names = name.split(separator), +5856 e = events; +5857 for (var i = 0, ii = names.length; i < ii; i++) { +5858 e = e.n; +5859 !e[names[i]] && (e[names[i]] = {n: {}}); +5860 e = e[names[i]]; +5861 } +5862 e.f = e.f || []; +5863 for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { +5864 return false; +5865 } +5866 e.f.push(f); +5867 }; +5868 eve.unbind = function (name, f) { +5869 var names = name.split(separator), +5870 e, +5871 key, +5872 splice, +5873 cur = [events]; +5874 for (var i = 0, ii = names.length; i < ii; i++) { +5875 for (var j = 0; j < cur.length; j += splice.length - 2) { +5876 splice = [j, 1]; +5877 e = cur[j].n; +5878 if (names[i] != wildcard) { +5879 if (e[names[i]]) { +5880 splice.push(e[names[i]]); +5881 } +5882 } else { +5883 for (key in e) if (e[has](key)) { +5884 splice.push(e[key]); +5885 } +5886 } +5887 cur.splice.apply(cur, splice); +5888 } +5889 } +5890 for (i = 0, ii = cur.length; i < ii; i++) { +5891 e = cur[i]; +5892 while (e.n) { +5893 if (f) { +5894 if (e.f) { +5895 for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { +5896 e.f.splice(i, 1); +5897 break; +5898 } +5899 !e.f.length && delete e.f; +5900 } +5901 for (key in e.n) if (e.n[has](key) && e.n[key].f) { +5902 var funcs = e.n[key].f; +5903 for (i = 0, ii = funcs.length; i < ii; i++) if (funcs[i] == f) { +5904 funcs.splice(i, 1); +5905 break; +5906 } +5907 !funcs.length && delete e.n[key].f; +5908 } +5909 } else { +5910 delete e.f; +5911 for (key in e.n) if (e.n[has](key) && e.n[key].f) { +5912 delete e.n[key].f; +5913 } +5914 } +5915 e = e.n; +5916 } +5917 } +5918 return true; +5919 }; +5920 eve.version = version; +5921 eve.toString = function () { +5922 return "You are running Eve " + version; +5923 }; +5924 return eve; +5925 })(); +5926})(); \ No newline at end of file diff --git a/raphael.js b/raphael.js index 571cc90..9f39b0c 100644 --- a/raphael.js +++ b/raphael.js @@ -29,8 +29,9 @@ - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`. = (object) @Paper > Usage - | // Each of the following examples create a canvas that is 320px wide by 200px high - | // Canvas is created at the viewport’s 10,50 coordinate + | // Each of the following examples create a canvas + | // that is 320px wide by 200px high. + | // Canvas is created at the viewport’s 10,50 coordinate. | var paper = Raphael(10, 50, 320, 200); | // Canvas is created at the top left corner of the #notepad element | // (or its top right corner in dir="rtl" elements) @@ -685,12 +686,12 @@ > Parameters - colour (string) colour string in one of formats: # -

Element.clone()

+

 Element.clone()

Returns: object clone of a given element

-

Element.drag(onmove, onstart, onend, [mcontext], [scontext], [econtext])

+

 Element.drag(onmove, onstart, onend, [mcontext], [scontext], [econtext])

Adds event handlers for drag of the element.

Parameters @@ -229,7 +229,7 @@ at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can o

  1. eventobjectDOM event object

Returns: object Element

-

Element.getBBox(isWithoutTransform)

+

 Element.getBBox(isWithoutTransform)

Return bounding box for a given element

Parameters @@ -244,7 +244,7 @@ at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can o

  • width:numberwidth
  • height:numberheight
  • }
  • -

    Element.getPointAtLength(length)

    +

     Element.getPointAtLength(length)

    Return coordinates of the point located at the given length on the given path. Only works for element of “path” type.

    Parameters @@ -258,7 +258,7 @@ at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can o

  • y:numbery coordinate
  • alpha:numberangle of derivative
  • }
  • -

    Element.getSubpath(from, to)

    +

     Element.getSubpath(from, to)

    Return subpath of a given element from given length to given length. Only works for element of “path” type.

    Parameters @@ -271,21 +271,21 @@ at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can o

    position of the end of the segment

    Returns: string pathstring for the segment

    -

    Element.getTotalLength()

    +

     Element.getTotalLength()

    Returns length of the path in pixels. Only works for element of “path” type.

    Returns: number length.

    -

    Element.glow()

    +

     Element.glow()

    Return set of elements that create glow-like effect around given element. See Paper.set.

    -

    Note: Glow is not connected to the elment. If you change element attributes it won’t adjust itself. +

    Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself.

    Returns: object Paper.set of elements that represents glow

    -

    Element.hide()

    +

     Element.hide()

    Makes element invisible. See Element.show.

    Returns: object Element

    -

    Element.hover(f_in, f_out, [icontext], [ocontext])

    +

     Element.hover(f_in, f_out, [icontext], [ocontext])

    Adds event handlers for hover for the element.

    Parameters @@ -306,22 +306,22 @@ at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can o

    context for hover out handler

    Returns: object Element

    -

    Element.id

    +

     Element.id

    number

    Unique id of the element. Especially usesful when you want to listen to events of the element, because all events are fired in format <module>.<action>.<id>. Also useful for Paper.getById method.

    -

    Element.insertAfter()

    +

     Element.insertAfter()

    Inserts current object after the given one.

    Returns: object Element

    -

    Element.insertBefore()

    +

     Element.insertBefore()

    Inserts current object before the given one.

    Returns: object Element

    -

    Element.next

    +

     Element.next

    object

    Reference to the next element in the hierarchy.

    -

    Element.node

    +

     Element.node

    object

    Gives you a reference to the DOM object, so you can assign event handlers or just mess around.

    Usage @@ -332,7 +332,7 @@ c.node.onclick = function () { c.attr("fill", "red"); }; -

    Element.onDragOver(f)

    +

     Element.onDragOver(f)

    Shortcut for assigning event handler for drag.over.<id> event, where id is id of the element (see Element.id).

    Parameters @@ -341,7 +341,7 @@ c.node.onclick = function () {

    function
    handler for event
    -

    Element.paper

    +

     Element.paper

    object

    Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions.

    Usage @@ -352,7 +352,7 @@ c.node.onclick = function () { .attr({stroke: "red"}); } -

    Element.pause([anim])

    +

     Element.pause([anim])

    Stops animation of the element with ability to resume it later on.

    Parameters @@ -363,10 +363,10 @@ c.node.onclick = function () {

    animation object

    Returns: object original element

    -

    Element.prev

    +

     Element.prev

    object

    Reference to the previous element in the hierarchy.

    -

    Element.raphael

    +

     Element.raphael

    object

    Internal reference to Raphael object. In case it is not available.

    Usage @@ -377,10 +377,10 @@ c.node.onclick = function () { this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex}); } -

    Element.remove()

    +

     Element.remove()

    Removes element form the paper.

    -

    Element.resume([anim])

    +

     Element.resume([anim])

    Resumes animation if it was paused with Element.pause method.

    Parameters @@ -391,7 +391,7 @@ c.node.onclick = function () {

    animation object

    Returns: object original element

    -

    Element.rotate(deg, [cx], [cy])

    +

     Element.rotate(deg, [cx], [cy])

    Adds rotation by given angle around given point to the list of transformations of the element.

    @@ -412,7 +412,7 @@ transformations of the element.

    If cx & cy aren’t specified centre of the shape is used as a point of rotation.

    Returns: object Element

    -

    Element.scale(sx, sy, [cx], [cy])

    +

     Element.scale(sx, sy, [cx], [cy])

    Adds scale by given amount relative to given point to the list of transformations of the element.

    @@ -436,7 +436,7 @@ transformations of the element.

    If cx & cy aren’t specified centre of the shape is used instead.

    Returns: object Element

    -

    Element.setTime(anim, value)

    +

     Element.setTime(anim, value)

    Sets the status of animation of the element in milliseconds. Similar to Element.status method.

    Parameters @@ -453,11 +453,11 @@ transformations of the element.

    On each animation frame event anim.frame.<id>, on start anim.start.<id> and on end anim.finish.<id>.

    -

    Element.show()

    +

     Element.show()

    Makes element visible. See Element.hide.

    Returns: object Element

    -

    Element.status([anim], [value])

    +

     Element.status([anim], [value])

    Gets or sets the status of animation of the element.

    Parameters @@ -481,7 +481,7 @@ transformations of the element.

    or

    Returns: object original element if value is specified

    -

    Element.stop([anim])

    +

     Element.stop([anim])

    Stops animation of the element.

    Parameters @@ -492,15 +492,15 @@ transformations of the element.

    animation object

    Returns: object original element

    -

    Element.toBack()

    +

     Element.toBack()

    Moves the element so it is the furthest from the viewer’s eyes, behind other elements.

    Returns: object Element

    -

    Element.toFront()

    +

     Element.toFront()

    Moves the element so it is the closest to the viewer’s eyes, on top of other elements.

    Returns: object Element

    -

    Element.transform([tstr])

    +

     Element.transform([tstr])

    Adds transformation to the element which is separate to other attributes, i.e. translation doesn’t change x or y of the rectange. The format of transformation string is similar to the path string syntax: @@ -510,9 +510,9 @@ of transformation string is similar to the path string syntax:

    Each letter is a command. There are four commands: t is for translate, r is for rotate, s is for scale and m is for matrix.

    -

    So, example line could be read like “translate by 100, 100, rotate 30° around 100, 100, scale twice around 100, 100 -rotate 45° around centre and scale 1.5 times relative to centre”. As you see rotate and scale commands has origin -coordinates as a optional parameters. +

    So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100; +rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin +coordinates as optional parameters, the default is the centre point of the element. Matrix accepts six parameters.

    Usage @@ -543,7 +543,7 @@ console.log(el.transform());

    else

    Returns: object Element

    -

    Element.translate(dx, dy)

    +

     Element.translate(dx, dy)

    Adds translation by given amount to the list of transformations of the element.

    Parameters @@ -556,10 +556,10 @@ console.log(el.transform());

    vertical shift

    Returns: object Element

    -

    Element.undrag()

    +

     Element.undrag()

    Removes all drag event handlers from given element.

    -

    Element.unhover(f_in, f_out)

    +

     Element.unhover(f_in, f_out)

    Removes event handlers for hover for the element.

    Parameters @@ -572,11 +572,11 @@ console.log(el.transform());

    handler for hover out

    Returns: object Element

    -

    Paper

    -

    Paper.bottom

    +

     Paper

    +

     Paper.bottom

    Points to the bottom element on the paper

    -

    Paper.circle(x, y, r)

    +

     Paper.circle(x, y, r)

    Draws a circle.

    Parameters @@ -596,10 +596,10 @@ console.log(el.transform());

    var c = paper.circle(50, 50, 40);
     
    -

    Paper.clear()

    +

     Paper.clear()

    Clears the paper, i.e. removes all the elements.

    -

    Paper.customAttributes

    +

     Paper.customAttributes

    object

    If you have a set of attributes that you would like to represent as a function of some number you can do it easily with custom attributes:

    @@ -624,7 +624,7 @@ paper.customAttributes.hsb = function (h, s, b) { c.attr({hsb: ".5 .8 1"}); c.animate({hsb: "1 0 .5"}, 1e3); -

    Paper.ellipse(x, y, rx, ry)

    +

     Paper.ellipse(x, y, rx, ry)

    Draws an ellipse.

    Parameters @@ -637,7 +637,7 @@ c.animate({hsb: "1 0 y coordinate of the centre

    rx
    number
    -
    horisontal radius
    +
    horizontal radius
    ry
    number
    vertical radius
    @@ -647,10 +647,10 @@ c.animate({hsb: "1 0
    var c = paper.ellipse(50, 50, 40, 20);
     
    -

    Paper.forEach(callback, thisArg)

    +

     Paper.forEach(callback, thisArg)

    Executes given function for each element on the paper

    -

    If function returns false it will stop loop running. +

    If callback function returns false it will stop loop running.

    Parameters

    @@ -662,8 +662,8 @@ c.animate({hsb: "1 0 context object for the callback

    Returns: object Paper object

    -

    Paper.getById(id)

    -

    Returns you element by it’s internal ID. +

     Paper.getById(id)

    +

    Returns you element by its internal ID.

    Parameters

    @@ -672,7 +672,7 @@ c.animate({hsb: "1 0 id

    Returns: object Raphaël element object

    -

    Paper.getElementByPoint(x, y)

    +

     Paper.getElementByPoint(x, y)

    Returns you topmost element under given point.

    Returns: object Raphaël element object

    @@ -689,7 +689,7 @@ c.animate({hsb: "1 0
    paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"});
     
    -

    Paper.image(src, x, y, width, height)

    +

     Paper.image(src, x, y, width, height)

    Embeds an image into the surface.

    Parameters @@ -715,7 +715,7 @@ c.animate({hsb: "1 0

    var c = paper.image("apple.png", 10, 10, 80, 80);
     
    -

    Paper.path(pathString)

    +

     Paper.path(pathString)

    Creates a path element by given path data string.

    Parameters @@ -732,10 +732,10 @@ Details of a path's data attribute's format are described in the // draw a diagonal line: // move to 10,10, line to 90,90 -

    Paper.raphael

    +

     Paper.raphael

    Points to the Raphael object/function

    -

    Paper.rect(x, y, width, height, r)

    +

     Paper.rect(x, y, width, height, [r])

    Draws a rectangle.

    @@ -753,9 +753,10 @@ Details of a path's data attribute's format are described in the height
    number
    height
    -
    r
    +
    r
    +
    optional
    number
    -
    optional radius for rounded corners, default is 0
    +
    radius for rounded corners, default is 0

    Returns: object Raphaël element object with type “rect”

    Usage @@ -765,33 +766,18 @@ Details of a path's data attribute's format are described in the // rectangle with rounded corners var c = paper.rect(40, 40, 50, 50, 10); -

    Paper.remove()

    +

     Paper.remove()

    Removes the paper from the DOM.

    -

    Paper.safari(f_in, f_out, [icontext], [ocontext])

    -

    Adds event handlers for hover for the element. +

     Paper.safari()

    +

    There is an inconvenient rendering bug in Safari (WebKit): +sometimes the rendering should be forced. +This method should help with dealing with this bug.

    -

    Parameters -

    -
    f_in
    -
    function
    -
    handler for hover in
    -
    f_out
    -
    function
    -
    handler for hover out
    -
    icontext
    -
    optional
    -
    object
    -
    context for hover in handler
    -
    ocontext
    -
    optional
    -
    object
    -
    context for hover out handler
    -
    -

    Returns: object Element

    -

    Paper.set()

    -

    Creates array-like object to keep and operate couple of elements at once. -Warning: it doesn’t create any elements for itself in the page. +

     Paper.set()

    +

    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.

    Returns: object array-like object that represents set of elements

    Usage @@ -803,7 +789,7 @@ st.push( ); st.attr({fill: "red"}); -

    Paper.setSize(width, height)

    +

     Paper.setSize(width, height)

    If you need to change dimensions of the canvas call this method

    Parameters @@ -824,7 +810,7 @@ st.push( ); st.attr({fill: "red"}); -

    Paper.setViewBox(x, y, w, h, fit)

    +

     Paper.setViewBox(x, y, w, h, fit)

    Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by specifying new boundaries.

    @@ -846,7 +832,7 @@ specifying new boundaries.
    boolean
    true if you want graphics to fit into new boundary box
    -

    Paper.text(x, y, text)

    +

     Paper.text(x, y, text)

    Draws a text string. If you need line breaks, put “\n” in the string.

    Parameters @@ -866,10 +852,10 @@ specifying new boundaries.

    var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!");
     
    -

    Paper.top

    +

     Paper.top

    Points to the topmost element on the paper

    -

    Raphael(…)

    +

     Raphael(…)

    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. @@ -878,7 +864,7 @@ from this instance will be bound to this canvas.

    container
    HTMLElement string
    -
    DOM element or it’s id which is going to be a parent for drawing surface
    +
    DOM element or its ID which is going to be a parent for drawing surface
    width
    number
     
    @@ -916,8 +902,9 @@ from this instance will be bound to this canvas.

    Returns: object Paper

    Usage

    -
    // Each of the following examples create a canvas that is 320px wide by 200px high
    -// Canvas is created at the viewport’s 10,50 coordinate
    +
    // Each of the following examples create a canvas
    +// that is 320px wide by 200px high.
    +// Canvas is created at the viewport’s 10,50 coordinate.
     var paper = Raphael(10, 50, 320, 200);
     // Canvas is created at the top left corner of the #notepad element
     // (or its top right corner in dir="rtl" elements)
    @@ -939,7 +926,7 @@ from this instance will be bound to this canvas.
         text: "Dump"
     }]);
     
    -

    Raphael.angle(x1, y1, x2, y2, [x3], [y3])

    +

     Raphael.angle(x1, y1, x2, y2, [x3], [y3])

    Returns angle between two or three points

    Parameters @@ -966,8 +953,8 @@ from this instance will be bound to this canvas.

    y coord of third point

    Returns: number angle in degrees.

    -

    Raphael.animation(params, ms, [easing], [callback])

    -

    Creates animation object. That later could be used for Element.animate or Element.animateWith methods. +

     Raphael.animation(params, ms, [easing], [callback])

    +

    Creates an animation object that can be passed to the Element.animate or Element.animateWith methods. See also Animation.delay and Animation.repeat methods.

    Parameters @@ -988,7 +975,7 @@ See also Animation.delay and callback function. Will be called at the end of animation.

    Returns: object Animation

    -

    Raphael.deg(deg)

    +

     Raphael.deg(deg)

    Transform angle to degrees

    Parameters @@ -998,8 +985,8 @@ See also Animation.delay and angle in radians

    Returns: number angle in degrees.

    -

    Raphael.easing_formulas

    -

    Object that contains easing formulas for animation. You could extend it with your owns. By default it has following list of easing: +

     Raphael.easing_formulas

    +

    Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:

    See also Easing demo.

    -

    Raphael.el

    +

     Raphael.el

    object

    You can add your own method to elements. This is usefull 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 +you can redefine element method at any time. Expending element methods wouldn’t affect set.

    Usage

    @@ -1025,7 +1012,7 @@ you can redefine element method at any time. Expending element methods wouldn’ // then use it paper.circle(100, 100, 20).red();
    -

    Raphael.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t)

    +

     Raphael.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t)

    Utility method Find dot coordinates on the given cubic bezier curve at the given t.

    @@ -1072,12 +1059,12 @@ Find dot coordinates on the given cubic bezier curve at the given t.
  • y:numbery coordinate of the end of the curve
  • }
  • alpha:numberangle of the curve derivative at the point
  • }
  • -

    Raphael.fn

    -
    object

    You can add your own method to the canvas. For example if you want to draw pie chart, +

     Raphael.fn

    +
    object

    You can add your own method to the canvas. For example if you want to draw a pie chart, you can create your own pie chart function and ship it as a Raphaël plugin. To do this -you need to extend Raphael.fn object. Please note that you can create your own namespaces -inside fn object. Methods will be run in context of canvas anyway. You should alter fn -object before Raphaël instance was created, otherwise it will take no effect. +you need to extend the Raphael.fn object. Please note that you can create your own namespaces +inside the fn object — methods will be run in the context of canvas anyway. You should alter +the fn object before a Raphaël instance is created, otherwise it will take no effect.

    Usage

    @@ -1096,7 +1083,7 @@ paper.arrow(10, 10, Raphael.getColor([value]) +

     Raphael.getColor([value])

    On each call returns next colour in the spectrum. To reset it back to red call Raphael.getColor.reset

    Parameters @@ -1107,10 +1094,10 @@ paper.mystuff.star();

    brightness, default is 0.75

    Returns: string hex representation of the colour.

    -

    Raphael.getColor.reset()

    +

     Raphael.getColor.reset()

    Resets spectrum position for Raphael.getColor back to red.

    -

    Raphael.getPointAtLength(path, length)

    +

     Raphael.getPointAtLength(path, length)

    Return coordinates of the point located at the given length on the given path.

    Parameters @@ -1127,7 +1114,7 @@ paper.mystuff.star();

  • y:numbery coordinate
  • alpha:numberangle of derivative
  • }
  • -

    Raphael.getRGB(colour)

    +

     Raphael.getRGB(colour)

    Parses colour string as RGB object

    Parameters @@ -1136,6 +1123,17 @@ paper.mystuff.star();

    string
    colour string in one of formats:
    +
      +
    • Colour name (“red”, “green”, “cornflowerblue”, etc)
    • +
    • #••• — shortened HTML colour: (“#000”, “#fc0”, etc)
    • +
    • #•••••• — full length HTML colour: (“#000000”, “#bd2300”)
    • +
    • rgb(•••, •••, •••) — red, green and blue channels’ values: (“rgb(200, 100, 0)”)
    • +
    • rgb(•••%, •••%, •••%) — same as above, but in %: (“rgb(100%, 175%, 0%)”)
    • +
    • hsb(•••, •••, •••) — hue, saturation and brightness values: (“hsb(0.5, 0.25, 1)”)
    • +
    • hsb(•••%, •••%, •••%) — same as above, but in %
    • +
    • hsl(•••, •••, •••) — same as hsb
    • +
    • hsl(•••%, •••%, •••%) — same as hsb
    • +

    Returns: object RGB object in format:

    1. {
      1. rnumberred,
      2. gnumbergreen, @@ -1143,7 +1141,7 @@ paper.mystuff.star();
      3. hexstringcolor in HTML/CSS format: #••••••,
      4. errorbooleantrue if string can’t be parsed
    2. }
    -

    Raphael.getSubpath(path, from, to)

    +

     Raphael.getSubpath(path, from, to)

    Return subpath of a given path from given length to given length.

    Parameters @@ -1159,7 +1157,7 @@ paper.mystuff.star();

    position of the end of the segment

    Returns: string pathstring for the segment

    -

    Raphael.getTotalLength(path)

    +

     Raphael.getTotalLength(path)

    Returns length of the given path in pixels.

    Parameters @@ -1169,7 +1167,7 @@ paper.mystuff.star();

    SVG path string.

    Returns: number length.

    -

    Raphael.hsb(h, s, b)

    +

     Raphael.hsb(h, s, b)

    Converts HSB values to hex representation of the colour.

    Parameters @@ -1185,7 +1183,7 @@ paper.mystuff.star();

    value or brightness

    Returns: string hex representation of the colour.

    -

    Raphael.hsb2rgb(h, s, v)

    +

     Raphael.hsb2rgb(h, s, v)

    Converts HSB values to RGB object.

    Parameters @@ -1206,7 +1204,7 @@ paper.mystuff.star();

  • bnumberblue,
  • hexstringcolor in HTML/CSS format: #••••••
  • }
  • -

    Raphael.hsl(h, s, l)

    +

     Raphael.hsl(h, s, l)

    Converts HSL values to hex representation of the colour.

    Parameters @@ -1222,7 +1220,7 @@ paper.mystuff.star();

    luminosity

    Returns: string hex representation of the colour.

    -

    Raphael.hsl2rgb(h, s, l)

    +

     Raphael.hsl2rgb(h, s, l)

    Converts HSL values to RGB object.

    Parameters @@ -1243,7 +1241,7 @@ paper.mystuff.star();

  • bnumberblue,
  • hexstringcolor in HTML/CSS format: #••••••
  • }
  • -

    Raphael.is(o, type)

    +

     Raphael.is(o, type)

    Handfull replacement for typeof operator.

    Parameters @@ -1256,7 +1254,7 @@ paper.mystuff.star();

    name of the type, i.e. “string”, “function”, “number”, etc.

    Returns: boolean is given value is of given type

    -

    Raphael.parsePathString(pathString)

    +

     Raphael.parsePathString(pathString)

    Utility method Parses given path string into an array of arrays of path segments.

    @@ -1264,10 +1262,10 @@ Parses given path string into an array of arrays of path segments.

    pathString
    string array
    -
    path string or array of segments (in the last case it will be returned stright away)
    +
    path string or array of segments (in the last case it will be returned straight away)

    Returns: array array of segments.

    -

    Raphael.parseTransformString(TString)

    +

     Raphael.parseTransformString(TString)

    Utility method Parses given path string into an array of transformations.

    @@ -1275,12 +1273,12 @@ Parses given path string into an array of transformations.

    TString
    string array
    -
    transform string or array of transformations (in the last case it will be returned stright away)
    +
    transform string or array of transformations (in the last case it will be returned straight away)

    Returns: array array of transformations.

    -

    Raphael.path2curve(pathString)

    +

     Raphael.path2curve(pathString)

    Utility method -Converts path to path where all segments are cubic bezier curves. +Converts path to a new path where all segments are cubic bezier curves.

    Parameters

    @@ -1289,7 +1287,7 @@ Converts path to path where all segments are cubic bezier curves.
    path string or array of segments

    Returns: array array of segments.

    -

    Raphael.pathToRelative(pathString)

    +

     Raphael.pathToRelative(pathString)

    Utility method Converts path to relative form

    @@ -1300,7 +1298,7 @@ Converts path to relative form
    path string or array of segments

    Returns: array array of segments.

    -

    Raphael.rad(deg)

    +

     Raphael.rad(deg)

    Transform angle to radians

    Parameters @@ -1310,7 +1308,7 @@ Converts path to relative form

    angle in degrees

    Returns: number angle in radians.

    -

    Raphael.rgb(r, g, b)

    +

     Raphael.rgb(r, g, b)

    Converts RGB values to hex representation of the colour.

    Parameters @@ -1326,7 +1324,7 @@ Converts path to relative form

    blue

    Returns: string hex representation of the colour.

    -

    Raphael.rgb2hsb(r, g, b)

    +

     Raphael.rgb2hsb(r, g, b)

    Converts RGB values to HSB object.

    Parameters @@ -1346,7 +1344,7 @@ Converts path to relative form

  • snumbersaturation
  • bnumberbrightness
  • }
  • -

    Raphael.rgb2hsl(r, g, b)

    +

     Raphael.rgb2hsl(r, g, b)

    Converts RGB values to HSL object.

    Parameters @@ -1366,7 +1364,7 @@ Converts path to relative form

  • snumbersaturation
  • lnumberluminosity
  • }
  • -

    Raphael.setWindow(newwin)

    +

     Raphael.setWindow(newwin)

    Used when you need to draw in <iframe>. Switched window to the iframe one.

    Parameters @@ -1375,7 +1373,7 @@ Converts path to relative form

    window
    new window object
    -

    Raphael.snapTo(values, value, [tolerance])

    +

     Raphael.snapTo(values, value, [tolerance])

    Snaps given value to given grid.

    Parameters @@ -1392,17 +1390,17 @@ Converts path to relative form

    tolerance for snapping. Default is 10.

    Returns: number adjusted value.

    -

    Raphael.svg

    +

     Raphael.svg

    boolean

    true if browser supports SVG.

    -

    Raphael.type

    +

     Raphael.type

    string

    Can be “SVG”, “VML” or empty, depending on browser support.

    -

    Raphael.vml

    +

     Raphael.vml

    boolean

    true if browser supports VML.

    -

    Set

    -

    Set.forEach(callback, thisArg)

    +

     Set

    +

     Set.forEach(callback, thisArg)

    Executes given function for each element in the set.

    If function returns false it will stop loop running. @@ -1417,11 +1415,11 @@ Converts path to relative form

    context object for the callback

    Returns: object Set object

    -

    Set.pop()

    +

     Set.pop()

    Removes last element and returns it.

    Returns: object element

    -

    Set.push()

    +

     Set.push()

    Adds each argument to the current set.

    Returns: object original element