From e345e3b514671b782c571ba90c810535cc910427 Mon Sep 17 00:00:00 2001 From: Dmitry Baranovskiy Date: Wed, 23 Mar 2011 12:36:40 +1100 Subject: [PATCH] Small fix to glow and animation. Added renderfix() method for subpixel rendering fix in Firefox and IE9. Special thanks to Mariusz Nowak. --- raphael-min.js | 2 +- raphael-src.html | 6010 +++++++++++++++++++++++----------------------- raphael.js | 72 +- reference.html | 111 +- 4 files changed, 3161 insertions(+), 3034 deletions(-) diff --git a/raphael-min.js b/raphael-min.js index 2ddda5f..b2a9353 100644 --- a/raphael-min.js +++ b/raphael-min.js @@ -5,4 +5,4 @@ * Copyright (c) 2011 Sencha Labs (http://sencha.com) * Licensed under the MIT (http://raphaeljs.com/license.html) license. */ -(function(){function c$(c,d,e,g,h){e=P(e);var i,j,k,l=[],m,n,o,p=c.ms,r={},s={},t={};if(g)for(v=0,w=cU.length;vg*c.top){e=c.percents[v],n=c.percents[v-1]||0,p=p/c.top*(e-n),m=c.percents[v+1],i=c.anim[e];break}g&&d.attr(c.anim[c.percents[v]])}if(!!i){if(!j){for(attr in i)if(i[f](attr))if(U[f](attr)||d.paper.customAttributes[f](attr)){r[attr]=d.attr(attr),r[attr]==null&&(r[attr]=T[attr]),s[attr]=i[attr];switch(U[attr]){case B:t[attr]=(s[attr]-r[attr])/p;break;case"colour":r[attr]=a.getRGB(r[attr]);var x=a.getRGB(s[attr]);t[attr]={r:(x.r-r[attr].r)/p,g:(x.g-r[attr].g)/p,b:(x.b-r[attr].b)/p};break;case"path":var y=bC(r[attr],s[attr]),z=y[1];r[attr]=y[0],t[attr]=[];for(v=0,w=r[attr].length;vd)return d;while(cf?c=e:d=e,e=(d-c)/2+c}return e}function n(a,b){var c=o(a,b);return((l*c+k)*c+j)*c}function m(a){return((i*a+h)*a+g)*a}var g=3*b,h=3*(d-b)-g,i=1-g-h,j=3*c,k=3*(e-c)-j,l=1-j-k;return n(a,1/(200*f))}function cM(){return this.x+p+this.y+p+this.width+"×"+this.height}function cL(){return this.x+p+this.y}function bP(a,b,c,d,e,f){a!=null?this.m=[[a,c,e],[b,d,f],[0,0,1]]:this.m=[[1,0,0],[0,1,0],[0,0,1]]}function bs(a,b){var c=g.doc.createElement("img");c.style.cssText="position:absolute;left:-9999em;top-9999em",c.onload=function(){b.call(this),this.onload=null,g.doc.body.removeChild(this)},c.onerror=function(){g.doc.body.removeChild(this)},g.doc.body.appendChild(c),c.src=a}function br(a,b,c){function d(){var e=Array.prototype.slice.call(arguments,0),g=e.join("␀"),h=d.cache=d.cache||{},i=d.count=d.count||[];if(h[f](g))return c?c(h[g]):h[g];i.length>=1e3&&delete h[i.shift()],i.push(g),h[g]=a[l](b,e);return c?c(h[g]):h[g]}return d}function a(b){if(a.is(b,"function"))return dc.on("DOMload",b);if(a.is(b,D)){var d=b,e=cl[l](a,d.splice(0,3+a.is(d[0],B))),g=e.set(),h=0,i=d.length,j;for(;h',bj=bi.firstChild,bj.style.behavior="url(#default#VML)";if(!bj||typeof bj.adj!="object")return a.type=o;bi=null}a.svg=!(a.vml=a.type=="VML"),j=i.prototype=a.prototype,j.customAttributes={},a._id=0,a._oid=0,a.fn={},a.is=function(a,b){b=u.call(b);if(b=="finite")return!L[f](+a);return b=="null"&&a===null||b==typeof a||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||G.call(a).slice(8,-1).toLowerCase()==b},a.angle=function(b,c,d,e,f,g){if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return(180+v.atan2(-i,-h)*180/A+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)},a.rad=function(a){return a%360*A/180},a.deg=function(a){return a*180/A%360},a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,D)){var e=b.length;while(e--)if(y(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(fb-d)return c-f+b}return c};var bk=function(a,b){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=v.random()*16|0,c=a=="x"?b:b&3|8;return c.toString(16)});a.setWindow=function(b){dc("setWindow",a,g.win,b),g.win=b,g.doc=g.win.document,cz&&cz(g.win)};var bl=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write(""),e.close(),d=e.body}catch(f){d=createPopup().document.body}var h=d.createTextRange();bl=br(function(a){try{d.style.color=q(a).replace(c,o);var b=h.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b.toString(16)).slice(-6)}catch(e){return"none"}})}else{var i=g.doc.createElement("i");i.title="Raphaël Colour Picker",i.style.display="none",g.doc.body.appendChild(i),bl=br(function(a){i.style.color=a;return g.doc.defaultView.getComputedStyle(i,o).getPropertyValue("color")})}return bl(b)},bm=function(){return"hsb("+[this.h,this.s,this.b]+")"},bn=function(){return"hsl("+[this.h,this.s,this.l]+")"},bo=function(){return this.hex},bp=function(b,c,d){c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b&&(d=b.b,c=b.g,b=b.r);if(c==null&&a.is(b,C)){var e=a.getRGB(b);b=e.r,c=e.g,d=e.b}if(b>1||c>1||d>1)b/=255,c/=255,d/=255;return[b,c,d]},bq=function(b,c,d,e){b*=255,c*=255,d*=255;var f={r:b,g:c,b:d,hex:a.rgb(b,c,d),toString:bo};a.is(e,"finite")&&(f.opacity=e);return f};a.hsb2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"b"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;a=a%360/60,i=c*b,h=i*(1-y(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bq(e,f,g,d)},a.hsl2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"l"in a&&(c=a.l,b=a.s,a=a.h);if(a>1||b>1||c>1)a/=360,b/=100,c/=100;a*=360;var e,f,g,h,i;a=a%360/60,i=2*b*(c<.5?c:1-c),h=i*(1-y(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bq(e,f,g,d)},a.rgb2hsb=function(a,b,c){c=bp(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;f=w(a,b,c),g=f-x(a,b,c),d=g==0?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=d%6*60,e=g==0?0:g/f;return{h:d,s:e,b:f,toString:bm}},a.rgb2hsl=function(a,b,c){c=bp(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;g=w(a,b,c),h=x(a,b,c),i=g-h,d=i==0?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=d%6*60,f=(g+h)/2,e=i==0?0:f<.5?i/(2*f):i/(2-2*f);return{h:d,s:e,l:f,toString:bn}},a._path2string=function(){return this.join(",").replace(X,"$1")},a.getRGB=br(function(b){if(!b||!!((b=q(b)).indexOf("-")+1))return{r:-1,g:-1,b:-1,hex:"none",error:1};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none"};!W[f](b.toLowerCase().substring(0,2))&&b.charAt()!="#"&&(b=bl(b));var c,d,e,g,h,i,j,k=b.match(K);if(k){k[2]&&(g=Q(k[2].substring(5),16),e=Q(k[2].substring(3,5),16),d=Q(k[2].substring(1,3),16)),k[3]&&(g=Q((i=k[3].charAt(3))+i,16),e=Q((i=k[3].charAt(2))+i,16),d=Q((i=k[3].charAt(1))+i,16)),k[4]&&(j=k[4].split(V),d=P(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=P(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),g=P(j[2]),j[2].slice(-1)=="%"&&(g*=2.55),k[1].toLowerCase().slice(0,4)=="rgba"&&(h=P(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100));if(k[5]){j=k[5].split(V),d=P(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=P(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),g=P(j[2]),j[2].slice(-1)=="%"&&(g*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsba"&&(h=P(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,g,h)}if(k[6]){j=k[6].split(V),d=P(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=P(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),g=P(j[2]),j[2].slice(-1)=="%"&&(g*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsla"&&(h=P(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,g,h)}k={r:d,g:e,b:g},k.hex="#"+(16777216|g|e<<8|d<<16).toString(16).slice(1),a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1}},a),a.hsb=br(function(b,c,d){return a.hsb2rgb(b,c,d).hex}),a.hsl=br(function(b,c,d){return a.hsl2rgb(b,c,d).hex}),a.rgb=br(function(a,b,c){return"#"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b}));return c.hex},a.getColor.reset=function(){delete this.start},a.parsePathString=br(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,D)&&a.is(b[0],D)&&(d=bu(b)),d.length||q(b).replace(Y,function(a,b,e){var f=[],g=u.call(b);e.replace($,function(a,b){b&&f.push(+b)}),g=="m"&&f.length>2&&(d.push([b][m](f.splice(0,2))),g="l",b=b=="m"?"l":"L");while(f.length>=c[g]){d.push([b][m](f.splice(0,c[g])));if(!c[g])break}}),d.toString=a._path2string;return d}),a.parseTransformString=br(function(b){if(!b)return null;var c={r:3,s:4,t:2,m:6},d=[];a.is(b,D)&&a.is(b[0],D)&&(d=bu(b)),d.length||q(b).replace(Z,function(a,b,c){var e=[],f=u.call(b);c.replace($,function(a,b){b&&e.push(+b)}),d.push([f][m](e))}),d.toString=a._path2string;return d}),a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=z(j,3)*a+z(j,2)*3*i*c+j*3*i*i*e+z(i,3)*g,l=z(j,3)*b+z(j,2)*3*i*d+j*3*i*i*f+z(i,3)*h,m=a+2*i*(c-a)+i*i*(e-2*c+a),n=b+2*i*(d-b)+i*i*(f-2*d+b),o=c+2*i*(e-c)+i*i*(g-2*e+c),p=d+2*i*(f-d)+i*i*(h-2*f+d),q=(1-i)*a+i*c,r=(1-i)*b+i*d,s=(1-i)*e+i*g,t=(1-i)*f+i*h,u=90-v.atan2(m-o,n-p)*180/A;(m>o||n1&&(u=v.sqrt(u),c=u*c,d=u*d);var w=c*c,x=d*d,z=(f==g?-1:1)*v.sqrt(y((w*x-w*t*t-x*s*s)/(w*t*t+x*s*s))),B=z*c*t/d+(a+h)/2,C=z*-d*s/c+(b+i)/2,D=v.asin(((b-C)/d).toFixed(9)),E=v.asin(((i-C)/d).toFixed(9));D=aE&&(D=D-A*2),!g&&E>D&&(E=E-A*2)}else D=j[0],E=j[1],B=j[2],C=j[3];var F=E-D;if(y(F)>k){var G=E,H=h,I=i;E=D+k*(g&&E>D?1:-1),h=B+c*v.cos(E),i=C+d*v.sin(E),n=bz(h,i,c,d,e,0,g,H,I,[E,G,B,C])}F=E-D;var J=v.cos(D),K=v.sin(D),L=v.cos(E),M=v.sin(E),N=v.tan(F/4),O=4/3*c*N,P=4/3*d*N,Q=[a,b],R=[a+O*K,b-P*J],S=[h+O*M,i-P*L],T=[h,i];R[0]=2*Q[0]-R[0],R[1]=2*Q[1]-R[1];if(j)return[R,S,T][m](n);n=[R,S,T][m](n).join().split(",");var U=[];for(var V=0,W=n.length;V"1e12"&&(m=.5),y(n)>"1e12"&&(n=.5),m>0&&m<1&&(q=bA(a,b,c,d,e,f,g,h,m),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bA(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y)),i=f-2*d+b-(h-2*f+d),j=2*(d-b)-2*(f-d),k=b-d,m=(-j+v.sqrt(j*j-4*i*k))/2/i,n=(-j-v.sqrt(j*j-4*i*k))/2/i,y(m)>"1e12"&&(m=.5),y(n)>"1e12"&&(n=.5),m>0&&m<1&&(q=bA(a,b,c,d,e,f,g,h,m),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bA(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y));return{min:{x:x[l](0,p),y:x[l](0,o)},max:{x:w[l](0,p),y:w[l](0,o)}}}),bC=br(function(a,b){var c=bw(a),d=b&&bw(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1],b.Y=a[2];break;case"A":a=["C"][m](bz[l](0,[b.x,b.y][m](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x)),d=b.y+(b.y-(b.by||b.y)),a=["C",c,d][m](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x)),b.qy=b.y+(b.y-(b.qy||b.y)),a=["C"][m](by(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1],b.qy=a[2],a=["C"][m](by(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][m](bx(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][m](bx(b.x,b.y,a[1],b.y));break;case"V":a=["C"][m](bx(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][m](bx(b.x,b.y,b.X,b.Y))}return a},h=function(a,b){if(a[b].length>7){a[b].shift();var e=a[b];while(e.length)a.splice(b++,0,["C"][m](e.splice(0,6)));a.splice(b,1),k=w(c.length,d&&d.length||0)}},i=function(a,b,e,f,g){a&&b&&a[g][0]=="M"&&b[g][0]!="M"&&(b.splice(g,0,["M",f.x,f.y]),e.bx=0,e.by=0,e.x=a[g][1],e.y=a[g][2],k=w(c.length,d&&d.length||0))};for(var j=0,k=w(c.length,d&&d.length||0);j.5)*2-1;z(f-.5,2)+z(h-.5,2)>.25&&(h=v.sqrt(.25-z(f-.5,2))*e+.5)&&h!=.5&&(h=h.toFixed(5)-1e-5*e)}return o}),c=c.split(/\s*\-\s*/);if(d=="linear"){var m=c.shift();m=-P(m);if(isNaN(m))return null;var n=[0,0,v.cos(a.rad(m)),v.sin(a.rad(m))],p=1/(w(y(n[2]),y(n[3]))||1);n[2]*=p,n[3]*=p,n[2]<0&&(n[0]=-n[2],n[2]=0),n[3]<0&&(n[1]=-n[3],n[3]=0)}var r=bD(c);if(!r)return null;b.gradient&&(j.defs.removeChild(b.gradient),delete b.gradient),l=bU(d+"Gradient",{id:e}),b.gradient=l,bU(l,d=="radial"?{fx:f,fy:h}:{x1:n[0],y1:n[1],x2:n[2],y2:n[3],gradientTransform:b.matrix.invert()}),j.defs.appendChild(l);for(var s=0,t=r.length;s1?z.opacity/100:z.opacity});case"stroke":z=a.getRGB(l),h[O](k,z.hex),k=="stroke"&&z[f]("opacity")&&bU(h,{"stroke-opacity":z.opacity>1?z.opacity/100:z.opacity}),k=="stroke"&&c._.arrows&&("startString"in c._.arrows&&b_(c,c._.arrows.startString),"endString"in c._.arrows&&b_(c,c._.arrows.endString,1));break;case"gradient":(c.type=="circle"||c.type=="ellipse"||q(l).charAt()!="r")&&bZ(c,l);break;case"opacity":i.gradient&&!i[f]("stroke-opacity")&&bU(h,{"stroke-opacity":l>1?l/100:l});case"fill-opacity":if(i.gradient){A=g.doc.getElementById(h.getAttribute(F).replace(/^url\(#|\)$/g,o)),A&&(B=A.getElementsByTagName("stop"),bU(B[B.length-1],{"stop-opacity":l}));break};default:k=="font-size"&&(l=Q(l,10)+"px");var C=k.replace(/(\-.)/g,function(a){return S.call(a.substring(1))});h.style[C]=l,c._.dirty=1,h[O](k,l)}}cc(c,d)},cb=1.2,cc=function(b,c){if(b.type=="text"&&!!(c[f]("text")||c[f]("font")||c[f]("font-size")||c[f]("x")||c[f]("y"))){var d=b.attrs,e=b.node,h=e.firstChild?Q(g.doc.defaultView.getComputedStyle(e.firstChild,o).getPropertyValue("font-size"),10):10;if(c[f]("text")){d.text=c.text;while(e.firstChild)e.removeChild(e.firstChild);var i=q(c.text).split("\n"),j=[],k;for(var l=0,m=i.length;l"));var T=Q.getBoundingClientRect();m.W=h.w=(T.right-T.left)/R,m.H=h.h=(T.bottom-T.top)/R,m.paper.canvas.style.display="none",m.X=h.x,m.Y=h.y+m.H/2,("x"in d||"y"in d)&&(m.path.v=a.format("m{0},{1}l{2},{1}",N(h.x*cs),N(h.y*cs),N(h.x*cs)+1));var U=["x","y","text","font","font-family","font-weight","font-style","font-size"];for(var V=0,W=U.length;V.25&&(c=v.sqrt(.25-z(b-.5,2))*((c>.5)*2-1)+.5),f=b+p+c);return o}),b=b.split(/\s*\-\s*/);if(e=="linear"){var g=b.shift();g=-P(g);if(isNaN(g))return null}var h=bD(b);if(!h)return null;a=a.shape||a.node;if(h.length){a.removeChild(c),c.on=!0,c.method="none",c.color=h[0].color,c.color2=h[h.length-1].color;var i=[];for(var j=0,k=h.length;j')}}catch(c){cy=function(a){return b.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}};cz(g.win),cl=function(){var b=bE[l](0,arguments),c=b.container,d=b.height,e,f=b.width,h=b.x,j=b.y;if(!c)throw new Error("VML container not found.");var k=new i,m=k.canvas=g.doc.createElement("div"),n=m.style;h=h||0,j=j||0,f=f||512,d=d||342,k.width=f,k.height=d,f==+f&&(f+="px"),d==+d&&(d+="px"),k.coordsize=cs*1e3+p+cs*1e3,k.coordorigin="0 0",k.span=g.doc.createElement("span"),k.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;",m.appendChild(k.span),n.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d),c==1?(g.doc.body.appendChild(m),n.left=h+"px",n.top=j+"px",n.position="absolute"):c.firstChild?c.insertBefore(m,c.firstChild):c.appendChild(m),bF.call(k,k,a.fn);return k},j.clear=function(){dc("clear",this),this.canvas.innerHTML=o,this.span=g.doc.createElement("span"),this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;",this.canvas.appendChild(this.span),this.bottom=this.top=null},j.remove=function(){dc("remove",this),this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=bL(a);return!0}}var cA=navigator.userAgent.match(/Version\/(.*?)\s/)||navigator.userAgent.match(/Chrome\/(\d+)/);navigator.vendor=="Apple Computer, Inc."&&(cA&&cA[1]<4||navigator.platform.slice(0,2)=="iP")||navigator.vendor=="Google Inc."&&cA&&cA[1]<8?j.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});setTimeout(function(){a.remove()})}:j.safari=bc;var cB=function(){this.returnValue=!1},cC=function(){return this.originalEvent.preventDefault()},cD=function(){this.cancelBubble=!0},cE=function(){return this.originalEvent.stopPropagation()},cF=function(){if(g.doc.addEventListener)return function(a,b,c,d){var e=n&&t[b]?t[b]:b,g=function(e){if(n&&t[f](b))for(var g=0,h=e.targetTouches&&e.targetTouches.length;g1&&(a=Array.prototype.splice.call(arguments,0,arguments.length));return new c_(a)},j.setSize=ck,j.setViewBox=cm,j.top=j.bottom=null,j.raphael=a;var cK=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,h=e.clientLeft||d.clientLeft||0,i=b.top+(g.win.pageYOffset||e.scrollTop||d.scrollTop)-f,j=b.left+(g.win.pageXOffset||e.scrollLeft||d.scrollLeft)-h;return{y:i,x:j}};j.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=g.doc.elementFromPoint(a,b);if(g.win.opera&&e.tagName=="svg"){var f=cK(d),h=d.createSVGRect();h.x=a-f.x,h.y=b-f.y,h.width=h.height=1;var i=d.getIntersectionList(h,null);i.length&&(e=i[i.length-1])}if(!e)return null;while(e.parentNode&&e!=d.parentNode&&!e.raphael)e=e.parentNode;e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null;return e},j.getById=function(a){var b=this.bottom;while(b){if(b.id==a)return b;b=b.next}return null},j.forEach=function(a,b){var c=this.bottom;while(c){if(a.call(b,c)===!1)return this;c=c.next}return this},ce.getBBox=function(a){if(this.removed)return{};var b=this._;if(a){if(b.dirty||!b.bboxwt)this.realPath=bg[this.type](this),b.bboxwt=bt(this.realPath),b.bboxwt.toString=cM,b.dirty=0;return b.bboxwt}if(b.dirty||b.dirtyT||!b.bbox){if(b.dirty||!this.realPath)b.bboxwt=0,this.realPath=bg[this.type](this);b.bbox=bt(bh(this.realPath,this.matrix)),b.bbox.toString=cM,b.dirty=b.dirtyT=0}return b.bbox},ce.clone=function(){if(this.removed)return null;var a=this.attr();delete a.scale,delete a.translation;return this.paper[this.type]().attr(a)},ce.glow=function(a){if(this.type=="text")return null;a=a||{};var b={width:a.width||10,fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||"#000"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||bg[this.type](this);f=this.matrix?bh(f,this.matrix):f;for(var g=1;g=j)return p;o=p}if(j==null)return k},cP=function(b,c){return function(d,e,f){d=bC(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;oe){if(c&&!l.start){m=cO(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),k+=["C"+m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k,k=["M"+m.x,m.y+"C"+m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!b&&!c){m=cO(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j,g=+i[5],h=+i[6]}k+=i.shift()+i}l.end=k,m=b?n:c?l:a.findDotsAtSegment(g,h,i[1],i[2],i[3],i[4],i[5],i[6],1),m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cQ=cP(1),cR=cP(),cS=cP(0,1);a.getTotalLength=cQ,a.getPointAtLength=cR,a.getSubpath=function(a,b,c){if(y(this.getTotalLength(a)-c)<1e-6)return cS(a,b).end;var d=cS(a,c,1);return b?cS(d,b).end:d},ce.getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return cQ(this.attrs.path)}},ce.getPointAtLength=function(a){if(this.type=="path")return cR(this.attrs.path,a)},ce.getSubpath=function(b,c){if(this.type=="path")return a.getSubpath(this.attrs.path,b,c)};var cT=a.easing_formulas={linear:function(a){return a},"<":function(a){return z(a,1.7)},">":function(a){return z(a,.48)},"<>":function(a){var b=.48-a/1.04,c=v.sqrt(.1734+b*b),d=c-b,e=z(y(d),1/3)*(d<0?-1:1),f=-c-b,g=z(y(f),1/3)*(f<0?-1:1),h=e+g+.5;return(1-h)*3*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==!!a)return a;return z(2,-10*a)*v.sin((a-.075)*2*A/.3)+1},bounce:function(a){var b=7.5625,c=2.75,d;a<1/c?d=b*a*a:a<2/c?(a-=1.5/c,d=b*a*a+.75):a<2.5/c?(a-=2.25/c,d=b*a*a+.9375):(a-=2.625/c,d=b*a*a+.984375);return d}};cT.easeIn=cT["ease-in"]=cT["<"],cT.easeOut=cT["ease-out"]=cT[">"],cT.easeInOut=cT["ease-in-out"]=cT["<>"],cT["back-in"]=cT.backIn,cT["back-out"]=cT.backOut;var cU=[],cV=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},cW=function(){var b=+(new Date),c=0;for(;cg*c.top){e=c.percents[v],n=c.percents[v-1]||0,p=p/c.top*(e-n),m=c.percents[v+1],i=c.anim[e];break}g&&d.attr(c.anim[c.percents[v]])}if(!!i){if(!j){for(attr in i)if(i[f](attr))if(U[f](attr)||d.paper.customAttributes[f](attr)){r[attr]=d.attr(attr),r[attr]==null&&(r[attr]=T[attr]),s[attr]=i[attr];switch(U[attr]){case B:t[attr]=(s[attr]-r[attr])/p;break;case"colour":r[attr]=a.getRGB(r[attr]);var x=a.getRGB(s[attr]);t[attr]={r:(x.r-r[attr].r)/p,g:(x.g-r[attr].g)/p,b:(x.b-r[attr].b)/p};break;case"path":var y=bC(r[attr],s[attr]),z=y[1];r[attr]=y[0],t[attr]=[];for(v=0,w=r[attr].length;vd)return d;while(cf?c=e:d=e,e=(d-c)/2+c}return e}function n(a,b){var c=o(a,b);return((l*c+k)*c+j)*c}function m(a){return((i*a+h)*a+g)*a}var g=3*b,h=3*(d-b)-g,i=1-g-h,j=3*c,k=3*(e-c)-j,l=1-j-k;return n(a,1/(200*f))}function cM(){return this.x+p+this.y+p+this.width+"×"+this.height}function cL(){return this.x+p+this.y}function bP(a,b,c,d,e,f){a!=null?this.m=[[a,c,e],[b,d,f],[0,0,1]]:this.m=[[1,0,0],[0,1,0],[0,0,1]]}function bs(a,b){var c=g.doc.createElement("img");c.style.cssText="position:absolute;left:-9999em;top-9999em",c.onload=function(){b.call(this),this.onload=null,g.doc.body.removeChild(this)},c.onerror=function(){g.doc.body.removeChild(this)},g.doc.body.appendChild(c),c.src=a}function br(a,b,c){function d(){var e=Array.prototype.slice.call(arguments,0),g=e.join("␀"),h=d.cache=d.cache||{},i=d.count=d.count||[];if(h[f](g))return c?c(h[g]):h[g];i.length>=1e3&&delete h[i.shift()],i.push(g),h[g]=a[l](b,e);return c?c(h[g]):h[g]}return d}function a(b){if(a.is(b,"function"))return dc.on("DOMload",b);if(a.is(b,D)){var d=b,e=cl[l](a,d.splice(0,3+a.is(d[0],B))),g=e.set(),h=0,i=d.length,j;for(;h',bj=bi.firstChild,bj.style.behavior="url(#default#VML)";if(!bj||typeof bj.adj!="object")return a.type=o;bi=null}a.svg=!(a.vml=a.type=="VML"),j=i.prototype=a.prototype,j.customAttributes={},a._id=0,a._oid=0,a.fn={},a.is=function(a,b){b=u.call(b);if(b=="finite")return!L[f](+a);return b=="null"&&a===null||b==typeof a||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||G.call(a).slice(8,-1).toLowerCase()==b},a.angle=function(b,c,d,e,f,g){if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return(180+v.atan2(-i,-h)*180/A+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)},a.rad=function(a){return a%360*A/180},a.deg=function(a){return a*180/A%360},a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,D)){var e=b.length;while(e--)if(y(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(fb-d)return c-f+b}return c};var bk=function(a,b){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=v.random()*16|0,c=a=="x"?b:b&3|8;return c.toString(16)});a.setWindow=function(b){dc("setWindow",a,g.win,b),g.win=b,g.doc=g.win.document,cz&&cz(g.win)};var bl=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write(""),e.close(),d=e.body}catch(f){d=createPopup().document.body}var h=d.createTextRange();bl=br(function(a){try{d.style.color=q(a).replace(c,o);var b=h.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b.toString(16)).slice(-6)}catch(e){return"none"}})}else{var i=g.doc.createElement("i");i.title="Raphaël Colour Picker",i.style.display="none",g.doc.body.appendChild(i),bl=br(function(a){i.style.color=a;return g.doc.defaultView.getComputedStyle(i,o).getPropertyValue("color")})}return bl(b)},bm=function(){return"hsb("+[this.h,this.s,this.b]+")"},bn=function(){return"hsl("+[this.h,this.s,this.l]+")"},bo=function(){return this.hex},bp=function(b,c,d){c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b&&(d=b.b,c=b.g,b=b.r);if(c==null&&a.is(b,C)){var e=a.getRGB(b);b=e.r,c=e.g,d=e.b}if(b>1||c>1||d>1)b/=255,c/=255,d/=255;return[b,c,d]},bq=function(b,c,d,e){b*=255,c*=255,d*=255;var f={r:b,g:c,b:d,hex:a.rgb(b,c,d),toString:bo};a.is(e,"finite")&&(f.opacity=e);return f};a.hsb2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"b"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;a=a%360/60,i=c*b,h=i*(1-y(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bq(e,f,g,d)},a.hsl2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"l"in a&&(c=a.l,b=a.s,a=a.h);if(a>1||b>1||c>1)a/=360,b/=100,c/=100;a*=360;var e,f,g,h,i;a=a%360/60,i=2*b*(c<.5?c:1-c),h=i*(1-y(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bq(e,f,g,d)},a.rgb2hsb=function(a,b,c){c=bp(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;f=w(a,b,c),g=f-x(a,b,c),d=g==0?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=d%6*60,e=g==0?0:g/f;return{h:d,s:e,b:f,toString:bm}},a.rgb2hsl=function(a,b,c){c=bp(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;g=w(a,b,c),h=x(a,b,c),i=g-h,d=i==0?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=d%6*60,f=(g+h)/2,e=i==0?0:f<.5?i/(2*f):i/(2-2*f);return{h:d,s:e,l:f,toString:bn}},a._path2string=function(){return this.join(",").replace(X,"$1")},a.getRGB=br(function(b){if(!b||!!((b=q(b)).indexOf("-")+1))return{r:-1,g:-1,b:-1,hex:"none",error:1};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none"};!W[f](b.toLowerCase().substring(0,2))&&b.charAt()!="#"&&(b=bl(b));var c,d,e,g,h,i,j,k=b.match(K);if(k){k[2]&&(g=Q(k[2].substring(5),16),e=Q(k[2].substring(3,5),16),d=Q(k[2].substring(1,3),16)),k[3]&&(g=Q((i=k[3].charAt(3))+i,16),e=Q((i=k[3].charAt(2))+i,16),d=Q((i=k[3].charAt(1))+i,16)),k[4]&&(j=k[4].split(V),d=P(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=P(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),g=P(j[2]),j[2].slice(-1)=="%"&&(g*=2.55),k[1].toLowerCase().slice(0,4)=="rgba"&&(h=P(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100));if(k[5]){j=k[5].split(V),d=P(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=P(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),g=P(j[2]),j[2].slice(-1)=="%"&&(g*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsba"&&(h=P(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,g,h)}if(k[6]){j=k[6].split(V),d=P(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=P(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),g=P(j[2]),j[2].slice(-1)=="%"&&(g*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsla"&&(h=P(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,g,h)}k={r:d,g:e,b:g},k.hex="#"+(16777216|g|e<<8|d<<16).toString(16).slice(1),a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1}},a),a.hsb=br(function(b,c,d){return a.hsb2rgb(b,c,d).hex}),a.hsl=br(function(b,c,d){return a.hsl2rgb(b,c,d).hex}),a.rgb=br(function(a,b,c){return"#"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b}));return c.hex},a.getColor.reset=function(){delete this.start},a.parsePathString=br(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,D)&&a.is(b[0],D)&&(d=bu(b)),d.length||q(b).replace(Y,function(a,b,e){var f=[],g=u.call(b);e.replace($,function(a,b){b&&f.push(+b)}),g=="m"&&f.length>2&&(d.push([b][m](f.splice(0,2))),g="l",b=b=="m"?"l":"L");while(f.length>=c[g]){d.push([b][m](f.splice(0,c[g])));if(!c[g])break}}),d.toString=a._path2string;return d}),a.parseTransformString=br(function(b){if(!b)return null;var c={r:3,s:4,t:2,m:6},d=[];a.is(b,D)&&a.is(b[0],D)&&(d=bu(b)),d.length||q(b).replace(Z,function(a,b,c){var e=[],f=u.call(b);c.replace($,function(a,b){b&&e.push(+b)}),d.push([f][m](e))}),d.toString=a._path2string;return d}),a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=z(j,3)*a+z(j,2)*3*i*c+j*3*i*i*e+z(i,3)*g,l=z(j,3)*b+z(j,2)*3*i*d+j*3*i*i*f+z(i,3)*h,m=a+2*i*(c-a)+i*i*(e-2*c+a),n=b+2*i*(d-b)+i*i*(f-2*d+b),o=c+2*i*(e-c)+i*i*(g-2*e+c),p=d+2*i*(f-d)+i*i*(h-2*f+d),q=(1-i)*a+i*c,r=(1-i)*b+i*d,s=(1-i)*e+i*g,t=(1-i)*f+i*h,u=90-v.atan2(m-o,n-p)*180/A;(m>o||n1&&(u=v.sqrt(u),c=u*c,d=u*d);var w=c*c,x=d*d,z=(f==g?-1:1)*v.sqrt(y((w*x-w*t*t-x*s*s)/(w*t*t+x*s*s))),B=z*c*t/d+(a+h)/2,C=z*-d*s/c+(b+i)/2,D=v.asin(((b-C)/d).toFixed(9)),E=v.asin(((i-C)/d).toFixed(9));D=aE&&(D=D-A*2),!g&&E>D&&(E=E-A*2)}else D=j[0],E=j[1],B=j[2],C=j[3];var F=E-D;if(y(F)>k){var G=E,H=h,I=i;E=D+k*(g&&E>D?1:-1),h=B+c*v.cos(E),i=C+d*v.sin(E),n=bz(h,i,c,d,e,0,g,H,I,[E,G,B,C])}F=E-D;var J=v.cos(D),K=v.sin(D),L=v.cos(E),M=v.sin(E),N=v.tan(F/4),O=4/3*c*N,P=4/3*d*N,Q=[a,b],R=[a+O*K,b-P*J],S=[h+O*M,i-P*L],T=[h,i];R[0]=2*Q[0]-R[0],R[1]=2*Q[1]-R[1];if(j)return[R,S,T][m](n);n=[R,S,T][m](n).join().split(",");var U=[];for(var V=0,W=n.length;V"1e12"&&(m=.5),y(n)>"1e12"&&(n=.5),m>0&&m<1&&(q=bA(a,b,c,d,e,f,g,h,m),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bA(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y)),i=f-2*d+b-(h-2*f+d),j=2*(d-b)-2*(f-d),k=b-d,m=(-j+v.sqrt(j*j-4*i*k))/2/i,n=(-j-v.sqrt(j*j-4*i*k))/2/i,y(m)>"1e12"&&(m=.5),y(n)>"1e12"&&(n=.5),m>0&&m<1&&(q=bA(a,b,c,d,e,f,g,h,m),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bA(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y));return{min:{x:x[l](0,p),y:x[l](0,o)},max:{x:w[l](0,p),y:w[l](0,o)}}}),bC=br(function(a,b){var c=bw(a),d=b&&bw(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1],b.Y=a[2];break;case"A":a=["C"][m](bz[l](0,[b.x,b.y][m](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x)),d=b.y+(b.y-(b.by||b.y)),a=["C",c,d][m](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x)),b.qy=b.y+(b.y-(b.qy||b.y)),a=["C"][m](by(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1],b.qy=a[2],a=["C"][m](by(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][m](bx(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][m](bx(b.x,b.y,a[1],b.y));break;case"V":a=["C"][m](bx(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][m](bx(b.x,b.y,b.X,b.Y))}return a},h=function(a,b){if(a[b].length>7){a[b].shift();var e=a[b];while(e.length)a.splice(b++,0,["C"][m](e.splice(0,6)));a.splice(b,1),k=w(c.length,d&&d.length||0)}},i=function(a,b,e,f,g){a&&b&&a[g][0]=="M"&&b[g][0]!="M"&&(b.splice(g,0,["M",f.x,f.y]),e.bx=0,e.by=0,e.x=a[g][1],e.y=a[g][2],k=w(c.length,d&&d.length||0))};for(var j=0,k=w(c.length,d&&d.length||0);j.5)*2-1;z(f-.5,2)+z(h-.5,2)>.25&&(h=v.sqrt(.25-z(f-.5,2))*e+.5)&&h!=.5&&(h=h.toFixed(5)-1e-5*e)}return o}),c=c.split(/\s*\-\s*/);if(d=="linear"){var m=c.shift();m=-P(m);if(isNaN(m))return null;var n=[0,0,v.cos(a.rad(m)),v.sin(a.rad(m))],p=1/(w(y(n[2]),y(n[3]))||1);n[2]*=p,n[3]*=p,n[2]<0&&(n[0]=-n[2],n[2]=0),n[3]<0&&(n[1]=-n[3],n[3]=0)}var r=bD(c);if(!r)return null;b.gradient&&(j.defs.removeChild(b.gradient),delete b.gradient),l=bU(d+"Gradient",{id:e}),b.gradient=l,bU(l,d=="radial"?{fx:f,fy:h}:{x1:n[0],y1:n[1],x2:n[2],y2:n[3],gradientTransform:b.matrix.invert()}),j.defs.appendChild(l);for(var s=0,t=r.length;s1?z.opacity/100:z.opacity});case"stroke":z=a.getRGB(l),h[O](k,z.hex),k=="stroke"&&z[f]("opacity")&&bU(h,{"stroke-opacity":z.opacity>1?z.opacity/100:z.opacity}),k=="stroke"&&c._.arrows&&("startString"in c._.arrows&&b_(c,c._.arrows.startString),"endString"in c._.arrows&&b_(c,c._.arrows.endString,1));break;case"gradient":(c.type=="circle"||c.type=="ellipse"||q(l).charAt()!="r")&&bZ(c,l);break;case"opacity":i.gradient&&!i[f]("stroke-opacity")&&bU(h,{"stroke-opacity":l>1?l/100:l});case"fill-opacity":if(i.gradient){A=g.doc.getElementById(h.getAttribute(F).replace(/^url\(#|\)$/g,o)),A&&(B=A.getElementsByTagName("stop"),bU(B[B.length-1],{"stop-opacity":l}));break};default:k=="font-size"&&(l=Q(l,10)+"px");var C=k.replace(/(\-.)/g,function(a){return S.call(a.substring(1))});h.style[C]=l,c._.dirty=1,h[O](k,l)}}cc(c,d)},cb=1.2,cc=function(b,c){if(b.type=="text"&&!!(c[f]("text")||c[f]("font")||c[f]("font-size")||c[f]("x")||c[f]("y"))){var d=b.attrs,e=b.node,h=e.firstChild?Q(g.doc.defaultView.getComputedStyle(e.firstChild,o).getPropertyValue("font-size"),10):10;if(c[f]("text")){d.text=c.text;while(e.firstChild)e.removeChild(e.firstChild);var i=q(c.text).split("\n"),j=[],k;for(var l=0,m=i.length;l"));var T=Q.getBoundingClientRect();m.W=h.w=(T.right-T.left)/R,m.H=h.h=(T.bottom-T.top)/R,m.paper.canvas.style.display="none",m.X=h.x,m.Y=h.y+m.H/2,("x"in d||"y"in d)&&(m.path.v=a.format("m{0},{1}l{2},{1}",N(h.x*cs),N(h.y*cs),N(h.x*cs)+1));var U=["x","y","text","font","font-family","font-weight","font-style","font-size"];for(var V=0,W=U.length;V.25&&(c=v.sqrt(.25-z(b-.5,2))*((c>.5)*2-1)+.5),f=b+p+c);return o}),b=b.split(/\s*\-\s*/);if(e=="linear"){var g=b.shift();g=-P(g);if(isNaN(g))return null}var h=bD(b);if(!h)return null;a=a.shape||a.node;if(h.length){a.removeChild(c),c.on=!0,c.method="none",c.color=h[0].color,c.color2=h[h.length-1].color;var i=[];for(var j=0,k=h.length;j')}}catch(c){cy=function(a){return b.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}};cz(g.win),cl=function(){var b=bE[l](0,arguments),c=b.container,d=b.height,e,f=b.width,h=b.x,j=b.y;if(!c)throw new Error("VML container not found.");var k=new i,m=k.canvas=g.doc.createElement("div"),n=m.style;h=h||0,j=j||0,f=f||512,d=d||342,k.width=f,k.height=d,f==+f&&(f+="px"),d==+d&&(d+="px"),k.coordsize=cs*1e3+p+cs*1e3,k.coordorigin="0 0",k.span=g.doc.createElement("span"),k.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;",m.appendChild(k.span),n.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d),c==1?(g.doc.body.appendChild(m),n.left=h+"px",n.top=j+"px",n.position="absolute"):c.firstChild?c.insertBefore(m,c.firstChild):c.appendChild(m),bF.call(k,k,a.fn),k.renderfix=bc;return k},j.clear=function(){dc("clear",this),this.canvas.innerHTML=o,this.span=g.doc.createElement("span"),this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;",this.canvas.appendChild(this.span),this.bottom=this.top=null},j.remove=function(){dc("remove",this),this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=bL(a);return!0}}var cA=navigator.userAgent.match(/Version\/(.*?)\s/)||navigator.userAgent.match(/Chrome\/(\d+)/);navigator.vendor=="Apple Computer, Inc."&&(cA&&cA[1]<4||navigator.platform.slice(0,2)=="iP")||navigator.vendor=="Google Inc."&&cA&&cA[1]<8?j.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});setTimeout(function(){a.remove()})}:j.safari=bc;var cB=function(){this.returnValue=!1},cC=function(){return this.originalEvent.preventDefault()},cD=function(){this.cancelBubble=!0},cE=function(){return this.originalEvent.stopPropagation()},cF=function(){if(g.doc.addEventListener)return function(a,b,c,d){var e=n&&t[b]?t[b]:b,g=function(e){if(n&&t[f](b))for(var g=0,h=e.targetTouches&&e.targetTouches.length;g1&&(a=Array.prototype.splice.call(arguments,0,arguments.length));return new c_(a)},j.setSize=ck,j.setViewBox=cm,j.top=j.bottom=null,j.raphael=a;var cK=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,h=e.clientLeft||d.clientLeft||0,i=b.top+(g.win.pageYOffset||e.scrollTop||d.scrollTop)-f,j=b.left+(g.win.pageXOffset||e.scrollLeft||d.scrollLeft)-h;return{y:i,x:j}};j.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=g.doc.elementFromPoint(a,b);if(g.win.opera&&e.tagName=="svg"){var f=cK(d),h=d.createSVGRect();h.x=a-f.x,h.y=b-f.y,h.width=h.height=1;var i=d.getIntersectionList(h,null);i.length&&(e=i[i.length-1])}if(!e)return null;while(e.parentNode&&e!=d.parentNode&&!e.raphael)e=e.parentNode;e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null;return e},j.getById=function(a){var b=this.bottom;while(b){if(b.id==a)return b;b=b.next}return null},j.forEach=function(a,b){var c=this.bottom;while(c){if(a.call(b,c)===!1)return this;c=c.next}return this},ce.getBBox=function(a){if(this.removed)return{};var b=this._;if(a){if(b.dirty||!b.bboxwt)this.realPath=bg[this.type](this),b.bboxwt=bt(this.realPath),b.bboxwt.toString=cM,b.dirty=0;return b.bboxwt}if(b.dirty||b.dirtyT||!b.bbox){if(b.dirty||!this.realPath)b.bboxwt=0,this.realPath=bg[this.type](this);b.bbox=bt(bh(this.realPath,this.matrix)),b.bbox.toString=cM,b.dirty=b.dirtyT=0}return b.bbox},ce.clone=function(){if(this.removed)return null;var a=this.attr();delete a.scale,delete a.translation;return this.paper[this.type]().attr(a)},ce.glow=function(a){if(this.type=="text")return null;a=a||{};var b={width:(a.width||10)+(+this.attr("stroke-width")||1),fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||"#000"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||bg[this.type](this);f=this.matrix?bh(f,this.matrix):f;for(var g=1;g=j)return p;o=p}if(j==null)return k},cP=function(b,c){return function(d,e,f){d=bC(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;oe){if(c&&!l.start){m=cO(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),k+=["C"+m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k,k=["M"+m.x,m.y+"C"+m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!b&&!c){m=cO(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j,g=+i[5],h=+i[6]}k+=i.shift()+i}l.end=k,m=b?n:c?l:a.findDotsAtSegment(g,h,i[1],i[2],i[3],i[4],i[5],i[6],1),m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cQ=cP(1),cR=cP(),cS=cP(0,1);a.getTotalLength=cQ,a.getPointAtLength=cR,a.getSubpath=function(a,b,c){if(y(this.getTotalLength(a)-c)<1e-6)return cS(a,b).end;var d=cS(a,c,1);return b?cS(d,b).end:d},ce.getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return cQ(this.attrs.path)}},ce.getPointAtLength=function(a){if(this.type=="path")return cR(this.attrs.path,a)},ce.getSubpath=function(b,c){if(this.type=="path")return a.getSubpath(this.attrs.path,b,c)};var cT=a.easing_formulas={linear:function(a){return a},"<":function(a){return z(a,1.7)},">":function(a){return z(a,.48)},"<>":function(a){var b=.48-a/1.04,c=v.sqrt(.1734+b*b),d=c-b,e=z(y(d),1/3)*(d<0?-1:1),f=-c-b,g=z(y(f),1/3)*(f<0?-1:1),h=e+g+.5;return(1-h)*3*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==!!a)return a;return z(2,-10*a)*v.sin((a-.075)*2*A/.3)+1},bounce:function(a){var b=7.5625,c=2.75,d;a<1/c?d=b*a*a:a<2/c?(a-=1.5/c,d=b*a*a+.75):a<2.5/c?(a-=2.25/c,d=b*a*a+.9375):(a-=2.625/c,d=b*a*a+.984375);return d}};cT.easeIn=cT["ease-in"]=cT["<"],cT.easeOut=cT["ease-out"]=cT[">"],cT.easeInOut=cT["ease-in-out"]=cT["<>"],cT["back-in"]=cT.backIn,cT["back-out"]=cT.backOut;var cU=[],cV=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},cW=function(){var b=+(new Date),c=0;for(;c2922 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 -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"]); +2925 css = "overflow:hidden;", +2926 isFloating; +2927 x = x || 0; +2928 y = y || 0; +2929 width = width || 512; +2930 height = height || 342; +2931 $(cnvs, { +2932 height: height, +2933 version: 1.1, +2934 width: width, +2935 xmlns: "http://www.w3.org/2000/svg" +2936 }); +2937 if (container == 1) { +2938 cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px"; +2939 g.doc.body.appendChild(cnvs); +2940 isFloating = 1; +2941 } else { +2942 cnvs.style.cssText = css + "position:relative"; +2943 if (container.firstChild) { +2944 container.insertBefore(cnvs, container.firstChild); +2945 } else { +2946 container.appendChild(cnvs); +2947 } +2948 } +2949 container = new Paper; +2950 container.width = width; +2951 container.height = height; +2952 container.canvas = cnvs; +2953 plugins.call(container, container, R.fn); +2954 container.clear(); +2955 container._left = container._top = 0; +2956 isFloating && (container.renderfix = fun); +2957 container.renderfix(); +2958 return container; +2959 }, +2960 setViewBox = function (x, y, w, h, fit) { +2961 eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); +2962 var size = mmax(w / this.width, h / this.height), +2963 top = this.top, +2964 aspectRatio = fit ? "meet" : "xMinYMin", +2965 vb, +2966 sw; +2967 if (x == null) { +2968 if (this._vbSize) { +2969 size = 1; +2970 } +2971 delete this._vbSize; +2972 vb = "0 0 " + this.width + S + this.height; +2973 } else { +2974 this._vbSize = size; +2975 vb = x + S + y + S + w + S + h; +2976 } +2977 $(this.canvas, { +2978 viewBox: vb, +2979 preserveAspectRatio: aspectRatio +2980 }); +2981 while (size && top) { +2982 sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1; +2983 top.attr({"stroke-width": sw}); +2984 top._.dirty = 1; +2985 top._.dirtyT = 1; +2986 top = top.prev; +2987 } +2988 this._viewBox = [x, y, w, h, !!fit]; +2989 return this; +2990 }; +2991 /*\ +2992 * Paper.renderfix +2993 [ method ] +2994 ** +2995 * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependant +2996 * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness. +2997 * This method fixes the issue. +2998 ** +2999 Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method. +3000 \*/ +3001 paperproto.renderfix = function () { +3002 var cnvs = this.canvas, +3003 s = cnvs.style, +3004 pos = cnvs.getScreenCTM(), +3005 left = -pos.e % 1, +3006 top = -pos.f % 1; +3007 if (left || top) { +3008 if (left) { +3009 this._left = (this._left + left) % 1; +3010 s.left = this._left + "px"; +3011 } +3012 if (top) { +3013 this._top = (this._top + top) % 1; +3014 s.top = this._top + "px"; +3015 } +3016 } +3017 }; +3018 /*\ +3019 * Paper.clear +3020 [ method ] +3021 ** +3022 * Clears the paper, i.e. removes all the elements. +3023 \*/ +3024 paperproto.clear = function () { +3025 eve("clear", this); +3026 var c = this.canvas; +3027 while (c.firstChild) { +3028 c.removeChild(c.firstChild); +3029 } +3030 this.bottom = this.top = null; +3031 (this.desc = $("desc")).appendChild(g.doc.createTextNode("Created with Rapha\xebl " + R.version)); +3032 c.appendChild(this.desc); +3033 c.appendChild(this.defs = $("defs")); +3034 }; +3035 /*\ +3036 * Paper.remove +3037 [ method ] +3038 ** +3039 * Removes the paper from the DOM. +3040 \*/ +3041 paperproto.remove = function () { +3042 eve("remove", this); +3043 this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas); +3044 for (var i in this) { +3045 this[i] = removed(i); +3046 } +3047 }; +3048 } +3049 +3050 // VML +3051 if (R.vml) { +3052 var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, +3053 bites = /([clmz]),?([^clmz]*)/gi, +3054 blurregexp = / progid:\S+Blur\([^\)]+\)/g, +3055 val = /-?[^,\s-]+/g, +3056 cssDot = "position:absolute;left:0;top:0;width:1px;height:1px", +3057 zoom = 21600, +3058 pathTypes = {path: 1, rect: 1}, +3059 ovalTypes = {circle: 1, ellipse: 1}, +3060 path2vml = function (path) { +3061 var total = /[ahqstv]/ig, +3062 command = pathToAbsolute; +3063 Str(path).match(total) && (command = path2curve); +3064 total = /[clmz]/g; +3065 if (command == pathToAbsolute && !Str(path).match(total)) { +3066 var res = Str(path).replace(bites, function (all, command, args) { +3067 var vals = [], +3068 isMove = lowerCase.call(command) == "m", +3069 res = map[command]; +3070 args.replace(val, function (value) { +3071 if (isMove && vals.length == 2) { +3072 res += vals + map[command == "m" ? "l" : "L"]; +3073 vals = []; +3074 } +3075 vals.push(round(value * zoom)); +3076 }); +3077 return res + vals; +3078 }); +3079 return res; +3080 } +3081 var pa = command(path), p, r; +3082 res = []; +3083 for (var i = 0, ii = pa.length; i < ii; i++) { +3084 p = pa[i]; +3085 r = lowerCase.call(pa[i][0]); +3086 r == "z" && (r = "x"); +3087 for (var j = 1, jj = p.length; j < jj; j++) { +3088 r += round(p[j] * zoom) + (j != jj - 1 ? "," : E); +3089 } +3090 res.push(r); +3091 } +3092 return res.join(S); +3093 }, +3094 compensation = function (deg, dx, dy) { +3095 var m = new Matrix; +3096 m.rotate(-deg, .5, .5); +3097 return { +3098 dx: m.x(dx, dy), +3099 dy: m.y(dx, dy) +3100 }; +3101 }, +3102 setCoords = function (p) { +3103 var _ = p._, +3104 sx = _.sx, +3105 sy = _.sy, +3106 deg = _.deg, +3107 dx = _.dx, +3108 dy = _.dy, +3109 fillpos = _.fillpos, +3110 o = p.node, +3111 s = o.style, +3112 y = 1, +3113 m = p.matrix, +3114 flip = "", +3115 dxdy, +3116 kx = zoom / sx, +3117 ky = zoom / sy; +3118 s.visibility = "hidden"; +3119 o.coordsize = abs(kx) + S + abs(ky); +3120 s.rotation = deg * (sx * sy < 0 ? -1 : 1); +3121 if (deg) { +3122 var c = compensation(deg, dx, dy); +3123 dx = c.dx; +3124 dy = c.dy; +3125 } +3126 sx < 0 && (flip += "x"); +3127 sy < 0 && (flip += " y") && (y = -1); +3128 s.flip = flip; +3129 o.coordorigin = (dx * -kx) + S + (dy * -ky); +3130 if (fillpos || _.fillsize) { +3131 var fill = o.getElementsByTagName(fillString); +3132 fill = fill && fill[0]; +3133 o.removeChild(fill); +3134 if (fillpos) { +3135 c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1])); +3136 fill.position = c.dx * y + S + c.dy * y; +3137 } +3138 if (_.fillsize) { +3139 fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy); +3140 } +3141 o.appendChild(fill); +3142 } +3143 s.visibility = "visible"; +3144 }; +3145 R.toString = function () { +3146 return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version; +3147 }; +3148 addArrow = function (o, value, isEnd) { +3149 var values = Str(value).toLowerCase().split("-"), +3150 se = isEnd ? "end" : "start", +3151 i = values.length, +3152 type = "classic", +3153 w = "medium", +3154 h = "medium"; +3155 while (i--) { +3156 switch (values[i]) { +3157 case "block": +3158 case "classic": +3159 case "oval": +3160 case "diamond": +3161 case "open": +3162 case "none": +3163 type = values[i]; +3164 break; +3165 case "wide": +3166 case "narrow": h = values[i]; break; +3167 case "long": +3168 case "short": w = values[i]; break; +3169 } +3170 } +3171 var stroke = o.node.getElementsByTagName("stroke")[0]; +3172 stroke[se + "arrow"] = type; +3173 stroke[se + "arrowlength"] = w; +3174 stroke[se + "arrowwidth"] = h; +3175 }; +3176 setFillAndStroke = function (o, params) { +3177 o.paper.canvas.style.display = "none"; +3178 o.attrs = o.attrs || {}; +3179 var node = o.node, +3180 a = o.attrs, +3181 s = node.style, +3182 xy, +3183 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), +3184 isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry), +3185 res = o; +3186 +3187 +3188 for (var par in params) if (params[has](par)) { +3189 a[par] = params[par]; +3190 } +3191 if (newpath) { +3192 a.path = getPath[o.type](o); +3193 o._.dirty = 1; +3194 } +3195 params.href && (node.href = params.href); +3196 params.title && (node.title = params.title); +3197 params.target && (node.target = params.target); +3198 params.cursor && (s.cursor = params.cursor); +3199 "blur" in params && o.blur(params.blur); +3200 "transform" in params && o.transform(params.transform); +3201 if (params.path && o.type == "path" || newpath) { +3202 node.path = path2vml(a.path); +3203 } +3204 if (isOval) { +3205 var cx = a.cx, +3206 cy = a.cy, +3207 rx = a.rx || a.r || 0, +3208 ry = a.ry || a.r || 0; +3209 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)); 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; +3211 if ("clip-rect" in params) { +3212 var rect = Str(params["clip-rect"]).split(separator); +3213 if (rect.length == 4) { +3214 rect[2] = +rect[2] + (+rect[0]); +3215 rect[3] = +rect[3] + (+rect[1]); +3216 var div = node.clipRect || g.doc.createElement("div"), +3217 dstyle = div.style, +3218 group = node.parentNode; +3219 dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect); +3220 if (!node.clipRect) { +3221 dstyle.position = "absolute"; +3222 dstyle.top = 0; +3223 dstyle.left = 0; +3224 dstyle.width = o.paper.width + "px"; +3225 dstyle.height = o.paper.height + "px"; +3226 group.parentNode.insertBefore(div, group); +3227 div.appendChild(group); +3228 node.clipRect = div; +3229 } +3230 } +3231 if (!params["clip-rect"]) { +3232 node.clipRect && (node.clipRect.style.clip = E); +3233 } +3234 } +3235 if (o.textpath) { +3236 var textpathStyle = o.textpath.style; +3237 params.font && (textpathStyle.font = params.font); +3238 params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"'); +3239 params["font-size"] && (textpathStyle.fontSize = params["font-size"]); +3240 params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]); +3241 params["font-style"] && (textpathStyle.fontStyle = params["font-style"]); +3242 } +3243 if ("arrow-start" in params) { +3244 addArrow(res, params["arrow-start"]); +3245 } +3246 if ("arrow-end" in params) { +3247 addArrow(res, params["arrow-end"], 1); +3248 } +3249 if (params.opacity != null || +3250 params["stroke-width"] != null || +3251 params.fill != null || +3252 params.src != null || +3253 params.stroke != null || +3254 params["stroke-width"] != null || +3255 params["stroke-opacity"] != null || +3256 params["fill-opacity"] != null || +3257 params["stroke-dasharray"] != null || +3258 params["stroke-miterlimit"] != null || +3259 params["stroke-linejoin"] != null || +3260 params["stroke-linecap"] != null) { +3261 var fill = node.getElementsByTagName(fillString), +3262 newfill = false; +3263 fill = fill && fill[0]; +3264 !fill && (newfill = fill = createNode(fillString)); +3265 if (o.type == "image" && params.src) { +3266 fill.src = params.src; +3267 } +3268 if ("fill-opacity" in params || "opacity" in params) { +3269 var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1); +3270 opacity = mmin(mmax(opacity, 0), 1); +3271 fill.opacity = opacity; +3272 } +3273 params.fill && (fill.on = true); +3274 if (fill.on == null || params.fill == "none" || params.fill === null) { +3275 fill.on = false; +3276 } +3277 if (fill.on && params.fill) { +3278 var isURL = params.fill.match(ISURL); +3279 if (isURL) { +3280 fill.parentNode == node && node.removeChild(fill); +3281 fill.rotate = true; +3282 fill.src = isURL[1]; +3283 fill.type = "tile"; +3284 var bbox = o.getBBox(1); +3285 fill.position = bbox.x + S + bbox.y; +3286 o._.fillpos = [bbox.x, bbox.y]; +3287 +3288 preload(isURL[1], function () { +3289 o._.fillsize = [this.offsetWidth, this.offsetHeight]; +3290 }); +3291 } else { +3292 fill.color = R.getRGB(params.fill).hex; +3293 fill.src = E; +3294 fill.type = "solid"; +3295 if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) { +3296 a.fill = "none"; +3297 a.gradient = params.fill; +3298 fill.rotate = false; +3299 } +3300 } +3301 } +3302 node.appendChild(fill); +3303 var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]), +3304 newstroke = false; +3305 !stroke && (newstroke = stroke = createNode("stroke")); +3306 if ((params.stroke && params.stroke != "none") || +3307 params["stroke-width"] || +3308 params["stroke-opacity"] != null || +3309 params["stroke-dasharray"] || +3310 params["stroke-miterlimit"] || +3311 params["stroke-linejoin"] || +3312 params["stroke-linecap"]) { +3313 stroke.on = true; +3314 } +3315 (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false); +3316 var strokeColor = R.getRGB(params.stroke); +3317 stroke.on && params.stroke && (stroke.color = strokeColor.hex); +3318 opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1); +3319 var width = (toFloat(params["stroke-width"]) || 1) * .75; +3320 opacity = mmin(mmax(opacity, 0), 1); +3321 params["stroke-width"] == null && (width = a["stroke-width"]); +3322 params["stroke-width"] && (stroke.weight = width); +3323 width && width < 1 && (opacity *= width) && (stroke.weight = 1); +3324 stroke.opacity = opacity; +3325 +3326 params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter"); +3327 stroke.miterlimit = params["stroke-miterlimit"] || 8; +3328 params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round"); +3329 if (params["stroke-dasharray"]) { +3330 var dasharray = { +3331 "-": "shortdash", +3332 ".": "shortdot", +3333 "-.": "shortdashdot", +3334 "-..": "shortdashdotdot", +3335 ". ": "dot", +3336 "- ": "dash", +3337 "--": "longdash", +3338 "- .": "dashdot", +3339 "--.": "longdashdot", +3340 "--..": "longdashdotdot" +3341 }; +3342 stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E; +3343 } +3344 newstroke && node.appendChild(stroke); +3345 } +3346 if (res.type == "text") { +3347 res.paper.canvas.style.display = E; +3348 var span = res.paper.span, +3349 m = 100, +3350 fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/); +3351 s = span.style; +3352 a.font && (s.font = a.font); +3353 a["font-family"] && (s.fontFamily = a["font-family"]); +3354 a["font-weight"] && (s.fontWeight = a["font-weight"]); +3355 a["font-style"] && (s.fontStyle = a["font-style"]); +3356 fontSize = toFloat(fontSize ? fontSize[0] : a["font-size"]); +3357 s.fontSize = fontSize * m + "px"; +3358 res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>")); +3359 var brect = span.getBoundingClientRect(); +3360 res.W = a.w = (brect.right - brect.left) / m; +3361 res.H = a.h = (brect.bottom - brect.top) / m; +3362 res.paper.canvas.style.display = "none"; +3363 res.X = a.x; +3364 res.Y = a.y + res.H / 2; +3365 +3366 ("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)); +3367 var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"]; +3368 for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) { +3369 res._.dirty = 1; +3370 break; +3371 } +3372 +3373 // text-anchor emulation +3374 switch (a["text-anchor"]) { +3375 case "start": +3376 res.textpath.style["v-text-align"] = "left"; +3377 res.bbx = res.W / 2; +3378 break; +3379 case "end": +3380 res.textpath.style["v-text-align"] = "right"; +3381 res.bbx = -res.W / 2; +3382 break; +3383 default: +3384 res.textpath.style["v-text-align"] = "center"; +3385 res.bbx = 0; +3386 break; +3387 } +3388 res.textpath.style["v-text-kern"] = true; +3389 } +3390 res.paper.canvas.style.display = E; +3391 }; +3392 addGradientFill = function (o, gradient, fill) { +3393 o.attrs = o.attrs || {}; +3394 var attrs = o.attrs, +3395 type = "linear", +3396 fxfy = ".5 .5"; +3397 o.attrs.gradient = gradient; +3398 gradient = Str(gradient).replace(radial_gradient, function (all, fx, fy) { +3399 type = "radial"; +3400 if (fx && fy) { +3401 fx = toFloat(fx); +3402 fy = toFloat(fy); +3403 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5); +3404 fxfy = fx + S + fy; +3405 } +3406 return E; +3407 }); +3408 gradient = gradient.split(/\s*\-\s*/); +3409 if (type == "linear") { +3410 var angle = gradient.shift(); +3411 angle = -toFloat(angle); +3412 if (isNaN(angle)) { +3413 return null; +3414 } +3415 } +3416 var dots = parseDots(gradient); +3417 if (!dots) { +3418 return null; +3419 } +3420 o = o.shape || o.node; +3421 if (dots.length) { +3422 o.removeChild(fill); +3423 fill.on = true; +3424 fill.method = "none"; +3425 fill.color = dots[0].color; +3426 fill.color2 = dots[dots.length - 1].color; +3427 var clrs = []; +3428 for (var i = 0, ii = dots.length; i < ii; i++) { +3429 dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color); +3430 } +3431 fill.colors && (fill.colors.value = clrs.length ? clrs.join() : "0% " + fill.color); +3432 if (type == "radial") { +3433 fill.type = "gradientTitle"; +3434 fill.focus = "100%"; +3435 fill.focussize = "0 0"; +3436 fill.focusposition = fxfy; +3437 fill.angle = 0; +3438 } else { +3439 // fill.rotate= true; +3440 fill.type = "gradient"; +3441 fill.angle = (270 - angle) % 360; +3442 } +3443 o.appendChild(fill); +3444 // alert(fill.outerHTML); +3445 } +3446 return 1; +3447 }; +3448 Element = function (node, vml) { +3449 this[0] = this.node = node; +3450 node.raphael = true; +3451 this.id = R._oid++; +3452 node.raphaelid = this.id; +3453 this.X = 0; +3454 this.Y = 0; +3455 this.attrs = {}; +3456 this.paper = vml; +3457 this.matrix = new Matrix; +3458 this._ = { +3459 transform: [], +3460 sx: 1, +3461 sy: 1, +3462 dx: 0, +3463 dy: 0, +3464 deg: 0, +3465 dirty: 1, +3466 dirtyT: 1 +3467 }; +3468 !vml.bottom && (vml.bottom = this); +3469 this.prev = vml.top; +3470 vml.top && (vml.top.next = this); +3471 vml.top = this; +3472 this.next = null; +3473 }; +3474 elproto = Element.prototype; +3475 elproto.transform = function (tstr) { +3476 if (tstr == null) { +3477 return this._.transform; +3478 } +3479 extractTransform(this, tstr); +3480 var matrix = this.matrix.clone(), +3481 skew = this.skew; +3482 matrix.translate(-.5, -.5); +3483 if (this.type == "image") { +3484 if (Str(tstr).indexOf("m") + 1) { +3485 this.node.style.filter = matrix.toFilter(); +3486 var bb = this.getBBox(), +3487 bbt = this.getBBox(1), +3488 im = matrix.invert(), +3489 dx = im.x(bb.x, bb.y) - im.x(bbt.x, bbt.y), +3490 dy = im.y(bb.x, bb.y) - im.y(bbt.x, bbt.y); +3491 // skew.offset = dx + S + dy; +3492 // this.node.getElementsByTagName(fillString)[0].position = skew.offset; +3493 } else { +3494 this.node.style.filter = E; +3495 setCoords(this); +3496 } +3497 } else { +3498 // o = this.node, +3499 // _ = this._, +3500 // fillpos = _.fillpos, +3501 // deg, +3502 // matrix = this.matrix; +3503 // fill = o.getElementsByTagName(fillString)[0], +3504 // angle = fill.angle; +3505 +3506 this.node.style.filter = E; +3507 skew.matrix = matrix; +3508 skew.offset = matrix.offset(); +3509 +3510 // if (0&&angle) { +3511 // angle = R.rad(270 - angle); +3512 // var dx = 100 * math.cos(angle), +3513 // dy = 100 * math.sin(angle), +3514 // zx = matrix.x(0, 0), +3515 // zy = matrix.y(0, 0), +3516 // mx = matrix.x(dx, dy), +3517 // my = matrix.y(dx, dy); +3518 // angle = R.angle(zx, zy, mx, my); +3519 // fill.angle = (270 - angle) % 360; +3520 // } +3521 } +3522 return this; +3523 }; +3524 elproto.rotate = function (deg, cx, cy) { +3525 if (this.removed) { +3526 return this; +3527 } +3528 if (deg == null) { +3529 return; +3530 } +3531 deg = Str(deg).split(separator); +3532 if (deg.length - 1) { +3533 cx = toFloat(deg[1]); +3534 cy = toFloat(deg[2]); 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; +3536 deg = toFloat(deg[0]); +3537 (cy == null) && (cx = cy); +3538 if (cx == null || cy == null) { +3539 var bbox = this.getBBox(1); +3540 cx = bbox.x + bbox.width / 2; +3541 cy = bbox.y + bbox.height / 2; +3542 } +3543 this._.dirtyT = 1; +3544 this.transform(this._.transform.concat([["r", deg, cx, cy]])); +3545 return this; +3546 }; +3547 elproto.translate = function (dx, dy) { +3548 if (this.removed) { +3549 return this; +3550 } +3551 dx = Str(dx).split(separator); +3552 if (dx.length - 1) { +3553 dy = toFloat(dx[1]); +3554 } +3555 dx = toFloat(dx[0]) || 0; +3556 dy = +dy || 0; +3557 if (this._.bbox) { +3558 this._.bbox.x += dx; +3559 this._.bbox.y += dy; +3560 } +3561 this.transform(this._.transform.concat([["t", dx, dy]])); +3562 return this; +3563 }; +3564 elproto.scale = function (sx, sy, cx, cy) { +3565 if (this.removed) { +3566 return this; +3567 } +3568 sx = Str(sx).split(separator); +3569 if (sx.length - 1) { +3570 sy = toFloat(sx[1]); +3571 cx = toFloat(sx[2]); +3572 cy = toFloat(sx[3]); +3573 isNaN(cx) && (cx = null); +3574 isNaN(cy) && (cy = null); +3575 } +3576 sx = toFloat(sx[0]); +3577 (sy == null) && (sy = sx); +3578 (cy == null) && (cx = cy); +3579 if (cx == null || cy == null) { +3580 var bbox = this.getBBox(1); +3581 } +3582 cx = cx == null ? bbox.x + bbox.width / 2 : cx; +3583 cy = cy == null ? bbox.y + bbox.height / 2 : cy; +3584 +3585 this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); +3586 this._.dirtyT = 1; +3587 return this; +3588 }; +3589 elproto.hide = function () { +3590 !this.removed && (this.node.style.display = "none"); +3591 return this; 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; +3593 elproto.show = function () { +3594 !this.removed && (this.node.style.display = E); +3595 return this; +3596 }; +3597 elproto._getBBox = function () { +3598 if (this.removed) { +3599 return {}; +3600 } +3601 if (this.type == "text") { +3602 return { +3603 x: this.X + (this.bbx || 0) - this.W / 2, +3604 y: this.Y - this.H, +3605 width: this.W, +3606 height: this.H +3607 }; +3608 } else { +3609 return pathDimensions(this.attrs.path); +3610 } +3611 }; +3612 elproto.remove = function () { +3613 if (this.removed) { +3614 return; +3615 } +3616 eve.unbind("*.*." + this.id); +3617 tear(this, this.paper); +3618 this.node.parentNode.removeChild(this.node); +3619 this.shape && this.shape.parentNode.removeChild(this.shape); +3620 for (var i in this) { +3621 delete this[i]; +3622 } +3623 this.removed = true; +3624 }; +3625 elproto.attr = function (name, value) { +3626 if (this.removed) { +3627 return this; 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 } +3629 if (name == null) { +3630 var res = {}; +3631 for (var i in this.attrs) if (this.attrs[has](i)) { +3632 res[i] = this.attrs[i]; +3633 } +3634 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; +3635 return res; +3636 } +3637 if (value == null && R.is(name, "string")) { +3638 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { +3639 return this.attrs.gradient; 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; +3641 if (name in this.attrs) { +3642 return this.attrs[name]; +3643 } else if (R.is(this.paper.customAttributes[name], "function")) { +3644 return this.paper.customAttributes[name].def; +3645 } else { +3646 return availableAttrs[name]; +3647 } +3648 } +3649 if (this.attrs && value == null && R.is(name, array)) { +3650 var ii, values = {}; +3651 for (i = 0, ii = name.length; i < ii; i++) { +3652 values[name[i]] = this.attr(name[i]); +3653 } +3654 return values; +3655 } +3656 var params; +3657 if (value != null) { +3658 params = {}; +3659 params[name] = value; +3660 } +3661 value == null && R.is(name, "object") && (params = name); +3662 for (var key in params) { +3663 eve("attr." + key + "." + this.id, this, params[key]); +3664 } +3665 if (params) { +3666 for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { +3667 var par = this.paper.customAttributes[key].apply(this, [][concat](params[key])); +3668 this.attrs[key] = params[key]; +3669 for (var subkey in par) if (par[has](subkey)) { +3670 params[subkey] = par[subkey]; +3671 } +3672 } +3673 // this.paper.canvas.style.display = "none"; +3674 if (params.text && this.type == "text") { +3675 this.textpath.string = params.text; +3676 } +3677 setFillAndStroke(this, params); +3678 // this.paper.canvas.style.display = E; +3679 } +3680 return this; +3681 }; +3682 elproto.toFront = function () { +3683 !this.removed && this.node.parentNode.appendChild(this.node); +3684 this.paper.top != this && tofront(this, this.paper); +3685 return this; +3686 }; +3687 elproto.toBack = function () { +3688 if (this.removed) { +3689 return this; +3690 } +3691 if (this.node.parentNode.firstChild != this.node) { +3692 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); +3693 toback(this, this.paper); +3694 } +3695 return this; +3696 }; +3697 elproto.insertAfter = function (element) { +3698 if (this.removed) { +3699 return this; +3700 } +3701 if (element.constructor == Set) { +3702 element = element[element.length - 1]; 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 stopPropagation = function () { -3969 this.cancelBubble = true; -3970 }, -3971 stopTouch = function () { -3972 return this.originalEvent.stopPropagation(); -3973 }, -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 +3704 if (element.node.nextSibling) { +3705 element.node.parentNode.insertBefore(this.node, element.node.nextSibling); +3706 } else { +3707 element.node.parentNode.appendChild(this.node); +3708 } +3709 insertafter(this, element, this.paper); +3710 return this; +3711 }; +3712 elproto.insertBefore = function (element) { +3713 if (this.removed) { +3714 return this; +3715 } +3716 if (element.constructor == Set) { +3717 element = element[0]; +3718 } +3719 element.node.parentNode.insertBefore(this.node, element.node); +3720 insertbefore(this, element, this.paper); +3721 return this; +3722 }; +3723 elproto.blur = function (size) { +3724 var s = this.node.runtimeStyle, +3725 f = s.filter; +3726 f = f.replace(blurregexp, E); +3727 if (+size !== 0) { +3728 this.attrs.blur = size; +3729 s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")"; +3730 s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5)); +3731 } else { +3732 s.filter = f; +3733 s.margin = 0; +3734 delete this.attrs.blur; +3735 } +3736 }; +3737 +3738 thePath = function (pathString, vml) { +3739 var el = createNode("shape"); +3740 el.style.cssText = cssDot; +3741 el.coordsize = zoom + S + zoom; +3742 el.coordorigin = vml.coordorigin; +3743 var p = new Element(el, vml), +3744 attr = {fill: "none", stroke: "#000"}; +3745 pathString && (attr.path = pathString); +3746 p.type = "path"; +3747 p.path = []; +3748 p.Path = E; +3749 setFillAndStroke(p, attr); +3750 vml.canvas.appendChild(el); +3751 var skew = createNode("skew"); +3752 skew.on = true; +3753 el.appendChild(skew); +3754 p.skew = skew; +3755 p.transform(E); +3756 return p; +3757 }; +3758 theRect = function (vml, x, y, w, h, r) { +3759 var path = rectPath(x, y, w, h, r), +3760 res = vml.path(path), +3761 a = res.attrs; +3762 res.X = a.x = x; +3763 res.Y = a.y = y; +3764 res.W = a.width = w; +3765 res.H = a.height = h; +3766 a.r = r; +3767 a.path = path; +3768 res.type = "rect"; +3769 return res; +3770 }; +3771 theEllipse = function (vml, x, y, rx, ry) { +3772 var res = vml.path(), +3773 a = res.attrs; +3774 res.X = x - rx; +3775 res.Y = y - ry; +3776 res.W = rx * 2; +3777 res.H = ry * 2; +3778 res.type = "ellipse"; +3779 setFillAndStroke(res, { +3780 cx: x, +3781 cy: y, +3782 rx: rx, +3783 ry: ry +3784 }); +3785 return res; +3786 }; +3787 theCircle = function (vml, x, y, r) { +3788 var res = vml.path(), +3789 a = res.attrs; +3790 res.X = x - r; +3791 res.Y = y - r; +3792 res.W = res.H = r * 2; +3793 res.type = "circle"; +3794 setFillAndStroke(res, { +3795 cx: x, +3796 cy: y, +3797 r: r +3798 }); +3799 return res; +3800 }; +3801 theImage = function (vml, src, x, y, w, h) { +3802 var path = rectPath(x, y, w, h), +3803 res = vml.path(path).attr({stroke: "none"}), +3804 a = res.attrs, +3805 node = res.node, +3806 fill = node.getElementsByTagName(fillString)[0]; +3807 a.src = src; +3808 res.X = a.x = x; +3809 res.Y = a.y = y; +3810 res.W = a.width = w; +3811 res.H = a.height = h; +3812 a.path = path; +3813 res.type = "image"; +3814 fill.parentNode == node && node.removeChild(fill); +3815 fill.rotate = true; +3816 fill.src = src; +3817 fill.type = "tile"; +3818 res._.fillpos = [x, y]; +3819 res._.fillsize = [w, h]; +3820 node.appendChild(fill); +3821 setCoords(res); +3822 return res; +3823 }; +3824 theText = function (vml, x, y, text) { +3825 var el = createNode("shape"), +3826 path = createNode("path"), +3827 o = createNode("textpath"); +3828 x = x || 0; +3829 y = y || 0; +3830 text = text || ""; +3831 path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1); +3832 path.textpathok = true; +3833 o.string = Str(text); +3834 o.on = true; +3835 el.style.cssText = "position:absolute;left:0;top:0;width:1;height:1"; +3836 el.coordsize = zoom + S + zoom; +3837 el.coordorigin = "0 0"; +3838 var p = new Element(el, vml), +3839 attr = {fill: "#000", stroke: "none", font: availableAttrs.font, text: text}; +3840 p.shape = el; +3841 p.path = path; +3842 p.textpath = o; +3843 p.type = "text"; +3844 p.attrs.text = Str(text); +3845 p.attrs.x = x; +3846 p.attrs.y = y; +3847 p.attrs.w = 1; +3848 p.attrs.h = 1; +3849 setFillAndStroke(p, attr); +3850 el.appendChild(o); +3851 el.appendChild(path); +3852 vml.canvas.appendChild(el); +3853 var skew = createNode("skew"); +3854 skew.on = true; +3855 el.appendChild(skew); +3856 p.skew = skew; +3857 p.transform(E); +3858 return p; +3859 }; +3860 setSize = function (width, height) { +3861 var cs = this.canvas.style; +3862 this.width = width; +3863 this.height = height; +3864 width == +width && (width += "px"); +3865 height == +height && (height += "px"); +3866 cs.width = width; +3867 cs.height = height; +3868 cs.clip = "rect(0 " + width + " " + height + " 0)"; +3869 if (this._viewBox) { +3870 setViewBox.apply(this, this._viewBox); +3871 } +3872 return this; +3873 }; +3874 setViewBox = function (x, y, w, h, fit) { +3875 eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); +3876 var width = this.width, +3877 height = this.height, +3878 size = 1e3 * mmax(w / width, h / height), +3879 H, W; +3880 if (fit) { +3881 H = height / h; +3882 W = width / w; +3883 if (w * H < width) { +3884 x -= (width - w * H) / 2 / H; +3885 } +3886 if (h * W < height) { +3887 y -= (height - h * W) / 2 / W; +3888 } +3889 } +3890 this._viewBox = [x, y, w, h, !!fit]; +3891 this.forEach(function (el) { +3892 el.transform("..."); +3893 }); +3894 return this; +3895 }; +3896 var createNode, +3897 initWin = function (win) { +3898 var doc = win.document; +3899 doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); +3900 try { +3901 !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); +3902 createNode = function (tagName) { +3903 return doc.createElement('<rvml:' + tagName + ' class="rvml">'); +3904 }; +3905 } catch (e) { +3906 createNode = function (tagName) { +3907 return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); +3908 }; +3909 } +3910 }; +3911 initWin(g.win); +3912 create = function () { +3913 var con = getContainer[apply](0, arguments), +3914 container = con.container, +3915 height = con.height, +3916 s, +3917 width = con.width, +3918 x = con.x, +3919 y = con.y; +3920 if (!container) { +3921 throw new Error("VML container not found."); +3922 } +3923 var res = new Paper, +3924 c = res.canvas = g.doc.createElement("div"), +3925 cs = c.style; +3926 x = x || 0; +3927 y = y || 0; +3928 width = width || 512; +3929 height = height || 342; +3930 res.width = width; +3931 res.height = height; +3932 width == +width && (width += "px"); +3933 height == +height && (height += "px"); +3934 res.coordsize = zoom * 1e3 + S + zoom * 1e3; +3935 res.coordorigin = "0 0"; +3936 res.span = g.doc.createElement("span"); +3937 res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;"; +3938 c.appendChild(res.span); +3939 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); +3940 if (container == 1) { +3941 g.doc.body.appendChild(c); +3942 cs.left = x + "px"; +3943 cs.top = y + "px"; +3944 cs.position = "absolute"; +3945 } else { +3946 if (container.firstChild) { +3947 container.insertBefore(c, container.firstChild); +3948 } else { +3949 container.appendChild(c); +3950 } +3951 } +3952 plugins.call(res, res, R.fn); +3953 res.renderfix = fun; +3954 return res; +3955 }; +3956 paperproto.clear = function () { +3957 eve("clear", this); +3958 this.canvas.innerHTML = E; +3959 this.span = g.doc.createElement("span"); +3960 this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;"; +3961 this.canvas.appendChild(this.span); +3962 this.bottom = this.top = null; +3963 }; +3964 paperproto.remove = function () { +3965 eve("remove", this); +3966 this.canvas.parentNode.removeChild(this.canvas); +3967 for (var i in this) { +3968 this[i] = removed(i); +3969 } +3970 return true; +3971 }; +3972 } +3973 +3974 // WebKit rendering bug workaround method +3975 var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/); +3976 if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") || +3977 (navigator.vendor == "Google Inc." && version && version[1] < 8)) { +3978 /*\ +3979 * Paper.safari +3980 [ method ] +3981 ** +3982 * There is an inconvenient rendering bug in Safari (WebKit): +3983 * sometimes the rendering should be forced. +3984 * This method should help with dealing with this bug. +3985 \*/ +3986 paperproto.safari = function () { +3987 var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"}); +3988 setTimeout(function () {rect.remove();}); +3989 }; +3990 } else { +3991 paperproto.safari = fun; +3992 } +3993 +3994 // Events +3995 var preventDefault = function () { +3996 this.returnValue = false; +3997 }, +3998 preventTouch = function () { +3999 return this.originalEvent.preventDefault(); +4000 }, +4001 stopPropagation = function () { +4002 this.cancelBubble = true; +4003 }, +4004 stopTouch = function () { +4005 return this.originalEvent.stopPropagation(); +4006 }, +4007 addEvent = (function () { +4008 if (g.doc.addEventListener) { +4009 return function (obj, type, fn, element) { +4010 var realName = supportsTouch && touchMap[type] ? touchMap[type] : type; +4011 var f = function (e) { +4012 if (supportsTouch && touchMap[has](type)) { +4013 for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { +4014 if (e.targetTouches[i].target == obj) { +4015 var olde = e; +4016 e = e.targetTouches[i]; +4017 e.originalEvent = olde; +4018 e.preventDefault = preventTouch; +4019 e.stopPropagation = stopTouch; +4020 break; +4021 } +4022 } +4023 } +4024 return fn.call(element, e); +4025 }; +4026 obj.addEventListener(realName, f, false); +4027 return function () { +4028 obj.removeEventListener(realName, f, false); +4029 return true; +4030 }; +4031 }; +4032 } else if (g.doc.attachEvent) { +4033 return function (obj, type, fn, element) { +4034 var f = function (e) { +4035 e = e || g.win.event; +4036 e.preventDefault = e.preventDefault || preventDefault; +4037 e.stopPropagation = e.stopPropagation || stopPropagation; +4038 return fn.call(element, e); +4039 }; +4040 obj.attachEvent("on" + type, f); +4041 var detacher = function () { +4042 obj.detachEvent("on" + type, f); +4043 return true; +4044 }; +4045 return detacher; +4046 }; +4047 } +4048 })(), +4049 drag = [], +4050 dragMove = function (e) { +4051 var x = e.clientX, +4052 y = e.clientY, +4053 scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, +4054 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, +4055 dragi, +4056 j = drag.length; +4057 while (j--) { +4058 dragi = drag[j]; +4059 if (supportsTouch) { +4060 var i = e.touches.length, +4061 touch; +4062 while (i--) { +4063 touch = e.touches[i]; +4064 if (touch.identifier == dragi.el._drag.id) { +4065 x = touch.clientX; +4066 y = touch.clientY; +4067 (e.originalEvent ? e.originalEvent : e).preventDefault(); +4068 break; +4069 } +4070 } +4071 } else { +4072 e.preventDefault(); +4073 } +4074 var node = dragi.el.node, +4075 o, +4076 next = node.nextSibling, +4077 parent = node.parentNode, +4078 display = node.style.display; +4079 g.win.opera && parent.removeChild(node); +4080 node.style.display = "none"; +4081 o = dragi.el.paper.getElementByPoint(x, y); +4082 node.style.display = display; +4083 g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node)); +4084 o && eve("drag.over." + dragi.el.id, dragi.el, o); +4085 x += scrollX; +4086 y += scrollY; +4087 eve("drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e); +4088 } +4089 }, +4090 dragUp = function (e) { +4091 R.unmousemove(dragMove).unmouseup(dragUp); +4092 var i = drag.length, +4093 dragi; +4094 while (i--) { +4095 dragi = drag[i]; +4096 dragi.el._drag = {}; +4097 eve("drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e); +4098 } +4099 drag = []; +4100 }; +4101 for (var i = events.length; i--;) { +4102 (function (eventName) { +4103 R[eventName] = Element.prototype[eventName] = function (fn, scope) { +4104 if (R.is(fn, "function")) { +4105 this.events = this.events || []; +4106 this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)}); +4107 } +4108 return this; +4109 }; +4110 R["un" + eventName] = Element.prototype["un" + eventName] = function (fn) { +4111 var events = this.events, +4112 l = events.length; +4113 while (l--) if (events[l].name == eventName && events[l].f == fn) { +4114 events[l].unbind(); +4115 events.splice(l, 1); +4116 !events.length && delete this.events; +4117 return this; +4118 } +4119 return this; +4120 }; +4121 })(events[i]); +4122 } +4123 /*\ +4124 * Element.hover +4125 [ method ] +4126 ** +4127 * Adds event handlers for hover for the element. +4128 > Parameters +4129 - f_in (function) handler for hover in +4130 - f_out (function) handler for hover out +4131 - icontext (object) #optional context for hover in handler +4132 - ocontext (object) #optional context for hover out handler +4133 = (object) @Element +4134 \*/ +4135 elproto.hover = function (f_in, f_out, scope_in, scope_out) { +4136 return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in); +4137 }; +4138 /*\ +4139 * Element.unhover +4140 [ method ] +4141 ** +4142 * Removes event handlers for hover for the element. +4143 > Parameters +4144 - f_in (function) handler for hover in +4145 - f_out (function) handler for hover out 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 ] +4148 elproto.unhover = function (f_in, f_out) { +4149 return this.unmouseover(f_in).unmouseout(f_out); +4150 }; +4151 /*\ +4152 * Element.drag +4153 [ method ] +4154 ** +4155 * Adds event handlers for drag of the element. +4156 > Parameters +4157 - onmove (function) handler for moving +4158 - onstart (function) handler for drag start +4159 - onend (function) handler for drag end +4160 - mcontext (object) #optional context for moving handler +4161 - scontext (object) #optional context for drag start handler +4162 - econtext (object) #optional context for drag end handler +4163 * Additionaly following `drag` events will be triggered: `drag.start.<id>` on start, +4164 * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element +4165 * `drag.over.<id>` will be fired as well. +4166 * +4167 * Start event and start handler will be called in specified context or in context of the element with following parameters: +4168 o x (number) x position of the mouse +4169 o y (number) y position of the mouse +4170 o event (object) DOM event object +4171 * Move event and move handler will be called in specified context or in context of the element with following parameters: +4172 o dx (number) shift by x from the start point +4173 o dy (number) shift by y from the start point +4174 o x (number) x position of the mouse +4175 o y (number) y position of the mouse +4176 o event (object) DOM event object +4177 * End event and end handler will be called in specified context or in context of the element with following parameters: +4178 o event (object) DOM event object +4179 = (object) @Element +4180 \*/ +4181 elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) { +4182 function start(e) { +4183 (e.originalEvent || e).preventDefault(); +4184 var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, +4185 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft; +4186 this._drag.x = e.clientX + scrollX; +4187 this._drag.y = e.clientY + scrollY; +4188 this._drag.id = e.identifier; +4189 !drag.length && R.mousemove(dragMove).mouseup(dragUp); +4190 drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope}); +4191 onstart && eve.on("drag.start." + this.id, onstart); +4192 onmove && eve.on("drag.move." + this.id, onmove); +4193 onend && eve.on("drag.end." + this.id, onend); +4194 eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e); +4195 } +4196 this._drag = {}; +4197 this.mousedown(start); +4198 return this; +4199 }; +4200 /*\ +4201 * Element.onDragOver +4202 [ method ] +4203 ** +4204 * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id). +4205 > Parameters +4206 - f (function) handler for event +4207 \*/ +4208 elproto.onDragOver = function (f) { +4209 f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id); +4210 }; +4211 /*\ +4212 * Element.undrag +4213 [ method ] +4214 ** +4215 * Removes all drag event handlers from given element. +4216 \*/ +4217 elproto.undrag = function () { +4218 var i = drag.length; +4219 while (i--) if (drag[i].el == this) { +4220 R.unmousedown(drag[i].start); +4221 drag.splice(i++, 1); +4222 eve.unbind("drag.*." + this.id); +4223 } +4224 !drag.length && R.unmousemove(dragMove).unmouseup(dragUp); +4225 }; +4226 /*\ +4227 * Paper.circle +4228 [ method ] +4229 ** +4230 * Draws a circle. +4231 ** +4232 > Parameters +4233 ** +4234 - x (number) x coordinate of the centre +4235 - y (number) y coordinate of the centre +4236 - r (number) radius +4237 = (object) Raphaël element object with type “circle” +4238 ** +4239 > Usage +4240 | var c = paper.circle(50, 50, 40); +4241 \*/ +4242 paperproto.circle = function (x, y, r) { +4243 return theCircle(this, x || 0, y || 0, r || 0); +4244 }; +4245 /*\ +4246 * Paper.rect +4247 [ method ] +4248 * +4249 * Draws a rectangle. +4250 ** +4251 > Parameters +4252 ** +4253 - x (number) x coordinate of the top left corner +4254 - y (number) y coordinate of the top left corner +4255 - width (number) width +4256 - height (number) height +4257 - r (number) #optional radius for rounded corners, default is 0 +4258 = (object) Raphaël element object with type “rect” 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. +4260 > Usage +4261 | // regular rectangle +4262 | var c = paper.rect(10, 10, 50, 50); +4263 | // rectangle with rounded corners +4264 | var c = paper.rect(40, 40, 50, 50, 10); +4265 \*/ +4266 paperproto.rect = function (x, y, w, h, r) { +4267 return theRect(this, x || 0, y || 0, w || 0, h || 0, r || 0); +4268 }; +4269 /*\ +4270 * Paper.ellipse +4271 [ method ] +4272 ** +4273 * Draws an ellipse. +4274 ** +4275 > Parameters +4276 ** +4277 - x (number) x coordinate of the centre +4278 - y (number) y coordinate of the centre +4279 - rx (number) horizontal radius +4280 - ry (number) vertical radius +4281 = (object) Raphaël element object with type “ellipse” 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 +4283 > Usage +4284 | var c = paper.ellipse(50, 50, 40, 20); +4285 \*/ +4286 paperproto.ellipse = function (x, y, rx, ry) { +4287 return theEllipse(this, x || 0, y || 0, rx || 0, ry || 0); +4288 }; +4289 /*\ +4290 * Paper.path +4291 [ method ] +4292 ** +4293 * Creates a path element by given path data string. +4294 ** +4295 > Parameters +4296 ** +4297 - pathString (string) path data in SVG path string format. +4298 = (object) Raphaël element object with type “ellipse” +4299 # 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>. +4300 ** +4301 > Usage +4302 | var c = paper.path("M10 10L90 90"); +4303 | // draw a diagonal line: +4304 | // move to 10,10, line to 90,90 +4305 \*/ +4306 paperproto.path = function (pathString) { +4307 pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E); +4308 return thePath(R.format[apply](R, arguments), this); +4309 }; +4310 /*\ +4311 * Paper.image +4312 [ method ] +4313 ** +4314 * Embeds an image into the surface. +4315 ** +4316 > Parameters +4317 ** +4318 - src (string) URI of the source image +4319 - x (number) x coordinate position +4320 - y (number) y coordinate position +4321 - width (number) width of the image +4322 - height (number) height of the image +4323 = (object) Raphaël element object with type “image” +4324 ** +4325 > Usage +4326 | var c = paper.image("apple.png", 10, 10, 80, 80); +4327 \*/ +4328 paperproto.image = function (src, x, y, w, h) { +4329 return theImage(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0); +4330 }; +4331 /*\ +4332 * Paper.text +4333 [ method ] +4334 ** +4335 * Draws a text string. If you need line breaks, put “\n” in the string. +4336 ** +4337 > Parameters +4338 ** +4339 - x (number) x coordinate position +4340 - y (number) y coordinate position +4341 - text (string) The text string to draw +4342 = (object) Raphaël element object with type “text” 4343 ** -4344 > Parameters -4345 ** -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 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 }; +4344 > Usage +4345 | var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!"); +4346 \*/ +4347 paperproto.text = function (x, y, text) { +4348 return theText(this, x || 0, y || 0, Str(text)); +4349 }; +4350 /*\ +4351 * Paper.set +4352 [ method ] +4353 ** +4354 * Creates array-like object to keep and operate several elements at once. +4355 * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements. +4356 * Sets act as pseudo elements — all methods available to an element can be used on a set. +4357 = (object) array-like object that represents set of elements +4358 ** +4359 > Usage +4360 | var st = paper.set(); +4361 | st.push( +4362 | paper.circle(10, 10, 5), +4363 | paper.circle(30, 10, 5) +4364 | ); +4365 | st.attr({fill: "red"}); +4366 \*/ +4367 paperproto.set = function (itemsArray) { +4368 arguments.length > 1 && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length)); +4369 return new Set(itemsArray); +4370 }; +4371 /*\ +4372 * Paper.setSize +4373 [ method ] +4374 ** +4375 * If you need to change dimensions of the canvas call this method +4376 ** +4377 > Parameters +4378 ** +4379 - width (number) new width of the canvas +4380 - height (number) new height of the canvas +4381 > Usage +4382 | var st = paper.set(); +4383 | st.push( +4384 | paper.circle(10, 10, 5), +4385 | paper.circle(30, 10, 5) +4386 | ); +4387 | st.attr({fill: "red"}); +4388 \*/ +4389 paperproto.setSize = setSize; +4390 /*\ +4391 * Paper.setViewBox +4392 [ method ] +4393 ** +4394 * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by +4395 * specifying new boundaries. +4396 ** +4397 > Parameters +4398 ** +4399 x, y, w, h, fit +4400 - x (number) new x position, default is `0` +4401 - y (number) new y position, default is `0` +4402 - w (number) new width of the canvas +4403 - h (number) new height of the canvas +4404 - fit (boolean) `true` if you want graphics to fit into new boundary box +4405 \*/ +4406 paperproto.setViewBox = setViewBox; 4407 /*\ -4408 * Paper.getElementByPoint -4409 [ method ] +4408 * Paper.top +4409 [ property ] 4410 ** -4411 * Returns you topmost element under given point. -4412 ** -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 > Parameters -4453 ** -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 - 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 > Parameters -4504 ** -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 } +4411 * Points to the topmost element on the paper +4412 \*/ +4413 /*\ +4414 * Paper.bottom +4415 [ property ] +4416 ** +4417 * Points to the bottom element on the paper +4418 \*/ +4419 paperproto.top = paperproto.bottom = null; +4420 /*\ +4421 * Paper.raphael +4422 [ property ] +4423 ** +4424 * Points to the @Raphael object/function +4425 \*/ +4426 paperproto.raphael = R; +4427 var getOffset = function (elem) { +4428 var box = elem.getBoundingClientRect(), +4429 doc = elem.ownerDocument, +4430 body = doc.body, +4431 docElem = doc.documentElement, +4432 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, +4433 top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop, +4434 left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft; +4435 return { +4436 y: top, +4437 x: left +4438 }; +4439 }; +4440 /*\ +4441 * Paper.getElementByPoint +4442 [ method ] +4443 ** +4444 * Returns you topmost element under given point. +4445 ** +4446 = (object) Raphaël element object +4447 > Parameters +4448 ** +4449 - x (number) x coordinate from the top left corner of the window +4450 - y (number) y coordinate from the top left corner of the window +4451 > Usage +4452 | paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"}); +4453 \*/ +4454 paperproto.getElementByPoint = function (x, y) { +4455 var paper = this, +4456 svg = paper.canvas, +4457 target = g.doc.elementFromPoint(x, y); +4458 if (g.win.opera && target.tagName == "svg") { +4459 var so = getOffset(svg), +4460 sr = svg.createSVGRect(); +4461 sr.x = x - so.x; +4462 sr.y = y - so.y; +4463 sr.width = sr.height = 1; +4464 var hits = svg.getIntersectionList(sr, null); +4465 if (hits.length) { +4466 target = hits[hits.length - 1]; +4467 } +4468 } +4469 if (!target) { +4470 return null; +4471 } +4472 while (target.parentNode && target != svg.parentNode && !target.raphael) { +4473 target = target.parentNode; +4474 } +4475 target == paper.canvas.parentNode && (target = svg); +4476 target = target && target.raphael ? paper.getById(target.raphaelid) : null; +4477 return target; +4478 }; +4479 /*\ +4480 * Paper.getById +4481 [ method ] +4482 ** +4483 * Returns you element by its internal ID. +4484 ** +4485 > Parameters +4486 ** +4487 - id (number) id +4488 = (object) Raphaël element object +4489 \*/ +4490 paperproto.getById = function (id) { +4491 var bot = this.bottom; +4492 while (bot) { +4493 if (bot.id == id) { +4494 return bot; +4495 } +4496 bot = bot.next; +4497 } +4498 return null; +4499 }; +4500 /*\ +4501 * Paper.forEach +4502 [ method ] +4503 ** +4504 * Executes given function for each element on the paper +4505 * +4506 * If callback function returns `false` it will stop loop running. +4507 ** +4508 > Parameters +4509 ** +4510 - callback (function) function to run +4511 - thisArg (object) context object for the callback +4512 = (object) Paper object 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 \*/ -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); +4514 paperproto.forEach = function (callback, thisArg) { +4515 var bot = this.bottom; +4516 while (bot) { +4517 if (callback.call(thisArg, bot) === false) { +4518 return this; +4519 } +4520 bot = bot.next; +4521 } +4522 return this; +4523 }; +4524 function x_y() { +4525 return this.x + S + this.y; +4526 } +4527 function x_y_w_h() { +4528 return this.x + S + this.y + S + this.width + "\xd7" + this.height; +4529 } +4530 /*\ +4531 * Element.getBBox +4532 [ method ] +4533 ** +4534 * Return bounding box for a given element +4535 ** +4536 > Parameters +4537 ** +4538 - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`. +4539 = (object) Bounding box object: +4540 o { +4541 o x: (number) top left corner x +4542 o y: (number) top left corner y +4543 o width: (number) width +4544 o height: (number) height +4545 o } +4546 \*/ +4547 elproto.getBBox = function (isWithoutTransform) { +4548 if (this.removed) { +4549 return {}; +4550 } +4551 var _ = this._; +4552 if (isWithoutTransform) { +4553 if (_.dirty || !_.bboxwt) { +4554 this.realPath = getPath[this.type](this); +4555 _.bboxwt = pathDimensions(this.realPath); +4556 _.bboxwt.toString = x_y_w_h; +4557 _.dirty = 0; +4558 } +4559 return _.bboxwt; +4560 } +4561 if (_.dirty || _.dirtyT || !_.bbox) { +4562 if (_.dirty || !this.realPath) { +4563 _.bboxwt = 0; +4564 this.realPath = getPath[this.type](this); +4565 } +4566 _.bbox = pathDimensions(mapPath(this.realPath, this.matrix)); +4567 _.bbox.toString = x_y_w_h; +4568 _.dirty = _.dirtyT = 0; +4569 } +4570 return _.bbox; +4571 }; +4572 /*\ +4573 * Element.clone +4574 [ method ] +4575 ** +4576 = (object) clone of a given element +4577 ** +4578 \*/ +4579 elproto.clone = function () { +4580 if (this.removed) { +4581 return null; +4582 } +4583 var attr = this.attr(); +4584 delete attr.scale; +4585 delete attr.translation; +4586 return this.paper[this.type]().attr(attr); 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 > Parameters -4672 ** -4673 - path (string) SVG path string. -4674 ** -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 > Parameters -4685 ** -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 > Parameters -4704 ** -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 ] +4588 /*\ +4589 * Element.glow +4590 [ method ] +4591 ** +4592 * Return set of elements that create glow-like effect around given element. See @Paper.set. +4593 * +4594 * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself. +4595 ** +4596 > Parameters +4597 ** +4598 - glow (object) #optional parameters object with all properties optional: +4599 o { +4600 o width (number) size of the glow, default is `10` +4601 o fill (boolean) will it be filled, default is `false` +4602 o opacity: opacity, default is `0.5` +4603 o offsetx: horizontal offset, default is `0` +4604 o offsety: vertical offset, default is `0` +4605 o color: glow colour, default is `black` +4606 o } +4607 = (object) @Paper.set of elements that represents glow +4608 \*/ +4609 elproto.glow = function (glow) { +4610 if (this.type == "text") { +4611 return null; +4612 } +4613 glow = glow || {}; +4614 var s = { +4615 width: (glow.width || 10) + (+this.attr("stroke-width") || 1), +4616 fill: glow.fill || false, +4617 opacity: glow.opacity || .5, +4618 offsetx: glow.offsetx || 0, +4619 offsety: glow.offsety || 0, +4620 color: glow.color || "#000" +4621 }, +4622 c = s.width / 2, +4623 r = this.paper, +4624 out = r.set(), +4625 path = this.realPath || getPath[this.type](this); +4626 path = this.matrix ? mapPath(path, this.matrix) : path; +4627 for (var i = 1; i < c + 1; i++) { +4628 out.push(r.path(path).attr({ +4629 stroke: s.color, +4630 fill: s.fill ? s.color : "none", +4631 "stroke-linejoin": "round", +4632 "stroke-linecap": "round", +4633 "stroke-width": +(s.width / c * i).toFixed(3), +4634 opacity: +(s.opacity / c).toFixed(3) +4635 })); +4636 } +4637 return out.insertBefore(this).translate(s.offsetx, s.offsety); +4638 }; +4639 var curveslengths = {}, +4640 getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { +4641 var len = 0, +4642 precision = 100, +4643 name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(), +4644 cache = curveslengths[name], +4645 old, dot; +4646 !cache && (curveslengths[name] = cache = {data: []}); +4647 cache.timer && clearTimeout(cache.timer); +4648 cache.timer = setTimeout(function () {delete curveslengths[name];}, 2e3); +4649 if (length != null && !cache.precision) { +4650 var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y); +4651 cache.precision = ~~total * 10; +4652 cache.data = []; +4653 } +4654 precision = cache.precision || precision; +4655 for (var i = 0; i < precision + 1; i++) { +4656 if (cache.data[i * precision]) { +4657 dot = cache.data[i * precision]; +4658 } else { +4659 dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision); +4660 cache.data[i * precision] = dot; +4661 } +4662 i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5)); +4663 if (length != null && len >= length) { +4664 return dot; +4665 } +4666 old = dot; +4667 } +4668 if (length == null) { +4669 return len; +4670 } +4671 }, +4672 getLengthFactory = function (istotal, subpath) { +4673 return function (path, length, onlystart) { +4674 path = path2curve(path); +4675 var x, y, p, l, sp = "", subpaths = {}, point, +4676 len = 0; +4677 for (var i = 0, ii = path.length; i < ii; i++) { +4678 p = path[i]; +4679 if (p[0] == "M") { +4680 x = +p[1]; +4681 y = +p[2]; +4682 } else { +4683 l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); +4684 if (len + l > length) { +4685 if (subpath && !subpaths.start) { +4686 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); +4687 sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y]; +4688 if (onlystart) {return sp;} +4689 subpaths.start = sp; +4690 sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join(); +4691 len += l; +4692 x = +p[5]; +4693 y = +p[6]; +4694 continue; +4695 } +4696 if (!istotal && !subpath) { +4697 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); +4698 return {x: point.x, y: point.y, alpha: point.alpha}; +4699 } +4700 } +4701 len += l; +4702 x = +p[5]; +4703 y = +p[6]; +4704 } +4705 sp += p.shift() + p; +4706 } +4707 subpaths.end = sp; +4708 point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], 1); +4709 point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha}); +4710 return point; +4711 }; +4712 }; +4713 var getTotalLength = getLengthFactory(1), +4714 getPointAtLength = getLengthFactory(), +4715 getSubpathsAtLength = getLengthFactory(0, 1); +4716 /*\ +4717 * Raphael.getTotalLength +4718 [ method ] +4719 ** +4720 * Returns length of the given path in pixels. 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 > Parameters +4722 > Parameters +4723 ** +4724 - path (string) SVG path string. +4725 ** +4726 = (number) length. +4727 \*/ +4728 R.getTotalLength = getTotalLength; +4729 /*\ +4730 * Raphael.getPointAtLength +4731 [ method ] +4732 ** +4733 * Return coordinates of the point located at the given length on the given path. +4734 ** +4735 > Parameters +4736 ** +4737 - path (string) SVG path string +4738 - length (number) 4739 ** -4740 - length (number) -4741 ** -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 > Parameters -4760 ** -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); +4740 = (object) representation of the point: +4741 o { +4742 o x: (number) x coordinate +4743 o y: (number) y coordinate +4744 o alpha: (number) angle of derivative +4745 o } +4746 \*/ +4747 R.getPointAtLength = getPointAtLength; +4748 /*\ +4749 * Raphael.getSubpath +4750 [ method ] +4751 ** +4752 * Return subpath of a given path from given length to given length. +4753 ** +4754 > Parameters +4755 ** +4756 - path (string) SVG path string +4757 - from (number) position of the start of the segment +4758 - to (number) position of the end of the segment +4759 ** +4760 = (string) pathstring for the segment +4761 \*/ +4762 R.getSubpath = function (path, from, to) { +4763 if (abs(this.getTotalLength(path) - to) < 1e-6) { +4764 return getSubpathsAtLength(path, from).end; +4765 } +4766 var a = getSubpathsAtLength(path, to, 1); +4767 return from ? getSubpathsAtLength(a, from).end : a; +4768 }; +4769 /*\ +4770 * Element.getTotalLength +4771 [ method ] +4772 ** +4773 * Returns length of the path in pixels. Only works for element of “path” type. +4774 = (number) length. +4775 \*/ +4776 elproto.getTotalLength = function () { +4777 if (this.type != "path") {return;} +4778 if (this.node.getTotalLength) { +4779 return this.node.getTotalLength(); +4780 } +4781 return getTotalLength(this.attrs.path); +4782 }; +4783 /*\ +4784 * Element.getPointAtLength +4785 [ method ] +4786 ** +4787 * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type. +4788 ** +4789 > Parameters +4790 ** +4791 - length (number) +4792 ** +4793 = (object) representation of the point: +4794 o { +4795 o x: (number) x coordinate +4796 o y: (number) y coordinate +4797 o alpha: (number) angle of derivative +4798 o } +4799 \*/ +4800 elproto.getPointAtLength = function (length) { +4801 if (this.type != "path") {return;} +4802 return getPointAtLength(this.attrs.path, length); +4803 }; +4804 /*\ +4805 * Element.getSubpath +4806 [ method ] +4807 ** +4808 * Return subpath of a given element from given length to given length. Only works for element of “path” type. +4809 ** +4810 > Parameters +4811 ** +4812 - from (number) position of the start of the segment +4813 - to (number) position of the end of the segment +4814 ** +4815 = (string) pathstring for the segment +4816 \*/ +4817 elproto.getSubpath = function (from, to) { +4818 if (this.type != "path") {return;} +4819 return R.getSubpath(this.attrs.path, from, to); +4820 }; +4821 /*\ +4822 * Raphael.easing_formulas +4823 [ property ] +4824 ** +4825 * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing: +4826 # <ul> +4827 # <li>“linear”</li> +4828 # <li>“<” or “easeIn” or “ease-in”</li> +4829 # <li>“>” or “easeOut” or “ease-out”</li> +4830 # <li>“<>” or “easeInOut” or “ease-in-out”</li> +4831 # <li>“backIn” or “back-in”</li> +4832 # <li>“backOut” or “back-out”</li> +4833 # <li>“elastic”</li> +4834 # <li>“bounce”</li> +4835 # </ul> +4836 # <p>See also <a href="http://raphaeljs.com/easing.html">Easing demo</a>.</p> +4837 \*/ +4838 var ef = R.easing_formulas = { +4839 linear: function (n) { +4840 return n; +4841 }, +4842 "<": function (n) { +4843 return pow(n, 1.7); +4844 }, +4845 ">": function (n) { +4846 return pow(n, .48); +4847 }, +4848 "<>": function (n) { +4849 var q = .48 - n / 1.04, +4850 Q = math.sqrt(.1734 + q * q), +4851 x = Q - q, +4852 X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1), +4853 y = -Q - q, +4854 Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1), +4855 t = X + Y + .5; +4856 return (1 - t) * 3 * t * t + t * t * t; +4857 }, +4858 backIn: function (n) { +4859 var s = 1.70158; +4860 return n * n * ((s + 1) * n - s); +4861 }, +4862 backOut: function (n) { +4863 n = n - 1; +4864 var s = 1.70158; +4865 return n * n * ((s + 1) * n + s) + 1; +4866 }, +4867 elastic: function (n) { +4868 if (n == !!n) { +4869 return n; +4870 } +4871 return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1; +4872 }, +4873 bounce: function (n) { +4874 var s = 7.5625, +4875 p = 2.75, +4876 l; +4877 if (n < (1 / p)) { +4878 l = s * n * n; +4879 } else { +4880 if (n < (2 / p)) { +4881 n -= (1.5 / p); +4882 l = s * n * n + .75; 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 > Parameters -4989 ** -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; +4884 if (n < (2.5 / p)) { +4885 n -= (2.25 / p); +4886 l = s * n * n + .9375; +4887 } else { +4888 n -= (2.625 / p); +4889 l = s * n * n + .984375; +4890 } +4891 } +4892 } +4893 return l; +4894 } +4895 }; +4896 ef.easeIn = ef["ease-in"] = ef["<"]; +4897 ef.easeOut = ef["ease-out"] = ef[">"]; +4898 ef.easeInOut = ef["ease-in-out"] = ef["<>"]; +4899 ef["back-in"] = ef.backIn; +4900 ef["back-out"] = ef.backOut; +4901 +4902 var animationElements = [], +4903 requestAnimFrame = window.requestAnimationFrame || +4904 window.webkitRequestAnimationFrame || +4905 window.mozRequestAnimationFrame || +4906 window.oRequestAnimationFrame || +4907 window.msRequestAnimationFrame || +4908 function (callback) { +4909 setTimeout(callback, 16); +4910 }, +4911 animation = function () { +4912 var Now = +new Date, +4913 l = 0; +4914 for (; l < animationElements.length; l++) { +4915 var e = animationElements[l]; +4916 if (e.el.removed || e.paused) { +4917 continue; +4918 } +4919 var time = Now - e.start, +4920 ms = e.ms, +4921 easing = e.easing, +4922 from = e.from, +4923 diff = e.diff, +4924 to = e.to, +4925 t = e.t, +4926 that = e.el, +4927 set = {}, +4928 now; +4929 if (e.initstatus) { +4930 time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms; +4931 e.status = e.initstatus; +4932 delete e.initstatus; +4933 e.stop && animationElements.splice(l--, 1); +4934 } else { +4935 e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top; +4936 } +4937 if (time < 0) { +4938 continue; +4939 } +4940 if (time < ms) { +4941 var pos = easing(time / ms); +4942 for (var attr in from) if (from[has](attr)) { +4943 switch (availableAnimAttrs[attr]) { +4944 case nu: +4945 now = +from[attr] + pos * ms * diff[attr]; +4946 break; +4947 case "colour": +4948 now = "rgb(" + [ +4949 upto255(round(from[attr].r + pos * ms * diff[attr].r)), +4950 upto255(round(from[attr].g + pos * ms * diff[attr].g)), +4951 upto255(round(from[attr].b + pos * ms * diff[attr].b)) +4952 ].join(",") + ")"; +4953 break; +4954 case "path": +4955 now = []; +4956 for (var i = 0, ii = from[attr].length; i < ii; i++) { +4957 now[i] = [from[attr][i][0]]; +4958 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { +4959 now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j]; +4960 } +4961 now[i] = now[i].join(S); +4962 } +4963 now = now.join(S); +4964 break; +4965 case "transform": +4966 if (diff[attr].real) { +4967 now = []; +4968 for (i = 0, ii = from[attr].length; i < ii; i++) { +4969 now[i] = [from[attr][i][0]]; +4970 for (j = 1, jj = from[attr][i].length; j < jj; j++) { +4971 now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j]; +4972 } +4973 } +4974 } else { +4975 var get = function (i) { +4976 return +from[attr][i] + pos * ms * diff[attr][i]; +4977 }; +4978 // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]]; +4979 now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]]; +4980 } +4981 break; +4982 case "csv": +4983 if (attr == "clip-rect") { +4984 now = []; +4985 i = 4; +4986 while (i--) { +4987 now[i] = +from[attr][i] + pos * ms * diff[attr][i]; +4988 } +4989 } +4990 break; +4991 default: +4992 var from2 = [].concat(from[attr]); +4993 now = []; +4994 i = that.paper.customAttributes[attr].length; +4995 while (i--) { +4996 now[i] = +from2[i] + pos * ms * diff[attr][i]; +4997 } +4998 break; +4999 } +5000 set[attr] = now; +5001 } +5002 that.attr(set); +5003 (function (id, that, anim) { +5004 setTimeout(function () { +5005 eve("anim.frame." + id, that, anim); +5006 }); +5007 })(that.id, that, e.anim); +5008 } else { +5009 (function(f, el, a) { +5010 setTimeout(function() { +5011 eve("anim.finish." + el.id, el, a); +5012 R.is(f, "function") && f.call(el); +5013 }); +5014 })(e.callback, that, e.anim); +5015 console.log(e.repeat); +5016 if (--e.repeat) { +5017 that.attr(e.origin); +5018 e.start = Now; +5019 } else { +5020 that.attr(to); +5021 animationElements.splice(l--, 1); +5022 } +5023 if (e.next && !e.stop) { +5024 runAnimation(e.anim, e.el, e.next, null, e.totalOrigin); +5025 } +5026 } +5027 } +5028 R.svg && that && that.paper && that.paper.safari(); +5029 animationElements.length && requestAnimFrame(animation); +5030 }, +5031 upto255 = function (color) { +5032 return mmax(mmin(color, 255), 0); +5033 }; +5034 /*\ +5035 * Element.animateWith +5036 [ method ] +5037 ** +5038 * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element. +5039 ** +5040 > Parameters +5041 ** +5042 - params (object) final attributes for the element, see also @Element.attr +5043 - ms (number) number of milliseconds for animation to run +5044 - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` +5045 - callback (function) #optional callback function. Will be called at the end of animation. +5046 * or +5047 - animation (object) animation object, see @Raphael.animation +5048 ** +5049 = (object) original element +5050 \*/ +5051 elproto.animateWith = function (element, params, ms, easing, callback) { +5052 this.animate(params, ms, easing, callback); +5053 var start, el; +5054 for (var i = 0, ii = animationElements.length; i < ii; i++) { +5055 el = animationElements[i]; +5056 if (el.el.id == element.id) { +5057 start = el.timestamp; +5058 } else if (el.el.id == this.id) { +5059 el.start = start; +5060 } +5061 } +5062 return this.animate(params, ms, easing, callback); 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 > Parameters -5085 ** -5086 - delay (number) number of ms to pass between animation start and actual animation -5087 ** -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 > Parameters -5103 ** -5104 - repeat (number) number iterations of animation. For infinite animation pass `Infinity` -5105 ** -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 - 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 > Parameters -5357 ** -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 > Parameters -5384 ** -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 > Parameters -5406 ** -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. +5064 function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) { +5065 var cx = 3 * p1x, +5066 bx = 3 * (p2x - p1x) - cx, +5067 ax = 1 - cx - bx, +5068 cy = 3 * p1y, +5069 by = 3 * (p2y - p1y) - cy, +5070 ay = 1 - cy - by; +5071 function sampleCurveX(t) { +5072 return ((ax * t + bx) * t + cx) * t; +5073 } +5074 function solve(x, epsilon) { +5075 var t = solveCurveX(x, epsilon); +5076 return ((ay * t + by) * t + cy) * t; +5077 } +5078 function solveCurveX(x, epsilon) { +5079 var t0, t1, t2, x2, d2, i; +5080 for(t2 = x, i = 0; i < 8; i++) { +5081 x2 = sampleCurveX(t2) - x; +5082 if (abs(x2) < epsilon) { +5083 return t2; +5084 } +5085 d2 = (3 * ax * t2 + 2 * bx) * t2 + cx; +5086 if (abs(d2) < 1e-6) { +5087 break; +5088 } +5089 t2 = t2 - x2 / d2; +5090 } +5091 t0 = 0; +5092 t1 = 1; +5093 t2 = x; +5094 if (t2 < t0) { +5095 return t0; +5096 } +5097 if (t2 > t1) { +5098 return t1; +5099 } +5100 while (t0 < t1) { +5101 x2 = sampleCurveX(t2); +5102 if (abs(x2 - x) < epsilon) { +5103 return t2; +5104 } +5105 if (x > x2) { +5106 t0 = t2; +5107 } else { +5108 t1 = t2; +5109 } +5110 t2 = (t1 - t0) / 2 + t0; +5111 } +5112 return t2; +5113 } +5114 return solve(t, 1 / (200 * duration)); +5115 } +5116 elproto.onAnimation = function (f) { +5117 f ? eve.on("anim.frame." + this.id, f) : eve.unbind("anim.frame." + this.id); +5118 return this; +5119 }; +5120 function Animation(anim, ms) { +5121 var percents = []; +5122 this.anim = anim; +5123 this.ms = ms; +5124 this.times = 1; +5125 if (this.anim) { +5126 for (var attr in this.anim) if (this.anim[has](attr)) { +5127 percents.push(+attr); +5128 } +5129 percents.sort(sortByNumber); +5130 } +5131 this.top = percents[percents.length - 1]; +5132 this.percents = percents; +5133 } +5134 /*\ +5135 * Animation.delay +5136 [ method ] +5137 ** +5138 * Creates a copy of existing animation object with given delay. +5139 ** +5140 > Parameters +5141 ** +5142 - delay (number) number of ms to pass between animation start and actual animation +5143 ** +5144 = (object) new altered Animation object +5145 \*/ +5146 Animation.prototype.delay = function (delay) { +5147 var a = new Animation(this.anim, this.ms); +5148 a.times = this.times; +5149 a.del = +delay || 0; +5150 return a; +5151 }; +5152 /*\ +5153 * Animation.repeat +5154 [ method ] +5155 ** +5156 * Creates a copy of existing animation object with given repetition. +5157 ** +5158 > Parameters +5159 ** +5160 - repeat (number) number iterations of animation. For infinite animation pass `Infinity` +5161 ** +5162 = (object) new altered Animation object +5163 \*/ +5164 Animation.prototype.repeat = function (times) { +5165 var a = new Animation(this.anim, this.ms); +5166 a.del = this.del; +5167 a.times = math.floor(mmax(times, 0)) || 1; +5168 return a; +5169 }; +5170 function runAnimation(anim, element, percent, status, totalOrigin) { +5171 percent = toFloat(percent); +5172 var params, +5173 isInAnim, +5174 isInAnimSet, +5175 percents = [], +5176 next, +5177 prev, +5178 timestamp, +5179 ms = anim.ms, +5180 from = {}, +5181 to = {}, +5182 diff = {}; +5183 if (status) { +5184 for (i = 0, ii = animationElements.length; i < ii; i++) { +5185 var e = animationElements[i]; +5186 if (e.el.id == element.id && e.anim == anim) { +5187 if (e.percent != percent) { +5188 animationElements.splice(i, 1); +5189 isInAnimSet = 1; +5190 } else { +5191 isInAnim = e; +5192 } +5193 element.attr(e.totalOrigin); +5194 break; +5195 } +5196 } +5197 } else { +5198 status = +to; // NaN +5199 } +5200 for (var i = 0, ii = anim.percents.length; i < ii; i++) { +5201 if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) { +5202 percent = anim.percents[i]; +5203 prev = anim.percents[i - 1] || 0; +5204 ms = ms / anim.top * (percent - prev); +5205 next = anim.percents[i + 1]; +5206 params = anim.anim[percent]; +5207 break; +5208 } else if (status) { +5209 element.attr(anim.anim[anim.percents[i]]); +5210 } +5211 } +5212 if (!params) { +5213 return; +5214 } +5215 if (!isInAnim) { +5216 for (attr in params) if (params[has](attr)) { +5217 if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) { +5218 from[attr] = element.attr(attr); +5219 (from[attr] == null) && (from[attr] = availableAttrs[attr]); +5220 to[attr] = params[attr]; +5221 switch (availableAnimAttrs[attr]) { +5222 case nu: +5223 diff[attr] = (to[attr] - from[attr]) / ms; +5224 break; +5225 case "colour": +5226 from[attr] = R.getRGB(from[attr]); +5227 var toColour = R.getRGB(to[attr]); +5228 diff[attr] = { +5229 r: (toColour.r - from[attr].r) / ms, +5230 g: (toColour.g - from[attr].g) / ms, +5231 b: (toColour.b - from[attr].b) / ms +5232 }; +5233 break; +5234 case "path": +5235 var pathes = path2curve(from[attr], to[attr]), +5236 toPath = pathes[1]; +5237 from[attr] = pathes[0]; +5238 diff[attr] = []; +5239 for (i = 0, ii = from[attr].length; i < ii; i++) { +5240 diff[attr][i] = [0]; +5241 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { +5242 diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms; +5243 } +5244 } +5245 break; +5246 case "transform": +5247 var _ = element._, +5248 eq = equaliseTransform(_[attr], to[attr]); +5249 if (eq) { +5250 from[attr] = eq.from; +5251 to[attr] = eq.to; +5252 diff[attr] = []; +5253 diff[attr].real = true; +5254 for (i = 0, ii = from[attr].length; i < ii; i++) { +5255 diff[attr][i] = [from[attr][i][0]]; +5256 for (j = 1, jj = from[attr][i].length; j < jj; j++) { +5257 diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms; +5258 } +5259 } +5260 } else { +5261 var m = (element.matrix || new Matrix).m, +5262 to2 = {_:{transform: _.transform}, getBBox: function () { return element.getBBox(); }}; +5263 from[attr] = [ +5264 m[0][0], +5265 m[1][0], +5266 m[0][1], +5267 m[1][1], +5268 m[0][2], +5269 m[1][2] +5270 ]; +5271 extractTransform(to2, to[attr]); +5272 to[attr] = to2._.transform; +5273 diff[attr] = [ +5274 (to2.matrix.m[0][0] - m[0][0]) / ms, +5275 (to2.matrix.m[1][0] - m[1][0]) / ms, +5276 (to2.matrix.m[0][1] - m[0][1]) / ms, +5277 (to2.matrix.m[1][1] - m[1][1]) / ms, +5278 (to2.matrix.m[0][2] - m[0][2]) / ms, +5279 (to2.matrix.m[1][2] - m[1][2]) / ms +5280 ]; +5281 // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy]; +5282 // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }}; +5283 // extractTransform(to2, to[attr]); +5284 // diff[attr] = [ +5285 // (to2._.sx - _.sx) / ms, +5286 // (to2._.sy - _.sy) / ms, +5287 // (to2._.deg - _.deg) / ms, +5288 // (to2._.dx - _.dx) / ms, +5289 // (to2._.dy - _.dy) / ms +5290 // ]; +5291 } +5292 break; +5293 case "csv": +5294 var values = Str(params[attr]).split(separator), +5295 from2 = Str(from[attr]).split(separator); +5296 if (attr == "clip-rect") { +5297 from[attr] = from2; +5298 diff[attr] = []; +5299 i = from2.length; +5300 while (i--) { +5301 diff[attr][i] = (values[i] - from[attr][i]) / ms; +5302 } +5303 } +5304 to[attr] = values; +5305 break; +5306 default: +5307 values = [].concat(params[attr]); +5308 from2 = [].concat(from[attr]); +5309 diff[attr] = []; +5310 i = element.paper.customAttributes[attr].length; +5311 while (i--) { +5312 diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms; +5313 } +5314 break; +5315 } +5316 } +5317 } +5318 var easing = params.easing, +5319 easyeasy = R.easing_formulas[easing]; +5320 if (!easyeasy) { +5321 easyeasy = Str(easing).match(bezierrg); +5322 if (easyeasy && easyeasy.length == 5) { +5323 var curve = easyeasy; +5324 easyeasy = function (t) { +5325 return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms); +5326 }; +5327 } else { +5328 easyeasy = pipe; +5329 } +5330 } +5331 timestamp = params.start || anim.start || +new Date; +5332 e = { +5333 anim: anim, +5334 percent: percent, +5335 timestamp: timestamp, +5336 start: timestamp + (anim.del || 0), +5337 status: 0, +5338 initstatus: status || 0, +5339 stop: false, +5340 ms: ms, +5341 easing: easyeasy, +5342 from: from, +5343 diff: diff, +5344 to: to, +5345 el: element, +5346 callback: params.callback, +5347 prev: prev, +5348 next: next, +5349 repeat: anim.times, +5350 origin: element.attr(), +5351 totalOrigin: totalOrigin +5352 }; +5353 animationElements.push(e); +5354 if (status && !isInAnim) { +5355 e.stop = true; +5356 e.start = new Date - ms * status; +5357 if (animationElements.length == 1) { +5358 return animation(); +5359 } +5360 } +5361 animationElements.length == 1 && requestAnimFrame(animation); +5362 } else { +5363 isInAnim.initstatus = status; +5364 isInAnim.start = new Date - isInAnim.ms * status; +5365 } +5366 eve("anim.start." + element.id, element, anim); +5367 } +5368 /*\ +5369 * Raphael.animation +5370 [ method ] +5371 ** +5372 * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods. +5373 * See also @Animation.delay and @Animation.repeat methods. +5374 ** +5375 > Parameters +5376 ** +5377 - params (object) final attributes for the element, see also @Element.attr +5378 - ms (number) number of milliseconds for animation to run +5379 - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` +5380 - callback (function) #optional callback function. Will be called at the end of animation. +5381 ** +5382 = (object) @Animation +5383 \*/ +5384 R.animation = function (params, ms, easing, callback) { +5385 if (R.is(easing, "function") || !easing) { +5386 callback = callback || easing || null; +5387 easing = null; +5388 } +5389 params = Object(params); +5390 ms = +ms || 0; +5391 var p = {}, +5392 json, +5393 attr; +5394 for (attr in params) if (params[has](attr) && toFloat(attr) != attr) { +5395 json = true; +5396 p[attr] = params[attr]; +5397 } +5398 if (!json) { +5399 return new Animation(params, ms); +5400 } else { +5401 easing && (p.easing = easing); +5402 callback && (p.callback = callback); +5403 return new Animation({100: p}, ms); +5404 } +5405 }; +5406 /*\ +5407 * Element.animate +5408 [ method ] 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 > Parameters -5452 ** -5453 - anim (object) #optional animation object -5454 ** -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 > Parameters -5472 ** -5473 - anim (object) #optional animation object -5474 ** -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 > Parameters -5494 ** -5495 - anim (object) #optional animation object -5496 ** -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. +5410 * Creates and starts animation for given element. +5411 ** +5412 > Parameters +5413 ** +5414 - params (object) final attributes for the element, see also @Element.attr +5415 - ms (number) number of milliseconds for animation to run +5416 - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX,&#160;XX,&#160;XX,&#160;XX)` +5417 - callback (function) #optional callback function. Will be called at the end of animation. +5418 * or +5419 - animation (object) animation object, see @Raphael.animation +5420 ** +5421 = (object) original element +5422 \*/ +5423 elproto.animate = function (params, ms, easing, callback) { +5424 var element = this; +5425 if (element.removed) { +5426 callback && callback.call(element); +5427 return element; +5428 } +5429 var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback); +5430 runAnimation(anim, element, anim.percents[0], null, element.attr()); +5431 return element; +5432 }; +5433 /*\ +5434 * Element.setTime +5435 [ method ] +5436 ** +5437 * Sets the status of animation of the element in milliseconds. Similar to @Element.status method. +5438 ** +5439 > Parameters +5440 ** +5441 - anim (object) animation object +5442 - value (number) number of milliseconds from the beginning of the animation +5443 ** +5444 = (object) original element if `value` is specified +5445 * Note, that during animation following events are triggered: +5446 * +5447 * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`. +5448 \*/ +5449 elproto.setTime = function (anim, value) { +5450 if (anim && value != null) { +5451 this.status(anim, mmin(value, anim.ms) / anim.ms); +5452 } +5453 return this; +5454 }; +5455 /*\ +5456 * Element.status +5457 [ method ] +5458 ** +5459 * Gets or sets the status of animation of the element. +5460 ** +5461 > Parameters +5462 ** +5463 - anim (object) #optional animation object +5464 - 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. +5465 ** +5466 = (number) status +5467 * or +5468 = (array) status if `anim` is not specified. Array of objects in format: +5469 o { +5470 o anim: (object) animation object +5471 o status: (number) status +5472 o } +5473 * or +5474 = (object) original element if `value` is specified +5475 \*/ +5476 elproto.status = function (anim, value) { +5477 var out = [], +5478 i = 0, +5479 len, +5480 e; +5481 if (value != null) { +5482 runAnimation(anim, this, -1, mmin(value, 1)); +5483 return this; +5484 } else { +5485 len = animationElements.length; +5486 for (; i < len; i++) { +5487 e = animationElements[i]; +5488 if (e.el.id == this.id && (!anim || e.anim == anim)) { +5489 if (anim) { +5490 return e.status; +5491 } +5492 out.push({anim: e.anim, status: e.status}); +5493 } +5494 } +5495 if (anim) { +5496 return 0; +5497 } +5498 return out; +5499 } +5500 }; +5501 /*\ +5502 * Element.pause +5503 [ method ] +5504 ** +5505 * Stops animation of the element with ability to resume it later on. +5506 ** +5507 > Parameters +5508 ** +5509 - anim (object) #optional animation object +5510 ** +5511 = (object) original element +5512 \*/ +5513 elproto.pause = function (anim) { +5514 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { +5515 if (eve("anim.pause." + this.id, this, animationElements[i].anim) !== false) { +5516 animationElements[i].paused = true; +5517 } +5518 } +5519 return this; +5520 }; +5521 /*\ +5522 * Element.resume +5523 [ method ] +5524 ** +5525 * Resumes animation if it was paused with @Element.pause method. +5526 ** +5527 > Parameters +5528 ** +5529 - anim (object) #optional animation object +5530 ** 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 - 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"; +5533 elproto.resume = function (anim) { +5534 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { +5535 var e = animationElements[i]; +5536 if (eve("anim.resume." + this.id, this, e.anim) !== false) { +5537 delete e.paused; +5538 this.status(e.anim, e.status); +5539 } +5540 } +5541 return this; +5542 }; +5543 /*\ +5544 * Element.stop +5545 [ method ] +5546 ** +5547 * Stops animation of the element. +5548 ** +5549 > Parameters +5550 ** +5551 - anim (object) #optional animation object +5552 ** +5553 = (object) original element +5554 \*/ +5555 elproto.stop = function (anim) { +5556 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { +5557 if (eve("anim.stop." + this.id, this, animationElements[i].anim) !== false) { +5558 animationElements.splice(i--, 1); +5559 } +5560 } +5561 return this; +5562 }; +5563 elproto.toString = function () { +5564 return "Rapha\xebl\u2019s object"; +5565 }; +5566 +5567 // Set +5568 var Set = function (items) { +5569 this.items = []; +5570 this.length = 0; +5571 this.type = "set"; +5572 if (items) { +5573 for (var i = 0, ii = items.length; i < ii; i++) { +5574 if (items[i] && (items[i].constructor == Element || items[i].constructor == Set)) { +5575 this[this.items.length] = this.items[this.items.length] = items[i]; +5576 this.length++; +5577 } +5578 } +5579 } +5580 }, +5581 setproto = Set.prototype; +5582 /*\ +5583 * Set.push +5584 [ method ] +5585 ** +5586 * Adds each argument to the current set. +5587 = (object) original element +5588 \*/ +5589 setproto.push = function () { +5590 var item, +5591 len; +5592 for (var i = 0, ii = arguments.length; i < ii; i++) { +5593 item = arguments[i]; +5594 if (item && (item.constructor == Element || item.constructor == Set)) { +5595 len = this.items.length; +5596 this[len] = this.items[len] = item; +5597 this.length++; +5598 } +5599 } +5600 return this; +5601 }; +5602 /*\ +5603 * Set.pop +5604 [ method ] +5605 ** +5606 * Removes last element and returns it. +5607 = (object) element +5608 \*/ +5609 setproto.pop = function () { +5610 this.length && delete this[this.length--]; +5611 return this.items.pop(); +5612 }; +5613 /*\ +5614 * Set.forEach +5615 [ method ] +5616 ** +5617 * Executes given function for each element in the set. +5618 * +5619 * If function returns `false` it will stop loop running. +5620 ** +5621 > Parameters +5622 ** +5623 - callback (function) function to run +5624 - thisArg (object) context object for the callback +5625 = (object) Set object +5626 \*/ +5627 setproto.forEach = function (callback, thisArg) { +5628 for (var i = 0, ii = this.items.length; i < ii; i++) { +5629 if (callback.call(thisArg, this.items[i]) === false) { +5630 return this; +5631 } +5632 } +5633 return this; +5634 }; +5635 for (var method in elproto) if (elproto[has](method)) { +5636 setproto[method] = (function (methodname) { +5637 return function () { +5638 var arg = arguments; +5639 return this.forEach(function (el) { +5640 el[methodname][apply](el, arg); +5641 }); +5642 }; +5643 })(method); +5644 } +5645 setproto.attr = function (name, value) { +5646 if (name && R.is(name, array) && R.is(name[0], "object")) { +5647 for (var j = 0, jj = name.length; j < jj; j++) { +5648 this.items[j].attr(name[j]); +5649 } +5650 } else { +5651 for (var i = 0, ii = this.items.length; i < ii; i++) { +5652 this.items[i].attr(name, value); +5653 } +5654 } +5655 return this; 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 /* -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 } +5657 setproto.animate = function (params, ms, easing, callback) { +5658 (R.is(easing, "function") || !easing) && (callback = easing || null); +5659 var len = this.items.length, +5660 i = len, +5661 item, +5662 set = this, +5663 collector; +5664 callback && (collector = function () { +5665 !--len && callback.call(set); +5666 }); +5667 easing = R.is(easing, string) ? easing : collector; +5668 var anim = params instanceof Animation ? params : R.animation(params, ms, easing, collector); +5669 item = this.items[--i].animate(anim); +5670 while (i--) { +5671 this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim); +5672 } +5673 return this; +5674 }; +5675 setproto.insertAfter = function (el) { +5676 var i = this.items.length; +5677 while (i--) { +5678 this.items[i].insertAfter(el); +5679 } +5680 return this; +5681 }; +5682 setproto.getBBox = function () { +5683 var x = [], +5684 y = [], +5685 w = [], +5686 h = []; +5687 for (var i = this.items.length; i--;) if (!this.items[i].removed) { +5688 var box = this.items[i].getBBox(); +5689 x.push(box.x); +5690 y.push(box.y); +5691 w.push(box.x + box.width); +5692 h.push(box.y + box.height); +5693 } +5694 x = mmin[apply](0, x); +5695 y = mmin[apply](0, y); +5696 return { +5697 x: x, +5698 y: y, +5699 width: mmax[apply](0, w) - x, +5700 height: mmax[apply](0, h) - y +5701 }; +5702 }; +5703 setproto.clone = function (s) { +5704 s = new Set; +5705 for (var i = 0, ii = this.items.length; i < ii; i++) { +5706 s.push(this.items[i].clone()); +5707 } +5708 return s; +5709 }; +5710 setproto.toString = function () { +5711 return "Rapha\xebl\u2018s set"; +5712 }; +5713 +5714 R.registerFont = function (font) { +5715 if (!font.face) { +5716 return font; +5717 } +5718 this.fonts = this.fonts || {}; +5719 var fontcopy = { +5720 w: font.w, +5721 face: {}, +5722 glyphs: {} +5723 }, +5724 family = font.face["font-family"]; +5725 for (var prop in font.face) if (font.face[has](prop)) { +5726 fontcopy.face[prop] = font.face[prop]; +5727 } +5728 if (this.fonts[family]) { +5729 this.fonts[family].push(fontcopy); +5730 } else { +5731 this.fonts[family] = [fontcopy]; +5732 } +5733 if (!font.svg) { +5734 fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10); +5735 for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) { +5736 var path = font.glyphs[glyph]; +5737 fontcopy.glyphs[glyph] = { +5738 w: path.w, +5739 k: {}, +5740 d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) { +5741 return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M"; +5742 }) + "z" +5743 }; +5744 if (path.k) { +5745 for (var k in path.k) if (path[has](k)) { +5746 fontcopy.glyphs[glyph].k[k] = path.k[k]; +5747 } +5748 } +5749 } +5750 } +5751 return font; +5752 }; +5753 paperproto.getFont = function (family, weight, style, stretch) { +5754 stretch = stretch || "normal"; +5755 style = style || "normal"; +5756 weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400; +5757 if (!R.fonts) { +5758 return; +5759 } +5760 var font = R.fonts[family]; +5761 if (!font) { +5762 var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i"); +5763 for (var fontName in R.fonts) if (R.fonts[has](fontName)) { +5764 if (name.test(fontName)) { +5765 font = R.fonts[fontName]; +5766 break; +5767 } +5768 } +5769 } +5770 var thefont; +5771 if (font) { +5772 for (var i = 0, ii = font.length; i < ii; i++) { +5773 thefont = font[i]; +5774 if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) { +5775 break; +5776 } +5777 } +5778 } +5779 return thefont; +5780 }; +5781 paperproto.print = function (x, y, string, font, size, origin, letter_spacing) { +5782 origin = origin || "middle"; // baseline|middle +5783 letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1); +5784 var out = this.set(), +5785 letters = Str(string).split(E), +5786 shift = 0, +5787 path = E, +5788 scale; +5789 R.is(font, string) && (font = this.getFont(font)); +5790 if (font) { +5791 scale = (size || 16) / font.face["units-per-em"]; +5792 var bb = font.face.bbox.split(separator), +5793 top = +bb[0], +5794 height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2); +5795 for (var i = 0, ii = letters.length; i < ii; i++) { +5796 var prev = i && font.glyphs[letters[i - 1]] || {}, +5797 curr = font.glyphs[letters[i]]; +5798 shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0; +5799 curr && curr.d && out.push(this.path(curr.d).attr({fill: "#000", stroke: "none", transform: [["t", shift, 0]]})); +5800 } +5801 out.scale(scale, scale, top, height).translate(x - top, y - height); +5802 } +5803 return out; +5804 }; +5805 +5806 R.format = function (token, params) { +5807 var args = R.is(params, array) ? [0][concat](params) : arguments; +5808 token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) { +5809 return args[++i] == null ? E : args[i]; +5810 })); +5811 return token || E; +5812 }; +5813 R.ninja = function () { +5814 oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael; +5815 return R; +5816 }; +5817 /*\ +5818 * Raphael.el +5819 [ property (object) ] +5820 ** +5821 * You can add your own method to elements. This is usefull when you want to hack default functionality or +5822 * want to wrap some common transformation or attributes in one method. In difference to canvas methods, +5823 * you can redefine element method at any time. Expending element methods wouldn’t affect set. +5824 > Usage +5825 | Raphael.el.red = function () { +5826 | this.attr({fill: "#f00"}); +5827 | }; +5828 | // then use it +5829 | paper.circle(100, 100, 20).red(); +5830 \*/ +5831 R.el = elproto; +5832 R.st = setproto; +5833 // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html +5834 (function (doc, loaded, f) { +5835 if (doc.readyState == null && doc.addEventListener){ +5836 doc.addEventListener(loaded, f = function () { +5837 doc.removeEventListener(loaded, f, false); +5838 doc.readyState = "complete"; +5839 }, false); +5840 doc.readyState = "loading"; +5841 } +5842 function isLoaded() { +5843 (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : eve("DOMload"); +5844 } +5845 isLoaded(); +5846 })(document, "DOMContentLoaded"); +5847 +5848 oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R); +5849 +5850 /* +5851 * Eve 0.2.1 - JavaScript Events Library +5852 * +5853 * Copyright (c) 2010 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) +5854 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. +5855 */ +5856 +5857 var eve = R.eve = (function () { +5858 var version = "0.2.1", +5859 has = "hasOwnProperty", +5860 separator = /[\.\/]/, +5861 wildcard = "*", +5862 events = {n: {}}, +5863 eve = function (name, scope) { +5864 var e = events, +5865 args = Array.prototype.slice.call(arguments, 2), +5866 listeners = eve.listeners(name), +5867 errors = []; +5868 for (var i = 0, ii = listeners.length; i < ii; i++) { +5869 try { +5870 listeners[i].apply(scope, args); +5871 } catch (ex) { +5872 errors.push({error: ex && ex.message || ex, func: listeners[i]}); +5873 } +5874 } +5875 if (errors.length) { +5876 return errors; +5877 } +5878 }; +5879 eve.listeners = function (name) { +5880 var names = name.split(separator), +5881 e = events, +5882 item, +5883 items, +5884 k, +5885 i, +5886 ii, +5887 j, +5888 jj, +5889 nes, +5890 es = [e], +5891 out = []; +5892 for (i = 0, ii = names.length; i < ii; i++) { +5893 nes = []; +5894 for (j = 0, jj = es.length; j < jj; j++) { +5895 e = es[j].n; +5896 items = [e[names[i]], e[wildcard]]; +5897 k = 2; +5898 while (k--) { +5899 item = items[k]; +5900 if (item) { +5901 nes.push(item); +5902 out = out.concat(item.f || []); +5903 } +5904 } +5905 } +5906 es = nes; +5907 } +5908 return out; +5909 }; +5910 eve.on = function (name, f) { +5911 var names = name.split(separator), +5912 e = events; +5913 for (var i = 0, ii = names.length; i < ii; i++) { +5914 e = e.n; +5915 !e[names[i]] && (e[names[i]] = {n: {}}); +5916 e = e[names[i]]; 5917 } -5918 return true; -5919 }; -5920 eve.version = version; -5921 eve.toString = function () { -5922 return "You are running Eve " + version; +5918 e.f = e.f || []; +5919 for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { +5920 return false; +5921 } +5922 e.f.push(f); 5923 }; -5924 return eve; -5925 })(); -5926})(); +5924 eve.unbind = function (name, f) { +5925 var names = name.split(separator), +5926 e, +5927 key, +5928 splice, +5929 cur = [events]; +5930 for (var i = 0, ii = names.length; i < ii; i++) { +5931 for (var j = 0; j < cur.length; j += splice.length - 2) { +5932 splice = [j, 1]; +5933 e = cur[j].n; +5934 if (names[i] != wildcard) { +5935 if (e[names[i]]) { +5936 splice.push(e[names[i]]); +5937 } +5938 } else { +5939 for (key in e) if (e[has](key)) { +5940 splice.push(e[key]); +5941 } +5942 } +5943 cur.splice.apply(cur, splice); +5944 } +5945 } +5946 for (i = 0, ii = cur.length; i < ii; i++) { +5947 e = cur[i]; +5948 while (e.n) { +5949 if (f) { +5950 if (e.f) { +5951 for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { +5952 e.f.splice(i, 1); +5953 break; +5954 } +5955 !e.f.length && delete e.f; +5956 } +5957 for (key in e.n) if (e.n[has](key) && e.n[key].f) { +5958 var funcs = e.n[key].f; +5959 for (i = 0, ii = funcs.length; i < ii; i++) if (funcs[i] == f) { +5960 funcs.splice(i, 1); +5961 break; +5962 } +5963 !funcs.length && delete e.n[key].f; +5964 } +5965 } else { +5966 delete e.f; +5967 for (key in e.n) if (e.n[has](key) && e.n[key].f) { +5968 delete e.n[key].f; +5969 } +5970 } +5971 e = e.n; +5972 } +5973 } +5974 return true; +5975 }; +5976 eve.version = version; +5977 eve.toString = function () { +5978 return "You are running Eve " + version; +5979 }; +5980 return eve; +5981 })(); +5982})(); \ No newline at end of file diff --git a/raphael.js b/raphael.js index 9f39b0c..15e1dcf 100644 --- a/raphael.js +++ b/raphael.js @@ -2922,7 +2922,8 @@ throw new Error("SVG container not found."); } var cnvs = $("svg"), - css = "overflow:hidden;"; + css = "overflow:hidden;", + isFloating; x = x || 0; y = y || 0; width = width || 512; @@ -2936,8 +2937,9 @@ if (container == 1) { cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px"; g.doc.body.appendChild(cnvs); + isFloating = 1; } else { - cnvs.style.cssText = css; + cnvs.style.cssText = css + "position:relative"; if (container.firstChild) { container.insertBefore(cnvs, container.firstChild); } else { @@ -2950,6 +2952,9 @@ container.canvas = cnvs; plugins.call(container, container, R.fn); container.clear(); + container._left = container._top = 0; + isFloating && (container.renderfix = fun); + container.renderfix(); return container; }, setViewBox = function (x, y, w, h, fit) { @@ -2983,6 +2988,33 @@ this._viewBox = [x, y, w, h, !!fit]; return this; }; + /*\ + * Paper.renderfix + [ method ] + ** + * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependant + * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness. + * This method fixes the issue. + ** + Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method. + \*/ + paperproto.renderfix = function () { + var cnvs = this.canvas, + s = cnvs.style, + pos = cnvs.getScreenCTM(), + left = -pos.e % 1, + top = -pos.f % 1; + if (left || top) { + if (left) { + this._left = (this._left + left) % 1; + s.left = this._left + "px"; + } + if (top) { + this._top = (this._top + top) % 1; + s.top = this._top + "px"; + } + } + }; /*\ * Paper.clear [ method ] @@ -3918,6 +3950,7 @@ } } plugins.call(res, res, R.fn); + res.renderfix = fun; return res; }; paperproto.clear = function () { @@ -4560,6 +4593,17 @@ * * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself. ** + > Parameters + ** + - glow (object) #optional parameters object with all properties optional: + o { + o width (number) size of the glow, default is `10` + o fill (boolean) will it be filled, default is `false` + o opacity: opacity, default is `0.5` + o offsetx: horizontal offset, default is `0` + o offsety: vertical offset, default is `0` + o color: glow colour, default is `black` + o } = (object) @Paper.set of elements that represents glow \*/ elproto.glow = function (glow) { @@ -4568,7 +4612,7 @@ } glow = glow || {}; var s = { - width: glow.width || 10, + width: (glow.width || 10) + (+this.attr("stroke-width") || 1), fill: glow.fill || false, opacity: glow.opacity || .5, offsetx: glow.offsetx || 0, @@ -4581,7 +4625,14 @@ path = this.realPath || getPath[this.type](this); path = this.matrix ? mapPath(path, this.matrix) : path; for (var i = 1; i < c + 1; i++) { - out.push(r.path(path).attr({stroke: s.color, fill: s.fill ? s.color : "none", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": +(s.width / c * i).toFixed(3), opacity: +(s.opacity / c).toFixed(3)})); + out.push(r.path(path).attr({ + stroke: s.color, + fill: s.fill ? s.color : "none", + "stroke-linejoin": "round", + "stroke-linecap": "round", + "stroke-width": +(s.width / c * i).toFixed(3), + opacity: +(s.opacity / c).toFixed(3) + })); } return out.insertBefore(this).translate(s.offsetx, s.offsety); }; @@ -4961,6 +5012,7 @@ R.is(f, "function") && f.call(el); }); })(e.callback, that, e.anim); + console.log(e.repeat); if (--e.repeat) { that.attr(e.origin); e.start = Now; @@ -4997,10 +5049,14 @@ = (object) original element \*/ elproto.animateWith = function (element, params, ms, easing, callback) { + this.animate(params, ms, easing, callback); + var start, el; for (var i = 0, ii = animationElements.length; i < ii; i++) { - if (animationElements[i].el.id == element.id) { - params.start = animationElements[i].timestamp; - break; + el = animationElements[i]; + if (el.el.id == element.id) { + start = el.timestamp; + } else if (el.el.id == this.id) { + el.start = start; } } return this.animate(params, ms, easing, callback); @@ -5139,7 +5195,7 @@ } } } else { - status = 0 / 0; + status = +to; // NaN } for (var i = 0, ii = anim.percents.length; i < ii; i++) { if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) { diff --git a/reference.html b/reference.html index 6ccc661..d715e93 100644 --- a/reference.html +++ b/reference.html @@ -1,7 +1,7 @@ -Raphaël Reference
  1. Animation
  2. Animation.delay()
  3. Animation.repeat()
  4. Element
  5. Element.animate()
  6. Element.animateWith()
  7. Element.attr()
  8. Element.clone()
  9. Element.drag()
  10. Element.getBBox()
  11. Element.getPointAtLength()
  12. Element.getSubpath()
  13. Element.getTotalLength()
  14. Element.glow()
  15. Element.hide()
  16. Element.hover()
  17. Element.id
  18. Element.insertAfter()
  19. Element.insertBefore()
  20. Element.next
  21. Element.node
  22. Element.onDragOver()
  23. Element.paper
  24. Element.pause()
  25. Element.prev
  26. Element.raphael
  27. Element.remove()
  28. Element.resume()
  29. Element.rotate()
  30. Element.scale()
  31. Element.setTime()
  32. Element.show()
  33. Element.status()
  34. Element.stop()
  35. Element.toBack()
  36. Element.toFront()
  37. Element.transform()
  38. Element.translate()
  39. Element.undrag()
  40. Element.unhover()
  41. Paper
  42. Paper.bottom
  43. Paper.circle()
  44. Paper.clear()
  45. Paper.customAttributes
  46. Paper.ellipse()
  47. Paper.forEach()
  48. Paper.getById()
  49. Paper.getElementByPoint()
  50. Paper.image()
  51. Paper.path()
  52. Paper.raphael
  53. Paper.rect()
  54. Paper.remove()
  55. Paper.safari()
  56. Paper.set()
  57. Paper.setSize()
  58. Paper.setViewBox()
  59. Paper.text()
  60. Paper.top
  61. Raphael()
  62. Raphael.angle()
  63. Raphael.animation()
  64. Raphael.deg()
  65. Raphael.easing_formulas
  66. Raphael.el
  67. Raphael.findDotsAtSegment()
  68. Raphael.fn
  69. Raphael.getColor()
  70. Raphael.getColor.reset()
  71. Raphael.getPointAtLength()
  72. Raphael.getRGB()
  73. Raphael.getSubpath()
  74. Raphael.getTotalLength()
  75. Raphael.hsb()
  76. Raphael.hsb2rgb()
  77. Raphael.hsl()
  78. Raphael.hsl2rgb()
  79. Raphael.is()
  80. Raphael.parsePathString()
  81. Raphael.parseTransformString()
  82. Raphael.path2curve()
  83. Raphael.pathToRelative()
  84. Raphael.rad()
  85. Raphael.rgb()
  86. Raphael.rgb2hsb()
  87. Raphael.rgb2hsl()
  88. Raphael.setWindow()
  89. Raphael.snapTo()
  90. Raphael.svg
  91. Raphael.type
  92. Raphael.vml
  93. Set
  94. Set.forEach()
  95. Set.pop()
  96. Set.push()

Raphaël Reference

Check out the source: raphael.js

 Animation

-

 Animation.delay(delay)

+Raphaël Reference
  1. Animation
  2. Animation.delay()
  3. Animation.repeat()
  4. Element
  5. Element.animate()
  6. Element.animateWith()
  7. Element.attr()
  8. Element.clone()
  9. Element.drag()
  10. Element.getBBox()
  11. Element.getPointAtLength()
  12. Element.getSubpath()
  13. Element.getTotalLength()
  14. Element.glow()
  15. Element.hide()
  16. Element.hover()
  17. Element.id
  18. Element.insertAfter()
  19. Element.insertBefore()
  20. Element.next
  21. Element.node
  22. Element.onDragOver()
  23. Element.paper
  24. Element.pause()
  25. Element.prev
  26. Element.raphael
  27. Element.remove()
  28. Element.resume()
  29. Element.rotate()
  30. Element.scale()
  31. Element.setTime()
  32. Element.show()
  33. Element.status()
  34. Element.stop()
  35. Element.toBack()
  36. Element.toFront()
  37. Element.transform()
  38. Element.translate()
  39. Element.undrag()
  40. Element.unhover()
  41. Paper
  42. Paper.bottom
  43. Paper.circle()
  44. Paper.clear()
  45. Paper.customAttributes
  46. Paper.ellipse()
  47. Paper.forEach()
  48. Paper.getById()
  49. Paper.getElementByPoint()
  50. Paper.image()
  51. Paper.path()
  52. Paper.raphael
  53. Paper.rect()
  54. Paper.remove()
  55. Paper.renderfix()
  56. Paper.safari()
  57. Paper.set()
  58. Paper.setSize()
  59. Paper.setViewBox()
  60. Paper.text()
  61. Paper.top
  62. Raphael()
  63. Raphael.angle()
  64. Raphael.animation()
  65. Raphael.deg()
  66. Raphael.easing_formulas
  67. Raphael.el
  68. Raphael.findDotsAtSegment()
  69. Raphael.fn
  70. Raphael.getColor()
  71. Raphael.getColor.reset()
  72. Raphael.getPointAtLength()
  73. Raphael.getRGB()
  74. Raphael.getSubpath()
  75. Raphael.getTotalLength()
  76. Raphael.hsb()
  77. Raphael.hsb2rgb()
  78. Raphael.hsl()
  79. Raphael.hsl2rgb()
  80. Raphael.is()
  81. Raphael.parsePathString()
  82. Raphael.parseTransformString()
  83. Raphael.path2curve()
  84. Raphael.pathToRelative()
  85. Raphael.rad()
  86. Raphael.rgb()
  87. Raphael.rgb2hsb()
  88. Raphael.rgb2hsl()
  89. Raphael.setWindow()
  90. Raphael.snapTo()
  91. Raphael.svg
  92. Raphael.type
  93. Raphael.vml
  94. Set
  95. Set.forEach()
  96. Set.pop()
  97. Set.push()

Raphaël Reference

Check out the source: raphael.js

 Animation

+

 Animation.delay(delay)

Creates a copy of existing animation object with given delay.

Parameters @@ -11,7 +11,7 @@

number of ms to pass between animation start and actual animation

Returns: object new altered Animation object

-

 Animation.repeat(repeat)

+

 Animation.repeat(repeat)

Creates a copy of existing animation object with given repetition.

Parameters @@ -22,7 +22,7 @@

Returns: object new altered Animation object

 Element

-

 Element.animate(…)

+

 Element.animate(…)

Creates and starts animation for given element.

Parameters @@ -49,7 +49,7 @@

animation object, see Raphael.animation

Returns: object original element

-

 Element.animateWith(…)

+

 Element.animateWith(…)

Acts similar to Element.animate, but ensure that given animation runs in sync with another given element.

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

  • hsla(•••, •••, •••) — same as above, but with opacity
  • Optionally for hsb and hsl you could specify hue as a degree: “hsl(240deg, 1, .5)” or, if you want to go fancy, “hsl(240°, 1, .5)”
  • -

     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,31 @@ 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([glow])

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

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

    +

    Parameters +

    +
    glow
    +
    optional
    +
    object
    +
    parameters object with all properties optional:
    +
    +
    1. {
      1. widthnumbersize of the glow, default is 10 +
      2. fillbooleanwill it be filled, default is false +
      3. opacity: opacity, default is `0.5`
      4. offsetx: horizontal offset, default is `0`
      5. offsety: vertical offset, default is `0`
      6. color: glow colour, default is `black`
    2. }

    Returns: object Paper.set of elements that represents glow

     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 @@ -332,7 +342,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 @@ -352,7 +362,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 @@ -380,7 +390,7 @@ c.node.onclick = function () {

     Element.remove()

    Removes element form the paper.

    -

     Element.resume([anim])

    +

     Element.resume([anim])

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

    Parameters @@ -436,7 +446,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 @@ -457,7 +467,7 @@ transformations of the element.

    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 +491,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 @@ -556,10 +566,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 @@ -573,10 +583,10 @@ console.log(el.transform());

    Returns: object Element

     Paper

    -

     Paper.bottom

    +

     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,7 +606,7 @@ 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

    @@ -624,7 +634,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 @@ -647,7 +657,7 @@ 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 callback function returns false it will stop loop running. @@ -662,7 +672,7 @@ c.animate({hsb: "1 0 context object for the callback

    Returns: object Paper object

    -

     Paper.getById(id)

    +

     Paper.getById(id)

    Returns you element by its internal ID.

    Parameters @@ -672,7 +682,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 +699,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 +725,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 +742,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.

    @@ -766,15 +776,20 @@ 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()

    +

     Paper.renderfix()

    +

    Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependant +on other elements after reflow it could shift half pixel which cause for lines to lost their crispness. +This method fixes the issue. +

    +

     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.

    -

     Paper.set()

    +

     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. @@ -789,7 +804,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 @@ -810,7 +825,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.

    @@ -832,7 +847,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 @@ -852,7 +867,7 @@ 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(…)

    @@ -953,7 +968,7 @@ 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])

    +

     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.

    @@ -985,7 +1000,7 @@ See also Animation.delay and angle in radians

    Returns: number angle in degrees.

    -

     Raphael.easing_formulas

    +

     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. @@ -1097,7 +1112,7 @@ paper.mystuff.star();

     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 @@ -1141,7 +1156,7 @@ paper.mystuff.star();

  • hexstringcolor in HTML/CSS format: #••••••,
  • errorbooleantrue if string can’t be parsed
  • }
  • -

     Raphael.getSubpath(path, from, to)

    +

     Raphael.getSubpath(path, from, to)

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

    Parameters @@ -1157,7 +1172,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 @@ -1400,7 +1415,7 @@ Converts path to relative form

    boolean

    true if browser supports VML.

     Set

    -

     Set.forEach(callback, thisArg)

    +

     Set.forEach(callback, thisArg)

    Executes given function for each element in the set.

    If function returns false it will stop loop running. @@ -1415,11 +1430,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

    -- 2.39.2