2017-07-01 20:16:47 +00:00
define ( [ "./raphael.core" ] , function ( R ) {
if ( R && ! R . svg ) {
return ;
}
var has = "hasOwnProperty" ,
Str = String ,
toFloat = parseFloat ,
toInt = parseInt ,
math = Math ,
mmax = math . max ,
abs = math . abs ,
pow = math . pow ,
separator = /[, ]+/ ,
eve = R . eve ,
E = "" ,
S = " " ;
var xlink = "http://www.w3.org/1999/xlink" ,
markers = {
block : "M5,0 0,2.5 5,5z" ,
classic : "M5,0 0,2.5 5,5 3.5,3 3.5,2z" ,
diamond : "M2.5,0 5,2.5 2.5,5 0,2.5z" ,
open : "M6,1 1,3.5 6,6" ,
oval : "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
} ,
markerCounter = { } ;
R . toString = function ( ) {
return "Your browser supports SVG.\nYou are running Rapha\xebl " + this . version ;
} ;
var $ = function ( el , attr ) {
if ( attr ) {
if ( typeof el == "string" ) {
el = $ ( el ) ;
}
for ( var key in attr ) if ( attr [ has ] ( key ) ) {
if ( key . substring ( 0 , 6 ) == "xlink:" ) {
el . setAttributeNS ( xlink , key . substring ( 6 ) , Str ( attr [ key ] ) ) ;
} else {
el . setAttribute ( key , Str ( attr [ key ] ) ) ;
}
}
} else {
el = R . _g . doc . createElementNS ( "http://www.w3.org/2000/svg" , el ) ;
el . style && ( el . style . webkitTapHighlightColor = "rgba(0,0,0,0)" ) ;
}
return el ;
} ,
addGradientFill = function ( element , gradient ) {
var type = "linear" ,
id = element . id + gradient ,
fx = . 5 , fy = . 5 ,
o = element . node ,
SVG = element . paper ,
s = o . style ,
el = R . _g . doc . getElementById ( id ) ;
if ( ! el ) {
gradient = Str ( gradient ) . replace ( R . _radial _gradient , function ( all , _fx , _fy ) {
type = "radial" ;
if ( _fx && _fy ) {
fx = toFloat ( _fx ) ;
fy = toFloat ( _fy ) ;
var dir = ( ( fy > . 5 ) * 2 - 1 ) ;
pow ( fx - . 5 , 2 ) + pow ( fy - . 5 , 2 ) > . 25 &&
( fy = math . sqrt ( . 25 - pow ( fx - . 5 , 2 ) ) * dir + . 5 ) &&
fy != . 5 &&
( fy = fy . toFixed ( 5 ) - 1e-5 * dir ) ;
}
return E ;
} ) ;
gradient = gradient . split ( /\s*\-\s*/ ) ;
if ( type == "linear" ) {
var angle = gradient . shift ( ) ;
angle = - toFloat ( angle ) ;
if ( isNaN ( angle ) ) {
return null ;
}
var vector = [ 0 , 0 , math . cos ( R . rad ( angle ) ) , math . sin ( R . rad ( angle ) ) ] ,
max = 1 / ( mmax ( abs ( vector [ 2 ] ) , abs ( vector [ 3 ] ) ) || 1 ) ;
vector [ 2 ] *= max ;
vector [ 3 ] *= max ;
if ( vector [ 2 ] < 0 ) {
vector [ 0 ] = - vector [ 2 ] ;
vector [ 2 ] = 0 ;
}
if ( vector [ 3 ] < 0 ) {
vector [ 1 ] = - vector [ 3 ] ;
vector [ 3 ] = 0 ;
}
}
var dots = R . _parseDots ( gradient ) ;
if ( ! dots ) {
return null ;
}
id = id . replace ( /[\(\)\s,\xb0#]/g , "_" ) ;
if ( element . gradient && id != element . gradient . id ) {
SVG . defs . removeChild ( element . gradient ) ;
delete element . gradient ;
}
if ( ! element . gradient ) {
el = $ ( type + "Gradient" , { id : id } ) ;
element . gradient = el ;
$ ( el , type == "radial" ? {
fx : fx ,
fy : fy
} : {
x1 : vector [ 0 ] ,
y1 : vector [ 1 ] ,
x2 : vector [ 2 ] ,
y2 : vector [ 3 ] ,
gradientTransform : element . matrix . invert ( )
} ) ;
SVG . defs . appendChild ( el ) ;
for ( var i = 0 , ii = dots . length ; i < ii ; i ++ ) {
el . appendChild ( $ ( "stop" , {
offset : dots [ i ] . offset ? dots [ i ] . offset : i ? "100%" : "0%" ,
"stop-color" : dots [ i ] . color || "#fff" ,
"stop-opacity" : isFinite ( dots [ i ] . opacity ) ? dots [ i ] . opacity : 1
} ) ) ;
}
}
}
$ ( o , {
fill : fillurl ( id ) ,
opacity : 1 ,
"fill-opacity" : 1
} ) ;
s . fill = E ;
s . opacity = 1 ;
s . fillOpacity = 1 ;
return 1 ;
} ,
isIE9or10 = function ( ) {
var mode = document . documentMode ;
return mode && ( mode === 9 || mode === 10 ) ;
} ,
fillurl = function ( id ) {
if ( isIE9or10 ( ) ) {
return "url('#" + id + "')" ;
}
var location = document . location ;
var locationString = (
location . protocol + '//' +
location . host +
location . pathname +
location . search
) ;
return "url('" + locationString + "#" + id + "')" ;
} ,
updatePosition = function ( o ) {
var bbox = o . getBBox ( 1 ) ;
$ ( o . pattern , { patternTransform : o . matrix . invert ( ) + " translate(" + bbox . x + "," + bbox . y + ")" } ) ;
} ,
addArrow = function ( o , value , isEnd ) {
if ( o . type == "path" ) {
var values = Str ( value ) . toLowerCase ( ) . split ( "-" ) ,
p = o . paper ,
se = isEnd ? "end" : "start" ,
node = o . node ,
attrs = o . attrs ,
stroke = attrs [ "stroke-width" ] ,
i = values . length ,
type = "classic" ,
from ,
to ,
dx ,
refX ,
attr ,
w = 3 ,
h = 3 ,
t = 5 ;
while ( i -- ) {
switch ( values [ i ] ) {
case "block" :
case "classic" :
case "oval" :
case "diamond" :
case "open" :
case "none" :
type = values [ i ] ;
break ;
case "wide" : h = 5 ; break ;
case "narrow" : h = 2 ; break ;
case "long" : w = 5 ; break ;
case "short" : w = 2 ; break ;
}
}
if ( type == "open" ) {
w += 2 ;
h += 2 ;
t += 2 ;
dx = 1 ;
refX = isEnd ? 4 : 1 ;
attr = {
fill : "none" ,
stroke : attrs . stroke
} ;
} else {
refX = dx = w / 2 ;
attr = {
fill : attrs . stroke ,
stroke : "none"
} ;
}
if ( o . _ . arrows ) {
if ( isEnd ) {
o . _ . arrows . endPath && markerCounter [ o . _ . arrows . endPath ] -- ;
o . _ . arrows . endMarker && markerCounter [ o . _ . arrows . endMarker ] -- ;
} else {
o . _ . arrows . startPath && markerCounter [ o . _ . arrows . startPath ] -- ;
o . _ . arrows . startMarker && markerCounter [ o . _ . arrows . startMarker ] -- ;
}
} else {
o . _ . arrows = { } ;
}
if ( type != "none" ) {
var pathId = "raphael-marker-" + type ,
markerId = "raphael-marker-" + se + type + w + h + "-obj" + o . id ;
if ( ! R . _g . doc . getElementById ( pathId ) ) {
p . defs . appendChild ( $ ( $ ( "path" ) , {
"stroke-linecap" : "round" ,
d : markers [ type ] ,
id : pathId
} ) ) ;
markerCounter [ pathId ] = 1 ;
} else {
markerCounter [ pathId ] ++ ;
}
var marker = R . _g . doc . getElementById ( markerId ) ,
use ;
if ( ! marker ) {
marker = $ ( $ ( "marker" ) , {
id : markerId ,
markerHeight : h ,
markerWidth : w ,
orient : "auto" ,
refX : refX ,
refY : h / 2
} ) ;
use = $ ( $ ( "use" ) , {
"xlink:href" : "#" + pathId ,
transform : ( isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E ) + "scale(" + w / t + "," + h / t + ")" ,
"stroke-width" : ( 1 / ( ( w / t + h / t ) / 2 ) ) . toFixed ( 4 )
} ) ;
marker . appendChild ( use ) ;
p . defs . appendChild ( marker ) ;
markerCounter [ markerId ] = 1 ;
} else {
markerCounter [ markerId ] ++ ;
use = marker . getElementsByTagName ( "use" ) [ 0 ] ;
}
$ ( use , attr ) ;
var delta = dx * ( type != "diamond" && type != "oval" ) ;
if ( isEnd ) {
from = o . _ . arrows . startdx * stroke || 0 ;
to = R . getTotalLength ( attrs . path ) - delta * stroke ;
} else {
from = delta * stroke ;
to = R . getTotalLength ( attrs . path ) - ( o . _ . arrows . enddx * stroke || 0 ) ;
}
attr = { } ;
attr [ "marker-" + se ] = "url(#" + markerId + ")" ;
if ( to || from ) {
attr . d = R . getSubpath ( attrs . path , from , to ) ;
}
$ ( node , attr ) ;
o . _ . arrows [ se + "Path" ] = pathId ;
o . _ . arrows [ se + "Marker" ] = markerId ;
o . _ . arrows [ se + "dx" ] = delta ;
o . _ . arrows [ se + "Type" ] = type ;
o . _ . arrows [ se + "String" ] = value ;
} else {
if ( isEnd ) {
from = o . _ . arrows . startdx * stroke || 0 ;
to = R . getTotalLength ( attrs . path ) - from ;
} else {
from = 0 ;
to = R . getTotalLength ( attrs . path ) - ( o . _ . arrows . enddx * stroke || 0 ) ;
}
o . _ . arrows [ se + "Path" ] && $ ( node , { d : R . getSubpath ( attrs . path , from , to ) } ) ;
delete o . _ . arrows [ se + "Path" ] ;
delete o . _ . arrows [ se + "Marker" ] ;
delete o . _ . arrows [ se + "dx" ] ;
delete o . _ . arrows [ se + "Type" ] ;
delete o . _ . arrows [ se + "String" ] ;
}
for ( attr in markerCounter ) if ( markerCounter [ has ] ( attr ) && ! markerCounter [ attr ] ) {
var item = R . _g . doc . getElementById ( attr ) ;
item && item . parentNode . removeChild ( item ) ;
}
}
} ,
dasharray = {
"-" : [ 3 , 1 ] ,
"." : [ 1 , 1 ] ,
"-." : [ 3 , 1 , 1 , 1 ] ,
"-.." : [ 3 , 1 , 1 , 1 , 1 , 1 ] ,
". " : [ 1 , 3 ] ,
"- " : [ 4 , 3 ] ,
"--" : [ 8 , 3 ] ,
"- ." : [ 4 , 3 , 1 , 3 ] ,
"--." : [ 8 , 3 , 1 , 3 ] ,
"--.." : [ 8 , 3 , 1 , 3 , 1 , 3 ]
} ,
addDashes = function ( o , value , params ) {
value = dasharray [ Str ( value ) . toLowerCase ( ) ] ;
if ( value ) {
var width = o . attrs [ "stroke-width" ] || "1" ,
butt = { round : width , square : width , butt : 0 } [ o . attrs [ "stroke-linecap" ] || params [ "stroke-linecap" ] ] || 0 ,
dashes = [ ] ,
i = value . length ;
while ( i -- ) {
dashes [ i ] = value [ i ] * width + ( ( i % 2 ) ? 1 : - 1 ) * butt ;
}
$ ( o . node , { "stroke-dasharray" : dashes . join ( "," ) } ) ;
}
else {
$ ( o . node , { "stroke-dasharray" : "none" } ) ;
}
} ,
setFillAndStroke = function ( o , params ) {
var node = o . node ,
attrs = o . attrs ,
vis = node . style . visibility ;
node . style . visibility = "hidden" ;
for ( var att in params ) {
if ( params [ has ] ( att ) ) {
if ( ! R . _availableAttrs [ has ] ( att ) ) {
continue ;
}
var value = params [ att ] ;
attrs [ att ] = value ;
switch ( att ) {
case "blur" :
o . blur ( value ) ;
break ;
case "title" :
var title = node . getElementsByTagName ( "title" ) ;
// Use the existing <title>.
if ( title . length && ( title = title [ 0 ] ) ) {
title . firstChild . nodeValue = value ;
} else {
title = $ ( "title" ) ;
var val = R . _g . doc . createTextNode ( value ) ;
title . appendChild ( val ) ;
node . appendChild ( title ) ;
}
break ;
case "href" :
case "target" :
var pn = node . parentNode ;
if ( pn . tagName . toLowerCase ( ) != "a" ) {
var hl = $ ( "a" ) ;
pn . insertBefore ( hl , node ) ;
hl . appendChild ( node ) ;
pn = hl ;
}
if ( att == "target" ) {
pn . setAttributeNS ( xlink , "show" , value == "blank" ? "new" : value ) ;
} else {
pn . setAttributeNS ( xlink , att , value ) ;
}
break ;
case "cursor" :
node . style . cursor = value ;
break ;
case "transform" :
o . transform ( value ) ;
break ;
case "arrow-start" :
addArrow ( o , value ) ;
break ;
case "arrow-end" :
addArrow ( o , value , 1 ) ;
break ;
case "clip-rect" :
var rect = Str ( value ) . split ( separator ) ;
if ( rect . length == 4 ) {
o . clip && o . clip . parentNode . parentNode . removeChild ( o . clip . parentNode ) ;
var el = $ ( "clipPath" ) ,
rc = $ ( "rect" ) ;
el . id = R . createUUID ( ) ;
$ ( rc , {
x : rect [ 0 ] ,
y : rect [ 1 ] ,
width : rect [ 2 ] ,
height : rect [ 3 ]
} ) ;
el . appendChild ( rc ) ;
o . paper . defs . appendChild ( el ) ;
$ ( node , { "clip-path" : "url(#" + el . id + ")" } ) ;
o . clip = rc ;
}
if ( ! value ) {
var path = node . getAttribute ( "clip-path" ) ;
if ( path ) {
var clip = R . _g . doc . getElementById ( path . replace ( /(^url\(#|\)$)/g , E ) ) ;
clip && clip . parentNode . removeChild ( clip ) ;
$ ( node , { "clip-path" : E } ) ;
delete o . clip ;
}
}
break ;
case "path" :
if ( o . type == "path" ) {
$ ( node , { d : value ? attrs . path = R . _pathToAbsolute ( value ) : "M0,0" } ) ;
o . _ . dirty = 1 ;
if ( o . _ . arrows ) {
"startString" in o . _ . arrows && addArrow ( o , o . _ . arrows . startString ) ;
"endString" in o . _ . arrows && addArrow ( o , o . _ . arrows . endString , 1 ) ;
}
}
break ;
case "width" :
node . setAttribute ( att , value ) ;
o . _ . dirty = 1 ;
if ( attrs . fx ) {
att = "x" ;
value = attrs . x ;
} else {
break ;
}
case "x" :
if ( attrs . fx ) {
value = - attrs . x - ( attrs . width || 0 ) ;
}
case "rx" :
if ( att == "rx" && o . type == "rect" ) {
break ;
}
case "cx" :
node . setAttribute ( att , value ) ;
o . pattern && updatePosition ( o ) ;
o . _ . dirty = 1 ;
break ;
case "height" :
node . setAttribute ( att , value ) ;
o . _ . dirty = 1 ;
if ( attrs . fy ) {
att = "y" ;
value = attrs . y ;
} else {
break ;
}
case "y" :
if ( attrs . fy ) {
value = - attrs . y - ( attrs . height || 0 ) ;
}
case "ry" :
if ( att == "ry" && o . type == "rect" ) {
break ;
}
case "cy" :
node . setAttribute ( att , value ) ;
o . pattern && updatePosition ( o ) ;
o . _ . dirty = 1 ;
break ;
case "r" :
if ( o . type == "rect" ) {
$ ( node , { rx : value , ry : value } ) ;
} else {
node . setAttribute ( att , value ) ;
}
o . _ . dirty = 1 ;
break ;
case "src" :
if ( o . type == "image" ) {
node . setAttributeNS ( xlink , "href" , value ) ;
}
break ;
case "stroke-width" :
if ( o . _ . sx != 1 || o . _ . sy != 1 ) {
value /= mmax ( abs ( o . _ . sx ) , abs ( o . _ . sy ) ) || 1 ;
}
node . setAttribute ( att , value ) ;
if ( attrs [ "stroke-dasharray" ] ) {
addDashes ( o , attrs [ "stroke-dasharray" ] , params ) ;
}
if ( o . _ . arrows ) {
"startString" in o . _ . arrows && addArrow ( o , o . _ . arrows . startString ) ;
"endString" in o . _ . arrows && addArrow ( o , o . _ . arrows . endString , 1 ) ;
}
break ;
case "stroke-dasharray" :
addDashes ( o , value , params ) ;
break ;
case "fill" :
var isURL = Str ( value ) . match ( R . _ISURL ) ;
if ( isURL ) {
el = $ ( "pattern" ) ;
var ig = $ ( "image" ) ;
el . id = R . createUUID ( ) ;
$ ( el , { x : 0 , y : 0 , patternUnits : "userSpaceOnUse" , height : 1 , width : 1 } ) ;
$ ( ig , { x : 0 , y : 0 , "xlink:href" : isURL [ 1 ] } ) ;
el . appendChild ( ig ) ;
( function ( el ) {
R . _preload ( isURL [ 1 ] , function ( ) {
var w = this . offsetWidth ,
h = this . offsetHeight ;
$ ( el , { width : w , height : h } ) ;
$ ( ig , { width : w , height : h } ) ;
} ) ;
} ) ( el ) ;
o . paper . defs . appendChild ( el ) ;
$ ( node , { fill : "url(#" + el . id + ")" } ) ;
o . pattern = el ;
o . pattern && updatePosition ( o ) ;
break ;
}
var clr = R . getRGB ( value ) ;
if ( ! clr . error ) {
delete params . gradient ;
delete attrs . gradient ;
! R . is ( attrs . opacity , "undefined" ) &&
R . is ( params . opacity , "undefined" ) &&
$ ( node , { opacity : attrs . opacity } ) ;
! R . is ( attrs [ "fill-opacity" ] , "undefined" ) &&
R . is ( params [ "fill-opacity" ] , "undefined" ) &&
$ ( node , { "fill-opacity" : attrs [ "fill-opacity" ] } ) ;
} else if ( ( o . type == "circle" || o . type == "ellipse" || Str ( value ) . charAt ( ) != "r" ) && addGradientFill ( o , value ) ) {
if ( "opacity" in attrs || "fill-opacity" in attrs ) {
var gradient = R . _g . doc . getElementById ( node . getAttribute ( "fill" ) . replace ( /^url\(#|\)$/g , E ) ) ;
if ( gradient ) {
var stops = gradient . getElementsByTagName ( "stop" ) ;
$ ( stops [ stops . length - 1 ] , { "stop-opacity" : ( "opacity" in attrs ? attrs . opacity : 1 ) * ( "fill-opacity" in attrs ? attrs [ "fill-opacity" ] : 1 ) } ) ;
}
}
attrs . gradient = value ;
attrs . fill = "none" ;
break ;
}
clr [ has ] ( "opacity" ) && $ ( node , { "fill-opacity" : clr . opacity > 1 ? clr . opacity / 100 : clr . opacity } ) ;
case "stroke" :
clr = R . getRGB ( value ) ;
node . setAttribute ( att , clr . hex ) ;
att == "stroke" && clr [ has ] ( "opacity" ) && $ ( node , { "stroke-opacity" : clr . opacity > 1 ? clr . opacity / 100 : clr . opacity } ) ;
if ( att == "stroke" && o . _ . arrows ) {
"startString" in o . _ . arrows && addArrow ( o , o . _ . arrows . startString ) ;
"endString" in o . _ . arrows && addArrow ( o , o . _ . arrows . endString , 1 ) ;
}
break ;
case "gradient" :
( o . type == "circle" || o . type == "ellipse" || Str ( value ) . charAt ( ) != "r" ) && addGradientFill ( o , value ) ;
break ;
case "opacity" :
if ( attrs . gradient && ! attrs [ has ] ( "stroke-opacity" ) ) {
$ ( node , { "stroke-opacity" : value > 1 ? value / 100 : value } ) ;
}
// fall
case "fill-opacity" :
if ( attrs . gradient ) {
gradient = R . _g . doc . getElementById ( node . getAttribute ( "fill" ) . replace ( /^url\(#|\)$/g , E ) ) ;
if ( gradient ) {
stops = gradient . getElementsByTagName ( "stop" ) ;
$ ( stops [ stops . length - 1 ] , { "stop-opacity" : value } ) ;
}
break ;
}
default :
att == "font-size" && ( value = toInt ( value , 10 ) + "px" ) ;
var cssrule = att . replace ( /(\-.)/g , function ( w ) {
return w . substring ( 1 ) . toUpperCase ( ) ;
} ) ;
node . style [ cssrule ] = value ;
o . _ . dirty = 1 ;
node . setAttribute ( att , value ) ;
break ;
}
}
}
tuneText ( o , params ) ;
node . style . visibility = vis ;
} ,
leading = 1.2 ,
tuneText = function ( el , params ) {
if ( el . type != "text" || ! ( params [ has ] ( "text" ) || params [ has ] ( "font" ) || params [ has ] ( "font-size" ) || params [ has ] ( "x" ) || params [ has ] ( "y" ) ) ) {
return ;
}
var a = el . attrs ,
node = el . node ,
fontSize = node . firstChild ? toInt ( R . _g . doc . defaultView . getComputedStyle ( node . firstChild , E ) . getPropertyValue ( "font-size" ) , 10 ) : 10 ;
if ( params [ has ] ( "text" ) ) {
a . text = params . text ;
while ( node . firstChild ) {
node . removeChild ( node . firstChild ) ;
}
var texts = Str ( params . text ) . split ( "\n" ) ,
tspans = [ ] ,
tspan ;
for ( var i = 0 , ii = texts . length ; i < ii ; i ++ ) {
tspan = $ ( "tspan" ) ;
i && $ ( tspan , { dy : fontSize * leading , x : a . x } ) ;
tspan . appendChild ( R . _g . doc . createTextNode ( texts [ i ] ) ) ;
node . appendChild ( tspan ) ;
tspans [ i ] = tspan ;
}
} else {
tspans = node . getElementsByTagName ( "tspan" ) ;
for ( i = 0 , ii = tspans . length ; i < ii ; i ++ ) if ( i ) {
$ ( tspans [ i ] , { dy : fontSize * leading , x : a . x } ) ;
} else {
$ ( tspans [ 0 ] , { dy : 0 } ) ;
}
}
$ ( node , { x : a . x , y : a . y } ) ;
el . _ . dirty = 1 ;
var bb = el . _getBBox ( ) ,
dif = a . y - ( bb . y + bb . height / 2 ) ;
dif && R . is ( dif , "finite" ) && $ ( tspans [ 0 ] , { dy : dif } ) ;
} ,
getRealNode = function ( node ) {
if ( node . parentNode && node . parentNode . tagName . toLowerCase ( ) === "a" ) {
return node . parentNode ;
} else {
return node ;
}
} ,
Element = function ( node , svg ) {
var X = 0 ,
Y = 0 ;
/ * \
* Element . node
[ property ( object ) ]
* *
* Gives you a reference to the DOM object , so you can assign event handlers or just mess around .
* *
* Note : Don ’ t mess with it .
> Usage
| // draw a circle at coordinate 10,10 with radius of 10
| var c = paper . circle ( 10 , 10 , 10 ) ;
| c . node . onclick = function ( ) {
| c . attr ( "fill" , "red" ) ;
| } ;
\ * /
this [ 0 ] = this . node = node ;
/ * \
* Element . raphael
[ property ( object ) ]
* *
* Internal reference to @ Raphael object . In case it is not available .
> Usage
| Raphael . el . red = function ( ) {
| var hsb = this . paper . raphael . rgb2hsb ( this . attr ( "fill" ) ) ;
| hsb . h = 1 ;
| this . attr ( { fill : this . paper . raphael . hsb2rgb ( hsb ) . hex } ) ;
| }
\ * /
node . raphael = true ;
/ * \
* Element . id
[ property ( number ) ]
* *
* Unique id of the element . Especially useful when you want to listen to events of the element ,
* because all events are fired in format ` <module>.<action>.<id> ` . Also useful for @ Paper . getById method .
\ * /
this . id = guid ( ) ;
node . raphaelid = this . id ;
/ * *
* Method that returns a 5 letter / digit id , enough for 36 ^ 5 = 60466176 elements
* @ returns { string } id
* /
function guid ( ) {
return ( "0000" + ( Math . random ( ) * Math . pow ( 36 , 5 ) << 0 ) . toString ( 36 ) ) . slice ( - 5 ) ;
}
this . matrix = R . matrix ( ) ;
this . realPath = null ;
/ * \
* Element . paper
[ property ( object ) ]
* *
* Internal reference to “ paper ” where object drawn . Mainly for use in plugins and element extensions .
> Usage
| Raphael . el . cross = function ( ) {
| this . attr ( { fill : "red" } ) ;
| this . paper . path ( "M10,10L50,50M50,10L10,50" )
| . attr ( { stroke : "red" } ) ;
| }
\ * /
this . paper = svg ;
this . attrs = this . attrs || { } ;
this . _ = {
transform : [ ] ,
sx : 1 ,
sy : 1 ,
deg : 0 ,
dx : 0 ,
dy : 0 ,
dirty : 1
} ;
! svg . bottom && ( svg . bottom = this ) ;
/ * \
* Element . prev
[ property ( object ) ]
* *
* Reference to the previous element in the hierarchy .
\ * /
this . prev = svg . top ;
svg . top && ( svg . top . next = this ) ;
svg . top = this ;
/ * \
* Element . next
[ property ( object ) ]
* *
* Reference to the next element in the hierarchy .
\ * /
this . next = null ;
} ,
elproto = R . el ;
Element . prototype = elproto ;
elproto . constructor = Element ;
R . _engine . path = function ( pathString , SVG ) {
var el = $ ( "path" ) ;
SVG . canvas && SVG . canvas . appendChild ( el ) ;
var p = new Element ( el , SVG ) ;
p . type = "path" ;
setFillAndStroke ( p , {
fill : "none" ,
stroke : "#000" ,
path : pathString
} ) ;
return p ;
} ;
/ * \
* Element . rotate
[ method ]
* *
* Deprecated ! Use @ Element . transform instead .
* Adds rotation by given angle around given point to the list of
* transformations of the element .
> Parameters
- deg ( number ) angle in degrees
- cx ( number ) # optional x coordinate of the centre of rotation
- cy ( number ) # optional y coordinate of the centre of rotation
* If cx & cy aren ’ t specified centre of the shape is used as a point of rotation .
= ( object ) @ Element
\ * /
elproto . rotate = function ( deg , cx , cy ) {
if ( this . removed ) {
return this ;
}
deg = Str ( deg ) . split ( separator ) ;
if ( deg . length - 1 ) {
cx = toFloat ( deg [ 1 ] ) ;
cy = toFloat ( deg [ 2 ] ) ;
}
deg = toFloat ( deg [ 0 ] ) ;
( cy == null ) && ( cx = cy ) ;
if ( cx == null || cy == null ) {
var bbox = this . getBBox ( 1 ) ;
cx = bbox . x + bbox . width / 2 ;
cy = bbox . y + bbox . height / 2 ;
}
this . transform ( this . _ . transform . concat ( [ [ "r" , deg , cx , cy ] ] ) ) ;
return this ;
} ;
/ * \
* Element . scale
[ method ]
* *
* Deprecated ! Use @ Element . transform instead .
* Adds scale by given amount relative to given point to the list of
* transformations of the element .
> Parameters
- sx ( number ) horisontal scale amount
- sy ( number ) vertical scale amount
- cx ( number ) # optional x coordinate of the centre of scale
- cy ( number ) # optional y coordinate of the centre of scale
* If cx & cy aren ’ t specified centre of the shape is used instead .
= ( object ) @ Element
\ * /
elproto . scale = function ( sx , sy , cx , cy ) {
if ( this . removed ) {
return this ;
}
sx = Str ( sx ) . split ( separator ) ;
if ( sx . length - 1 ) {
sy = toFloat ( sx [ 1 ] ) ;
cx = toFloat ( sx [ 2 ] ) ;
cy = toFloat ( sx [ 3 ] ) ;
}
sx = toFloat ( sx [ 0 ] ) ;
( sy == null ) && ( sy = sx ) ;
( cy == null ) && ( cx = cy ) ;
if ( cx == null || cy == null ) {
var bbox = this . getBBox ( 1 ) ;
}
cx = cx == null ? bbox . x + bbox . width / 2 : cx ;
cy = cy == null ? bbox . y + bbox . height / 2 : cy ;
this . transform ( this . _ . transform . concat ( [ [ "s" , sx , sy , cx , cy ] ] ) ) ;
return this ;
} ;
/ * \
* Element . translate
[ method ]
* *
* Deprecated ! Use @ Element . transform instead .
* Adds translation by given amount to the list of transformations of the element .
> Parameters
- dx ( number ) horisontal shift
- dy ( number ) vertical shift
= ( object ) @ Element
\ * /
elproto . translate = function ( dx , dy ) {
if ( this . removed ) {
return this ;
}
dx = Str ( dx ) . split ( separator ) ;
if ( dx . length - 1 ) {
dy = toFloat ( dx [ 1 ] ) ;
}
dx = toFloat ( dx [ 0 ] ) || 0 ;
dy = + dy || 0 ;
this . transform ( this . _ . transform . concat ( [ [ "t" , dx , dy ] ] ) ) ;
return this ;
} ;
/ * \
* Element . transform
[ method ]
* *
* Adds transformation to the element which is separate to other attributes ,
* i . e . translation doesn ’ t change ` x ` or ` y ` of the rectange . The format
* of transformation string is similar to the path string syntax :
| "t100,100r30,100,100s2,2,100,100r45s1.5"
* Each letter is a command . There are four commands : ` t ` is for translate , ` r ` is for rotate , ` s ` is for
* scale and ` m ` is for matrix .
*
* There are also alternative “ absolute ” translation , rotation and scale : ` T ` , ` R ` and ` S ` . They will not take previous transformation into account . For example , ` ...T100,0 ` will always move element 100 px horisontally , while ` ...t100,0 ` could move it vertically if there is ` r90 ` before . Just compare results of ` r90t100,0 ` and ` r90T100,0 ` .
*
* So , the example line above could be read like “ translate by 100 , 100 ; rotate 30 ° around 100 , 100 ; scale twice around 100 , 100 ;
* rotate 45 ° around centre ; scale 1.5 times relative to centre ” . As you can see rotate and scale commands have origin
* coordinates as optional parameters , the default is the centre point of the element .
* Matrix accepts six parameters .
> Usage
| var el = paper . rect ( 10 , 20 , 300 , 200 ) ;
| // translate 100, 100, rotate 45°, translate -100, 0
| el . transform ( "t100,100r45t-100,0" ) ;
| // if you want you can append or prepend transformations
| el . transform ( "...t50,50" ) ;
| el . transform ( "s2..." ) ;
| // or even wrap
| el . transform ( "t50,50...t-50-50" ) ;
| // to reset transformation call method with empty string
| el . transform ( "" ) ;
| // to get current value call it without parameters
| console . log ( el . transform ( ) ) ;
> Parameters
- tstr ( string ) # optional transformation string
* If tstr isn ’ t specified
= ( string ) current transformation string
* else
= ( object ) @ Element
\ * /
elproto . transform = function ( tstr ) {
var _ = this . _ ;
if ( tstr == null ) {
return _ . transform ;
}
R . _extractTransform ( this , tstr ) ;
this . clip && $ ( this . clip , { transform : this . matrix . invert ( ) } ) ;
this . pattern && updatePosition ( this ) ;
this . node && $ ( this . node , { transform : this . matrix } ) ;
if ( _ . sx != 1 || _ . sy != 1 ) {
var sw = this . attrs [ has ] ( "stroke-width" ) ? this . attrs [ "stroke-width" ] : 1 ;
this . attr ( { "stroke-width" : sw } ) ;
}
return this ;
} ;
/ * \
* Element . hide
[ method ]
* *
* Makes element invisible . See @ Element . show .
= ( object ) @ Element
\ * /
elproto . hide = function ( ) {
if ( ! this . removed ) this . node . style . display = "none" ;
return this ;
} ;
/ * \
* Element . show
[ method ]
* *
* Makes element visible . See @ Element . hide .
= ( object ) @ Element
\ * /
elproto . show = function ( ) {
if ( ! this . removed ) this . node . style . display = "" ;
return this ;
} ;
/ * \
* Element . remove
[ method ]
* *
* Removes element from the paper .
\ * /
elproto . remove = function ( ) {
var node = getRealNode ( this . node ) ;
if ( this . removed || ! node . parentNode ) {
return ;
}
var paper = this . paper ;
paper . _ _set _ _ && paper . _ _set _ _ . exclude ( this ) ;
eve . unbind ( "raphael.*.*." + this . id ) ;
if ( this . gradient ) {
paper . defs . removeChild ( this . gradient ) ;
}
R . _tear ( this , paper ) ;
node . parentNode . removeChild ( node ) ;
// Remove custom data for element
this . removeData ( ) ;
for ( var i in this ) {
this [ i ] = typeof this [ i ] == "function" ? R . _removedFactory ( i ) : null ;
}
this . removed = true ;
} ;
elproto . _getBBox = function ( ) {
if ( this . node . style . display == "none" ) {
this . show ( ) ;
var hide = true ;
}
var canvasHidden = false ,
containerStyle ;
if ( this . paper . canvas . parentElement ) {
containerStyle = this . paper . canvas . parentElement . style ;
} //IE10+ can't find parentElement
else if ( this . paper . canvas . parentNode ) {
containerStyle = this . paper . canvas . parentNode . style ;
}
if ( containerStyle && containerStyle . display == "none" ) {
canvasHidden = true ;
containerStyle . display = "" ;
}
var bbox = { } ;
try {
bbox = this . node . getBBox ( ) ;
} catch ( e ) {
// Firefox 3.0.x, 25.0.1 (probably more versions affected) play badly here - possible fix
bbox = {
x : this . node . clientLeft ,
y : this . node . clientTop ,
width : this . node . clientWidth ,
height : this . node . clientHeight
}
} finally {
bbox = bbox || { } ;
if ( canvasHidden ) {
containerStyle . display = "none" ;
}
}
hide && this . hide ( ) ;
return bbox ;
} ;
/ * \
* Element . attr
[ method ]
* *
* Sets the attributes of the element .
> Parameters
- attrName ( string ) attribute ’ s name
- value ( string ) value
* or
- params ( object ) object of name / value pairs
* or
- attrName ( string ) attribute ’ s name
* or
- attrNames ( array ) in this case method returns array of current values for given attribute names
= ( object ) @ Element if attrsName & value or params are passed in .
= ( ... ) value of the attribute if only attrsName is passed in .
= ( array ) array of values of the attribute if attrsNames is passed in .
= ( object ) object of attributes if nothing is passed in .
> Possible parameters
# < p > Please refer to the < a href = "http://www.w3.org/TR/SVG/" title = "The W3C Recommendation for the SVG language describes these properties in detail." > SVG specification < / a > f o r a n e x p l a n a t i o n o f t h e s e p a r a m e t e r s . < / p >
o arrow - end ( string ) arrowhead on the end of the path . The format for string is ` <type>[-<width>[-<length>]] ` . Possible types : ` classic ` , ` block ` , ` open ` , ` oval ` , ` diamond ` , ` none ` , width : ` wide ` , ` narrow ` , ` medium ` , length : ` long ` , ` short ` , ` midium ` .
o clip - rect ( string ) comma or space separated values : x , y , width and height
o cursor ( string ) CSS type of the cursor
o cx ( number ) the x - axis coordinate of the center of the circle , or ellipse
o cy ( number ) the y - axis coordinate of the center of the circle , or ellipse
o fill ( string ) colour , gradient or image
o fill - opacity ( number )
o font ( string )
o font - family ( string )
o font - size ( number ) font size in pixels
o font - weight ( string )
o height ( number )
o href ( string ) URL , if specified element behaves as hyperlink
o opacity ( number )
o path ( string ) SVG path string format
o r ( number ) radius of the circle , ellipse or rounded corner on the rect
o rx ( number ) horisontal radius of the ellipse
o ry ( number ) vertical radius of the ellipse
o src ( string ) image URL , only works for @ Element . image element
o stroke ( string ) stroke colour
o stroke - dasharray ( string ) [ “ ” , “ none ” , “ ` - ` ” , “ ` . ` ” , “ ` -. ` ” , “ ` -.. ` ” , “ ` . ` ” , “ ` - ` ” , “ ` -- ` ” , “ ` - . ` ” , “ ` --. ` ” , “ ` --.. ` ” ]
o stroke - linecap ( string ) [ “ ` butt ` ” , “ ` square ` ” , “ ` round ` ” ]
o stroke - linejoin ( string ) [ “ ` bevel ` ” , “ ` round ` ” , “ ` miter ` ” ]
o stroke - miterlimit ( number )
o stroke - opacity ( number )
o stroke - width ( number ) stroke width in pixels , default is '1'
o target ( string ) used with href
o text ( string ) contents of the text element . Use ` \n ` for multiline text
o text - anchor ( string ) [ “ ` start ` ” , “ ` middle ` ” , “ ` end ` ” ] , default is “ ` middle ` ”
o title ( string ) will create tooltip with a given text
o transform ( string ) see @ Element . transform
o width ( number )
o x ( number )
o y ( number )
> Gradients
* Linear gradient format : “ ` ‹ angle› -‹ colour› [-‹ colour› [:‹ offset› ]]*-‹ colour› ` ” , example : “ ` 90-#fff-#000 ` ” – 90 °
* gradient from white to black or “ ` 0-#fff-#f00:20-#000 ` ” – 0 ° gradient from white via red ( at 20 % ) to black .
*
* radial gradient : “ ` r[(‹ fx› , ‹ fy› )]‹ colour› [-‹ colour› [:‹ offset› ]]*-‹ colour› ` ” , example : “ ` r#fff-#000 ` ” –
* gradient from white to black or “ ` r(0.25, 0.75)#fff-#000 ` ” – gradient from white to black with focus point
* at 0.25 , 0.75 . Focus point coordinates are in 0. . 1 range . Radial gradients can only be applied to circles and ellipses .
> Path String
# < p > Please refer to < a href = "http://www.w3.org/TR/SVG/paths.html#PathData" title = "Details of a path’ s data attribute’ s format are described in the SVG specification." > SVG documentation regarding path string < / a > . R a p h a ë l f u l l y s u p p o r t s i t . < / p >
> Colour Parsing
# < ul >
# < li > Colour name ( “ < code > red < / c o d e > ” , “ < c o d e > g r e e n < / c o d e > ” , “ < c o d e > c o r n f l o w e r b l u e < / c o d e > ” , e t c ) < / l i >
# < li > # • • • — shortened HTML colour : ( “ < code > # 000 < / c o d e > ” , “ < c o d e > # f c 0 < / c o d e > ” , e t c ) < / l i >
# < li > # • • • • • • — full length HTML colour : ( “ < code > # 000000 < / c o d e > ” , “ < c o d e > # b d 2 3 0 0 < / c o d e > ” ) < / l i >
# < li > rgb ( • • • , • • • , • • • ) — red , green and blue channels ’ values : ( “ < code > rgb ( 200 , & nbsp ; 100 , & nbsp ; 0 ) < / c o d e > ” ) < / l i >
# < li > rgb ( • • • % , • • • % , • • • % ) — same as above , but in % : ( “ < code > rgb ( 100 % , & nbsp ; 175 % , & nbsp ; 0 % ) < / c o d e > ” ) < / l i >
# < li > rgba ( • • • , • • • , • • • , • • • ) — red , green and blue channels ’ values : ( “ < code > rgba ( 200 , & nbsp ; 100 , & nbsp ; 0 , . 5 ) < / c o d e > ” ) < / l i >
# < li > rgba ( • • • % , • • • % , • • • % , • • • % ) — same as above , but in % : ( “ < code > rgba ( 100 % , & nbsp ; 175 % , & nbsp ; 0 % , 50 % ) < / c o d e > ” ) < / l i >
# < li > hsb ( • • • , • • • , • • • ) — hue , saturation and brightness values : ( “ < code > hsb ( 0.5 , & nbsp ; 0.25 , & nbsp ; 1 ) < / c o d e > ” ) < / l i >
# < li > hsb ( • • • % , • • • % , • • • % ) — same as above , but in % < / l i >
# < li > hsba ( • • • , • • • , • • • , • • • ) — same as above , but with opacity < / l i >
# < li > hsl ( • • • , • • • , • • • ) — almost the same as hsb , see < a href = "http://en.wikipedia.org/wiki/HSL_and_HSV" title = "HSL and HSV - Wikipedia, the free encyclopedia" > Wikipedia page < / a > < / l i >
# < li > hsl ( • • • % , • • • % , • • • % ) — same as above , but in % < / l i >
# < li > hsla ( • • • , • • • , • • • , • • • ) — same as above , but with opacity < / l i >
# < li > Optionally for hsb and hsl you could specify hue as a degree : “ < code > hsl ( 240 deg , & nbsp ; 1 , & nbsp ; . 5 ) < / c o d e > ” o r , i f y o u w a n t t o g o f a n c y , “ < c o d e > h s l ( 2 4 0 ° , & n b s p ; 1 , & n b s p ; . 5 ) < / c o d e > ” < / l i >
# < / u l >
\ * /
elproto . attr = function ( name , value ) {
if ( this . removed ) {
return this ;
}
if ( name == null ) {
var res = { } ;
for ( var a in this . attrs ) if ( this . attrs [ has ] ( a ) ) {
res [ a ] = this . attrs [ a ] ;
}
res . gradient && res . fill == "none" && ( res . fill = res . gradient ) && delete res . gradient ;
res . transform = this . _ . transform ;
return res ;
}
if ( value == null && R . is ( name , "string" ) ) {
if ( name == "fill" && this . attrs . fill == "none" && this . attrs . gradient ) {
return this . attrs . gradient ;
}
if ( name == "transform" ) {
return this . _ . transform ;
}
var names = name . split ( separator ) ,
out = { } ;
for ( var i = 0 , ii = names . length ; i < ii ; i ++ ) {
name = names [ i ] ;
if ( name in this . attrs ) {
out [ name ] = this . attrs [ name ] ;
} else if ( R . is ( this . paper . customAttributes [ name ] , "function" ) ) {
out [ name ] = this . paper . customAttributes [ name ] . def ;
} else {
out [ name ] = R . _availableAttrs [ name ] ;
}
}
return ii - 1 ? out : out [ names [ 0 ] ] ;
}
if ( value == null && R . is ( name , "array" ) ) {
out = { } ;
for ( i = 0 , ii = name . length ; i < ii ; i ++ ) {
out [ name [ i ] ] = this . attr ( name [ i ] ) ;
}
return out ;
}
if ( value != null ) {
var params = { } ;
params [ name ] = value ;
} else if ( name != null && R . is ( name , "object" ) ) {
params = name ;
}
for ( var key in params ) {
eve ( "raphael.attr." + key + "." + this . id , this , params [ key ] ) ;
}
for ( key in this . paper . customAttributes ) if ( this . paper . customAttributes [ has ] ( key ) && params [ has ] ( key ) && R . is ( this . paper . customAttributes [ key ] , "function" ) ) {
var par = this . paper . customAttributes [ key ] . apply ( this , [ ] . concat ( params [ key ] ) ) ;
this . attrs [ key ] = params [ key ] ;
for ( var subkey in par ) if ( par [ has ] ( subkey ) ) {
params [ subkey ] = par [ subkey ] ;
}
}
setFillAndStroke ( this , params ) ;
return this ;
} ;
/ * \
* Element . toFront
[ method ]
* *
* Moves the element so it is the closest to the viewer ’ s eyes , on top of other elements .
= ( object ) @ Element
\ * /
elproto . toFront = function ( ) {
if ( this . removed ) {
return this ;
}
var node = getRealNode ( this . node ) ;
node . parentNode . appendChild ( node ) ;
var svg = this . paper ;
svg . top != this && R . _tofront ( this , svg ) ;
return this ;
} ;
/ * \
* Element . toBack
[ method ]
* *
* Moves the element so it is the furthest from the viewer ’ s eyes , behind other elements .
= ( object ) @ Element
\ * /
elproto . toBack = function ( ) {
if ( this . removed ) {
return this ;
}
var node = getRealNode ( this . node ) ;
var parentNode = node . parentNode ;
parentNode . insertBefore ( node , parentNode . firstChild ) ;
R . _toback ( this , this . paper ) ;
var svg = this . paper ;
return this ;
} ;
/ * \
* Element . insertAfter
[ method ]
* *
* Inserts current object after the given one .
= ( object ) @ Element
\ * /
elproto . insertAfter = function ( element ) {
if ( this . removed || ! element ) {
return this ;
}
var node = getRealNode ( this . node ) ;
var afterNode = getRealNode ( element . node || element [ element . length - 1 ] . node ) ;
if ( afterNode . nextSibling ) {
afterNode . parentNode . insertBefore ( node , afterNode . nextSibling ) ;
} else {
afterNode . parentNode . appendChild ( node ) ;
}
R . _insertafter ( this , element , this . paper ) ;
return this ;
} ;
/ * \
* Element . insertBefore
[ method ]
* *
* Inserts current object before the given one .
= ( object ) @ Element
\ * /
elproto . insertBefore = function ( element ) {
if ( this . removed || ! element ) {
return this ;
}
var node = getRealNode ( this . node ) ;
var beforeNode = getRealNode ( element . node || element [ 0 ] . node ) ;
beforeNode . parentNode . insertBefore ( node , beforeNode ) ;
R . _insertbefore ( this , element , this . paper ) ;
return this ;
} ;
elproto . blur = function ( size ) {
// Experimental. No Safari support. Use it on your own risk.
var t = this ;
if ( + size !== 0 ) {
var fltr = $ ( "filter" ) ,
blur = $ ( "feGaussianBlur" ) ;
t . attrs . blur = size ;
fltr . id = R . createUUID ( ) ;
$ ( blur , { stdDeviation : + size || 1.5 } ) ;
fltr . appendChild ( blur ) ;
t . paper . defs . appendChild ( fltr ) ;
t . _blur = fltr ;
$ ( t . node , { filter : "url(#" + fltr . id + ")" } ) ;
} else {
if ( t . _blur ) {
t . _blur . parentNode . removeChild ( t . _blur ) ;
delete t . _blur ;
delete t . attrs . blur ;
}
t . node . removeAttribute ( "filter" ) ;
}
return t ;
} ;
R . _engine . circle = function ( svg , x , y , r ) {
var el = $ ( "circle" ) ;
svg . canvas && svg . canvas . appendChild ( el ) ;
var res = new Element ( el , svg ) ;
res . attrs = { cx : x , cy : y , r : r , fill : "none" , stroke : "#000" } ;
res . type = "circle" ;
$ ( el , res . attrs ) ;
return res ;
} ;
R . _engine . rect = function ( svg , x , y , w , h , r ) {
var el = $ ( "rect" ) ;
svg . canvas && svg . canvas . appendChild ( el ) ;
var res = new Element ( el , svg ) ;
res . attrs = { x : x , y : y , width : w , height : h , rx : r || 0 , ry : r || 0 , fill : "none" , stroke : "#000" } ;
res . type = "rect" ;
$ ( el , res . attrs ) ;
return res ;
} ;
R . _engine . ellipse = function ( svg , x , y , rx , ry ) {
var el = $ ( "ellipse" ) ;
svg . canvas && svg . canvas . appendChild ( el ) ;
var res = new Element ( el , svg ) ;
res . attrs = { cx : x , cy : y , rx : rx , ry : ry , fill : "none" , stroke : "#000" } ;
res . type = "ellipse" ;
$ ( el , res . attrs ) ;
return res ;
} ;
R . _engine . image = function ( svg , src , x , y , w , h ) {
var el = $ ( "image" ) ;
$ ( el , { x : x , y : y , width : w , height : h , preserveAspectRatio : "none" } ) ;
el . setAttributeNS ( xlink , "href" , src ) ;
svg . canvas && svg . canvas . appendChild ( el ) ;
var res = new Element ( el , svg ) ;
res . attrs = { x : x , y : y , width : w , height : h , src : src } ;
res . type = "image" ;
return res ;
} ;
R . _engine . text = function ( svg , x , y , text ) {
var el = $ ( "text" ) ;
svg . canvas && svg . canvas . appendChild ( el ) ;
var res = new Element ( el , svg ) ;
res . attrs = {
x : x ,
y : y ,
"text-anchor" : "middle" ,
text : text ,
"font-family" : R . _availableAttrs [ "font-family" ] ,
"font-size" : R . _availableAttrs [ "font-size" ] ,
stroke : "none" ,
fill : "#000"
} ;
res . type = "text" ;
setFillAndStroke ( res , res . attrs ) ;
return res ;
} ;
R . _engine . setSize = function ( width , height ) {
this . width = width || this . width ;
this . height = height || this . height ;
this . canvas . setAttribute ( "width" , this . width ) ;
this . canvas . setAttribute ( "height" , this . height ) ;
if ( this . _viewBox ) {
this . setViewBox . apply ( this , this . _viewBox ) ;
}
return this ;
} ;
R . _engine . create = function ( ) {
var con = R . _getContainer . apply ( 0 , arguments ) ,
2019-08-09 11:38:10 +00:00
container = con && con . container ;
2017-07-01 20:16:47 +00:00
if ( ! container ) {
throw new Error ( "SVG container not found." ) ;
}
2019-08-09 11:38:10 +00:00
var x = con . x ,
y = con . y ,
width = con . width ,
height = con . height ,
cnvs = $ ( "svg" ) ,
2017-07-01 20:16:47 +00:00
css = "overflow:hidden;" ,
isFloating ;
x = x || 0 ;
y = y || 0 ;
width = width || 512 ;
height = height || 342 ;
$ ( cnvs , {
height : height ,
version : 1.1 ,
width : width ,
xmlns : "http://www.w3.org/2000/svg" ,
"xmlns:xlink" : "http://www.w3.org/1999/xlink"
} ) ;
if ( container == 1 ) {
cnvs . style . cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px" ;
R . _g . doc . body . appendChild ( cnvs ) ;
isFloating = 1 ;
} else {
cnvs . style . cssText = css + "position:relative" ;
if ( container . firstChild ) {
container . insertBefore ( cnvs , container . firstChild ) ;
} else {
container . appendChild ( cnvs ) ;
}
}
container = new R . _Paper ;
container . width = width ;
container . height = height ;
container . canvas = cnvs ;
container . clear ( ) ;
container . _left = container . _top = 0 ;
isFloating && ( container . renderfix = function ( ) { } ) ;
container . renderfix ( ) ;
return container ;
} ;
R . _engine . setViewBox = function ( x , y , w , h , fit ) {
eve ( "raphael.setViewBox" , this , this . _viewBox , [ x , y , w , h , fit ] ) ;
var paperSize = this . getSize ( ) ,
size = mmax ( w / paperSize . width , h / paperSize . height ) ,
top = this . top ,
aspectRatio = fit ? "xMidYMid meet" : "xMinYMin" ,
vb ,
sw ;
if ( x == null ) {
if ( this . _vbSize ) {
size = 1 ;
}
delete this . _vbSize ;
vb = "0 0 " + this . width + S + this . height ;
} else {
this . _vbSize = size ;
vb = x + S + y + S + w + S + h ;
}
$ ( this . canvas , {
viewBox : vb ,
preserveAspectRatio : aspectRatio
} ) ;
while ( size && top ) {
sw = "stroke-width" in top . attrs ? top . attrs [ "stroke-width" ] : 1 ;
top . attr ( { "stroke-width" : sw } ) ;
top . _ . dirty = 1 ;
top . _ . dirtyT = 1 ;
top = top . prev ;
}
this . _viewBox = [ x , y , w , h , ! ! fit ] ;
return this ;
} ;
/ * \
* Paper . renderfix
[ method ]
* *
* Fixes the issue of Firefox and IE9 regarding subpixel rendering . If paper is dependent
* on other elements after reflow it could shift half pixel which cause for lines to lost their crispness .
* This method fixes the issue .
* *
Special thanks to Mariusz Nowak ( http : //www.medikoo.com/) for this method.
\ * /
R . prototype . renderfix = function ( ) {
var cnvs = this . canvas ,
s = cnvs . style ,
pos ;
try {
pos = cnvs . getScreenCTM ( ) || cnvs . createSVGMatrix ( ) ;
} catch ( e ) {
pos = cnvs . createSVGMatrix ( ) ;
}
var left = - pos . e % 1 ,
top = - pos . f % 1 ;
if ( left || top ) {
if ( left ) {
this . _left = ( this . _left + left ) % 1 ;
s . left = this . _left + "px" ;
}
if ( top ) {
this . _top = ( this . _top + top ) % 1 ;
s . top = this . _top + "px" ;
}
}
} ;
/ * \
* Paper . clear
[ method ]
* *
* Clears the paper , i . e . removes all the elements .
\ * /
R . prototype . clear = function ( ) {
R . eve ( "raphael.clear" , this ) ;
var c = this . canvas ;
while ( c . firstChild ) {
c . removeChild ( c . firstChild ) ;
}
this . bottom = this . top = null ;
( this . desc = $ ( "desc" ) ) . appendChild ( R . _g . doc . createTextNode ( "Created with Rapha\xebl " + R . version ) ) ;
c . appendChild ( this . desc ) ;
c . appendChild ( this . defs = $ ( "defs" ) ) ;
} ;
/ * \
* Paper . remove
[ method ]
* *
* Removes the paper from the DOM .
\ * /
R . prototype . remove = function ( ) {
eve ( "raphael.remove" , this ) ;
this . canvas . parentNode && this . canvas . parentNode . removeChild ( this . canvas ) ;
for ( var i in this ) {
this [ i ] = typeof this [ i ] == "function" ? R . _removedFactory ( i ) : null ;
}
} ;
var setproto = R . st ;
for ( var method in elproto ) if ( elproto [ has ] ( method ) && ! setproto [ has ] ( method ) ) {
setproto [ method ] = ( function ( methodname ) {
return function ( ) {
var arg = arguments ;
return this . forEach ( function ( el ) {
el [ methodname ] . apply ( el , arg ) ;
} ) ;
} ;
} ) ( method ) ;
}
} ) ;