2017-02-07 02:25:01 +00:00
// Snap.svg 0.5.1
2015-04-13 06:21:39 +00:00
//
2017-01-02 23:34:35 +00:00
// Copyright (c) 2013 – 2017 Adobe Systems Incorporated. All rights reserved.
2015-04-13 06:21:39 +00:00
//
2013-08-05 08:04:30 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2015-04-13 06:21:39 +00:00
//
2013-08-05 08:04:30 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2015-04-13 06:21:39 +00:00
//
2013-08-05 08:04:30 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2015-04-13 06:21:39 +00:00
//
2017-02-07 02:25:01 +00:00
// build: 2017-02-07
2014-08-25 06:52:37 +00:00
2013-08-05 08:04:30 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2016-12-29 05:13:00 +00:00
//
2013-08-05 08:04:30 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2016-12-29 05:13:00 +00:00
//
2013-08-05 08:04:30 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2016-12-29 05:13:00 +00:00
//
2013-08-05 08:04:30 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-08-23 23:31:00 +00:00
// ┌────────────────────────────────────────────────────────────┐ \\
2017-01-18 00:42:08 +00:00
// │ Eve 0.5.0 - JavaScript Events Library │ \\
2013-08-23 23:31:00 +00:00
// ├────────────────────────────────────────────────────────────┤ \\
// │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\
// └────────────────────────────────────────────────────────────┘ \\
( function ( glob ) {
2017-01-18 00:42:08 +00:00
var version = "0.5.0" ,
2013-08-23 23:31:00 +00:00
has = "hasOwnProperty" ,
separator = /[\.\/]/ ,
2014-05-23 11:03:03 +00:00
comaseparator = /\s*,\s*/ ,
2013-08-23 23:31:00 +00:00
wildcard = "*" ,
fun = function ( ) { } ,
numsort = function ( a , b ) {
return a - b ;
} ,
current _event ,
stop ,
events = { n : { } } ,
2014-05-23 11:03:03 +00:00
firstDefined = function ( ) {
for ( var i = 0 , ii = this . length ; i < ii ; i ++ ) {
if ( typeof this [ i ] != "undefined" ) {
return this [ i ] ;
}
}
} ,
lastDefined = function ( ) {
var i = this . length ;
while ( -- i ) {
if ( typeof this [ i ] != "undefined" ) {
return this [ i ] ;
}
}
} ,
2017-01-18 00:42:08 +00:00
objtos = Object . prototype . toString ,
Str = String ,
isArray = Array . isArray || function ( ar ) {
return ar instanceof Array || objtos . call ( ar ) == "[object Array]" ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* eve
[ method ]
* Fires event with given ` name ` , given scope and other parameters .
> Arguments
- name ( string ) name of the * event * , dot ( ` . ` ) or slash ( ` / ` ) separated
- scope ( object ) context for the event handlers
- varargs ( ... ) the rest of arguments will be sent to event handlers
2014-05-23 11:03:03 +00:00
= ( object ) array of returned values from the listeners . Array has two methods ` .firstDefined() ` and ` .lastDefined() ` to get first or last not ` undefined ` value .
2013-08-23 23:31:00 +00:00
\ * /
eve = function ( name , scope ) {
var e = events ,
oldstop = stop ,
args = Array . prototype . slice . call ( arguments , 2 ) ,
listeners = eve . listeners ( name ) ,
z = 0 ,
f = false ,
l ,
indexed = [ ] ,
queue = { } ,
out = [ ] ,
ce = current _event ,
errors = [ ] ;
2014-05-23 11:03:03 +00:00
out . firstDefined = firstDefined ;
out . lastDefined = lastDefined ;
2013-08-23 23:31:00 +00:00
current _event = name ;
stop = 0 ;
for ( var i = 0 , ii = listeners . length ; i < ii ; i ++ ) if ( "zIndex" in listeners [ i ] ) {
indexed . push ( listeners [ i ] . zIndex ) ;
if ( listeners [ i ] . zIndex < 0 ) {
queue [ listeners [ i ] . zIndex ] = listeners [ i ] ;
}
}
indexed . sort ( numsort ) ;
while ( indexed [ z ] < 0 ) {
l = queue [ indexed [ z ++ ] ] ;
out . push ( l . apply ( scope , args ) ) ;
if ( stop ) {
stop = oldstop ;
return out ;
}
}
for ( i = 0 ; i < ii ; i ++ ) {
l = listeners [ i ] ;
if ( "zIndex" in l ) {
if ( l . zIndex == indexed [ z ] ) {
out . push ( l . apply ( scope , args ) ) ;
if ( stop ) {
break ;
}
do {
z ++ ;
l = queue [ indexed [ z ] ] ;
l && out . push ( l . apply ( scope , args ) ) ;
if ( stop ) {
break ;
}
} while ( l )
} else {
queue [ l . zIndex ] = l ;
}
} else {
out . push ( l . apply ( scope , args ) ) ;
if ( stop ) {
break ;
}
}
}
stop = oldstop ;
current _event = ce ;
2014-05-23 11:03:03 +00:00
return out ;
2013-08-23 23:31:00 +00:00
} ;
2014-05-23 11:03:03 +00:00
// Undocumented. Debug only.
eve . _events = events ;
2013-08-23 23:31:00 +00:00
/ * \
* eve . listeners
[ method ]
* Internal method which gives you array of all event handlers that will be triggered by the given ` name ` .
> Arguments
- name ( string ) name of the event , dot ( ` . ` ) or slash ( ` / ` ) separated
= ( array ) array of event handlers
\ * /
eve . listeners = function ( name ) {
2017-01-18 00:42:08 +00:00
var names = isArray ( name ) ? name : name . split ( separator ) ,
2013-08-23 23:31:00 +00:00
e = events ,
item ,
items ,
k ,
i ,
ii ,
j ,
jj ,
nes ,
es = [ e ] ,
out = [ ] ;
for ( i = 0 , ii = names . length ; i < ii ; i ++ ) {
nes = [ ] ;
for ( j = 0 , jj = es . length ; j < jj ; j ++ ) {
e = es [ j ] . n ;
items = [ e [ names [ i ] ] , e [ wildcard ] ] ;
k = 2 ;
while ( k -- ) {
item = items [ k ] ;
if ( item ) {
nes . push ( item ) ;
out = out . concat ( item . f || [ ] ) ;
}
}
}
es = nes ;
}
return out ;
} ;
2017-01-18 00:42:08 +00:00
/ * \
* eve . separator
[ method ]
* If for some reasons you don ’ t like default separators ( ` . ` or ` / ` ) you can specify yours
* here . Be aware that if you pass a string longer than one character it will be treated as
* a list of characters .
- separator ( string ) new separator . Empty string resets to default : ` . ` or ` / ` .
\ * /
eve . separator = function ( sep ) {
if ( sep ) {
sep = Str ( sep ) . replace ( /(?=[\.\^\]\[\-])/g , "\\" ) ;
sep = "[" + sep + "]" ;
separator = new RegExp ( sep ) ;
} else {
separator = /[\.\/]/ ;
}
} ;
2013-08-23 23:31:00 +00:00
/ * \
* eve . on
[ method ]
* *
* Binds given event handler with a given name . You can use wildcards “ ` * ` ” for the names :
| eve . on ( "*.under.*" , f ) ;
| eve ( "mouse.under.floor" ) ; // triggers f
* Use @ eve to trigger the listener .
* *
- name ( string ) name of the event , dot ( ` . ` ) or slash ( ` / ` ) separated , with optional wildcards
- f ( function ) event handler function
* *
2017-01-18 00:42:08 +00:00
- name ( array ) if you don ’ t want to use separators , you can use array of strings
- f ( function ) event handler function
* *
2016-12-29 05:13:00 +00:00
= ( function ) returned function accepts a single numeric parameter that represents z - index of the handler . It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order , despite of the order of assignment .
2013-08-23 23:31:00 +00:00
> Example :
| eve . on ( "mouse" , eatIt ) ( 2 ) ;
| eve . on ( "mouse" , scream ) ;
| eve . on ( "mouse" , catchIt ) ( 1 ) ;
2014-05-23 11:03:03 +00:00
* This will ensure that ` catchIt ` function will be called before ` eatIt ` .
*
2013-08-23 23:31:00 +00:00
* If you want to put your handler before non - indexed handlers , specify a negative value .
* Note : I assume most of the time you don ’ t need to worry about z - index , but it ’ s nice to have this feature “ just in case ” .
\ * /
eve . on = function ( name , f ) {
2014-05-23 11:03:03 +00:00
if ( typeof f != "function" ) {
return function ( ) { } ;
2013-08-23 23:31:00 +00:00
}
2017-01-18 00:42:08 +00:00
var names = isArray ( name ) ? ( isArray ( name [ 0 ] ) ? name : [ name ] ) : Str ( name ) . split ( comaseparator ) ;
2014-05-23 11:03:03 +00:00
for ( var i = 0 , ii = names . length ; i < ii ; i ++ ) {
( function ( name ) {
2017-01-18 00:42:08 +00:00
var names = isArray ( name ) ? name : Str ( name ) . split ( separator ) ,
2014-05-23 11:03:03 +00:00
e = events ,
exist ;
for ( var i = 0 , ii = names . length ; i < ii ; i ++ ) {
e = e . n ;
e = e . hasOwnProperty ( names [ i ] ) && e [ names [ i ] ] || ( e [ names [ i ] ] = { n : { } } ) ;
}
e . f = e . f || [ ] ;
for ( i = 0 , ii = e . f . length ; i < ii ; i ++ ) if ( e . f [ i ] == f ) {
exist = true ;
break ;
}
! exist && e . f . push ( f ) ;
} ( names [ i ] ) ) ;
2013-08-23 23:31:00 +00:00
}
return function ( zIndex ) {
if ( + zIndex == + zIndex ) {
f . zIndex = + zIndex ;
}
} ;
} ;
/ * \
* eve . f
[ method ]
* *
* Returns function that will fire given event with optional arguments .
2014-05-23 11:03:03 +00:00
* Arguments that will be passed to the result function will be also
* concated to the list of final arguments .
| el . onclick = eve . f ( "click" , 1 , 2 ) ;
| eve . on ( "click" , function ( a , b , c ) {
| console . log ( a , b , c ) ; // 1, 2, [event object]
| } ) ;
2013-08-23 23:31:00 +00:00
> Arguments
2014-05-23 11:03:03 +00:00
- event ( string ) event name
- varargs ( … ) and any other arguments
= ( function ) possible event handler function
2013-08-23 23:31:00 +00:00
\ * /
2014-05-23 11:03:03 +00:00
eve . f = function ( event ) {
var attrs = [ ] . slice . call ( arguments , 1 ) ;
return function ( ) {
eve . apply ( null , [ event , null ] . concat ( attrs ) . concat ( [ ] . slice . call ( arguments , 0 ) ) ) ;
} ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* eve . stop
[ method ]
* *
* Is used inside an event handler to stop the event , preventing any subsequent listeners from firing .
\ * /
eve . stop = function ( ) {
stop = 1 ;
} ;
/ * \
* eve . nt
[ method ]
* *
* Could be used inside event handler to figure out actual name of the event .
* *
> Arguments
* *
- subname ( string ) # optional subname of the event
* *
= ( string ) name of the event , if ` subname ` is not specified
* or
= ( boolean ) ` true ` , if current event ’ s name contains ` subname `
\ * /
eve . nt = function ( subname ) {
2017-01-18 00:42:08 +00:00
var cur = isArray ( current _event ) ? current _event . join ( "." ) : current _event ;
2013-08-23 23:31:00 +00:00
if ( subname ) {
2017-01-18 00:42:08 +00:00
return new RegExp ( "(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)" ) . test ( cur ) ;
2013-08-23 23:31:00 +00:00
}
2017-01-18 00:42:08 +00:00
return cur ;
2013-08-23 23:31:00 +00:00
} ;
/ * \
* eve . nts
[ method ]
* *
* Could be used inside event handler to figure out actual name of the event .
* *
* *
= ( array ) names of the event
\ * /
eve . nts = function ( ) {
2017-01-18 00:42:08 +00:00
return isArray ( current _event ) ? current _event : current _event . split ( separator ) ;
2013-08-23 23:31:00 +00:00
} ;
/ * \
* eve . off
[ method ]
* *
* Removes given function from the list of event listeners assigned to given name .
2014-05-23 11:03:03 +00:00
* If no arguments specified all the events will be cleared .
2013-08-23 23:31:00 +00:00
* *
> Arguments
* *
- name ( string ) name of the event , dot ( ` . ` ) or slash ( ` / ` ) separated , with optional wildcards
- f ( function ) event handler function
\ * /
/ * \
* eve . unbind
[ method ]
* *
* See @ eve . off
\ * /
eve . off = eve . unbind = function ( name , f ) {
2014-05-23 11:03:03 +00:00
if ( ! name ) {
eve . _events = events = { n : { } } ;
return ;
}
2017-01-18 00:42:08 +00:00
var names = isArray ( name ) ? ( isArray ( name [ 0 ] ) ? name : [ name ] ) : Str ( name ) . split ( comaseparator ) ;
2014-05-23 11:03:03 +00:00
if ( names . length > 1 ) {
for ( var i = 0 , ii = names . length ; i < ii ; i ++ ) {
eve . off ( names [ i ] , f ) ;
}
return ;
}
2017-01-18 00:42:08 +00:00
names = isArray ( name ) ? name : Str ( name ) . split ( separator ) ;
2014-05-23 11:03:03 +00:00
var e ,
2013-08-23 23:31:00 +00:00
key ,
splice ,
i , ii , j , jj ,
2017-01-18 00:42:08 +00:00
cur = [ events ] ,
inodes = [ ] ;
2013-08-23 23:31:00 +00:00
for ( i = 0 , ii = names . length ; i < ii ; i ++ ) {
for ( j = 0 ; j < cur . length ; j += splice . length - 2 ) {
splice = [ j , 1 ] ;
e = cur [ j ] . n ;
if ( names [ i ] != wildcard ) {
if ( e [ names [ i ] ] ) {
splice . push ( e [ names [ i ] ] ) ;
2017-01-18 00:42:08 +00:00
inodes . unshift ( {
n : e ,
name : names [ i ]
} ) ;
2013-08-23 23:31:00 +00:00
}
} else {
for ( key in e ) if ( e [ has ] ( key ) ) {
splice . push ( e [ key ] ) ;
2017-01-18 00:42:08 +00:00
inodes . unshift ( {
n : e ,
name : key
} ) ;
2013-08-23 23:31:00 +00:00
}
}
cur . splice . apply ( cur , splice ) ;
}
}
for ( i = 0 , ii = cur . length ; i < ii ; i ++ ) {
e = cur [ i ] ;
while ( e . n ) {
if ( f ) {
if ( e . f ) {
for ( j = 0 , jj = e . f . length ; j < jj ; j ++ ) if ( e . f [ j ] == f ) {
e . f . splice ( j , 1 ) ;
break ;
}
! e . f . length && delete e . f ;
}
for ( key in e . n ) if ( e . n [ has ] ( key ) && e . n [ key ] . f ) {
var funcs = e . n [ key ] . f ;
for ( j = 0 , jj = funcs . length ; j < jj ; j ++ ) if ( funcs [ j ] == f ) {
funcs . splice ( j , 1 ) ;
break ;
}
! funcs . length && delete e . n [ key ] . f ;
}
} else {
delete e . f ;
for ( key in e . n ) if ( e . n [ has ] ( key ) && e . n [ key ] . f ) {
delete e . n [ key ] . f ;
}
}
e = e . n ;
}
}
2017-01-18 00:42:08 +00:00
// prune inner nodes in path
prune : for ( i = 0 , ii = inodes . length ; i < ii ; i ++ ) {
e = inodes [ i ] ;
for ( key in e . n [ e . name ] . f ) {
// not empty (has listeners)
continue prune ;
}
for ( key in e . n [ e . name ] . n ) {
// not empty (has children)
continue prune ;
}
// is empty
delete e . n [ e . name ] ;
}
2013-08-23 23:31:00 +00:00
} ;
/ * \
* eve . once
[ method ]
* *
* Binds given event handler with a given name to only run once then unbind itself .
| eve . once ( "login" , f ) ;
| eve ( "login" ) ; // triggers f
| eve ( "login" ) ; // no listeners
* Use @ eve to trigger the listener .
* *
> Arguments
* *
- name ( string ) name of the event , dot ( ` . ` ) or slash ( ` / ` ) separated , with optional wildcards
- f ( function ) event handler function
* *
= ( function ) same return function as @ eve . on
\ * /
eve . once = function ( name , f ) {
var f2 = function ( ) {
2017-01-18 00:42:08 +00:00
eve . off ( name , f2 ) ;
2013-08-23 23:31:00 +00:00
return f . apply ( this , arguments ) ;
} ;
return eve . on ( name , f2 ) ;
} ;
/ * \
* eve . version
[ property ( string ) ]
* *
* Current version of the library .
\ * /
eve . version = version ;
eve . toString = function ( ) {
return "You are running Eve " + version ;
} ;
2014-05-23 11:03:03 +00:00
( typeof module != "undefined" && module . exports ) ? ( module . exports = eve ) : ( typeof define === "function" && define . amd ? ( define ( "eve" , [ ] , function ( ) { return eve ; } ) ) : ( glob . eve = eve ) ) ;
2013-08-23 23:31:00 +00:00
} ) ( this ) ;
2013-09-25 05:52:57 +00:00
( function ( glob , factory ) {
// AMD support
2014-09-17 07:44:54 +00:00
if ( typeof define == "function" && define . amd ) {
2013-09-25 05:52:57 +00:00
// Define as an anonymous module
2014-09-17 07:44:54 +00:00
define ( [ "eve" ] , function ( eve ) {
2013-09-25 05:52:57 +00:00
return factory ( glob , eve ) ;
} ) ;
2017-01-24 02:32:41 +00:00
} else if ( typeof exports != "undefined" ) {
2014-09-17 07:44:54 +00:00
// Next for Node.js or CommonJS
2017-01-24 02:32:41 +00:00
var eve = require ( "eve" ) ;
2014-09-17 07:44:54 +00:00
module . exports = factory ( glob , eve ) ;
2013-09-25 05:52:57 +00:00
} else {
// Browser globals (glob is window)
// Snap adds itself to window
factory ( glob , glob . eve ) ;
}
2014-09-17 07:44:54 +00:00
} ( window || this , function ( window , eve ) {
2017-01-18 00:42:08 +00:00
// Copyright (c) 2017 Adobe Systems Incorporated. All rights reserved.
//
2013-08-23 23:31:00 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2017-01-18 00:42:08 +00:00
//
2013-08-23 23:31:00 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2017-01-18 00:42:08 +00:00
//
2013-08-23 23:31:00 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var mina = ( function ( eve ) {
2013-08-20 09:42:07 +00:00
var animations = { } ,
2013-08-05 08:04:30 +00:00
requestAnimFrame = window . requestAnimationFrame ||
window . webkitRequestAnimationFrame ||
window . mozRequestAnimationFrame ||
window . oRequestAnimationFrame ||
window . msRequestAnimationFrame ||
function ( callback ) {
2017-02-02 01:51:35 +00:00
setTimeout ( callback , 16 , new Date ( ) . getTime ( ) ) ;
return true ;
2013-08-05 08:04:30 +00:00
} ,
2017-02-02 01:51:35 +00:00
requestID ,
2013-08-05 08:04:30 +00:00
isArray = Array . isArray || function ( a ) {
return a instanceof Array ||
Object . prototype . toString . call ( a ) == "[object Array]" ;
} ,
2013-08-16 02:56:19 +00:00
idgen = 0 ,
idprefix = "M" + ( + new Date ) . toString ( 36 ) ,
ID = function ( ) {
return idprefix + ( idgen ++ ) . toString ( 36 ) ;
} ,
2013-08-05 08:04:30 +00:00
diff = function ( a , b , A , B ) {
if ( isArray ( a ) ) {
res = [ ] ;
for ( var i = 0 , ii = a . length ; i < ii ; i ++ ) {
res [ i ] = diff ( a [ i ] , b , A [ i ] , B ) ;
}
return res ;
}
var dif = ( A - a ) / ( B - b ) ;
return function ( bb ) {
return a + dif * ( bb - b ) ;
} ;
} ,
2013-10-25 22:53:09 +00:00
timer = Date . now || function ( ) {
2013-08-05 08:04:30 +00:00
return + new Date ;
} ,
2013-08-15 08:29:47 +00:00
sta = function ( val ) {
var a = this ;
if ( val == null ) {
return a . s ;
2013-08-05 08:04:30 +00:00
}
2013-08-15 08:29:47 +00:00
var ds = a . s - val ;
a . b += a . dur * ds ;
a . B += a . dur * ds ;
a . s = val ;
2013-08-05 08:04:30 +00:00
} ,
2013-08-15 08:29:47 +00:00
speed = function ( val ) {
var a = this ;
if ( val == null ) {
return a . spd ;
2013-08-05 08:04:30 +00:00
}
2013-08-15 08:29:47 +00:00
a . spd = val ;
2013-08-05 08:04:30 +00:00
} ,
2013-08-15 08:29:47 +00:00
duration = function ( val ) {
var a = this ;
if ( val == null ) {
return a . dur ;
}
a . s = a . s * val / a . dur ;
a . dur = val ;
} ,
2013-08-20 09:42:07 +00:00
stopit = function ( ) {
var a = this ;
delete animations [ a . id ] ;
2014-03-07 06:16:58 +00:00
a . update ( ) ;
2013-08-20 09:42:07 +00:00
eve ( "mina.stop." + a . id , a ) ;
} ,
2013-09-19 11:03:24 +00:00
pause = function ( ) {
var a = this ;
if ( a . pdif ) {
return ;
}
delete animations [ a . id ] ;
2014-03-07 06:16:58 +00:00
a . update ( ) ;
2013-09-19 11:03:24 +00:00
a . pdif = a . get ( ) - a . b ;
} ,
resume = function ( ) {
var a = this ;
if ( ! a . pdif ) {
return ;
}
a . b = a . get ( ) - a . pdif ;
delete a . pdif ;
animations [ a . id ] = a ;
2017-02-02 01:51:35 +00:00
frame ( ) ;
2013-09-19 11:03:24 +00:00
} ,
2014-03-07 06:16:58 +00:00
update = function ( ) {
var a = this ,
res ;
if ( isArray ( a . start ) ) {
res = [ ] ;
for ( var j = 0 , jj = a . start . length ; j < jj ; j ++ ) {
res [ j ] = + a . start [ j ] +
( a . end [ j ] - a . start [ j ] ) * a . easing ( a . s ) ;
}
} else {
res = + a . start + ( a . end - a . start ) * a . easing ( a . s ) ;
}
a . set ( res ) ;
} ,
2017-02-02 01:51:35 +00:00
frame = function ( timeStamp ) {
// Manual invokation?
if ( ! timeStamp ) {
// Frame loop stopped?
if ( ! requestID ) {
// Start frame loop...
requestID = requestAnimFrame ( frame ) ;
}
return ;
}
2013-08-20 09:42:07 +00:00
var len = 0 ;
for ( var i in animations ) if ( animations . hasOwnProperty ( i ) ) {
2013-08-15 08:29:47 +00:00
var a = animations [ i ] ,
b = a . get ( ) ,
res ;
2013-08-20 09:42:07 +00:00
len ++ ;
2013-08-15 08:29:47 +00:00
a . s = ( b - a . b ) / ( a . dur / a . spd ) ;
if ( a . s >= 1 ) {
2013-08-20 09:42:07 +00:00
delete animations [ i ] ;
2013-08-15 08:29:47 +00:00
a . s = 1 ;
2013-08-20 09:42:07 +00:00
len -- ;
2013-11-18 12:02:11 +00:00
( function ( a ) {
setTimeout ( function ( ) {
eve ( "mina.finish." + a . id , a ) ;
} ) ;
} ( a ) ) ;
2013-08-05 08:04:30 +00:00
}
2014-03-07 06:16:58 +00:00
a . update ( ) ;
2013-08-05 08:04:30 +00:00
}
2017-02-02 01:51:35 +00:00
requestID = len ? requestAnimFrame ( frame ) : false ;
2013-08-05 08:04:30 +00:00
} ,
2013-08-23 23:31:00 +00:00
/ * \
* mina
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Generic animation of numbers
2013-08-23 23:31:00 +00:00
* *
2013-10-14 11:59:34 +00:00
- a ( number ) start _slave _ number
- A ( number ) end _slave _ number
2013-11-18 12:02:11 +00:00
- b ( number ) start _master _ number ( start time in general case )
2017-01-18 00:42:08 +00:00
- B ( number ) end _master _ number ( end time in general case )
2013-10-14 11:59:34 +00:00
- get ( function ) getter of _master _ number ( see @ mina . time )
- set ( function ) setter of _slave _ number
2013-08-23 23:31:00 +00:00
- easing ( function ) # optional easing function , default is @ mina . linear
= ( object ) animation descriptor
o {
o id ( string ) animation id ,
2013-10-14 11:59:34 +00:00
o start ( number ) start _slave _ number ,
o end ( number ) end _slave _ number ,
o b ( number ) start _master _ number ,
2013-08-23 23:31:00 +00:00
o s ( number ) animation status ( 0. . 1 ) ,
o dur ( number ) animation duration ,
o spd ( number ) animation speed ,
2013-10-14 11:59:34 +00:00
o get ( function ) getter of _master _ number ( see @ mina . time ) ,
o set ( function ) setter of _slave _ number ,
2013-08-23 23:31:00 +00:00
o easing ( function ) easing function , default is @ mina . linear ,
o status ( function ) status getter / setter ,
o speed ( function ) speed getter / setter ,
o duration ( function ) duration getter / setter ,
o stop ( function ) animation stopper
2014-03-07 06:16:58 +00:00
o pause ( function ) pauses the animation
o resume ( function ) resumes the animation
o update ( function ) calles setter with the right value of the animation
2013-08-23 23:31:00 +00:00
o }
\ * /
2013-08-15 08:29:47 +00:00
mina = function ( a , A , b , B , get , set , easing ) {
2013-08-05 08:04:30 +00:00
var anim = {
2013-08-16 02:56:19 +00:00
id : ID ( ) ,
2013-08-15 08:29:47 +00:00
start : a ,
end : A ,
2013-08-05 08:04:30 +00:00
b : b ,
2013-08-15 08:29:47 +00:00
s : 0 ,
dur : B - b ,
spd : 1 ,
get : get ,
set : set ,
easing : easing || mina . linear ,
status : sta ,
speed : speed ,
2013-08-20 09:42:07 +00:00
duration : duration ,
2013-09-19 11:03:24 +00:00
stop : stopit ,
pause : pause ,
2014-03-07 06:16:58 +00:00
resume : resume ,
update : update
2013-08-05 08:04:30 +00:00
} ;
2013-08-20 09:42:07 +00:00
animations [ anim . id ] = anim ;
var len = 0 , i ;
for ( i in animations ) if ( animations . hasOwnProperty ( i ) ) {
len ++ ;
if ( len == 2 ) {
break ;
}
}
2017-02-02 01:51:35 +00:00
len == 1 && frame ( ) ;
2013-08-05 08:04:30 +00:00
return anim ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . time
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns the current time . Equivalent to :
2013-08-23 23:31:00 +00:00
| function ( ) {
| return ( new Date ) . getTime ( ) ;
| }
\ * /
2013-08-15 08:29:47 +00:00
mina . time = timer ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . getById
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an animation by its id
- id ( string ) animation ' s id
2013-08-23 23:31:00 +00:00
= ( object ) See @ mina
\ * /
2013-08-20 09:42:07 +00:00
mina . getById = function ( id ) {
2013-09-19 11:03:24 +00:00
return animations [ id ] || null ;
2013-08-20 09:42:07 +00:00
} ;
2013-08-15 08:29:47 +00:00
2013-08-23 23:31:00 +00:00
/ * \
* mina . linear
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Default linear easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-05 08:04:30 +00:00
mina . linear = function ( n ) {
return n ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . easeout
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Easeout easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-05 08:04:30 +00:00
mina . easeout = function ( n ) {
return Math . pow ( n , 1.7 ) ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . easein
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Easein easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-15 08:29:47 +00:00
mina . easein = function ( n ) {
2013-08-05 08:04:30 +00:00
return Math . pow ( n , . 48 ) ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . easeinout
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Easeinout easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-05 08:04:30 +00:00
mina . easeinout = function ( n ) {
2013-09-13 12:51:01 +00:00
if ( n == 1 ) {
return 1 ;
}
if ( n == 0 ) {
return 0 ;
}
2013-08-05 08:04:30 +00:00
var q = . 48 - n / 1.04 ,
Q = Math . sqrt ( . 1734 + q * q ) ,
x = Q - q ,
X = Math . pow ( Math . abs ( x ) , 1 / 3 ) * ( x < 0 ? - 1 : 1 ) ,
y = - Q - q ,
Y = Math . pow ( Math . abs ( y ) , 1 / 3 ) * ( y < 0 ? - 1 : 1 ) ,
t = X + Y + . 5 ;
return ( 1 - t ) * 3 * t * t + t * t * t ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . backin
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Backin easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-05 08:04:30 +00:00
mina . backin = function ( n ) {
2013-09-13 12:51:01 +00:00
if ( n == 1 ) {
return 1 ;
}
2013-08-05 08:04:30 +00:00
var s = 1.70158 ;
return n * n * ( ( s + 1 ) * n - s ) ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . backout
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Backout easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-05 08:04:30 +00:00
mina . backout = function ( n ) {
2013-09-13 12:51:01 +00:00
if ( n == 0 ) {
return 0 ;
}
2013-08-05 08:04:30 +00:00
n = n - 1 ;
var s = 1.70158 ;
return n * n * ( ( s + 1 ) * n + s ) + 1 ;
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . elastic
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Elastic easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-05 08:04:30 +00:00
mina . elastic = function ( n ) {
if ( n == ! ! n ) {
return n ;
}
2013-08-15 08:29:47 +00:00
return Math . pow ( 2 , - 10 * n ) * Math . sin ( ( n - . 075 ) *
( 2 * Math . PI ) / . 3 ) + 1 ;
2013-08-05 08:04:30 +00:00
} ;
2013-08-23 23:31:00 +00:00
/ * \
* mina . bounce
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Bounce easing
2013-08-23 23:31:00 +00:00
- n ( number ) input 0. . 1
= ( number ) output 0. . 1
\ * /
2013-08-05 08:04:30 +00:00
mina . bounce = function ( n ) {
var s = 7.5625 ,
p = 2.75 ,
l ;
2017-01-24 02:32:41 +00:00
if ( n < 1 / p ) {
2013-08-05 08:04:30 +00:00
l = s * n * n ;
} else {
2017-01-24 02:32:41 +00:00
if ( n < 2 / p ) {
n -= 1.5 / p ;
2013-08-05 08:04:30 +00:00
l = s * n * n + . 75 ;
} else {
2017-01-24 02:32:41 +00:00
if ( n < 2.5 / p ) {
n -= 2.25 / p ;
2013-08-05 08:04:30 +00:00
l = s * n * n + . 9375 ;
} else {
2017-01-24 02:32:41 +00:00
n -= 2.625 / p ;
2013-08-05 08:04:30 +00:00
l = s * n * n + . 984375 ;
}
}
}
return l ;
} ;
2013-09-25 05:52:57 +00:00
window . mina = mina ;
2013-08-05 08:04:30 +00:00
return mina ;
2013-08-20 09:42:07 +00:00
} ) ( typeof eve == "undefined" ? function ( ) { } : eve ) ;
2017-01-18 00:42:08 +00:00
2017-02-03 23:39:45 +00:00
// Copyright (c) 2013 - 2017 Adobe Systems Incorporated. All rights reserved.
2016-06-09 12:02:46 +00:00
//
2013-08-20 09:42:07 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2016-06-09 12:02:46 +00:00
//
2013-08-20 09:42:07 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2016-06-09 12:02:46 +00:00
//
2013-08-20 09:42:07 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2014-09-17 07:44:54 +00:00
var Snap = ( function ( root ) {
2017-02-06 01:05:34 +00:00
Snap . version = "0.5.1" ;
2013-08-22 10:00:40 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap
2013-08-22 10:00:40 +00:00
[ method ]
* *
2013-10-20 15:46:25 +00:00
* Creates a drawing surface or wraps existing SVG element .
2013-08-22 10:00:40 +00:00
* *
- width ( number | string ) width of surface
- height ( number | string ) height of surface
* or
2013-10-14 11:59:34 +00:00
- DOM ( SVGElement ) element to be wrapped into Snap structure
2013-08-22 10:00:40 +00:00
* or
2014-05-06 00:13:22 +00:00
- array ( array ) array of elements ( will return set of elements )
* or
2013-08-22 10:00:40 +00:00
- query ( string ) CSS query selector
= ( object ) @ Element
\ * /
2013-09-25 05:52:57 +00:00
function Snap ( w , h ) {
2013-08-05 08:04:30 +00:00
if ( w ) {
2014-10-28 10:48:17 +00:00
if ( w . nodeType ) {
2013-08-09 12:13:22 +00:00
return wrap ( w ) ;
2013-08-05 08:04:30 +00:00
}
2014-05-06 00:13:22 +00:00
if ( is ( w , "array" ) && Snap . set ) {
return Snap . set . apply ( Snap , w ) ;
}
2013-08-05 08:04:30 +00:00
if ( w instanceof Element ) {
return w ;
}
if ( h == null ) {
2017-02-07 02:25:01 +00:00
try {
2017-02-06 01:05:34 +00:00
w = glob . doc . querySelector ( String ( w ) ) ;
return wrap ( w ) ;
2017-02-07 02:25:01 +00:00
} catch ( e ) {
return null ;
}
2013-08-05 08:04:30 +00:00
}
}
w = w == null ? "100%" : w ;
h = h == null ? "100%" : h ;
return new Paper ( w , h ) ;
}
2013-09-25 05:52:57 +00:00
Snap . toString = function ( ) {
return "Snap v" + this . version ;
2013-08-05 08:04:30 +00:00
} ;
2013-09-25 05:52:57 +00:00
Snap . _ = { } ;
2013-08-05 08:04:30 +00:00
var glob = {
2014-09-17 07:44:54 +00:00
win : root . window ,
doc : root . window . document
2013-08-05 08:04:30 +00:00
} ;
2013-09-25 05:52:57 +00:00
Snap . _ . glob = glob ;
2013-08-05 08:04:30 +00:00
var has = "hasOwnProperty" ,
Str = String ,
toFloat = parseFloat ,
toInt = parseInt ,
math = Math ,
mmax = math . max ,
mmin = math . min ,
abs = math . abs ,
pow = math . pow ,
PI = math . PI ,
round = math . round ,
E = "" ,
S = " " ,
objectToString = Object . prototype . toString ,
ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i ,
2013-09-16 06:55:33 +00:00
colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\))\s*$/i ,
2013-08-05 08:04:30 +00:00
bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/ ,
2014-07-31 08:37:34 +00:00
separator = Snap . _ . separator = /[,\s]+/ ,
whitespace = /[\s]/g ,
commaSpaces = /[\s]*,[\s]*/ ,
2013-08-05 08:04:30 +00:00
hsrg = { hs : 1 , rg : 1 } ,
2014-07-31 08:37:34 +00:00
pathCommand = /([a-z])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?[\s]*)+)/ig ,
tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\s]*,?[\s]*)+)/ig ,
2017-01-18 00:42:08 +00:00
pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\s]*,?[\s]*/ig ,
2013-08-05 08:04:30 +00:00
idgen = 0 ,
idprefix = "S" + ( + new Date ) . toString ( 36 ) ,
2014-08-04 11:22:04 +00:00
ID = function ( el ) {
return ( el && el . type ? el . type : E ) + idprefix + ( idgen ++ ) . toString ( 36 ) ;
2013-08-05 08:04:30 +00:00
} ,
xlink = "http://www.w3.org/1999/xlink" ,
2013-11-18 00:17:17 +00:00
xmlns = "http://www.w3.org/2000/svg" ,
2013-12-23 01:26:40 +00:00
hub = { } ,
2017-01-31 23:47:28 +00:00
/ * \
2017-02-05 01:17:21 +00:00
* Snap . url
2017-01-31 23:47:28 +00:00
[ method ]
* *
* Wraps path into ` "url('<path>')" ` .
- value ( string ) path
= ( string ) wrapped path
\ * /
2013-12-23 01:26:40 +00:00
URL = Snap . url = function ( url ) {
return "url('#" + url + "')" ;
} ;
2013-08-05 08:04:30 +00:00
function $ ( el , attr ) {
if ( attr ) {
2014-04-18 00:31:07 +00:00
if ( el == "#text" ) {
2014-10-28 10:48:17 +00:00
el = glob . doc . createTextNode ( attr . text || attr [ "#text" ] || "" ) ;
}
if ( el == "#comment" ) {
el = glob . doc . createComment ( attr . text || attr [ "#text" ] || "" ) ;
2014-04-18 00:31:07 +00:00
}
2013-08-05 08:04:30 +00:00
if ( typeof el == "string" ) {
el = $ ( el ) ;
}
if ( typeof attr == "string" ) {
2014-10-28 10:48:17 +00:00
if ( el . nodeType == 1 ) {
if ( attr . substring ( 0 , 6 ) == "xlink:" ) {
return el . getAttributeNS ( xlink , attr . substring ( 6 ) ) ;
}
if ( attr . substring ( 0 , 4 ) == "xml:" ) {
return el . getAttributeNS ( xmlns , attr . substring ( 4 ) ) ;
}
return el . getAttribute ( attr ) ;
} else if ( attr == "text" ) {
return el . nodeValue ;
} else {
return null ;
2013-11-18 00:17:17 +00:00
}
2013-08-05 08:04:30 +00:00
}
2014-10-28 10:48:17 +00:00
if ( el . nodeType == 1 ) {
for ( var key in attr ) if ( attr [ has ] ( key ) ) {
var val = Str ( attr [ key ] ) ;
if ( val ) {
if ( key . substring ( 0 , 6 ) == "xlink:" ) {
el . setAttributeNS ( xlink , key . substring ( 6 ) , val ) ;
} else if ( key . substring ( 0 , 4 ) == "xml:" ) {
el . setAttributeNS ( xmlns , key . substring ( 4 ) , val ) ;
} else {
el . setAttribute ( key , val ) ;
}
2013-08-05 08:04:30 +00:00
} else {
2014-10-28 10:48:17 +00:00
el . removeAttribute ( key ) ;
2013-08-05 08:04:30 +00:00
}
}
2014-10-28 10:48:17 +00:00
} else if ( "text" in attr ) {
el . nodeValue = attr . text ;
2013-08-05 08:04:30 +00:00
}
} else {
2013-11-18 00:17:17 +00:00
el = glob . doc . createElementNS ( xmlns , el ) ;
2013-08-05 08:04:30 +00:00
}
return el ;
}
2013-09-25 05:52:57 +00:00
Snap . _ . $ = $ ;
Snap . _ . id = ID ;
2013-08-05 08:04:30 +00:00
function getAttrs ( el ) {
var attrs = el . attributes ,
name ,
out = { } ;
for ( var i = 0 ; i < attrs . length ; i ++ ) {
if ( attrs [ i ] . namespaceURI == xlink ) {
name = "xlink:" ;
} else {
name = "" ;
}
name += attrs [ i ] . name ;
out [ name ] = attrs [ i ] . textContent ;
}
return out ;
}
function is ( o , type ) {
type = Str . prototype . toLowerCase . call ( type ) ;
if ( type == "finite" ) {
2013-10-25 22:53:09 +00:00
return isFinite ( o ) ;
2013-08-05 08:04:30 +00:00
}
if ( type == "array" &&
( o instanceof Array || Array . isArray && Array . isArray ( o ) ) ) {
return true ;
}
2017-01-24 02:32:41 +00:00
return type == "null" && o === null ||
type == typeof o && o !== null ||
type == "object" && o === Object ( o ) ||
2013-08-05 08:04:30 +00:00
objectToString . call ( o ) . slice ( 8 , - 1 ) . toLowerCase ( ) == type ;
}
2013-08-15 08:29:47 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . format
2013-08-15 08:29:47 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Replaces construction of type ` {<name>} ` to the corresponding argument
2013-08-15 08:29:47 +00:00
* *
- token ( string ) string to format
2013-10-14 11:59:34 +00:00
- json ( object ) object which properties are used as a replacement
= ( string ) formatted string
2013-08-15 08:29:47 +00:00
> Usage
2013-10-14 11:59:34 +00:00
| // this draws a rectangular shape equivalent to "M10,20h40v50h-40z"
2013-09-25 05:52:57 +00:00
| paper . path ( Snap . format ( "M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z" , {
2013-08-15 08:29:47 +00:00
| x : 10 ,
| y : 20 ,
| dim : {
| width : 40 ,
| height : 50 ,
| "negative width" : - 40
| }
| } ) ) ;
\ * /
2013-09-25 05:52:57 +00:00
Snap . format = ( function ( ) {
2013-08-15 08:29:47 +00:00
var tokenRegex = /\{([^\}]+)\}/g ,
objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g , // matches .xxxxx or ["xxxxx"] to run over object properties
replacer = function ( all , key , obj ) {
var res = obj ;
key . replace ( objNotationRegex , function ( all , name , quote , quotedName , isFunc ) {
name = name || quotedName ;
if ( res ) {
if ( name in res ) {
res = res [ name ] ;
}
typeof res == "function" && isFunc && ( res = res ( ) ) ;
}
} ) ;
res = ( res == null || res == obj ? all : res ) + "" ;
return res ;
} ;
return function ( str , obj ) {
return Str ( str ) . replace ( tokenRegex , function ( all , key ) {
return replacer ( all , key , obj ) ;
} ) ;
} ;
} ) ( ) ;
2013-08-05 08:04:30 +00:00
function clone ( obj ) {
if ( typeof obj == "function" || Object ( obj ) !== obj ) {
return obj ;
}
var res = new obj . constructor ;
for ( var key in obj ) if ( obj [ has ] ( key ) ) {
res [ key ] = clone ( obj [ key ] ) ;
}
return res ;
}
2013-09-25 05:52:57 +00:00
Snap . _ . clone = clone ;
2013-08-05 08:04:30 +00:00
function repush ( array , item ) {
for ( var i = 0 , ii = array . length ; i < ii ; i ++ ) if ( array [ i ] === item ) {
return array . push ( array . splice ( i , 1 ) [ 0 ] ) ;
}
}
function cacher ( f , scope , postprocessor ) {
function newf ( ) {
var arg = Array . prototype . slice . call ( arguments , 0 ) ,
args = arg . join ( "\u2400" ) ,
cache = newf . cache = newf . cache || { } ,
count = newf . count = newf . count || [ ] ;
if ( cache [ has ] ( args ) ) {
repush ( count , args ) ;
return postprocessor ? postprocessor ( cache [ args ] ) : cache [ args ] ;
}
count . length >= 1e3 && delete cache [ count . shift ( ) ] ;
count . push ( args ) ;
cache [ args ] = f . apply ( scope , arg ) ;
return postprocessor ? postprocessor ( cache [ args ] ) : cache [ args ] ;
}
return newf ;
}
2013-09-25 05:52:57 +00:00
Snap . _ . cacher = cacher ;
2013-09-19 11:03:24 +00:00
function angle ( x1 , y1 , x2 , y2 , x3 , y3 ) {
if ( x3 == null ) {
var x = x1 - x2 ,
y = y1 - y2 ;
if ( ! x && ! y ) {
return 0 ;
}
return ( 180 + math . atan2 ( - y , - x ) * 180 / PI + 360 ) % 360 ;
} else {
return angle ( x1 , y1 , x3 , y3 ) - angle ( x2 , y2 , x3 , y3 ) ;
}
}
2013-08-05 08:04:30 +00:00
function rad ( deg ) {
return deg % 360 * PI / 180 ;
}
function deg ( rad ) {
return rad * 180 / PI % 360 ;
}
function x _y ( ) {
return this . x + S + this . y ;
}
function x _y _w _h ( ) {
return this . x + S + this . y + S + this . width + " \xd7 " + this . height ;
}
/ * \
2013-09-25 05:52:57 +00:00
* Snap . rad
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Transform angle to radians
- deg ( number ) angle in degrees
2013-10-14 11:59:34 +00:00
= ( number ) angle in radians
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . rad = rad ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . deg
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Transform angle to degrees
2013-10-14 11:59:34 +00:00
- rad ( number ) angle in radians
= ( number ) angle in degrees
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . deg = deg ;
2014-10-28 10:48:17 +00:00
/ * \
* Snap . sin
[ method ]
* *
* Equivalent to ` Math.sin() ` only works with degrees , not radians .
- angle ( number ) angle in degrees
= ( number ) sin
\ * /
Snap . sin = function ( angle ) {
return math . sin ( Snap . rad ( angle ) ) ;
} ;
/ * \
* Snap . tan
[ method ]
* *
* Equivalent to ` Math.tan() ` only works with degrees , not radians .
- angle ( number ) angle in degrees
= ( number ) tan
\ * /
Snap . tan = function ( angle ) {
return math . tan ( Snap . rad ( angle ) ) ;
} ;
/ * \
* Snap . cos
[ method ]
* *
* Equivalent to ` Math.cos() ` only works with degrees , not radians .
- angle ( number ) angle in degrees
= ( number ) cos
\ * /
Snap . cos = function ( angle ) {
return math . cos ( Snap . rad ( angle ) ) ;
} ;
/ * \
* Snap . asin
[ method ]
* *
* Equivalent to ` Math.asin() ` only works with degrees , not radians .
- num ( number ) value
= ( number ) asin in degrees
\ * /
Snap . asin = function ( num ) {
return Snap . deg ( math . asin ( num ) ) ;
} ;
/ * \
* Snap . acos
[ method ]
* *
* Equivalent to ` Math.acos() ` only works with degrees , not radians .
- num ( number ) value
= ( number ) acos in degrees
\ * /
Snap . acos = function ( num ) {
return Snap . deg ( math . acos ( num ) ) ;
} ;
/ * \
* Snap . atan
[ method ]
* *
* Equivalent to ` Math.atan() ` only works with degrees , not radians .
- num ( number ) value
= ( number ) atan in degrees
\ * /
Snap . atan = function ( num ) {
return Snap . deg ( math . atan ( num ) ) ;
} ;
/ * \
* Snap . atan2
[ method ]
* *
* Equivalent to ` Math.atan2() ` only works with degrees , not radians .
- num ( number ) value
= ( number ) atan2 in degrees
\ * /
Snap . atan2 = function ( num ) {
return Snap . deg ( math . atan2 ( num ) ) ;
} ;
2013-09-19 11:03:24 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . angle
2013-09-19 11:03:24 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an angle between two or three points
2013-09-19 11:03:24 +00:00
- x1 ( number ) x coord of first point
- y1 ( number ) y coord of first point
- x2 ( number ) x coord of second point
- y2 ( number ) y coord of second point
- x3 ( number ) # optional x coord of third point
- y3 ( number ) # optional y coord of third point
2013-10-14 11:59:34 +00:00
= ( number ) angle in degrees
2013-09-19 11:03:24 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . angle = angle ;
2014-10-28 10:48:17 +00:00
/ * \
* Snap . len
[ method ]
* *
* Returns distance between two points
- x1 ( number ) x coord of first point
- y1 ( number ) y coord of first point
- x2 ( number ) x coord of second point
- y2 ( number ) y coord of second point
= ( number ) distance
\ * /
Snap . len = function ( x1 , y1 , x2 , y2 ) {
return Math . sqrt ( Snap . len2 ( x1 , y1 , x2 , y2 ) ) ;
} ;
/ * \
* Snap . len2
[ method ]
* *
* Returns squared distance between two points
- x1 ( number ) x coord of first point
- y1 ( number ) y coord of first point
- x2 ( number ) x coord of second point
- y2 ( number ) y coord of second point
= ( number ) distance
\ * /
Snap . len2 = function ( x1 , y1 , x2 , y2 ) {
return ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) ;
} ;
/ * \
* Snap . closestPoint
[ method ]
* *
* Returns closest point to a given one on a given path .
- path ( Element ) path element
- x ( number ) x coord of a point
- y ( number ) y coord of a point
= ( object ) in format
{
x ( number ) x coord of the point on the path
y ( number ) y coord of the point on the path
length ( number ) length of the path to the point
distance ( number ) distance from the given point to the path
}
\ * /
// Copied from http://bl.ocks.org/mbostock/8027637
Snap . closestPoint = function ( path , x , y ) {
function distance2 ( p ) {
var dx = p . x - x ,
dy = p . y - y ;
return dx * dx + dy * dy ;
}
var pathNode = path . node ,
pathLength = pathNode . getTotalLength ( ) ,
precision = pathLength / pathNode . pathSegList . numberOfItems * . 125 ,
best ,
bestLength ,
bestDistance = Infinity ;
// linear scan for coarse approximation
for ( var scan , scanLength = 0 , scanDistance ; scanLength <= pathLength ; scanLength += precision ) {
if ( ( scanDistance = distance2 ( scan = pathNode . getPointAtLength ( scanLength ) ) ) < bestDistance ) {
2017-01-24 02:32:41 +00:00
best = scan ;
bestLength = scanLength ;
bestDistance = scanDistance ;
2014-10-28 10:48:17 +00:00
}
}
// binary search for precise estimate
precision *= . 5 ;
while ( precision > . 5 ) {
var before ,
after ,
beforeLength ,
afterLength ,
beforeDistance ,
afterDistance ;
if ( ( beforeLength = bestLength - precision ) >= 0 && ( beforeDistance = distance2 ( before = pathNode . getPointAtLength ( beforeLength ) ) ) < bestDistance ) {
2017-01-24 02:32:41 +00:00
best = before ;
bestLength = beforeLength ;
bestDistance = beforeDistance ;
2014-10-28 10:48:17 +00:00
} else if ( ( afterLength = bestLength + precision ) <= pathLength && ( afterDistance = distance2 ( after = pathNode . getPointAtLength ( afterLength ) ) ) < bestDistance ) {
2017-01-24 02:32:41 +00:00
best = after ;
bestLength = afterLength ;
bestDistance = afterDistance ;
2014-10-28 10:48:17 +00:00
} else {
precision *= . 5 ;
}
}
best = {
x : best . x ,
y : best . y ,
length : bestLength ,
distance : Math . sqrt ( bestDistance )
} ;
return best ;
}
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . is
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Handy replacement for the ` typeof ` operator
2013-08-05 08:04:30 +00:00
- o ( … ) any object or primitive
2013-10-14 11:59:34 +00:00
- type ( string ) name of the type , e . g . , ` string ` , ` function ` , ` number ` , etc .
= ( boolean ) ` true ` if given value is of given type
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . is = is ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . snapTo
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Snaps given value to given grid
2013-08-05 08:04:30 +00:00
- values ( array | number ) given array of values or step of the grid
- value ( number ) value to adjust
2013-10-14 11:59:34 +00:00
- tolerance ( number ) # optional maximum distance to the target value that would trigger the snap . Default is ` 10 ` .
= ( number ) adjusted value
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . snapTo = function ( values , value , tolerance ) {
2013-08-05 08:04:30 +00:00
tolerance = is ( tolerance , "finite" ) ? tolerance : 10 ;
if ( is ( values , "array" ) ) {
var i = values . length ;
while ( i -- ) if ( abs ( values [ i ] - value ) <= tolerance ) {
return values [ i ] ;
}
} else {
values = + values ;
var rem = value % values ;
if ( rem < tolerance ) {
return value - rem ;
}
if ( rem > values - tolerance ) {
return value - rem + values ;
}
}
return value ;
} ;
// Colour
/ * \
2013-09-25 05:52:57 +00:00
* Snap . getRGB
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Parses color string as RGB object
- color ( string ) color string in one of the following formats :
2013-08-05 08:04:30 +00:00
# < ul >
2013-10-14 11:59:34 +00:00
# < li > Color 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 color : ( < 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 color : ( < 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 >
2013-09-17 06:33:21 +00:00
# < li > rgba ( • • • , • • • , • • • , • • • ) — also with opacity < / l i >
2013-10-14 11:59:34 +00:00
# < li > rgb ( • • • % , • • • % , • • • % ) — same as above , but in % : ( < code > rgb ( 100 % , & nbsp ; 175 % , & nbsp ; 0 % ) < / c o d e > ) < / l i >
2013-09-17 06:33:21 +00:00
# < li > rgba ( • • • % , • • • % , • • • % , • • • % ) — also with opacity < / l i >
2013-10-14 11:59:34 +00:00
# < li > hsb ( • • • , • • • , • • • ) — hue , saturation and brightness values : ( < code > hsb ( 0.5 , & nbsp ; 0.25 , & nbsp ; 1 ) < / c o d e > ) < / l i >
2013-09-17 06:33:21 +00:00
# < li > hsba ( • • • , • • • , • • • , • • • ) — also with opacity < / l i >
2013-08-05 08:04:30 +00:00
# < li > hsb ( • • • % , • • • % , • • • % ) — same as above , but in % < / l i >
2013-09-17 06:33:21 +00:00
# < li > hsba ( • • • % , • • • % , • • • % , • • • % ) — also with opacity < / l i >
2013-10-14 11:59:34 +00:00
# < li > hsl ( • • • , • • • , • • • ) — hue , saturation and luminosity values : ( < code > hsb ( 0.5 , & nbsp ; 0.25 , & nbsp ; 0.5 ) < / c o d e > ) < / l i >
2013-09-17 06:33:21 +00:00
# < li > hsla ( • • • , • • • , • • • , • • • ) — also with opacity < / l i >
# < li > hsl ( • • • % , • • • % , • • • % ) — same as above , but in % < / l i >
# < li > hsla ( • • • % , • • • % , • • • % , • • • % ) — also with opacity < / l i >
2013-08-05 08:04:30 +00:00
# < / u l >
2013-09-17 06:33:21 +00:00
* Note that ` % ` can be used any time : ` rgb(20%, 255, 50%) ` .
2013-10-14 11:59:34 +00:00
= ( object ) RGB object in the following format :
2013-08-05 08:04:30 +00:00
o {
o r ( number ) red ,
o g ( number ) green ,
2013-10-14 11:59:34 +00:00
o b ( number ) blue ,
2013-08-05 08:04:30 +00:00
o hex ( string ) color in HTML / CSS format : # • • • • • • ,
2013-10-14 11:59:34 +00:00
o error ( boolean ) true if string can ' t be parsed
2013-08-05 08:04:30 +00:00
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . getRGB = cacher ( function ( colour ) {
2013-08-05 08:04:30 +00:00
if ( ! colour || ! ! ( ( colour = Str ( colour ) ) . indexOf ( "-" ) + 1 ) ) {
return { r : - 1 , g : - 1 , b : - 1 , hex : "none" , error : 1 , toString : rgbtoString } ;
}
if ( colour == "none" ) {
return { r : - 1 , g : - 1 , b : - 1 , hex : "none" , toString : rgbtoString } ;
}
! ( hsrg [ has ] ( colour . toLowerCase ( ) . substring ( 0 , 2 ) ) || colour . charAt ( ) == "#" ) && ( colour = toHex ( colour ) ) ;
2013-09-11 12:25:30 +00:00
if ( ! colour ) {
return { r : - 1 , g : - 1 , b : - 1 , hex : "none" , error : 1 , toString : rgbtoString } ;
}
2013-08-05 08:04:30 +00:00
var res ,
red ,
green ,
blue ,
opacity ,
t ,
values ,
rgb = colour . match ( colourRegExp ) ;
if ( rgb ) {
if ( rgb [ 2 ] ) {
blue = toInt ( rgb [ 2 ] . substring ( 5 ) , 16 ) ;
green = toInt ( rgb [ 2 ] . substring ( 3 , 5 ) , 16 ) ;
red = toInt ( rgb [ 2 ] . substring ( 1 , 3 ) , 16 ) ;
}
if ( rgb [ 3 ] ) {
blue = toInt ( ( t = rgb [ 3 ] . charAt ( 3 ) ) + t , 16 ) ;
green = toInt ( ( t = rgb [ 3 ] . charAt ( 2 ) ) + t , 16 ) ;
red = toInt ( ( t = rgb [ 3 ] . charAt ( 1 ) ) + t , 16 ) ;
}
if ( rgb [ 4 ] ) {
values = rgb [ 4 ] . split ( commaSpaces ) ;
red = toFloat ( values [ 0 ] ) ;
values [ 0 ] . slice ( - 1 ) == "%" && ( red *= 2.55 ) ;
green = toFloat ( values [ 1 ] ) ;
values [ 1 ] . slice ( - 1 ) == "%" && ( green *= 2.55 ) ;
blue = toFloat ( values [ 2 ] ) ;
values [ 2 ] . slice ( - 1 ) == "%" && ( blue *= 2.55 ) ;
rgb [ 1 ] . toLowerCase ( ) . slice ( 0 , 4 ) == "rgba" && ( opacity = toFloat ( values [ 3 ] ) ) ;
values [ 3 ] && values [ 3 ] . slice ( - 1 ) == "%" && ( opacity /= 100 ) ;
}
if ( rgb [ 5 ] ) {
values = rgb [ 5 ] . split ( commaSpaces ) ;
red = toFloat ( values [ 0 ] ) ;
2013-09-16 06:55:33 +00:00
values [ 0 ] . slice ( - 1 ) == "%" && ( red /= 100 ) ;
2013-08-05 08:04:30 +00:00
green = toFloat ( values [ 1 ] ) ;
2013-09-16 06:55:33 +00:00
values [ 1 ] . slice ( - 1 ) == "%" && ( green /= 100 ) ;
2013-08-05 08:04:30 +00:00
blue = toFloat ( values [ 2 ] ) ;
2013-09-16 06:55:33 +00:00
values [ 2 ] . slice ( - 1 ) == "%" && ( blue /= 100 ) ;
2013-08-05 08:04:30 +00:00
( values [ 0 ] . slice ( - 3 ) == "deg" || values [ 0 ] . slice ( - 1 ) == "\xb0" ) && ( red /= 360 ) ;
rgb [ 1 ] . toLowerCase ( ) . slice ( 0 , 4 ) == "hsba" && ( opacity = toFloat ( values [ 3 ] ) ) ;
values [ 3 ] && values [ 3 ] . slice ( - 1 ) == "%" && ( opacity /= 100 ) ;
2013-09-25 05:52:57 +00:00
return Snap . hsb2rgb ( red , green , blue , opacity ) ;
2013-08-05 08:04:30 +00:00
}
if ( rgb [ 6 ] ) {
values = rgb [ 6 ] . split ( commaSpaces ) ;
red = toFloat ( values [ 0 ] ) ;
2013-09-16 06:55:33 +00:00
values [ 0 ] . slice ( - 1 ) == "%" && ( red /= 100 ) ;
2013-08-05 08:04:30 +00:00
green = toFloat ( values [ 1 ] ) ;
2013-09-16 06:55:33 +00:00
values [ 1 ] . slice ( - 1 ) == "%" && ( green /= 100 ) ;
2013-08-05 08:04:30 +00:00
blue = toFloat ( values [ 2 ] ) ;
2013-09-16 06:55:33 +00:00
values [ 2 ] . slice ( - 1 ) == "%" && ( blue /= 100 ) ;
2013-08-05 08:04:30 +00:00
( values [ 0 ] . slice ( - 3 ) == "deg" || values [ 0 ] . slice ( - 1 ) == "\xb0" ) && ( red /= 360 ) ;
rgb [ 1 ] . toLowerCase ( ) . slice ( 0 , 4 ) == "hsla" && ( opacity = toFloat ( values [ 3 ] ) ) ;
values [ 3 ] && values [ 3 ] . slice ( - 1 ) == "%" && ( opacity /= 100 ) ;
2013-09-25 05:52:57 +00:00
return Snap . hsl2rgb ( red , green , blue , opacity ) ;
2013-08-05 08:04:30 +00:00
}
2013-09-16 06:55:33 +00:00
red = mmin ( math . round ( red ) , 255 ) ;
green = mmin ( math . round ( green ) , 255 ) ;
blue = mmin ( math . round ( blue ) , 255 ) ;
opacity = mmin ( mmax ( opacity , 0 ) , 1 ) ;
2013-08-05 08:04:30 +00:00
rgb = { r : red , g : green , b : blue , toString : rgbtoString } ;
2017-01-24 02:32:41 +00:00
rgb . hex = "#" + ( 16777216 | blue | green << 8 | red << 16 ) . toString ( 16 ) . slice ( 1 ) ;
2013-08-15 08:29:47 +00:00
rgb . opacity = is ( opacity , "finite" ) ? opacity : 1 ;
2013-08-05 08:04:30 +00:00
return rgb ;
}
return { r : - 1 , g : - 1 , b : - 1 , hex : "none" , error : 1 , toString : rgbtoString } ;
2013-09-25 05:52:57 +00:00
} , Snap ) ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . hsb
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Converts HSB values to a hex representation of the color
2013-08-05 08:04:30 +00:00
- h ( number ) hue
- s ( number ) saturation
- b ( number ) value or brightness
2013-10-14 11:59:34 +00:00
= ( string ) hex representation of the color
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . hsb = cacher ( function ( h , s , b ) {
return Snap . hsb2rgb ( h , s , b ) . hex ;
2013-08-05 08:04:30 +00:00
} ) ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . hsl
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Converts HSL values to a hex representation of the color
2013-08-05 08:04:30 +00:00
- h ( number ) hue
- s ( number ) saturation
- l ( number ) luminosity
2013-10-14 11:59:34 +00:00
= ( string ) hex representation of the color
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . hsl = cacher ( function ( h , s , l ) {
return Snap . hsl2rgb ( h , s , l ) . hex ;
2013-08-05 08:04:30 +00:00
} ) ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . rgb
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Converts RGB values to a hex representation of the color
2013-08-05 08:04:30 +00:00
- r ( number ) red
- g ( number ) green
- b ( number ) blue
2013-10-14 11:59:34 +00:00
= ( string ) hex representation of the color
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . rgb = cacher ( function ( r , g , b , o ) {
2013-08-05 08:04:30 +00:00
if ( is ( o , "finite" ) ) {
var round = math . round ;
return "rgba(" + [ round ( r ) , round ( g ) , round ( b ) , + o . toFixed ( 2 ) ] + ")" ;
}
2017-01-24 02:32:41 +00:00
return "#" + ( 16777216 | b | g << 8 | r << 16 ) . toString ( 16 ) . slice ( 1 ) ;
2013-08-05 08:04:30 +00:00
} ) ;
var toHex = function ( color ) {
2014-05-29 15:58:58 +00:00
var i = glob . doc . getElementsByTagName ( "head" ) [ 0 ] || glob . doc . getElementsByTagName ( "svg" ) [ 0 ] ,
2013-09-11 12:25:30 +00:00
red = "rgb(255, 0, 0)" ;
2013-08-05 08:04:30 +00:00
toHex = cacher ( function ( color ) {
2013-09-11 12:25:30 +00:00
if ( color . toLowerCase ( ) == "red" ) {
return red ;
}
i . style . color = red ;
2013-08-05 08:04:30 +00:00
i . style . color = color ;
var out = glob . doc . defaultView . getComputedStyle ( i , E ) . getPropertyValue ( "color" ) ;
2013-09-11 12:25:30 +00:00
return out == red ? null : out ;
2013-08-05 08:04:30 +00:00
} ) ;
return toHex ( color ) ;
} ,
hsbtoString = function ( ) {
return "hsb(" + [ this . h , this . s , this . b ] + ")" ;
} ,
hsltoString = function ( ) {
return "hsl(" + [ this . h , this . s , this . l ] + ")" ;
} ,
rgbtoString = function ( ) {
return this . opacity == 1 || this . opacity == null ?
this . hex :
"rgba(" + [ this . r , this . g , this . b , this . opacity ] + ")" ;
} ,
prepareRGB = function ( r , g , b ) {
if ( g == null && is ( r , "object" ) && "r" in r && "g" in r && "b" in r ) {
b = r . b ;
g = r . g ;
r = r . r ;
}
if ( g == null && is ( r , string ) ) {
2013-09-25 05:52:57 +00:00
var clr = Snap . getRGB ( r ) ;
2013-08-05 08:04:30 +00:00
r = clr . r ;
g = clr . g ;
b = clr . b ;
}
if ( r > 1 || g > 1 || b > 1 ) {
r /= 255 ;
g /= 255 ;
b /= 255 ;
}
2016-06-09 12:02:46 +00:00
2013-08-05 08:04:30 +00:00
return [ r , g , b ] ;
} ,
packageRGB = function ( r , g , b , o ) {
r = math . round ( r * 255 ) ;
g = math . round ( g * 255 ) ;
b = math . round ( b * 255 ) ;
var rgb = {
r : r ,
g : g ,
b : b ,
2013-08-15 08:29:47 +00:00
opacity : is ( o , "finite" ) ? o : 1 ,
2013-09-25 05:52:57 +00:00
hex : Snap . rgb ( r , g , b ) ,
2013-08-05 08:04:30 +00:00
toString : rgbtoString
} ;
is ( o , "finite" ) && ( rgb . opacity = o ) ;
return rgb ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . color
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Parses the color string and returns an object featuring the color ' s component values
2013-09-25 05:52:57 +00:00
- clr ( string ) color string in one of the supported formats ( see @ Snap . getRGB )
2013-10-14 11:59:34 +00:00
= ( object ) Combined RGB / HSB object in the following format :
2013-08-05 08:04:30 +00:00
o {
o r ( number ) red ,
o g ( number ) green ,
o b ( number ) blue ,
o hex ( string ) color in HTML / CSS format : # • • • • • • ,
2013-10-14 11:59:34 +00:00
o error ( boolean ) ` true ` if string can ' t be parsed ,
2013-08-05 08:04:30 +00:00
o h ( number ) hue ,
o s ( number ) saturation ,
o v ( number ) value ( brightness ) ,
o l ( number ) lightness
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . color = function ( clr ) {
2013-08-05 08:04:30 +00:00
var rgb ;
if ( is ( clr , "object" ) && "h" in clr && "s" in clr && "b" in clr ) {
2013-09-25 05:52:57 +00:00
rgb = Snap . hsb2rgb ( clr ) ;
2013-08-05 08:04:30 +00:00
clr . r = rgb . r ;
clr . g = rgb . g ;
clr . b = rgb . b ;
2013-08-15 08:29:47 +00:00
clr . opacity = 1 ;
2013-08-05 08:04:30 +00:00
clr . hex = rgb . hex ;
} else if ( is ( clr , "object" ) && "h" in clr && "s" in clr && "l" in clr ) {
2013-09-25 05:52:57 +00:00
rgb = Snap . hsl2rgb ( clr ) ;
2013-08-05 08:04:30 +00:00
clr . r = rgb . r ;
clr . g = rgb . g ;
clr . b = rgb . b ;
2013-08-15 08:29:47 +00:00
clr . opacity = 1 ;
2013-08-05 08:04:30 +00:00
clr . hex = rgb . hex ;
} else {
if ( is ( clr , "string" ) ) {
2013-09-25 05:52:57 +00:00
clr = Snap . getRGB ( clr ) ;
2013-08-05 08:04:30 +00:00
}
2013-09-11 12:25:30 +00:00
if ( is ( clr , "object" ) && "r" in clr && "g" in clr && "b" in clr && ! ( "error" in clr ) ) {
2013-09-25 05:52:57 +00:00
rgb = Snap . rgb2hsl ( clr ) ;
2013-08-05 08:04:30 +00:00
clr . h = rgb . h ;
clr . s = rgb . s ;
clr . l = rgb . l ;
2013-09-25 05:52:57 +00:00
rgb = Snap . rgb2hsb ( clr ) ;
2013-08-05 08:04:30 +00:00
clr . v = rgb . b ;
} else {
clr = { hex : "none" } ;
clr . r = clr . g = clr . b = clr . h = clr . s = clr . v = clr . l = - 1 ;
2013-09-11 12:25:30 +00:00
clr . error = 1 ;
2013-08-05 08:04:30 +00:00
}
}
clr . toString = rgbtoString ;
return clr ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . hsb2rgb
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Converts HSB values to an RGB object
2013-08-05 08:04:30 +00:00
- h ( number ) hue
- s ( number ) saturation
- v ( number ) value or brightness
2013-10-14 11:59:34 +00:00
= ( object ) RGB object in the following format :
2013-08-05 08:04:30 +00:00
o {
o r ( number ) red ,
o g ( number ) green ,
o b ( number ) blue ,
o hex ( string ) color in HTML / CSS format : # • • • • • •
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . hsb2rgb = function ( h , s , v , o ) {
2013-08-05 08:04:30 +00:00
if ( is ( h , "object" ) && "h" in h && "s" in h && "b" in h ) {
v = h . b ;
s = h . s ;
o = h . o ;
2014-10-28 10:48:17 +00:00
h = h . h ;
2013-08-05 08:04:30 +00:00
}
h *= 360 ;
var R , G , B , X , C ;
2017-01-24 02:32:41 +00:00
h = h % 360 / 60 ;
2013-08-05 08:04:30 +00:00
C = v * s ;
X = C * ( 1 - abs ( h % 2 - 1 ) ) ;
R = G = B = v - C ;
h = ~ ~ h ;
R += [ C , X , 0 , 0 , X , C ] [ h ] ;
G += [ X , C , C , X , 0 , 0 ] [ h ] ;
B += [ 0 , 0 , X , C , C , X ] [ h ] ;
return packageRGB ( R , G , B , o ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . hsl2rgb
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Converts HSL values to an RGB object
2013-08-05 08:04:30 +00:00
- h ( number ) hue
- s ( number ) saturation
- l ( number ) luminosity
2013-10-14 11:59:34 +00:00
= ( object ) RGB object in the following format :
2013-08-05 08:04:30 +00:00
o {
o r ( number ) red ,
o g ( number ) green ,
o b ( number ) blue ,
o hex ( string ) color in HTML / CSS format : # • • • • • •
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . hsl2rgb = function ( h , s , l , o ) {
2013-08-05 08:04:30 +00:00
if ( is ( h , "object" ) && "h" in h && "s" in h && "l" in h ) {
l = h . l ;
s = h . s ;
h = h . h ;
}
if ( h > 1 || s > 1 || l > 1 ) {
h /= 360 ;
s /= 100 ;
l /= 100 ;
}
h *= 360 ;
var R , G , B , X , C ;
2017-01-24 02:32:41 +00:00
h = h % 360 / 60 ;
2013-08-05 08:04:30 +00:00
C = 2 * s * ( l < . 5 ? l : 1 - l ) ;
X = C * ( 1 - abs ( h % 2 - 1 ) ) ;
R = G = B = l - C / 2 ;
h = ~ ~ h ;
R += [ C , X , 0 , 0 , X , C ] [ h ] ;
G += [ X , C , C , X , 0 , 0 ] [ h ] ;
B += [ 0 , 0 , X , C , C , X ] [ h ] ;
return packageRGB ( R , G , B , o ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . rgb2hsb
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Converts RGB values to an HSB object
2013-08-05 08:04:30 +00:00
- r ( number ) red
- g ( number ) green
- b ( number ) blue
2013-10-14 11:59:34 +00:00
= ( object ) HSB object in the following format :
2013-08-05 08:04:30 +00:00
o {
2013-10-14 11:59:34 +00:00
o h ( number ) hue ,
o s ( number ) saturation ,
2013-08-05 08:04:30 +00:00
o b ( number ) brightness
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . rgb2hsb = function ( r , g , b ) {
2013-08-05 08:04:30 +00:00
b = prepareRGB ( r , g , b ) ;
r = b [ 0 ] ;
g = b [ 1 ] ;
b = b [ 2 ] ;
var H , S , V , C ;
V = mmax ( r , g , b ) ;
C = V - mmin ( r , g , b ) ;
2017-01-24 02:32:41 +00:00
H = C == 0 ? null :
V == r ? ( g - b ) / C :
V == g ? ( b - r ) / C + 2 :
( r - g ) / C + 4 ;
H = ( H + 360 ) % 6 * 60 / 360 ;
2013-08-05 08:04:30 +00:00
S = C == 0 ? 0 : C / V ;
return { h : H , s : S , b : V , toString : hsbtoString } ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . rgb2hsl
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Converts RGB values to an HSL object
2013-08-05 08:04:30 +00:00
- r ( number ) red
- g ( number ) green
- b ( number ) blue
2013-10-14 11:59:34 +00:00
= ( object ) HSL object in the following format :
2013-08-05 08:04:30 +00:00
o {
2013-10-14 11:59:34 +00:00
o h ( number ) hue ,
o s ( number ) saturation ,
2013-08-05 08:04:30 +00:00
o l ( number ) luminosity
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . rgb2hsl = function ( r , g , b ) {
2013-08-05 08:04:30 +00:00
b = prepareRGB ( r , g , b ) ;
r = b [ 0 ] ;
g = b [ 1 ] ;
b = b [ 2 ] ;
var H , S , L , M , m , C ;
M = mmax ( r , g , b ) ;
m = mmin ( r , g , b ) ;
C = M - m ;
2017-01-24 02:32:41 +00:00
H = C == 0 ? null :
M == r ? ( g - b ) / C :
M == g ? ( b - r ) / C + 2 :
( r - g ) / C + 4 ;
H = ( H + 360 ) % 6 * 60 / 360 ;
2013-08-05 08:04:30 +00:00
L = ( M + m ) / 2 ;
2017-01-24 02:32:41 +00:00
S = C == 0 ? 0 :
2013-08-05 08:04:30 +00:00
L < . 5 ? C / ( 2 * L ) :
2017-01-24 02:32:41 +00:00
C / ( 2 - 2 * L ) ;
2013-08-05 08:04:30 +00:00
return { h : H , s : S , l : L , toString : hsltoString } ;
} ;
// Transformations
2013-08-20 09:42:07 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . parsePathString
2013-08-20 09:42:07 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Parses given path string into an array of arrays of path segments
- pathString ( string | array ) path string or array of segments ( in the last case it is returned straight away )
= ( array ) array of segments
2013-08-20 09:42:07 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . parsePathString = function ( pathString ) {
2013-08-20 09:42:07 +00:00
if ( ! pathString ) {
return null ;
}
2013-09-25 05:52:57 +00:00
var pth = Snap . path ( pathString ) ;
2013-08-20 09:42:07 +00:00
if ( pth . arr ) {
2013-09-25 05:52:57 +00:00
return Snap . path . clone ( pth . arr ) ;
2013-08-20 09:42:07 +00:00
}
2016-06-09 12:02:46 +00:00
2013-08-20 09:42:07 +00:00
var paramCounts = { a : 7 , c : 6 , o : 2 , h : 1 , l : 2 , m : 2 , r : 4 , q : 4 , s : 4 , t : 2 , v : 1 , u : 3 , z : 0 } ,
data = [ ] ;
if ( is ( pathString , "array" ) && is ( pathString [ 0 ] , "array" ) ) { // rough assumption
2013-09-25 05:52:57 +00:00
data = Snap . path . clone ( pathString ) ;
2013-08-20 09:42:07 +00:00
}
if ( ! data . length ) {
Str ( pathString ) . replace ( pathCommand , function ( a , b , c ) {
var params = [ ] ,
name = b . toLowerCase ( ) ;
c . replace ( pathValues , function ( a , b ) {
b && params . push ( + b ) ;
2013-08-05 08:04:30 +00:00
} ) ;
2013-08-20 09:42:07 +00:00
if ( name == "m" && params . length > 2 ) {
data . push ( [ b ] . concat ( params . splice ( 0 , 2 ) ) ) ;
name = "l" ;
b = b == "m" ? "l" : "L" ;
}
if ( name == "o" && params . length == 1 ) {
data . push ( [ b , params [ 0 ] ] ) ;
}
if ( name == "r" ) {
data . push ( [ b ] . concat ( params ) ) ;
} else while ( params . length >= paramCounts [ name ] ) {
data . push ( [ b ] . concat ( params . splice ( 0 , paramCounts [ name ] ) ) ) ;
if ( ! paramCounts [ name ] ) {
break ;
}
}
} ) ;
}
2013-09-25 05:52:57 +00:00
data . toString = Snap . path . toString ;
pth . arr = Snap . path . clone ( data ) ;
2013-08-20 09:42:07 +00:00
return data ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . parseTransformString
2013-08-20 09:42:07 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Parses given transform string into an array of transformations
- TString ( string | array ) transform string or array of transformations ( in the last case it is returned straight away )
= ( array ) array of transformations
2013-08-20 09:42:07 +00:00
\ * /
2013-09-25 05:52:57 +00:00
var parseTransformString = Snap . parseTransformString = function ( TString ) {
2013-08-05 08:04:30 +00:00
if ( ! TString ) {
return null ;
}
var paramCounts = { r : 3 , s : 4 , t : 2 , m : 6 } ,
data = [ ] ;
if ( is ( TString , "array" ) && is ( TString [ 0 ] , "array" ) ) { // rough assumption
2013-09-25 05:52:57 +00:00
data = Snap . path . clone ( TString ) ;
2013-08-05 08:04:30 +00:00
}
if ( ! data . length ) {
Str ( TString ) . replace ( tCommand , function ( a , b , c ) {
var params = [ ] ,
name = b . toLowerCase ( ) ;
c . replace ( pathValues , function ( a , b ) {
b && params . push ( + b ) ;
} ) ;
data . push ( [ b ] . concat ( params ) ) ;
} ) ;
}
2013-09-25 05:52:57 +00:00
data . toString = Snap . path . toString ;
2013-08-05 08:04:30 +00:00
return data ;
} ;
function svgTransform2string ( tstr ) {
var res = [ ] ;
tstr = tstr . replace ( /(?:^|\s)(\w+)\(([^)]+)\)/g , function ( all , name , params ) {
2013-12-23 01:26:40 +00:00
params = params . split ( /\s*,\s*|\s+/ ) ;
2013-08-05 08:04:30 +00:00
if ( name == "rotate" && params . length == 1 ) {
params . push ( 0 , 0 ) ;
}
if ( name == "scale" ) {
2014-04-22 03:56:47 +00:00
if ( params . length > 2 ) {
params = params . slice ( 0 , 2 ) ;
} else if ( params . length == 2 ) {
2013-08-05 08:04:30 +00:00
params . push ( 0 , 0 ) ;
}
if ( params . length == 1 ) {
params . push ( params [ 0 ] , 0 , 0 ) ;
}
}
if ( name == "skewX" ) {
res . push ( [ "m" , 1 , 0 , math . tan ( rad ( params [ 0 ] ) ) , 1 , 0 , 0 ] ) ;
} else if ( name == "skewY" ) {
res . push ( [ "m" , 1 , math . tan ( rad ( params [ 0 ] ) ) , 0 , 1 , 0 , 0 ] ) ;
} else {
res . push ( [ name . charAt ( 0 ) ] . concat ( params ) ) ;
}
return all ;
} ) ;
return res ;
}
2013-11-25 01:00:34 +00:00
Snap . _ . svgTransform2string = svgTransform2string ;
2014-07-31 08:37:34 +00:00
Snap . _ . rgTransform = /^[a-z][\s]*-?\.?\d/i ;
2013-09-28 12:25:29 +00:00
function transform2matrix ( tstr , bbox ) {
2013-08-05 08:04:30 +00:00
var tdata = parseTransformString ( tstr ) ,
2014-05-07 08:37:05 +00:00
m = new Snap . Matrix ;
2013-08-05 08:04:30 +00:00
if ( tdata ) {
for ( var i = 0 , ii = tdata . length ; i < ii ; i ++ ) {
var t = tdata [ i ] ,
tlen = t . length ,
command = Str ( t [ 0 ] ) . toLowerCase ( ) ,
absolute = t [ 0 ] != command ,
inver = absolute ? m . invert ( ) : 0 ,
x1 ,
y1 ,
x2 ,
y2 ,
bb ;
2013-12-23 01:26:40 +00:00
if ( command == "t" && tlen == 2 ) {
m . translate ( t [ 1 ] , 0 ) ;
} else if ( command == "t" && tlen == 3 ) {
2013-08-05 08:04:30 +00:00
if ( absolute ) {
x1 = inver . x ( 0 , 0 ) ;
y1 = inver . y ( 0 , 0 ) ;
x2 = inver . x ( t [ 1 ] , t [ 2 ] ) ;
y2 = inver . y ( t [ 1 ] , t [ 2 ] ) ;
m . translate ( x2 - x1 , y2 - y1 ) ;
} else {
m . translate ( t [ 1 ] , t [ 2 ] ) ;
}
} else if ( command == "r" ) {
if ( tlen == 2 ) {
2013-09-28 12:25:29 +00:00
bb = bb || bbox ;
2013-08-05 08:04:30 +00:00
m . rotate ( t [ 1 ] , bb . x + bb . width / 2 , bb . y + bb . height / 2 ) ;
} else if ( tlen == 4 ) {
if ( absolute ) {
x2 = inver . x ( t [ 2 ] , t [ 3 ] ) ;
y2 = inver . y ( t [ 2 ] , t [ 3 ] ) ;
m . rotate ( t [ 1 ] , x2 , y2 ) ;
} else {
m . rotate ( t [ 1 ] , t [ 2 ] , t [ 3 ] ) ;
}
}
} else if ( command == "s" ) {
if ( tlen == 2 || tlen == 3 ) {
2013-09-28 12:25:29 +00:00
bb = bb || bbox ;
2013-08-05 08:04:30 +00:00
m . scale ( t [ 1 ] , t [ tlen - 1 ] , bb . x + bb . width / 2 , bb . y + bb . height / 2 ) ;
2013-10-20 03:59:06 +00:00
} else if ( tlen == 4 ) {
if ( absolute ) {
x2 = inver . x ( t [ 2 ] , t [ 3 ] ) ;
y2 = inver . y ( t [ 2 ] , t [ 3 ] ) ;
m . scale ( t [ 1 ] , t [ 1 ] , x2 , y2 ) ;
} else {
m . scale ( t [ 1 ] , t [ 1 ] , t [ 2 ] , t [ 3 ] ) ;
}
2013-08-05 08:04:30 +00:00
} else if ( tlen == 5 ) {
if ( absolute ) {
x2 = inver . x ( t [ 3 ] , t [ 4 ] ) ;
y2 = inver . y ( t [ 3 ] , t [ 4 ] ) ;
m . scale ( t [ 1 ] , t [ 2 ] , x2 , y2 ) ;
} else {
m . scale ( t [ 1 ] , t [ 2 ] , t [ 3 ] , t [ 4 ] ) ;
}
}
} else if ( command == "m" && tlen == 7 ) {
m . add ( t [ 1 ] , t [ 2 ] , t [ 3 ] , t [ 4 ] , t [ 5 ] , t [ 6 ] ) ;
}
}
2013-09-28 12:25:29 +00:00
}
return m ;
}
Snap . _ . transform2matrix = transform2matrix ;
2013-09-25 05:52:57 +00:00
Snap . _unit2px = unit2px ;
2013-11-18 03:44:45 +00:00
var contains = glob . doc . contains || glob . doc . compareDocumentPosition ?
function ( a , b ) {
var adown = a . nodeType == 9 ? a . documentElement : a ,
bup = b && b . parentNode ;
return a == bup || ! ! ( bup && bup . nodeType == 1 && (
adown . contains ?
adown . contains ( bup ) :
a . compareDocumentPosition && a . compareDocumentPosition ( bup ) & 16
) ) ;
} :
function ( a , b ) {
if ( b ) {
2013-11-19 07:03:38 +00:00
while ( b ) {
b = b . parentNode ;
2013-11-18 03:44:45 +00:00
if ( b == a ) {
return true ;
}
}
}
return false ;
} ;
2013-09-19 11:03:24 +00:00
function getSomeDefs ( el ) {
2017-01-24 02:32:41 +00:00
var p = el . node . ownerSVGElement && wrap ( el . node . ownerSVGElement ) ||
el . node . parentNode && wrap ( el . node . parentNode ) ||
2013-09-25 05:52:57 +00:00
Snap . select ( "svg" ) ||
Snap ( 0 , 0 ) ,
2013-12-23 01:27:58 +00:00
pdefs = p . select ( "defs" ) ,
defs = pdefs == null ? false : pdefs . node ;
2013-09-19 11:03:24 +00:00
if ( ! defs ) {
defs = make ( "defs" , p . node ) . node ;
}
return defs ;
}
2014-05-22 02:23:30 +00:00
function getSomeSVG ( el ) {
return el . node . ownerSVGElement && wrap ( el . node . ownerSVGElement ) || Snap . select ( "svg" ) ;
}
2013-09-25 05:52:57 +00:00
Snap . _ . getSomeDefs = getSomeDefs ;
2014-05-22 02:23:30 +00:00
Snap . _ . getSomeSVG = getSomeSVG ;
2013-08-05 08:04:30 +00:00
function unit2px ( el , name , value ) {
2014-05-23 11:03:03 +00:00
var svg = getSomeSVG ( el ) . node ,
2013-08-05 08:04:30 +00:00
out = { } ,
2014-05-21 02:38:18 +00:00
mgr = svg . querySelector ( ".svg---mgr" ) ;
2013-08-05 08:04:30 +00:00
if ( ! mgr ) {
2013-09-19 11:03:24 +00:00
mgr = $ ( "rect" ) ;
2014-05-21 02:38:18 +00:00
$ ( mgr , { x : - 9e9 , y : - 9e9 , width : 10 , height : 10 , "class" : "svg---mgr" , fill : "none" } ) ;
svg . appendChild ( mgr ) ;
2013-08-05 08:04:30 +00:00
}
function getW ( val ) {
if ( val == null ) {
return E ;
}
if ( val == + val ) {
return val ;
}
$ ( mgr , { width : val } ) ;
2014-05-22 02:23:30 +00:00
try {
return mgr . getBBox ( ) . width ;
} catch ( e ) {
return 0 ;
}
2013-08-05 08:04:30 +00:00
}
function getH ( val ) {
if ( val == null ) {
return E ;
}
if ( val == + val ) {
return val ;
}
$ ( mgr , { height : val } ) ;
2014-05-22 02:23:30 +00:00
try {
return mgr . getBBox ( ) . height ;
} catch ( e ) {
return 0 ;
}
2013-08-05 08:04:30 +00:00
}
function set ( nam , f ) {
if ( name == null ) {
2014-04-18 00:31:07 +00:00
out [ nam ] = f ( el . attr ( nam ) || 0 ) ;
2013-08-05 08:04:30 +00:00
} else if ( nam == name ) {
2014-04-18 00:31:07 +00:00
out = f ( value == null ? el . attr ( nam ) || 0 : value ) ;
2013-08-05 08:04:30 +00:00
}
}
switch ( el . type ) {
case "rect" :
set ( "rx" , getW ) ;
set ( "ry" , getH ) ;
case "image" :
set ( "width" , getW ) ;
set ( "height" , getH ) ;
case "text" :
set ( "x" , getW ) ;
set ( "y" , getH ) ;
break ;
case "circle" :
set ( "cx" , getW ) ;
set ( "cy" , getH ) ;
set ( "r" , getW ) ;
break ;
case "ellipse" :
set ( "cx" , getW ) ;
set ( "cy" , getH ) ;
set ( "rx" , getW ) ;
set ( "ry" , getH ) ;
break ;
case "line" :
set ( "x1" , getW ) ;
set ( "x2" , getW ) ;
set ( "y1" , getH ) ;
set ( "y2" , getH ) ;
break ;
case "marker" :
set ( "refX" , getW ) ;
set ( "markerWidth" , getW ) ;
set ( "refY" , getH ) ;
set ( "markerHeight" , getH ) ;
break ;
case "radialGradient" :
set ( "fx" , getW ) ;
set ( "fy" , getH ) ;
break ;
case "tspan" :
set ( "dx" , getW ) ;
set ( "dy" , getH ) ;
break ;
default :
2013-10-15 00:12:33 +00:00
set ( name , getW ) ;
2013-08-05 08:04:30 +00:00
}
2014-05-29 15:58:58 +00:00
svg . removeChild ( mgr ) ;
2013-08-05 08:04:30 +00:00
return out ;
}
/ * \
2013-09-25 05:52:57 +00:00
* Snap . select
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Wraps a DOM element specified by CSS selector as @ Element
2013-08-05 08:04:30 +00:00
- query ( string ) CSS selector of the element
2013-10-14 11:59:34 +00:00
= ( Element ) the current element
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . select = function ( query ) {
2014-07-31 08:37:34 +00:00
query = Str ( query ) . replace ( /([^\\]):/g , "$1\\:" ) ;
2013-08-09 12:13:22 +00:00
return wrap ( glob . doc . querySelector ( query ) ) ;
2013-08-05 08:04:30 +00:00
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . selectAll
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Wraps DOM elements specified by CSS selector as set or array of @ Element
- query ( string ) CSS selector of the element
2013-10-14 11:59:34 +00:00
= ( Element ) the current element
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . selectAll = function ( query ) {
2013-08-05 08:04:30 +00:00
var nodelist = glob . doc . querySelectorAll ( query ) ,
2013-09-25 05:52:57 +00:00
set = ( Snap . set || Array ) ( ) ;
2013-08-05 08:04:30 +00:00
for ( var i = 0 ; i < nodelist . length ; i ++ ) {
2013-08-09 12:13:22 +00:00
set . push ( wrap ( nodelist [ i ] ) ) ;
2013-08-05 08:04:30 +00:00
}
return set ;
} ;
2013-09-05 13:24:16 +00:00
function add2group ( list ) {
if ( ! is ( list , "array" ) ) {
list = Array . prototype . slice . call ( arguments , 0 ) ;
}
var i = 0 ,
j = 0 ,
node = this . node ;
while ( this [ i ] ) delete this [ i ++ ] ;
for ( i = 0 ; i < list . length ; i ++ ) {
if ( list [ i ] . type == "set" ) {
list [ i ] . forEach ( function ( el ) {
node . appendChild ( el . node ) ;
} ) ;
} else {
node . appendChild ( list [ i ] . node ) ;
}
}
var children = node . childNodes ;
2013-11-26 07:46:13 +00:00
for ( i = 0 ; i < children . length ; i ++ ) {
this [ j ++ ] = wrap ( children [ i ] ) ;
2013-09-05 13:24:16 +00:00
}
2013-12-23 01:27:58 +00:00
return this ;
2013-09-05 13:24:16 +00:00
}
2014-05-08 04:21:19 +00:00
// Hub garbage collector every 10s
setInterval ( function ( ) {
for ( var key in hub ) if ( hub [ has ] ( key ) ) {
var el = hub [ key ] ,
node = el . node ;
if ( el . type != "svg" && ! node . ownerSVGElement || el . type == "svg" && ( ! node . parentNode || "ownerSVGElement" in node . parentNode && ! node . ownerSVGElement ) ) {
delete hub [ key ] ;
}
}
} , 1e4 ) ;
2013-08-05 08:04:30 +00:00
function Element ( el ) {
2013-09-25 05:52:57 +00:00
if ( el . snap in hub ) {
return hub [ el . snap ] ;
2013-08-05 08:04:30 +00:00
}
2014-08-04 11:22:04 +00:00
var svg ;
2013-08-05 08:04:30 +00:00
try {
svg = el . ownerSVGElement ;
} catch ( e ) { }
2014-01-08 02:07:30 +00:00
/ * \
* Element . node
[ property ( object ) ]
* *
* Gives you a reference to the DOM object , so you can assign event handlers or just mess around .
> 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" ) ;
| } ;
\ * /
2013-08-05 08:04:30 +00:00
this . node = el ;
if ( svg ) {
this . paper = new Paper ( svg ) ;
}
2014-01-08 02:07:30 +00:00
/ * \
* Element . type
[ property ( string ) ]
* *
* SVG tag name of the given element .
\ * /
2014-10-28 10:48:17 +00:00
this . type = el . tagName || el . nodeName ;
2014-08-04 11:22:04 +00:00
var id = this . id = ID ( this ) ;
2013-08-20 09:42:07 +00:00
this . anims = { } ;
2013-08-05 08:04:30 +00:00
this . _ = {
2013-11-19 07:03:38 +00:00
transform : [ ]
2013-08-05 08:04:30 +00:00
} ;
2013-09-25 05:52:57 +00:00
el . snap = id ;
2013-08-05 08:04:30 +00:00
hub [ id ] = this ;
2013-09-05 13:24:16 +00:00
if ( this . type == "g" ) {
this . add = add2group ;
2014-05-06 00:13:22 +00:00
}
2014-08-04 11:22:04 +00:00
if ( this . type in { g : 1 , mask : 1 , pattern : 1 , symbol : 1 } ) {
2013-09-05 13:24:16 +00:00
for ( var method in Paper . prototype ) if ( Paper . prototype [ has ] ( method ) ) {
this [ method ] = Paper . prototype [ method ] ;
}
}
2013-08-05 08:04:30 +00:00
}
2014-08-13 12:46:40 +00:00
/ * \
2013-08-20 09:42:07 +00:00
* Element . attr
[ method ]
* *
2014-05-15 06:58:04 +00:00
* Gets or sets given attributes of the element .
2013-08-20 09:42:07 +00:00
* *
2013-10-14 11:59:34 +00:00
- params ( object ) contains key - value pairs of attributes you want to set
2013-08-20 09:42:07 +00:00
* or
- param ( string ) name of the attribute
2013-10-14 11:59:34 +00:00
= ( Element ) the current element
2013-08-20 09:42:07 +00:00
* or
= ( string ) value of attribute
> Usage
| el . attr ( {
| fill : "#fc0" ,
| stroke : "#000" ,
| strokeWidth : 2 , // CamelCase...
2014-05-15 06:58:04 +00:00
| "fill-opacity" : 0.5 , // or dash-separated names
| width : "*=2" // prefixed values
2013-08-20 09:42:07 +00:00
| } ) ;
2013-10-14 11:59:34 +00:00
| console . log ( el . attr ( "fill" ) ) ; // #fc0
2014-05-15 06:58:04 +00:00
* Prefixed values in format ` "+=10" ` supported . All four operations
* ( ` + ` , ` - ` , ` * ` and ` / ` ) could be used . Optionally you can use units for ` + `
* and ` - ` : ` "+=2em" ` .
2013-08-20 09:42:07 +00:00
\ * /
2014-08-13 12:46:40 +00:00
Element . prototype . attr = function ( params , value ) {
2013-09-10 00:38:04 +00:00
var el = this ,
node = el . node ;
2013-09-09 07:36:48 +00:00
if ( ! params ) {
2014-10-28 10:48:17 +00:00
if ( node . nodeType != 1 ) {
return {
text : node . nodeValue
} ;
}
var attr = node . attributes ,
out = { } ;
for ( var i = 0 , ii = attr . length ; i < ii ; i ++ ) {
out [ attr [ i ] . nodeName ] = attr [ i ] . nodeValue ;
}
return out ;
2013-09-09 07:36:48 +00:00
}
2013-08-05 08:04:30 +00:00
if ( is ( params , "string" ) ) {
2013-09-10 00:38:04 +00:00
if ( arguments . length > 1 ) {
var json = { } ;
json [ params ] = value ;
params = json ;
} else {
2014-05-23 11:03:03 +00:00
return eve ( "snap.util.getattr." + params , el ) . firstDefined ( ) ;
2013-09-10 00:38:04 +00:00
}
2013-08-05 08:04:30 +00:00
}
for ( var att in params ) {
if ( params [ has ] ( att ) ) {
2013-09-25 05:52:57 +00:00
eve ( "snap.util.attr." + att , el , params [ att ] ) ;
2013-08-05 08:04:30 +00:00
}
}
2013-09-10 00:38:04 +00:00
return el ;
2013-08-05 08:04:30 +00:00
} ;
2014-08-13 12:46:40 +00:00
/ * \
* Snap . parse
[ method ]
* *
* Parses SVG fragment and converts it into a @ Fragment
* *
- svg ( string ) SVG string
= ( Fragment ) the @ Fragment
\ * /
Snap . parse = function ( svg ) {
var f = glob . doc . createDocumentFragment ( ) ,
full = true ,
div = glob . doc . createElement ( "div" ) ;
svg = Str ( svg ) ;
if ( ! svg . match ( /^\s*<\s*svg(?:\s|>)/ ) ) {
svg = "<svg>" + svg + "</svg>" ;
full = false ;
}
div . innerHTML = svg ;
svg = div . getElementsByTagName ( "svg" ) [ 0 ] ;
if ( svg ) {
if ( full ) {
f = svg ;
} else {
while ( svg . firstChild ) {
f . appendChild ( svg . firstChild ) ;
2014-03-07 02:22:40 +00:00
}
2013-09-19 11:03:24 +00:00
}
2014-08-13 12:46:40 +00:00
}
return new Fragment ( f ) ;
} ;
function Fragment ( frag ) {
this . node = frag ;
}
/ * \
* Snap . fragment
[ method ]
* *
* Creates a DOM fragment from a given list of elements or strings
* *
- varargs ( … ) SVG string
= ( Fragment ) the @ Fragment
\ * /
Snap . fragment = function ( ) {
var args = Array . prototype . slice . call ( arguments , 0 ) ,
f = glob . doc . createDocumentFragment ( ) ;
for ( var i = 0 , ii = args . length ; i < ii ; i ++ ) {
var item = args [ i ] ;
if ( item . node && item . node . nodeType ) {
f . appendChild ( item . node ) ;
2013-08-05 08:04:30 +00:00
}
2014-08-13 12:46:40 +00:00
if ( item . nodeType ) {
f . appendChild ( item ) ;
2013-08-05 08:04:30 +00:00
}
2014-08-13 12:46:40 +00:00
if ( typeof item == "string" ) {
f . appendChild ( Snap . parse ( item ) . node ) ;
2013-08-05 08:04:30 +00:00
}
2014-08-13 12:46:40 +00:00
}
return new Fragment ( f ) ;
} ;
2013-08-05 08:04:30 +00:00
2014-08-13 12:46:40 +00:00
function make ( name , parent ) {
var res = $ ( name ) ;
parent . appendChild ( res ) ;
var el = wrap ( res ) ;
return el ;
}
function Paper ( w , h ) {
var res ,
desc ,
defs ,
proto = Paper . prototype ;
2016-06-09 12:02:46 +00:00
if ( w && w . tagName && w . tagName . toLowerCase ( ) == "svg" ) {
2014-08-13 12:46:40 +00:00
if ( w . snap in hub ) {
return hub [ w . snap ] ;
2013-08-05 08:04:30 +00:00
}
2014-08-13 12:46:40 +00:00
var doc = w . ownerDocument ;
res = new Element ( w ) ;
desc = w . getElementsByTagName ( "desc" ) [ 0 ] ;
defs = w . getElementsByTagName ( "defs" ) [ 0 ] ;
if ( ! desc ) {
desc = $ ( "desc" ) ;
desc . appendChild ( doc . createTextNode ( "Created with Snap" ) ) ;
res . node . appendChild ( desc ) ;
}
if ( ! defs ) {
defs = $ ( "defs" ) ;
res . node . appendChild ( defs ) ;
}
res . defs = defs ;
for ( var key in proto ) if ( proto [ has ] ( key ) ) {
res [ key ] = proto [ key ] ;
}
res . paper = res . root = res ;
} else {
res = make ( "svg" , glob . doc . body ) ;
$ ( res . node , {
height : h ,
version : 1.1 ,
width : w ,
xmlns : xmlns
} ) ;
}
return res ;
}
function wrap ( dom ) {
if ( ! dom ) {
return dom ;
}
if ( dom instanceof Element || dom instanceof Fragment ) {
return dom ;
}
if ( dom . tagName && dom . tagName . toLowerCase ( ) == "svg" ) {
return new Paper ( dom ) ;
}
if ( dom . tagName && dom . tagName . toLowerCase ( ) == "object" && dom . type == "image/svg+xml" ) {
return new Paper ( dom . contentDocument . getElementsByTagName ( "svg" ) [ 0 ] ) ;
}
return new Element ( dom ) ;
}
Snap . _ . make = make ;
Snap . _ . wrap = wrap ;
/ * \
* Paper . el
[ method ]
* *
* Creates an element on paper with a given name and no attributes
* *
- name ( string ) tag name
- attr ( object ) attributes
= ( Element ) the current element
> Usage
| var c = paper . circle ( 10 , 10 , 10 ) ; // is the same as...
| var c = paper . el ( "circle" ) . attr ( {
| cx : 10 ,
| cy : 10 ,
| r : 10
| } ) ;
| // and the same as
| var c = paper . el ( "circle" , {
| cx : 10 ,
| cy : 10 ,
| r : 10
| } ) ;
\ * /
Paper . prototype . el = function ( name , attr ) {
var el = make ( name , this . node ) ;
attr && el . attr ( attr ) ;
return el ;
} ;
2014-10-28 10:48:17 +00:00
/ * \
* Element . children
[ method ]
* *
* Returns array of all the children of the element .
= ( array ) array of Elements
\ * /
Element . prototype . children = function ( ) {
var out = [ ] ,
ch = this . node . childNodes ;
for ( var i = 0 , ii = ch . length ; i < ii ; i ++ ) {
out [ i ] = Snap ( ch [ i ] ) ;
}
return out ;
} ;
function jsonFiller ( root , o ) {
for ( var i = 0 , ii = root . length ; i < ii ; i ++ ) {
var item = {
type : root [ i ] . type ,
attr : root [ i ] . attr ( )
} ,
children = root [ i ] . children ( ) ;
o . push ( item ) ;
if ( children . length ) {
jsonFiller ( children , item . childNodes = [ ] ) ;
}
}
}
/ * \
* Element . toJSON
[ method ]
* *
* Returns object representation of the given element and all its children .
= ( object ) in format
o {
o type ( string ) this . type ,
o attr ( object ) attributes map ,
o childNodes ( array ) optional array of children in the same format
o }
\ * /
Element . prototype . toJSON = function ( ) {
var out = [ ] ;
jsonFiller ( [ this ] , out ) ;
return out [ 0 ] ;
} ;
2014-08-13 12:46:40 +00:00
// default
eve . on ( "snap.util.getattr" , function ( ) {
var att = eve . nt ( ) ;
att = att . substring ( att . lastIndexOf ( "." ) + 1 ) ;
var css = att . replace ( /[A-Z]/g , function ( letter ) {
return "-" + letter . toLowerCase ( ) ;
} ) ;
if ( cssAttr [ has ] ( css ) ) {
return this . node . ownerDocument . defaultView . getComputedStyle ( this . node , null ) . getPropertyValue ( css ) ;
} else {
return $ ( this . node , att ) ;
}
} ) ;
var cssAttr = {
"alignment-baseline" : 0 ,
"baseline-shift" : 0 ,
"clip" : 0 ,
"clip-path" : 0 ,
"clip-rule" : 0 ,
"color" : 0 ,
"color-interpolation" : 0 ,
"color-interpolation-filters" : 0 ,
"color-profile" : 0 ,
"color-rendering" : 0 ,
"cursor" : 0 ,
"direction" : 0 ,
"display" : 0 ,
"dominant-baseline" : 0 ,
"enable-background" : 0 ,
"fill" : 0 ,
"fill-opacity" : 0 ,
"fill-rule" : 0 ,
"filter" : 0 ,
"flood-color" : 0 ,
"flood-opacity" : 0 ,
"font" : 0 ,
"font-family" : 0 ,
"font-size" : 0 ,
"font-size-adjust" : 0 ,
"font-stretch" : 0 ,
"font-style" : 0 ,
"font-variant" : 0 ,
"font-weight" : 0 ,
"glyph-orientation-horizontal" : 0 ,
"glyph-orientation-vertical" : 0 ,
"image-rendering" : 0 ,
"kerning" : 0 ,
"letter-spacing" : 0 ,
"lighting-color" : 0 ,
"marker" : 0 ,
"marker-end" : 0 ,
"marker-mid" : 0 ,
"marker-start" : 0 ,
"mask" : 0 ,
"opacity" : 0 ,
"overflow" : 0 ,
"pointer-events" : 0 ,
"shape-rendering" : 0 ,
"stop-color" : 0 ,
"stop-opacity" : 0 ,
"stroke" : 0 ,
"stroke-dasharray" : 0 ,
"stroke-dashoffset" : 0 ,
"stroke-linecap" : 0 ,
"stroke-linejoin" : 0 ,
"stroke-miterlimit" : 0 ,
"stroke-opacity" : 0 ,
"stroke-width" : 0 ,
"text-anchor" : 0 ,
"text-decoration" : 0 ,
"text-rendering" : 0 ,
"unicode-bidi" : 0 ,
"visibility" : 0 ,
"word-spacing" : 0 ,
"writing-mode" : 0
} ;
eve . on ( "snap.util.attr" , function ( value ) {
var att = eve . nt ( ) ,
attr = { } ;
att = att . substring ( att . lastIndexOf ( "." ) + 1 ) ;
attr [ att ] = value ;
var style = att . replace ( /-(\w)/gi , function ( all , letter ) {
return letter . toUpperCase ( ) ;
} ) ,
css = att . replace ( /[A-Z]/g , function ( letter ) {
return "-" + letter . toLowerCase ( ) ;
} ) ;
if ( cssAttr [ has ] ( css ) ) {
this . node . style [ style ] = value == null ? E : value ;
} else {
$ ( this . node , attr ) ;
}
} ) ;
( function ( proto ) { } ( Paper . prototype ) ) ;
// simple ajax
/ * \
* Snap . ajax
[ method ]
* *
* Simple implementation of Ajax
* *
- url ( string ) URL
- postData ( object | string ) data for post request
- callback ( function ) callback
- scope ( object ) # optional scope of callback
* or
- url ( string ) URL
- callback ( function ) callback
- scope ( object ) # optional scope of callback
= ( XMLHttpRequest ) the XMLHttpRequest object , just in case
\ * /
Snap . ajax = function ( url , postData , callback , scope ) {
var req = new XMLHttpRequest ,
id = ID ( ) ;
if ( req ) {
if ( is ( postData , "function" ) ) {
scope = callback ;
callback = postData ;
postData = null ;
} else if ( is ( postData , "object" ) ) {
var pd = [ ] ;
for ( var key in postData ) if ( postData . hasOwnProperty ( key ) ) {
pd . push ( encodeURIComponent ( key ) + "=" + encodeURIComponent ( postData [ key ] ) ) ;
}
postData = pd . join ( "&" ) ;
}
2017-01-24 02:32:41 +00:00
req . open ( postData ? "POST" : "GET" , url , true ) ;
2014-08-13 12:46:40 +00:00
if ( postData ) {
req . setRequestHeader ( "X-Requested-With" , "XMLHttpRequest" ) ;
req . setRequestHeader ( "Content-type" , "application/x-www-form-urlencoded" ) ;
}
if ( callback ) {
eve . once ( "snap.ajax." + id + ".0" , callback ) ;
eve . once ( "snap.ajax." + id + ".200" , callback ) ;
eve . once ( "snap.ajax." + id + ".304" , callback ) ;
}
req . onreadystatechange = function ( ) {
if ( req . readyState != 4 ) return ;
eve ( "snap.ajax." + id + "." + req . status , scope , req ) ;
} ;
if ( req . readyState == 4 ) {
return req ;
}
req . send ( postData ) ;
return req ;
}
} ;
/ * \
* Snap . load
[ method ]
* *
* Loads external SVG file as a @ Fragment ( see @ Snap . ajax for more advanced AJAX )
* *
- url ( string ) URL
- callback ( function ) callback
- scope ( object ) # optional scope of callback
\ * /
Snap . load = function ( url , callback , scope ) {
Snap . ajax ( url , function ( req ) {
var f = Snap . parse ( req . responseText ) ;
scope ? callback . call ( scope , f ) : callback ( f ) ;
} ) ;
} ;
var getOffset = function ( elem ) {
var box = elem . getBoundingClientRect ( ) ,
doc = elem . ownerDocument ,
body = doc . body ,
docElem = doc . documentElement ,
clientTop = docElem . clientTop || body . clientTop || 0 , clientLeft = docElem . clientLeft || body . clientLeft || 0 ,
top = box . top + ( g . win . pageYOffset || docElem . scrollTop || body . scrollTop ) - clientTop ,
left = box . left + ( g . win . pageXOffset || docElem . scrollLeft || body . scrollLeft ) - clientLeft ;
return {
y : top ,
x : left
} ;
} ;
/ * \
* Snap . getElementByPoint
[ method ]
* *
* Returns you topmost element under given point .
* *
= ( object ) Snap element object
- x ( number ) x coordinate from the top left corner of the window
- y ( number ) y coordinate from the top left corner of the window
> Usage
| Snap . getElementByPoint ( mouseX , mouseY ) . attr ( { stroke : "#f00" } ) ;
\ * /
Snap . getElementByPoint = function ( x , y ) {
var paper = this ,
svg = paper . canvas ,
target = glob . doc . elementFromPoint ( x , y ) ;
if ( glob . win . opera && target . tagName == "svg" ) {
var so = getOffset ( target ) ,
sr = target . createSVGRect ( ) ;
sr . x = x - so . x ;
sr . y = y - so . y ;
sr . width = sr . height = 1 ;
var hits = target . getIntersectionList ( sr , null ) ;
if ( hits . length ) {
target = hits [ hits . length - 1 ] ;
}
}
if ( ! target ) {
return null ;
}
return wrap ( target ) ;
} ;
/ * \
* Snap . plugin
[ method ]
* *
2014-10-28 10:48:17 +00:00
* Let you write plugins . You pass in a function with five arguments , like this :
2014-08-13 12:46:40 +00:00
| Snap . plugin ( function ( Snap , Element , Paper , global , Fragment ) {
| Snap . newmethod = function ( ) { } ;
| Element . prototype . newmethod = function ( ) { } ;
| Paper . prototype . newmethod = function ( ) { } ;
| } ) ;
* Inside the function you have access to all main objects ( and their
* prototypes ) . This allow you to extend anything you want .
* *
- f ( function ) your plugin body
\ * /
Snap . plugin = function ( f ) {
f ( Snap , Element , Paper , glob , Fragment ) ;
} ;
glob . win . Snap = Snap ;
return Snap ;
2014-09-17 07:44:54 +00:00
} ( window || this ) ) ;
2014-08-13 12:46:40 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var elproto = Element . prototype ,
is = Snap . is ,
Str = String ,
unit2px = Snap . _unit2px ,
$ = Snap . _ . $ ,
make = Snap . _ . make ,
getSomeDefs = Snap . _ . getSomeDefs ,
has = "hasOwnProperty" ,
wrap = Snap . _ . wrap ;
/ * \
* Element . getBBox
[ method ]
* *
* Returns the bounding box descriptor for the given element
* *
= ( object ) bounding box descriptor :
o {
o cx : ( number ) x of the center ,
o cy : ( number ) x of the center ,
o h : ( number ) height ,
o height : ( number ) height ,
o path : ( string ) path command for the box ,
o r0 : ( number ) radius of a circle that fully encloses the box ,
o r1 : ( number ) radius of the smallest circle that can be enclosed ,
o r2 : ( number ) radius of the largest circle that can be enclosed ,
o vb : ( string ) box as a viewbox command ,
o w : ( number ) width ,
o width : ( number ) width ,
o x2 : ( number ) x of the right side ,
o x : ( number ) x of the left side ,
o y2 : ( number ) y of the bottom edge ,
o y : ( number ) y of the top edge
o }
\ * /
elproto . getBBox = function ( isWithoutTransform ) {
2016-08-01 01:37:11 +00:00
if ( this . type == "tspan" ) {
return Snap . _ . box ( this . node . getClientRects ( ) . item ( 0 ) ) ;
}
2014-08-13 12:46:40 +00:00
if ( ! Snap . Matrix || ! Snap . path ) {
return this . node . getBBox ( ) ;
}
var el = this ,
m = new Snap . Matrix ;
if ( el . removed ) {
return Snap . _ . box ( ) ;
}
while ( el . type == "use" ) {
if ( ! isWithoutTransform ) {
m = m . add ( el . transform ( ) . localMatrix . translate ( el . attr ( "x" ) || 0 , el . attr ( "y" ) || 0 ) ) ;
}
if ( el . original ) {
el = el . original ;
} else {
var href = el . attr ( "xlink:href" ) ;
el = el . original = el . node . ownerDocument . getElementById ( href . substring ( href . indexOf ( "#" ) + 1 ) ) ;
}
}
var _ = el . _ ,
pathfinder = Snap . path . get [ el . type ] || Snap . path . get . deflt ;
try {
if ( isWithoutTransform ) {
_ . bboxwt = pathfinder ? Snap . path . getBBox ( el . realPath = pathfinder ( el ) ) : Snap . _ . box ( el . node . getBBox ( ) ) ;
return Snap . _ . box ( _ . bboxwt ) ;
} else {
el . realPath = pathfinder ( el ) ;
el . matrix = el . transform ( ) . localMatrix ;
_ . bbox = Snap . path . getBBox ( Snap . path . map ( el . realPath , m . add ( el . matrix ) ) ) ;
return Snap . _ . box ( _ . bbox ) ;
}
} catch ( e ) {
// Firefox doesn’ t give you bbox of hidden element
return Snap . _ . box ( ) ;
}
} ;
var propString = function ( ) {
return this . string ;
} ;
function extractTransform ( el , tstr ) {
if ( tstr == null ) {
var doReturn = true ;
if ( el . type == "linearGradient" || el . type == "radialGradient" ) {
tstr = el . node . getAttribute ( "gradientTransform" ) ;
} else if ( el . type == "pattern" ) {
tstr = el . node . getAttribute ( "patternTransform" ) ;
} else {
tstr = el . node . getAttribute ( "transform" ) ;
}
if ( ! tstr ) {
return new Snap . Matrix ;
}
tstr = Snap . _ . svgTransform2string ( tstr ) ;
} else {
if ( ! Snap . _ . rgTransform . test ( tstr ) ) {
tstr = Snap . _ . svgTransform2string ( tstr ) ;
} else {
2015-04-13 06:21:39 +00:00
tstr = Str ( tstr ) . replace ( /\.{3}|\u2026/g , el . _ . transform || "" ) ;
2014-08-13 12:46:40 +00:00
}
if ( is ( tstr , "array" ) ) {
tstr = Snap . path ? Snap . path . toString . call ( tstr ) : Str ( tstr ) ;
}
el . _ . transform = tstr ;
}
var m = Snap . _ . transform2matrix ( tstr , el . getBBox ( 1 ) ) ;
if ( doReturn ) {
return m ;
} else {
el . matrix = m ;
}
}
/ * \
* Element . transform
[ method ]
* *
* Gets or sets transformation of the element
* *
- tstr ( string ) transform string in Snap or SVG format
= ( Element ) the current element
* or
= ( object ) transformation descriptor :
o {
o string ( string ) transform string ,
o globalMatrix ( Matrix ) matrix of all transformations applied to element or its parents ,
o localMatrix ( Matrix ) matrix of transformations applied only to the element ,
o diffMatrix ( Matrix ) matrix of difference between global and local transformations ,
o global ( string ) global transformation as string ,
o local ( string ) local transformation as string ,
o toString ( function ) returns ` string ` property
o }
\ * /
elproto . transform = function ( tstr ) {
var _ = this . _ ;
if ( tstr == null ) {
var papa = this ,
global = new Snap . Matrix ( this . node . getCTM ( ) ) ,
local = extractTransform ( this ) ,
ms = [ local ] ,
m = new Snap . Matrix ,
i ,
localString = local . toTransformString ( ) ,
string = Str ( local ) == Str ( this . matrix ) ?
Str ( _ . transform ) : localString ;
while ( papa . type != "svg" && ( papa = papa . parent ( ) ) ) {
ms . push ( extractTransform ( papa ) ) ;
}
i = ms . length ;
while ( i -- ) {
m . add ( ms [ i ] ) ;
}
return {
string : string ,
globalMatrix : global ,
totalMatrix : m ,
localMatrix : local ,
diffMatrix : global . clone ( ) . add ( local . invert ( ) ) ,
global : global . toTransformString ( ) ,
total : m . toTransformString ( ) ,
local : localString ,
toString : propString
} ;
}
if ( tstr instanceof Snap . Matrix ) {
this . matrix = tstr ;
2014-09-17 07:40:16 +00:00
this . _ . transform = tstr . toTransformString ( ) ;
2014-08-13 12:46:40 +00:00
} else {
extractTransform ( this , tstr ) ;
}
if ( this . node ) {
if ( this . type == "linearGradient" || this . type == "radialGradient" ) {
$ ( this . node , { gradientTransform : this . matrix } ) ;
} else if ( this . type == "pattern" ) {
$ ( this . node , { patternTransform : this . matrix } ) ;
} else {
$ ( this . node , { transform : this . matrix } ) ;
}
}
return this ;
} ;
/ * \
* Element . parent
[ method ]
* *
* Returns the element ' s parent
* *
= ( Element ) the parent element
\ * /
elproto . parent = function ( ) {
return wrap ( this . node . parentNode ) ;
} ;
/ * \
* Element . append
[ method ]
* *
* Appends the given element to current one
* *
- el ( Element | Set ) element to append
= ( Element ) the parent element
\ * /
/ * \
* Element . add
[ method ]
* *
* See @ Element . append
\ * /
elproto . append = elproto . add = function ( el ) {
if ( el ) {
if ( el . type == "set" ) {
var it = this ;
el . forEach ( function ( el ) {
it . add ( el ) ;
} ) ;
return this ;
}
el = wrap ( el ) ;
this . node . appendChild ( el . node ) ;
el . paper = this . paper ;
2013-08-05 08:04:30 +00:00
}
return this ;
} ;
2013-11-19 07:31:04 +00:00
/ * \
* Element . appendTo
[ method ]
* *
* Appends the current element to the given one
* *
- el ( Element ) parent element to append to
= ( Element ) the child element
\ * /
elproto . appendTo = function ( el ) {
2013-11-26 07:46:13 +00:00
if ( el ) {
el = wrap ( el ) ;
el . append ( this ) ;
}
2013-11-19 07:31:04 +00:00
return this ;
} ;
2013-08-20 09:42:07 +00:00
/ * \
* Element . prepend
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Prepends the given element to the current one
2013-08-20 09:42:07 +00:00
* *
- el ( Element ) element to prepend
2013-10-14 11:59:34 +00:00
= ( Element ) the parent element
2013-08-20 09:42:07 +00:00
\ * /
2013-08-05 08:04:30 +00:00
elproto . prepend = function ( el ) {
2013-11-26 07:46:13 +00:00
if ( el ) {
2014-05-15 07:08:19 +00:00
if ( el . type == "set" ) {
2014-05-16 01:15:29 +00:00
var it = this ,
first ;
2014-05-15 07:08:19 +00:00
el . forEach ( function ( el ) {
2014-05-16 01:15:29 +00:00
if ( first ) {
first . after ( el ) ;
} else {
it . prepend ( el ) ;
}
first = el ;
2014-05-15 07:08:19 +00:00
} ) ;
return this ;
}
2013-11-26 07:46:13 +00:00
el = wrap ( el ) ;
var parent = el . parent ( ) ;
this . node . insertBefore ( el . node , this . node . firstChild ) ;
this . add && this . add ( ) ;
el . paper = this . paper ;
this . parent ( ) && this . parent ( ) . add ( ) ;
parent && parent . add ( ) ;
}
2013-08-05 08:04:30 +00:00
return this ;
} ;
2013-11-19 07:31:04 +00:00
/ * \
* Element . prependTo
[ method ]
* *
* Prepends the current element to the given one
* *
- el ( Element ) parent element to prepend to
= ( Element ) the child element
\ * /
elproto . prependTo = function ( el ) {
el = wrap ( el ) ;
el . prepend ( this ) ;
return this ;
} ;
2013-08-20 09:42:07 +00:00
/ * \
* Element . before
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Inserts given element before the current one
2013-08-20 09:42:07 +00:00
* *
- el ( Element ) element to insert
2013-10-14 11:59:34 +00:00
= ( Element ) the parent element
2013-08-20 09:42:07 +00:00
\ * /
2013-08-05 08:04:30 +00:00
elproto . before = function ( el ) {
2013-11-26 07:46:13 +00:00
if ( el . type == "set" ) {
var it = this ;
el . forEach ( function ( el ) {
var parent = el . parent ( ) ;
it . node . parentNode . insertBefore ( el . node , it . node ) ;
parent && parent . add ( ) ;
} ) ;
this . parent ( ) . add ( ) ;
2014-08-13 12:46:40 +00:00
return this ;
}
el = wrap ( el ) ;
var parent = el . parent ( ) ;
this . node . parentNode . insertBefore ( el . node , this . node ) ;
this . parent ( ) && this . parent ( ) . add ( ) ;
parent && parent . add ( ) ;
el . paper = this . paper ;
return this ;
2013-08-05 08:04:30 +00:00
} ;
2013-09-19 11:03:24 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . after
2013-09-19 11:03:24 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Inserts given element after the current one
2013-09-19 11:03:24 +00:00
* *
2014-08-13 12:46:40 +00:00
- el ( Element ) element to insert
= ( Element ) the parent element
2013-09-19 11:03:24 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . after = function ( el ) {
el = wrap ( el ) ;
var parent = el . parent ( ) ;
if ( this . node . nextSibling ) {
this . node . parentNode . insertBefore ( el . node , this . node . nextSibling ) ;
} else {
this . node . parentNode . appendChild ( el . node ) ;
}
this . parent ( ) && this . parent ( ) . add ( ) ;
parent && parent . add ( ) ;
el . paper = this . paper ;
2013-09-19 11:03:24 +00:00
return this ;
} ;
2013-08-20 09:42:07 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . insertBefore
2014-05-06 00:13:22 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Inserts the element after the given one
2013-08-20 09:42:07 +00:00
* *
2014-08-13 12:46:40 +00:00
- el ( Element ) element next to whom insert to
= ( Element ) the parent element
2013-08-20 09:42:07 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . insertBefore = function ( el ) {
el = wrap ( el ) ;
var parent = this . parent ( ) ;
el . node . parentNode . insertBefore ( this . node , el . node ) ;
this . paper = el . paper ;
parent && parent . add ( ) ;
el . parent ( ) && el . parent ( ) . add ( ) ;
return this ;
2013-08-05 08:04:30 +00:00
} ;
2013-08-20 09:42:07 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . insertAfter
2013-08-20 09:42:07 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Inserts the element after the given one
2013-08-20 09:42:07 +00:00
* *
2014-08-13 12:46:40 +00:00
- el ( Element ) element next to whom insert to
= ( Element ) the parent element
2013-08-20 09:42:07 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . insertAfter = function ( el ) {
el = wrap ( el ) ;
var parent = this . parent ( ) ;
el . node . parentNode . insertBefore ( this . node , el . node . nextSibling ) ;
this . paper = el . paper ;
parent && parent . add ( ) ;
el . parent ( ) && el . parent ( ) . add ( ) ;
return this ;
2013-08-20 09:42:07 +00:00
} ;
/ * \
2014-08-13 12:46:40 +00:00
* Element . remove
2013-08-20 09:42:07 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Removes element from the DOM
= ( Element ) the detached element
2013-08-20 09:42:07 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . remove = function ( ) {
var parent = this . parent ( ) ;
this . node . parentNode && this . node . parentNode . removeChild ( this . node ) ;
delete this . paper ;
this . removed = true ;
parent && parent . add ( ) ;
return this ;
2013-08-20 09:42:07 +00:00
} ;
/ * \
2014-08-13 12:46:40 +00:00
* Element . select
2013-08-20 09:42:07 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Gathers the nested @ Element matching the given set of CSS selectors
2013-08-20 09:42:07 +00:00
* *
2014-08-13 12:46:40 +00:00
- query ( string ) CSS selector
= ( Element ) result of query selection
2013-08-20 09:42:07 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . select = function ( query ) {
return wrap ( this . node . querySelector ( query ) ) ;
2013-08-20 09:42:07 +00:00
} ;
2013-08-22 10:00:40 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . selectAll
2013-08-22 10:00:40 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Gathers nested @ Element objects matching the given set of CSS selectors
2013-08-22 10:00:40 +00:00
* *
2014-08-13 12:46:40 +00:00
- query ( string ) CSS selector
= ( Set | array ) result of query selection
2013-08-22 10:00:40 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . selectAll = function ( query ) {
var nodelist = this . node . querySelectorAll ( query ) ,
set = ( Snap . set || Array ) ( ) ;
for ( var i = 0 ; i < nodelist . length ; i ++ ) {
set . push ( wrap ( nodelist [ i ] ) ) ;
2013-08-20 09:42:07 +00:00
}
2014-08-13 12:46:40 +00:00
return set ;
2013-08-20 09:42:07 +00:00
} ;
2013-09-02 04:26:51 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . asPX
2013-09-02 04:26:51 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Returns given attribute of the element as a ` px ` value ( not % , em , etc . )
2013-09-02 04:26:51 +00:00
* *
2014-08-13 12:46:40 +00:00
- attr ( string ) attribute name
- value ( string ) # optional attribute value
= ( Element ) result of query selection
2013-09-02 04:26:51 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . asPX = function ( attr , value ) {
if ( value == null ) {
value = this . attr ( attr ) ;
2013-09-02 04:26:51 +00:00
}
2014-08-13 12:46:40 +00:00
return + unit2px ( this , attr , value ) ;
2013-09-02 04:26:51 +00:00
} ;
2014-08-13 12:46:40 +00:00
// SIERRA Element.use(): I suggest adding a note about how to access the original element the returned <use> instantiates. It's a part of SVG with which ordinary web developers may be least familiar.
2013-08-22 10:00:40 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . use
2013-08-22 10:00:40 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Creates a ` <use> ` element linked to the current element
2013-08-22 10:00:40 +00:00
* *
2014-08-13 12:46:40 +00:00
= ( Element ) the ` <use> ` element
2013-08-22 10:00:40 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . use = function ( ) {
var use ,
id = this . node . id ;
if ( ! id ) {
id = this . id ;
$ ( this . node , {
id : id
} ) ;
2013-08-20 09:42:07 +00:00
}
2014-08-13 12:46:40 +00:00
if ( this . type == "linearGradient" || this . type == "radialGradient" ||
this . type == "pattern" ) {
use = make ( this . type , this . node . parentNode ) ;
} else {
use = make ( "use" , this . node . parentNode ) ;
2013-08-20 09:42:07 +00:00
}
2014-08-13 12:46:40 +00:00
$ ( use . node , {
"xlink:href" : "#" + id
} ) ;
use . original = this ;
return use ;
} ;
function fixids ( el ) {
var els = el . selectAll ( "*" ) ,
it ,
url = /^\s*url\(("|'|)(.*)\1\)\s*$/ ,
ids = [ ] ,
uses = { } ;
function urltest ( it , name ) {
var val = $ ( it . node , name ) ;
val = val && val . match ( url ) ;
val = val && val [ 2 ] ;
if ( val && val . charAt ( ) == "#" ) {
val = val . substring ( 1 ) ;
2013-08-05 08:04:30 +00:00
} else {
2014-08-13 12:46:40 +00:00
return ;
}
if ( val ) {
uses [ val ] = ( uses [ val ] || [ ] ) . concat ( function ( id ) {
var attr = { } ;
2017-01-31 23:47:28 +00:00
attr [ name ] = Snap . url ( id ) ;
2014-08-13 12:46:40 +00:00
$ ( it . node , attr ) ;
} ) ;
2013-08-05 08:04:30 +00:00
}
2013-08-15 08:29:47 +00:00
}
2014-08-13 12:46:40 +00:00
function linktest ( it ) {
var val = $ ( it . node , "xlink:href" ) ;
if ( val && val . charAt ( ) == "#" ) {
val = val . substring ( 1 ) ;
} else {
return ;
}
if ( val ) {
uses [ val ] = ( uses [ val ] || [ ] ) . concat ( function ( id ) {
it . attr ( "xlink:href" , "#" + id ) ;
} ) ;
}
}
for ( var i = 0 , ii = els . length ; i < ii ; i ++ ) {
it = els [ i ] ;
urltest ( it , "fill" ) ;
urltest ( it , "stroke" ) ;
urltest ( it , "filter" ) ;
urltest ( it , "mask" ) ;
urltest ( it , "clip-path" ) ;
linktest ( it ) ;
var oldid = $ ( it . node , "id" ) ;
if ( oldid ) {
$ ( it . node , { id : it . id } ) ;
ids . push ( {
old : oldid ,
id : it . id
} ) ;
}
}
for ( i = 0 , ii = ids . length ; i < ii ; i ++ ) {
var fs = uses [ ids [ i ] . old ] ;
if ( fs ) {
for ( var j = 0 , jj = fs . length ; j < jj ; j ++ ) {
fs [ j ] ( ids [ i ] . id ) ;
2013-08-16 02:56:19 +00:00
}
2014-08-13 12:46:40 +00:00
}
}
}
/ * \
* Element . clone
[ method ]
* *
* Creates a clone of the element and inserts it after the element
* *
= ( Element ) the clone
\ * /
elproto . clone = function ( ) {
var clone = wrap ( this . node . cloneNode ( true ) ) ;
if ( $ ( clone . node , "id" ) ) {
$ ( clone . node , { id : clone . id } ) ;
}
fixids ( clone ) ;
clone . insertAfter ( this ) ;
return clone ;
2013-08-05 08:04:30 +00:00
} ;
2013-09-10 00:06:35 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . toDefs
2013-09-10 00:06:35 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Moves element to the shared ` <defs> ` area
* *
= ( Element ) the element
2013-09-10 00:06:35 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . toDefs = function ( ) {
var defs = getSomeDefs ( this ) ;
defs . appendChild ( this . node ) ;
return this ;
} ;
/ * \
* Element . toPattern
[ method ]
* *
* Creates a ` <pattern> ` element from the current element
* *
* To create a pattern you have to specify the pattern rect :
- x ( string | number )
- y ( string | number )
- width ( string | number )
- height ( string | number )
= ( Element ) the ` <pattern> ` element
* You can use pattern later on as an argument for ` fill ` attribute :
| var p = paper . path ( "M10-5-10,15M15,0,0,15M0-5-20,15" ) . attr ( {
| fill : "none" ,
| stroke : "#bada55" ,
| strokeWidth : 5
| } ) . pattern ( 0 , 0 , 10 , 10 ) ,
| c = paper . circle ( 200 , 200 , 100 ) ;
| c . attr ( {
| fill : p
| } ) ;
\ * /
elproto . pattern = elproto . toPattern = function ( x , y , width , height ) {
var p = make ( "pattern" , getSomeDefs ( this ) ) ;
if ( x == null ) {
x = this . getBBox ( ) ;
2013-12-23 01:27:58 +00:00
}
2014-08-13 12:46:40 +00:00
if ( is ( x , "object" ) && "x" in x ) {
y = x . y ;
width = x . width ;
height = x . height ;
x = x . x ;
2013-09-10 00:06:35 +00:00
}
2014-08-13 12:46:40 +00:00
$ ( p . node , {
x : x ,
y : y ,
width : width ,
height : height ,
patternUnits : "userSpaceOnUse" ,
id : p . id ,
viewBox : [ x , y , width , height ] . join ( " " )
} ) ;
p . node . appendChild ( this . node ) ;
return p ;
2013-09-10 00:06:35 +00:00
} ;
2014-08-13 12:46:40 +00:00
// SIERRA Element.marker(): clarify what a reference point is. E.g., helps you offset the object from its edge such as when centering it over a path.
// SIERRA Element.marker(): I suggest the method should accept default reference point values. Perhaps centered with (refX = width/2) and (refY = height/2)? Also, couldn't it assume the element's current _width_ and _height_? And please specify what _x_ and _y_ mean: offsets? If so, from where? Couldn't they also be assigned default values?
2013-09-10 00:06:35 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . marker
2013-09-10 00:06:35 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Creates a ` <marker> ` element from the current element
* *
* To create a marker you have to specify the bounding rect and reference point :
- x ( number )
- y ( number )
- width ( number )
- height ( number )
- refX ( number )
- refY ( number )
= ( Element ) the ` <marker> ` element
* You can specify the marker later as an argument for ` marker-start ` , ` marker-end ` , ` marker-mid ` , and ` marker ` attributes . The ` marker ` attribute places the marker at every point along the path , and ` marker-mid ` places them at every point except the start and end .
2013-09-10 00:06:35 +00:00
\ * /
2014-08-13 12:46:40 +00:00
// TODO add usage for markers
elproto . marker = function ( x , y , width , height , refX , refY ) {
var p = make ( "marker" , getSomeDefs ( this ) ) ;
if ( x == null ) {
x = this . getBBox ( ) ;
2013-09-10 00:06:35 +00:00
}
2014-08-13 12:46:40 +00:00
if ( is ( x , "object" ) && "x" in x ) {
y = x . y ;
width = x . width ;
height = x . height ;
refX = x . refX || x . cx ;
refY = x . refY || x . cy ;
x = x . x ;
}
$ ( p . node , {
viewBox : [ x , y , width , height ] . join ( " " ) ,
markerWidth : width ,
markerHeight : height ,
orient : "auto" ,
refX : refX || 0 ,
refY : refY || 0 ,
id : p . id
} ) ;
p . node . appendChild ( this . node ) ;
return p ;
} ;
2016-12-29 05:13:00 +00:00
var eldata = { } ;
/ * \
* Element . data
[ method ]
* *
* Adds or retrieves given value associated with given key . ( Don ’ t confuse
* with ` data- ` attributes )
*
* See also @ Element . removeData
- key ( string ) key to store data
- value ( any ) # optional value to store
= ( object ) @ Element
* or , if value is not specified :
= ( any ) value
> Usage
| for ( var i = 0 , i < 5 , i ++ ) {
| paper . circle ( 10 + 15 * i , 10 , 10 )
| . attr ( { fill : "#000" } )
| . data ( "i" , i )
| . click ( function ( ) {
| alert ( this . data ( "i" ) ) ;
| } ) ;
| }
\ * /
elproto . data = function ( key , value ) {
var data = eldata [ this . id ] = eldata [ this . id ] || { } ;
if ( arguments . length == 0 ) {
eve ( "snap.data.get." + this . id , this , data , null ) ;
return data ;
}
if ( arguments . length == 1 ) {
if ( Snap . is ( key , "object" ) ) {
for ( var i in key ) if ( key [ has ] ( i ) ) {
this . data ( i , key [ i ] ) ;
}
return this ;
}
eve ( "snap.data.get." + this . id , this , data [ key ] , key ) ;
return data [ key ] ;
}
data [ key ] = value ;
eve ( "snap.data.set." + this . id , this , value , key ) ;
return this ;
} ;
/ * \
* Element . removeData
[ method ]
* *
* Removes value associated with an element by given key .
* If key is not provided , removes all the data of the element .
- key ( string ) # optional key
= ( object ) @ Element
\ * /
elproto . removeData = function ( key ) {
if ( key == null ) {
eldata [ this . id ] = { } ;
} else {
eldata [ this . id ] && delete eldata [ this . id ] [ key ] ;
}
return this ;
} ;
/ * \
* Element . outerSVG
[ method ]
* *
* Returns SVG code for the element , equivalent to HTML ' s ` outerHTML ` .
*
* See also @ Element . innerSVG
= ( string ) SVG code for the element
\ * /
/ * \
* Element . toString
[ method ]
* *
* See @ Element . outerSVG
\ * /
elproto . outerSVG = elproto . toString = toString ( 1 ) ;
/ * \
* Element . innerSVG
[ method ]
* *
* Returns SVG code for the element 's contents, equivalent to HTML' s ` innerHTML `
= ( string ) SVG code for the element
\ * /
elproto . innerSVG = toString ( ) ;
function toString ( type ) {
return function ( ) {
var res = type ? "<" + this . type : "" ,
attr = this . node . attributes ,
chld = this . node . childNodes ;
if ( type ) {
for ( var i = 0 , ii = attr . length ; i < ii ; i ++ ) {
res += " " + attr [ i ] . name + '="' +
attr [ i ] . value . replace ( /"/g , '\\"' ) + '"' ;
}
}
if ( chld . length ) {
type && ( res += ">" ) ;
for ( i = 0 , ii = chld . length ; i < ii ; i ++ ) {
if ( chld [ i ] . nodeType == 3 ) {
res += chld [ i ] . nodeValue ;
} else if ( chld [ i ] . nodeType == 1 ) {
res += wrap ( chld [ i ] ) . toString ( ) ;
}
}
type && ( res += "</" + this . type + ">" ) ;
} else {
type && ( res += "/>" ) ;
}
return res ;
} ;
}
elproto . toDataURL = function ( ) {
if ( window && window . btoa ) {
var bb = this . getBBox ( ) ,
svg = Snap . format ( '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{width}" height="{height}" viewBox="{x} {y} {width} {height}">{contents}</svg>' , {
x : + bb . x . toFixed ( 3 ) ,
y : + bb . y . toFixed ( 3 ) ,
width : + bb . width . toFixed ( 3 ) ,
height : + bb . height . toFixed ( 3 ) ,
contents : this . outerSVG ( )
} ) ;
return "data:image/svg+xml;base64," + btoa ( unescape ( encodeURIComponent ( svg ) ) ) ;
}
} ;
/ * \
* Fragment . select
[ method ]
* *
* See @ Element . select
\ * /
Fragment . prototype . select = elproto . select ;
/ * \
* Fragment . selectAll
[ method ]
* *
* See @ Element . selectAll
\ * /
Fragment . prototype . selectAll = elproto . selectAll ;
} ) ;
// Copyright (c) 2016 Adobe Systems Incorporated. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var elproto = Element . prototype ,
is = Snap . is ,
Str = String ,
has = "hasOwnProperty" ;
2014-08-13 12:46:40 +00:00
function slice ( from , to , f ) {
return function ( arr ) {
var res = arr . slice ( from , to ) ;
if ( res . length == 1 ) {
res = res [ 0 ] ;
}
return f ? f ( res ) : res ;
} ;
}
var Animation = function ( attr , ms , easing , callback ) {
if ( typeof easing == "function" && ! easing . length ) {
callback = easing ;
easing = mina . linear ;
}
this . attr = attr ;
this . dur = ms ;
easing && ( this . easing = easing ) ;
callback && ( this . callback = callback ) ;
2013-09-10 00:06:35 +00:00
} ;
2014-08-13 12:46:40 +00:00
Snap . _ . Animation = Animation ;
2013-09-11 04:38:52 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Snap . animation
2013-09-11 04:38:52 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Creates an animation object
2013-11-25 01:00:34 +00:00
* *
2014-08-13 12:46:40 +00:00
- attr ( object ) attributes of final destination
- duration ( number ) duration of the animation , in milliseconds
- easing ( function ) # optional one of easing functions of @ mina or custom one
- callback ( function ) # optional callback function that fires when animation ends
= ( object ) animation object
2013-11-25 01:00:34 +00:00
\ * /
2014-08-13 12:46:40 +00:00
Snap . animation = function ( attr , ms , easing , callback ) {
return new Animation ( attr , ms , easing , callback ) ;
} ;
2013-09-11 04:38:52 +00:00
/ * \
2014-08-13 12:46:40 +00:00
* Element . inAnim
2013-09-11 04:38:52 +00:00
[ method ]
* *
2014-08-13 12:46:40 +00:00
* Returns a set of animations that may be able to manipulate the current element
* *
= ( object ) in format :
o {
o anim ( object ) animation object ,
o mina ( object ) @ mina object ,
o curStatus ( number ) 0. . 1 — status of the animation : 0 — just started , 1 — just finished ,
o status ( function ) gets or sets the status of the animation ,
o stop ( function ) stops the animation
o }
2013-09-11 04:38:52 +00:00
\ * /
2014-08-13 12:46:40 +00:00
elproto . inAnim = function ( ) {
var el = this ,
res = [ ] ;
for ( var id in el . anims ) if ( el . anims [ has ] ( id ) ) {
( function ( a ) {
res . push ( {
anim : new Animation ( a . _attrs , a . dur , a . easing , a . _callback ) ,
mina : a ,
curStatus : a . status ( ) ,
status : function ( val ) {
return a . status ( val ) ;
} ,
stop : function ( ) {
a . stop ( ) ;
2013-09-11 04:38:52 +00:00
}
2014-08-13 12:46:40 +00:00
} ) ;
} ( el . anims [ id ] ) ) ;
2013-08-05 08:04:30 +00:00
}
2014-08-13 12:46:40 +00:00
return res ;
} ;
/ * \
* Snap . animate
[ method ]
* *
* Runs generic animation of one number into another with a caring function
* *
- from ( number | array ) number or array of numbers
- to ( number | array ) number or array of numbers
- setter ( function ) caring function that accepts one number argument
- duration ( number ) duration , in milliseconds
- easing ( function ) # optional easing function from @ mina or custom
- callback ( function ) # optional callback function to execute when animation ends
= ( object ) animation object in @ mina format
o {
o id ( string ) animation id , consider it read - only ,
o duration ( function ) gets or sets the duration of the animation ,
o easing ( function ) easing ,
o speed ( function ) gets or sets the speed of the animation ,
o status ( function ) gets or sets the status of the animation ,
o stop ( function ) stops the animation
o }
| var rect = Snap ( ) . rect ( 0 , 0 , 10 , 10 ) ;
| Snap . animate ( 0 , 10 , function ( val ) {
| rect . attr ( {
| x : val
| } ) ;
| } , 1000 ) ;
| // in given context is equivalent to
| rect . animate ( { x : 10 } , 1000 ) ;
\ * /
Snap . animate = function ( from , to , setter , ms , easing , callback ) {
if ( typeof easing == "function" && ! easing . length ) {
callback = easing ;
easing = mina . linear ;
2013-08-05 08:04:30 +00:00
}
2014-08-13 12:46:40 +00:00
var now = mina . time ( ) ,
anim = mina ( from , to , now , now + ms , mina . time , setter , easing ) ;
callback && eve . once ( "mina.finish." + anim . id , callback ) ;
return anim ;
} ;
/ * \
* Element . stop
[ method ]
* *
* Stops all the animations for the current element
* *
= ( Element ) the current element
\ * /
elproto . stop = function ( ) {
var anims = this . inAnim ( ) ;
for ( var i = 0 , ii = anims . length ; i < ii ; i ++ ) {
anims [ i ] . stop ( ) ;
2013-09-19 11:03:24 +00:00
}
2014-08-13 12:46:40 +00:00
return this ;
} ;
/ * \
* Element . animate
[ method ]
* *
* Animates the given attributes of the element
* *
- attrs ( object ) key - value pairs of destination attributes
- duration ( number ) duration of the animation in milliseconds
- easing ( function ) # optional easing function from @ mina or custom
- callback ( function ) # optional callback function that executes when the animation ends
= ( Element ) the current element
\ * /
elproto . animate = function ( attrs , ms , easing , callback ) {
if ( typeof easing == "function" && ! easing . length ) {
callback = easing ;
easing = mina . linear ;
2013-09-19 11:03:24 +00:00
}
2014-08-13 12:46:40 +00:00
if ( attrs instanceof Animation ) {
callback = attrs . callback ;
easing = attrs . easing ;
2015-04-13 06:21:39 +00:00
ms = attrs . dur ;
2014-08-13 12:46:40 +00:00
attrs = attrs . attr ;
2013-09-19 11:03:24 +00:00
}
2014-08-13 12:46:40 +00:00
var fkeys = [ ] , tkeys = [ ] , keys = { } , from , to , f , eq ,
el = this ;
for ( var key in attrs ) if ( attrs [ has ] ( key ) ) {
if ( el . equal ) {
eq = el . equal ( key , Str ( attrs [ key ] ) ) ;
from = eq . from ;
to = eq . to ;
f = eq . f ;
} else {
from = + el . attr ( key ) ;
to = + attrs [ key ] ;
2014-05-07 08:37:05 +00:00
}
2014-08-13 12:46:40 +00:00
var len = is ( from , "array" ) ? from . length : 1 ;
keys [ key ] = slice ( fkeys . length , fkeys . length + len , f ) ;
fkeys = fkeys . concat ( from ) ;
tkeys = tkeys . concat ( to ) ;
2014-05-07 08:37:05 +00:00
}
2014-08-13 12:46:40 +00:00
var now = mina . time ( ) ,
anim = mina ( fkeys , tkeys , now , now + ms , mina . time , function ( val ) {
var attr = { } ;
for ( var key in keys ) if ( keys [ has ] ( key ) ) {
attr [ key ] = keys [ key ] ( val ) ;
}
el . attr ( attr ) ;
} , easing ) ;
el . anims [ anim . id ] = anim ;
anim . _attrs = attrs ;
anim . _callback = callback ;
eve ( "snap.animcreated." + el . id , anim ) ;
eve . once ( "mina.finish." + anim . id , function ( ) {
2016-08-01 01:37:11 +00:00
eve . off ( "mina.*." + anim . id ) ;
2014-08-13 12:46:40 +00:00
delete el . anims [ anim . id ] ;
callback && callback . call ( el ) ;
} ) ;
eve . once ( "mina.stop." + anim . id , function ( ) {
2016-08-01 01:37:11 +00:00
eve . off ( "mina.*." + anim . id ) ;
2014-08-13 12:46:40 +00:00
delete el . anims [ anim . id ] ;
} ) ;
return el ;
} ;
} ) ;
2014-08-25 06:52:37 +00:00
2014-05-07 08:37:05 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2016-08-01 01:37:11 +00:00
//
2014-05-07 08:37:05 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2016-08-01 01:37:11 +00:00
//
2014-05-07 08:37:05 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2016-08-01 01:37:11 +00:00
//
2014-05-07 08:37:05 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var objectToString = Object . prototype . toString ,
Str = String ,
math = Math ,
E = "" ;
function Matrix ( a , b , c , d , e , f ) {
if ( b == null && objectToString . call ( a ) == "[object SVGMatrix]" ) {
this . a = a . a ;
this . b = a . b ;
this . c = a . c ;
this . d = a . d ;
this . e = a . e ;
this . f = a . f ;
return ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
if ( a != null ) {
this . a = + a ;
this . b = + b ;
this . c = + c ;
this . d = + d ;
this . e = + e ;
this . f = + f ;
} else {
this . a = 1 ;
this . b = 0 ;
this . c = 0 ;
this . d = 1 ;
this . e = 0 ;
this . f = 0 ;
}
}
( function ( matrixproto ) {
/ * \
* Matrix . add
[ method ]
* *
* Adds the given matrix to existing one
- a ( number )
- b ( number )
- c ( number )
- d ( number )
- e ( number )
- f ( number )
* or
- matrix ( object ) @ Matrix
\ * /
matrixproto . add = function ( a , b , c , d , e , f ) {
2016-08-01 01:37:11 +00:00
if ( a && a instanceof Matrix ) {
return this . add ( a . a , a . b , a . c , a . d , a . e , a . f ) ;
}
var aNew = a * this . a + b * this . c ,
bNew = a * this . b + b * this . d ;
this . e += e * this . a + f * this . c ;
this . f += e * this . b + f * this . d ;
this . c = c * this . a + d * this . c ;
this . d = c * this . b + d * this . d ;
2014-05-07 08:37:05 +00:00
2016-08-01 01:37:11 +00:00
this . a = aNew ;
this . b = bNew ;
return this ;
} ;
/ * \
* Matrix . multLeft
[ method ]
* *
* Multiplies a passed affine transform to the left : M * this .
- a ( number )
- b ( number )
- c ( number )
- d ( number )
- e ( number )
- f ( number )
* or
- matrix ( object ) @ Matrix
\ * /
Matrix . prototype . multLeft = function ( a , b , c , d , e , f ) {
2014-05-07 08:37:05 +00:00
if ( a && a instanceof Matrix ) {
2016-08-01 01:37:11 +00:00
return this . multLeft ( a . a , a . b , a . c , a . d , a . e , a . f ) ;
}
var aNew = a * this . a + c * this . b ,
cNew = a * this . c + c * this . d ,
eNew = a * this . e + c * this . f + e ;
this . b = b * this . a + d * this . b ;
this . d = b * this . c + d * this . d ;
this . f = b * this . e + d * this . f + f ;
2014-05-07 08:37:05 +00:00
2016-08-01 01:37:11 +00:00
this . a = aNew ;
this . c = cNew ;
this . e = eNew ;
2014-05-07 08:37:05 +00:00
return this ;
} ;
/ * \
* Matrix . invert
[ method ]
* *
* Returns an inverted version of the matrix
= ( object ) @ Matrix
\ * /
matrixproto . invert = function ( ) {
var me = this ,
x = me . a * me . d - me . b * me . c ;
return new Matrix ( me . d / x , - me . b / x , - me . c / x , me . a / x , ( me . c * me . f - me . d * me . e ) / x , ( me . b * me . e - me . a * me . f ) / x ) ;
} ;
/ * \
* Matrix . clone
[ method ]
* *
* Returns a copy of the matrix
= ( object ) @ Matrix
\ * /
matrixproto . clone = function ( ) {
return new Matrix ( this . a , this . b , this . c , this . d , this . e , this . f ) ;
} ;
/ * \
* Matrix . translate
[ method ]
* *
* Translate the matrix
- x ( number ) horizontal offset distance
- y ( number ) vertical offset distance
\ * /
matrixproto . translate = function ( x , y ) {
2016-12-14 00:40:56 +00:00
this . e += x * this . a + y * this . c ;
this . f += x * this . b + y * this . d ;
2016-08-01 01:37:11 +00:00
return this ;
2014-05-07 08:37:05 +00:00
} ;
/ * \
* Matrix . scale
[ method ]
* *
* Scales the matrix
- x ( number ) amount to be scaled , with ` 1 ` resulting in no change
- y ( number ) # optional amount to scale along the vertical axis . ( Otherwise ` x ` applies to both axes . )
- cx ( number ) # optional horizontal origin point from which to scale
- cy ( number ) # optional vertical origin point from which to scale
* Default cx , cy is the middle point of the element .
\ * /
matrixproto . scale = function ( x , y , cx , cy ) {
2016-12-14 00:40:56 +00:00
y == null && ( y = x ) ;
( cx || cy ) && this . translate ( cx , cy ) ;
this . a *= x ;
this . b *= x ;
this . c *= y ;
this . d *= y ;
( cx || cy ) && this . translate ( - cx , - cy ) ;
2014-05-07 08:37:05 +00:00
return this ;
} ;
/ * \
* Matrix . rotate
[ method ]
* *
* Rotates the matrix
- a ( number ) angle of rotation , in degrees
- x ( number ) horizontal origin point from which to rotate
- y ( number ) vertical origin point from which to rotate
\ * /
matrixproto . rotate = function ( a , x , y ) {
a = Snap . rad ( a ) ;
x = x || 0 ;
y = y || 0 ;
var cos = + math . cos ( a ) . toFixed ( 9 ) ,
sin = + math . sin ( a ) . toFixed ( 9 ) ;
this . add ( cos , sin , - sin , cos , x , y ) ;
return this . add ( 1 , 0 , 0 , 1 , - x , - y ) ;
} ;
2016-08-01 01:37:11 +00:00
/ * \
* Matrix . skewX
[ method ]
* *
* Skews the matrix along the x - axis
- x ( number ) Angle to skew along the x - axis ( in degrees ) .
\ * /
matrixproto . skewX = function ( x ) {
return this . skew ( x , 0 ) ;
} ;
/ * \
* Matrix . skewY
[ method ]
* *
* Skews the matrix along the y - axis
- y ( number ) Angle to skew along the y - axis ( in degrees ) .
\ * /
matrixproto . skewY = function ( y ) {
return this . skew ( 0 , y ) ;
} ;
/ * \
* Matrix . skew
[ method ]
* *
* Skews the matrix
- y ( number ) Angle to skew along the y - axis ( in degrees ) .
- x ( number ) Angle to skew along the x - axis ( in degrees ) .
\ * /
matrixproto . skew = function ( x , y ) {
x = x || 0 ;
y = y || 0 ;
x = Snap . rad ( x ) ;
y = Snap . rad ( y ) ;
var c = math . tan ( x ) . toFixed ( 9 ) ;
var b = math . tan ( y ) . toFixed ( 9 ) ;
return this . add ( 1 , b , c , 1 , 0 , 0 ) ;
} ;
2014-05-07 08:37:05 +00:00
/ * \
* Matrix . x
[ method ]
* *
* Returns x coordinate for given point after transformation described by the matrix . See also @ Matrix . y
- x ( number )
- y ( number )
= ( number ) x
\ * /
matrixproto . x = function ( x , y ) {
return x * this . a + y * this . c + this . e ;
} ;
/ * \
* Matrix . y
[ method ]
* *
* Returns y coordinate for given point after transformation described by the matrix . See also @ Matrix . x
- x ( number )
- y ( number )
= ( number ) y
\ * /
matrixproto . y = function ( x , y ) {
return x * this . b + y * this . d + this . f ;
} ;
matrixproto . get = function ( i ) {
return + this [ Str . fromCharCode ( 97 + i ) ] . toFixed ( 4 ) ;
} ;
matrixproto . toString = function ( ) {
return "matrix(" + [ this . get ( 0 ) , this . get ( 1 ) , this . get ( 2 ) , this . get ( 3 ) , this . get ( 4 ) , this . get ( 5 ) ] . join ( ) + ")" ;
} ;
matrixproto . offset = function ( ) {
return [ this . e . toFixed ( 4 ) , this . f . toFixed ( 4 ) ] ;
} ;
function norm ( a ) {
return a [ 0 ] * a [ 0 ] + a [ 1 ] * a [ 1 ] ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
function normalize ( a ) {
var mag = math . sqrt ( norm ( a ) ) ;
a [ 0 ] && ( a [ 0 ] /= mag ) ;
a [ 1 ] && ( a [ 1 ] /= mag ) ;
}
/ * \
* Matrix . determinant
[ method ]
* *
* Finds determinant of the given matrix .
= ( number ) determinant
\ * /
matrixproto . determinant = function ( ) {
return this . a * this . d - this . b * this . c ;
} ;
/ * \
* Matrix . split
[ method ]
* *
* Splits matrix into primitive transformations
= ( object ) in format :
o dx ( number ) translation by x
o dy ( number ) translation by y
o scalex ( number ) scale by x
o scaley ( number ) scale by y
o shear ( number ) shear
o rotate ( number ) rotation in deg
o isSimple ( boolean ) could it be represented via simple transformations
\ * /
matrixproto . split = function ( ) {
var out = { } ;
// translation
out . dx = this . e ;
out . dy = this . f ;
// scale and shear
2016-12-14 00:40:56 +00:00
var row = [ [ this . a , this . b ] , [ this . c , this . d ] ] ;
2014-05-07 08:37:05 +00:00
out . scalex = math . sqrt ( norm ( row [ 0 ] ) ) ;
normalize ( row [ 0 ] ) ;
out . shear = row [ 0 ] [ 0 ] * row [ 1 ] [ 0 ] + row [ 0 ] [ 1 ] * row [ 1 ] [ 1 ] ;
row [ 1 ] = [ row [ 1 ] [ 0 ] - row [ 0 ] [ 0 ] * out . shear , row [ 1 ] [ 1 ] - row [ 0 ] [ 1 ] * out . shear ] ;
out . scaley = math . sqrt ( norm ( row [ 1 ] ) ) ;
normalize ( row [ 1 ] ) ;
out . shear /= out . scaley ;
if ( this . determinant ( ) < 0 ) {
out . scalex = - out . scalex ;
}
// rotation
2016-12-14 00:40:56 +00:00
var sin = row [ 0 ] [ 1 ] ,
2014-05-07 08:37:05 +00:00
cos = row [ 1 ] [ 1 ] ;
if ( cos < 0 ) {
out . rotate = Snap . deg ( math . acos ( cos ) ) ;
if ( sin < 0 ) {
out . rotate = 360 - out . rotate ;
}
} else {
out . rotate = Snap . deg ( math . asin ( sin ) ) ;
}
out . isSimple = ! + out . shear . toFixed ( 9 ) && ( out . scalex . toFixed ( 9 ) == out . scaley . toFixed ( 9 ) || ! out . rotate ) ;
out . isSuperSimple = ! + out . shear . toFixed ( 9 ) && out . scalex . toFixed ( 9 ) == out . scaley . toFixed ( 9 ) && ! out . rotate ;
out . noRotation = ! + out . shear . toFixed ( 9 ) && ! out . rotate ;
return out ;
} ;
/ * \
* Matrix . toTransformString
[ method ]
* *
* Returns transform string that represents given matrix
= ( string ) transform string
\ * /
matrixproto . toTransformString = function ( shorter ) {
var s = shorter || this . split ( ) ;
if ( ! + s . shear . toFixed ( 9 ) ) {
s . scalex = + s . scalex . toFixed ( 4 ) ;
s . scaley = + s . scaley . toFixed ( 4 ) ;
s . rotate = + s . rotate . toFixed ( 4 ) ;
2016-08-01 01:37:11 +00:00
return ( s . dx || s . dy ? "t" + [ + s . dx . toFixed ( 4 ) , + s . dy . toFixed ( 4 ) ] : E ) +
2016-12-14 00:40:56 +00:00
( s . rotate ? "r" + [ + s . rotate . toFixed ( 4 ) , 0 , 0 ] : E ) +
( s . scalex != 1 || s . scaley != 1 ? "s" + [ s . scalex , s . scaley , 0 , 0 ] : E ) ;
2014-05-07 08:37:05 +00:00
} else {
return "m" + [ this . get ( 0 ) , this . get ( 1 ) , this . get ( 2 ) , this . get ( 3 ) , this . get ( 4 ) , this . get ( 5 ) ] ;
}
} ;
} ) ( Matrix . prototype ) ;
2013-08-22 10:00:40 +00:00
/ * \
2014-05-07 08:37:05 +00:00
* Snap . Matrix
2013-08-22 10:00:40 +00:00
[ method ]
* *
2014-05-23 11:03:03 +00:00
* Matrix constructor , extend on your own risk .
* To create matrices use @ Snap . matrix .
\ * /
Snap . Matrix = Matrix ;
/ * \
* Snap . matrix
[ method ]
* *
2014-05-07 08:37:05 +00:00
* Utility method
2013-08-22 10:00:40 +00:00
* *
2014-05-07 08:37:05 +00:00
* Returns a matrix based on the given parameters
- a ( number )
- b ( number )
- c ( number )
- d ( number )
- e ( number )
- f ( number )
* or
- svgMatrix ( SVGMatrix )
= ( object ) @ Matrix
\ * /
2014-05-23 11:03:03 +00:00
Snap . matrix = function ( a , b , c , d , e , f ) {
return new Matrix ( a , b , c , d , e , f ) ;
} ;
2014-05-07 08:37:05 +00:00
} ) ;
2016-08-01 01:37:11 +00:00
2014-05-07 08:37:05 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2017-01-18 00:42:08 +00:00
//
2014-05-07 08:37:05 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2017-01-18 00:42:08 +00:00
//
2014-05-07 08:37:05 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2017-01-18 00:42:08 +00:00
//
2014-05-07 08:37:05 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var has = "hasOwnProperty" ,
make = Snap . _ . make ,
wrap = Snap . _ . wrap ,
is = Snap . is ,
getSomeDefs = Snap . _ . getSomeDefs ,
2017-02-05 02:17:33 +00:00
reURLValue = /^url\((['"]?)([^)]+)\1\)$/ ,
2014-05-07 08:37:05 +00:00
$ = Snap . _ . $ ,
URL = Snap . url ,
Str = String ,
separator = Snap . _ . separator ,
E = "" ;
2017-01-24 02:32:41 +00:00
/ * \
2017-02-05 01:17:21 +00:00
* Snap . deurl
2017-01-24 02:32:41 +00:00
[ method ]
* *
* Unwraps path from ` "url(<path>)" ` .
- value ( string ) url path
= ( string ) unwrapped path
\ * /
2017-01-24 02:08:13 +00:00
Snap . deurl = function ( value ) {
2017-02-06 01:05:34 +00:00
var res = String ( value ) . match ( reURLValue ) ;
return res ? res [ 2 ] : value ;
2017-01-24 02:08:13 +00:00
}
2014-05-07 08:37:05 +00:00
// Attributes event handlers
eve . on ( "snap.util.attr.mask" , function ( value ) {
if ( value instanceof Element || value instanceof Fragment ) {
eve . stop ( ) ;
if ( value instanceof Fragment && value . node . childNodes . length == 1 ) {
value = value . node . firstChild ;
getSomeDefs ( this ) . appendChild ( value ) ;
value = wrap ( value ) ;
}
if ( value . type == "mask" ) {
var mask = value ;
} else {
mask = make ( "mask" , getSomeDefs ( this ) ) ;
mask . node . appendChild ( value . node ) ;
}
2014-05-16 02:30:49 +00:00
! mask . node . id && $ ( mask . node , {
id : mask . id
} ) ;
2014-05-07 08:37:05 +00:00
$ ( this . node , {
mask : URL ( mask . id )
} ) ;
}
} ) ;
( function ( clipIt ) {
eve . on ( "snap.util.attr.clip" , clipIt ) ;
eve . on ( "snap.util.attr.clip-path" , clipIt ) ;
eve . on ( "snap.util.attr.clipPath" , clipIt ) ;
} ( function ( value ) {
if ( value instanceof Element || value instanceof Fragment ) {
eve . stop ( ) ;
2017-02-03 11:19:22 +00:00
var clip ,
node = value . node ;
while ( node ) {
if ( node . nodeName === "clipPath" ) {
clip = new Element ( node ) ;
break ;
}
if ( node . nodeName === "svg" ) {
clip = undefined ;
break ;
}
node = node . parentNode ;
}
if ( ! clip ) {
2014-05-07 08:37:05 +00:00
clip = make ( "clipPath" , getSomeDefs ( this ) ) ;
clip . node . appendChild ( value . node ) ;
! clip . node . id && $ ( clip . node , {
id : clip . id
} ) ;
}
$ ( this . node , {
2014-08-03 22:59:28 +00:00
"clip-path" : URL ( clip . node . id || clip . id )
2014-05-07 08:37:05 +00:00
} ) ;
}
} ) ) ;
function fillStroke ( name ) {
return function ( value ) {
eve . stop ( ) ;
if ( value instanceof Fragment && value . node . childNodes . length == 1 &&
( value . node . firstChild . tagName == "radialGradient" ||
value . node . firstChild . tagName == "linearGradient" ||
value . node . firstChild . tagName == "pattern" ) ) {
value = value . node . firstChild ;
getSomeDefs ( this ) . appendChild ( value ) ;
value = wrap ( value ) ;
}
if ( value instanceof Element ) {
if ( value . type == "radialGradient" || value . type == "linearGradient"
|| value . type == "pattern" ) {
if ( ! value . node . id ) {
$ ( value . node , {
id : value . id
} ) ;
}
var fill = URL ( value . node . id ) ;
} else {
fill = value . attr ( name ) ;
}
} else {
fill = Snap . color ( value ) ;
if ( fill . error ) {
2014-05-12 06:47:29 +00:00
var grad = Snap ( getSomeDefs ( this ) . ownerSVGElement ) . gradient ( value ) ;
2014-05-07 08:37:05 +00:00
if ( grad ) {
if ( ! grad . node . id ) {
$ ( grad . node , {
id : grad . id
} ) ;
}
fill = URL ( grad . node . id ) ;
} else {
fill = value ;
}
} else {
fill = Str ( fill ) ;
}
}
var attrs = { } ;
attrs [ name ] = fill ;
$ ( this . node , attrs ) ;
this . node . style [ name ] = E ;
} ;
}
eve . on ( "snap.util.attr.fill" , fillStroke ( "fill" ) ) ;
eve . on ( "snap.util.attr.stroke" , fillStroke ( "stroke" ) ) ;
var gradrg = /^([lr])(?:\(([^)]*)\))?(.*)$/i ;
eve . on ( "snap.util.grad.parse" , function parseGrad ( string ) {
string = Str ( string ) ;
var tokens = string . match ( gradrg ) ;
if ( ! tokens ) {
return null ;
}
var type = tokens [ 1 ] ,
params = tokens [ 2 ] ,
stops = tokens [ 3 ] ;
params = params . split ( /\s*,\s*/ ) . map ( function ( el ) {
return + el == el ? + el : el ;
} ) ;
if ( params . length == 1 && params [ 0 ] == 0 ) {
params = [ ] ;
}
stops = stops . split ( "-" ) ;
stops = stops . map ( function ( el ) {
el = el . split ( ":" ) ;
var out = {
color : el [ 0 ]
} ;
if ( el [ 1 ] ) {
out . offset = parseFloat ( el [ 1 ] ) ;
}
return out ;
} ) ;
2017-01-24 02:08:13 +00:00
var len = stops . length ,
start = 0 ,
j = 0 ;
function seed ( i , end ) {
var step = ( end - start ) / ( i - j ) ;
for ( var k = j ; k < i ; k ++ ) {
stops [ k ] . offset = + ( + start + step * ( k - j ) ) . toFixed ( 2 ) ;
}
j = i ;
start = end ;
}
len -- ;
for ( var i = 0 ; i < len ; i ++ ) if ( "offset" in stops [ i ] ) {
seed ( i , stops [ i ] . offset ) ;
}
stops [ len ] . offset = stops [ len ] . offset || 100 ;
seed ( len , stops [ len ] . offset ) ;
2014-05-07 08:37:05 +00:00
return {
type : type ,
params : params ,
stops : stops
} ;
} ) ;
eve . on ( "snap.util.attr.d" , function ( value ) {
eve . stop ( ) ;
if ( is ( value , "array" ) && is ( value [ 0 ] , "array" ) ) {
value = Snap . path . toString . call ( value ) ;
}
value = Str ( value ) ;
if ( value . match ( /[ruo]/i ) ) {
value = Snap . path . toAbsolute ( value ) ;
}
$ ( this . node , { d : value } ) ;
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.#text" , function ( value ) {
eve . stop ( ) ;
value = Str ( value ) ;
var txt = glob . doc . createTextNode ( value ) ;
while ( this . node . firstChild ) {
this . node . removeChild ( this . node . firstChild ) ;
}
this . node . appendChild ( txt ) ;
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.path" , function ( value ) {
eve . stop ( ) ;
this . attr ( { d : value } ) ;
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.class" , function ( value ) {
eve . stop ( ) ;
this . node . className . baseVal = value ;
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.viewBox" , function ( value ) {
var vb ;
if ( is ( value , "object" ) && "x" in value ) {
vb = [ value . x , value . y , value . width , value . height ] . join ( " " ) ;
} else if ( is ( value , "array" ) ) {
vb = value . join ( " " ) ;
} else {
vb = value ;
}
$ ( this . node , {
viewBox : vb
} ) ;
eve . stop ( ) ;
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.transform" , function ( value ) {
this . transform ( value ) ;
eve . stop ( ) ;
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.r" , function ( value ) {
if ( this . type == "rect" ) {
eve . stop ( ) ;
$ ( this . node , {
rx : value ,
ry : value
} ) ;
}
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.textpath" , function ( value ) {
eve . stop ( ) ;
if ( this . type == "text" ) {
var id , tp , node ;
if ( ! value && this . textPath ) {
tp = this . textPath ;
while ( tp . node . firstChild ) {
this . node . appendChild ( tp . node . firstChild ) ;
}
tp . remove ( ) ;
delete this . textPath ;
return ;
}
if ( is ( value , "string" ) ) {
var defs = getSomeDefs ( this ) ,
path = wrap ( defs . parentNode ) . path ( value ) ;
defs . appendChild ( path . node ) ;
id = path . id ;
path . attr ( { id : id } ) ;
} else {
value = wrap ( value ) ;
if ( value instanceof Element ) {
id = value . attr ( "id" ) ;
if ( ! id ) {
id = value . id ;
value . attr ( { id : id } ) ;
}
}
}
if ( id ) {
tp = this . textPath ;
node = this . node ;
if ( tp ) {
tp . attr ( { "xlink:href" : "#" + id } ) ;
} else {
tp = $ ( "textPath" , {
"xlink:href" : "#" + id
} ) ;
while ( node . firstChild ) {
tp . appendChild ( node . firstChild ) ;
}
node . appendChild ( tp ) ;
this . textPath = wrap ( tp ) ;
}
}
}
} ) ( - 1 ) ;
eve . on ( "snap.util.attr.text" , function ( value ) {
if ( this . type == "text" ) {
var i = 0 ,
node = this . node ,
tuner = function ( chunk ) {
var out = $ ( "tspan" ) ;
if ( is ( chunk , "array" ) ) {
for ( var i = 0 ; i < chunk . length ; i ++ ) {
out . appendChild ( tuner ( chunk [ i ] ) ) ;
}
} else {
out . appendChild ( glob . doc . createTextNode ( chunk ) ) ;
}
out . normalize && out . normalize ( ) ;
return out ;
} ;
while ( node . firstChild ) {
node . removeChild ( node . firstChild ) ;
}
var tuned = tuner ( value ) ;
while ( tuned . firstChild ) {
node . appendChild ( tuned . firstChild ) ;
}
}
eve . stop ( ) ;
} ) ( - 1 ) ;
2014-05-28 20:29:35 +00:00
function setFontSize ( value ) {
eve . stop ( ) ;
if ( value == + value ) {
value += "px" ;
}
this . node . style . fontSize = value ;
}
eve . on ( "snap.util.attr.fontSize" , setFontSize ) ( - 1 ) ;
eve . on ( "snap.util.attr.font-size" , setFontSize ) ( - 1 ) ;
2014-05-07 08:37:05 +00:00
eve . on ( "snap.util.getattr.transform" , function ( ) {
eve . stop ( ) ;
return this . transform ( ) ;
} ) ( - 1 ) ;
eve . on ( "snap.util.getattr.textpath" , function ( ) {
eve . stop ( ) ;
return this . textPath ;
} ) ( - 1 ) ;
// Markers
( function ( ) {
function getter ( end ) {
return function ( ) {
eve . stop ( ) ;
var style = glob . doc . defaultView . getComputedStyle ( this . node , null ) . getPropertyValue ( "marker-" + end ) ;
if ( style == "none" ) {
return style ;
} else {
return Snap ( glob . doc . getElementById ( style . match ( reURLValue ) [ 1 ] ) ) ;
}
} ;
}
function setter ( end ) {
return function ( value ) {
eve . stop ( ) ;
var name = "marker" + end . charAt ( 0 ) . toUpperCase ( ) + end . substring ( 1 ) ;
if ( value == "" || ! value ) {
this . node . style [ name ] = "none" ;
return ;
}
if ( value . type == "marker" ) {
var id = value . node . id ;
if ( ! id ) {
$ ( value . node , { id : value . id } ) ;
}
this . node . style [ name ] = URL ( id ) ;
return ;
}
} ;
}
eve . on ( "snap.util.getattr.marker-end" , getter ( "end" ) ) ( - 1 ) ;
eve . on ( "snap.util.getattr.markerEnd" , getter ( "end" ) ) ( - 1 ) ;
eve . on ( "snap.util.getattr.marker-start" , getter ( "start" ) ) ( - 1 ) ;
eve . on ( "snap.util.getattr.markerStart" , getter ( "start" ) ) ( - 1 ) ;
eve . on ( "snap.util.getattr.marker-mid" , getter ( "mid" ) ) ( - 1 ) ;
eve . on ( "snap.util.getattr.markerMid" , getter ( "mid" ) ) ( - 1 ) ;
eve . on ( "snap.util.attr.marker-end" , setter ( "end" ) ) ( - 1 ) ;
eve . on ( "snap.util.attr.markerEnd" , setter ( "end" ) ) ( - 1 ) ;
eve . on ( "snap.util.attr.marker-start" , setter ( "start" ) ) ( - 1 ) ;
eve . on ( "snap.util.attr.markerStart" , setter ( "start" ) ) ( - 1 ) ;
eve . on ( "snap.util.attr.marker-mid" , setter ( "mid" ) ) ( - 1 ) ;
eve . on ( "snap.util.attr.markerMid" , setter ( "mid" ) ) ( - 1 ) ;
} ( ) ) ;
eve . on ( "snap.util.getattr.r" , function ( ) {
if ( this . type == "rect" && $ ( this . node , "rx" ) == $ ( this . node , "ry" ) ) {
eve . stop ( ) ;
return $ ( this . node , "rx" ) ;
}
} ) ( - 1 ) ;
function textExtract ( node ) {
var out = [ ] ;
var children = node . childNodes ;
for ( var i = 0 , ii = children . length ; i < ii ; i ++ ) {
var chi = children [ i ] ;
if ( chi . nodeType == 3 ) {
out . push ( chi . nodeValue ) ;
}
if ( chi . tagName == "tspan" ) {
if ( chi . childNodes . length == 1 && chi . firstChild . nodeType == 3 ) {
out . push ( chi . firstChild . nodeValue ) ;
} else {
out . push ( textExtract ( chi ) ) ;
}
}
}
return out ;
}
eve . on ( "snap.util.getattr.text" , function ( ) {
if ( this . type == "text" || this . type == "tspan" ) {
eve . stop ( ) ;
var out = textExtract ( this . node ) ;
return out . length == 1 ? out [ 0 ] : out ;
}
} ) ( - 1 ) ;
eve . on ( "snap.util.getattr.#text" , function ( ) {
return this . node . textContent ;
} ) ( - 1 ) ;
2017-01-24 02:08:13 +00:00
eve . on ( "snap.util.getattr.fill" , function ( internal ) {
if ( internal ) {
return ;
}
eve . stop ( ) ;
var value = eve ( "snap.util.getattr.fill" , this , true ) . firstDefined ( ) ;
2017-02-05 02:17:33 +00:00
return Snap ( Snap . deurl ( value ) ) || value ;
2017-01-24 02:08:13 +00:00
} ) ( - 1 ) ;
eve . on ( "snap.util.getattr.stroke" , function ( internal ) {
if ( internal ) {
return ;
}
eve . stop ( ) ;
var value = eve ( "snap.util.getattr.stroke" , this , true ) . firstDefined ( ) ;
2017-02-05 02:17:33 +00:00
return Snap ( Snap . deurl ( value ) ) || value ;
2017-01-24 02:08:13 +00:00
} ) ( - 1 ) ;
2014-05-07 08:37:05 +00:00
eve . on ( "snap.util.getattr.viewBox" , function ( ) {
eve . stop ( ) ;
var vb = $ ( this . node , "viewBox" ) ;
if ( vb ) {
vb = vb . split ( separator ) ;
return Snap . _ . box ( + vb [ 0 ] , + vb [ 1 ] , + vb [ 2 ] , + vb [ 3 ] ) ;
} else {
return ;
}
} ) ( - 1 ) ;
eve . on ( "snap.util.getattr.points" , function ( ) {
var p = $ ( this . node , "points" ) ;
eve . stop ( ) ;
2014-05-15 07:08:19 +00:00
if ( p ) {
return p . split ( separator ) ;
} else {
return ;
}
2014-05-23 11:03:03 +00:00
} ) ( - 1 ) ;
2014-05-07 08:37:05 +00:00
eve . on ( "snap.util.getattr.path" , function ( ) {
var p = $ ( this . node , "d" ) ;
eve . stop ( ) ;
return p ;
2014-05-23 11:03:03 +00:00
} ) ( - 1 ) ;
2014-05-07 08:37:05 +00:00
eve . on ( "snap.util.getattr.class" , function ( ) {
return this . node . className . baseVal ;
2014-05-23 11:03:03 +00:00
} ) ( - 1 ) ;
2014-05-07 08:37:05 +00:00
function getFontSize ( ) {
eve . stop ( ) ;
return this . node . style . fontSize ;
}
eve . on ( "snap.util.getattr.fontSize" , getFontSize ) ( - 1 ) ;
eve . on ( "snap.util.getattr.font-size" , getFontSize ) ( - 1 ) ;
} ) ;
2014-08-04 11:22:04 +00:00
2014-06-13 03:48:24 +00:00
// Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
2014-07-31 08:39:33 +00:00
//
2014-06-13 03:48:24 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2014-07-31 08:39:33 +00:00
//
2014-06-13 03:48:24 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2014-07-31 08:39:33 +00:00
//
2014-06-13 03:48:24 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var rgNotSpace = /\S+/g ,
rgBadSpace = /[\t\r\n\f]/g ,
rgTrim = /(^\s+|\s+$)/g ,
Str = String ,
elproto = Element . prototype ;
/ * \
* Element . addClass
[ method ]
* *
* Adds given class name or list of class names to the element .
- value ( string ) class name or space separated list of class names
* *
= ( Element ) original element .
\ * /
elproto . addClass = function ( value ) {
var classes = Str ( value || "" ) . match ( rgNotSpace ) || [ ] ,
elem = this . node ,
className = elem . className . baseVal ,
curClasses = className . match ( rgNotSpace ) || [ ] ,
j ,
pos ,
clazz ,
finalValue ;
if ( classes . length ) {
j = 0 ;
2017-01-24 02:32:41 +00:00
while ( clazz = classes [ j ++ ] ) {
2014-06-13 03:48:24 +00:00
pos = curClasses . indexOf ( clazz ) ;
if ( ! ~ pos ) {
curClasses . push ( clazz ) ;
}
}
finalValue = curClasses . join ( " " ) ;
if ( className != finalValue ) {
elem . className . baseVal = finalValue ;
}
}
return this ;
} ;
/ * \
* Element . removeClass
[ method ]
* *
* Removes given class name or list of class names from the element .
- value ( string ) class name or space separated list of class names
* *
= ( Element ) original element .
\ * /
elproto . removeClass = function ( value ) {
var classes = Str ( value || "" ) . match ( rgNotSpace ) || [ ] ,
elem = this . node ,
className = elem . className . baseVal ,
curClasses = className . match ( rgNotSpace ) || [ ] ,
j ,
pos ,
clazz ,
finalValue ;
if ( curClasses . length ) {
j = 0 ;
2017-01-24 02:32:41 +00:00
while ( clazz = classes [ j ++ ] ) {
2014-06-13 03:48:24 +00:00
pos = curClasses . indexOf ( clazz ) ;
if ( ~ pos ) {
curClasses . splice ( pos , 1 ) ;
}
}
finalValue = curClasses . join ( " " ) ;
if ( className != finalValue ) {
elem . className . baseVal = finalValue ;
}
}
return this ;
} ;
/ * \
* Element . hasClass
[ method ]
* *
* Checks if the element has a given class name in the list of class names applied to it .
- value ( string ) class name
* *
= ( boolean ) ` true ` if the element has given class
\ * /
elproto . hasClass = function ( value ) {
var elem = this . node ,
className = elem . className . baseVal ,
curClasses = className . match ( rgNotSpace ) || [ ] ;
return ! ! ~ curClasses . indexOf ( value ) ;
} ;
/ * \
* Element . toggleClass
[ method ]
* *
* Add or remove one or more classes from the element , depending on either
2014-07-31 08:39:33 +00:00
* the class ’ s presence or the value of the ` flag ` argument .
2014-06-13 03:48:24 +00:00
- value ( string ) class name or space separated list of class names
- flag ( boolean ) value to determine whether the class should be added or removed
* *
= ( Element ) original element .
\ * /
elproto . toggleClass = function ( value , flag ) {
if ( flag != null ) {
if ( flag ) {
return this . addClass ( value ) ;
} else {
return this . removeClass ( value ) ;
}
}
var classes = ( value || "" ) . match ( rgNotSpace ) || [ ] ,
elem = this . node ,
className = elem . className . baseVal ,
curClasses = className . match ( rgNotSpace ) || [ ] ,
j ,
pos ,
clazz ,
finalValue ;
j = 0 ;
2017-01-24 02:32:41 +00:00
while ( clazz = classes [ j ++ ] ) {
2014-06-13 03:48:24 +00:00
pos = curClasses . indexOf ( clazz ) ;
if ( ~ pos ) {
curClasses . splice ( pos , 1 ) ;
} else {
curClasses . push ( clazz ) ;
}
}
finalValue = curClasses . join ( " " ) ;
if ( className != finalValue ) {
elem . className . baseVal = finalValue ;
}
return this ;
} ;
} ) ;
2014-08-03 22:59:28 +00:00
2014-05-07 08:37:05 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2016-12-22 00:33:43 +00:00
//
2014-05-07 08:37:05 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2016-12-22 00:33:43 +00:00
//
2014-05-07 08:37:05 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2016-12-22 00:33:43 +00:00
//
2014-05-07 08:37:05 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2014-05-15 06:58:04 +00:00
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var operators = {
"+" : function ( x , y ) {
return x + y ;
} ,
"-" : function ( x , y ) {
return x - y ;
} ,
"/" : function ( x , y ) {
return x / y ;
} ,
"*" : function ( x , y ) {
return x * y ;
}
} ,
Str = String ,
reUnit = /[a-z]+$/i ,
reAddon = /^\s*([+\-\/*])\s*=\s*([\d.eE+\-]+)\s*([^\d\s]+)?\s*$/ ;
function getNumber ( val ) {
return val ;
}
function getUnit ( unit ) {
return function ( val ) {
return + val . toFixed ( 3 ) + unit ;
} ;
}
eve . on ( "snap.util.attr" , function ( val ) {
var plus = Str ( val ) . match ( reAddon ) ;
if ( plus ) {
var evnt = eve . nt ( ) ,
name = evnt . substring ( evnt . lastIndexOf ( "." ) + 1 ) ,
a = this . attr ( name ) ,
atr = { } ;
eve . stop ( ) ;
var unit = plus [ 3 ] || "" ,
aUnit = a . match ( reUnit ) ,
op = operators [ plus [ 1 ] ] ;
if ( aUnit && aUnit == unit ) {
val = op ( parseFloat ( a ) , + plus [ 2 ] ) ;
} else {
a = this . asPX ( name ) ;
val = op ( this . asPX ( name ) , this . asPX ( name , plus [ 2 ] + unit ) ) ;
}
if ( isNaN ( a ) || isNaN ( val ) ) {
return ;
}
atr [ name ] = val ;
this . attr ( atr ) ;
}
} ) ( - 10 ) ;
eve . on ( "snap.util.equal" , function ( name , b ) {
var A , B , a = Str ( this . attr ( name ) || "" ) ,
el = this ,
bplus = Str ( b ) . match ( reAddon ) ;
if ( bplus ) {
eve . stop ( ) ;
var unit = bplus [ 3 ] || "" ,
aUnit = a . match ( reUnit ) ,
op = operators [ bplus [ 1 ] ] ;
if ( aUnit && aUnit == unit ) {
return {
from : parseFloat ( a ) ,
to : op ( parseFloat ( a ) , + bplus [ 2 ] ) ,
f : getUnit ( aUnit )
} ;
} else {
a = this . asPX ( name ) ;
return {
from : a ,
to : op ( a , this . asPX ( name , bplus [ 2 ] + unit ) ) ,
f : getNumber
} ;
}
}
} ) ( - 10 ) ;
} ) ;
2016-12-29 05:13:00 +00:00
2014-05-15 06:58:04 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2017-01-18 00:42:08 +00:00
//
2014-05-15 06:58:04 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2017-01-18 00:42:08 +00:00
//
2014-05-15 06:58:04 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2017-01-18 00:42:08 +00:00
//
2014-05-15 06:58:04 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2014-05-07 08:37:05 +00:00
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var proto = Paper . prototype ,
is = Snap . is ;
/ * \
* Paper . rect
[ method ]
*
* Draws a rectangle
* *
- x ( number ) x coordinate of the top left corner
- y ( number ) y coordinate of the top left corner
- width ( number ) width
- height ( number ) height
- rx ( number ) # optional horizontal radius for rounded corners , default is 0
- ry ( number ) # optional vertical radius for rounded corners , default is rx or 0
= ( object ) the ` rect ` element
* *
> Usage
| // regular rectangle
| var c = paper . rect ( 10 , 10 , 50 , 50 ) ;
| // rectangle with rounded corners
| var c = paper . rect ( 40 , 40 , 50 , 50 , 10 ) ;
\ * /
proto . rect = function ( x , y , w , h , rx , ry ) {
var attr ;
if ( ry == null ) {
ry = rx ;
}
if ( is ( x , "object" ) && x == "[object Object]" ) {
attr = x ;
} else if ( x != null ) {
attr = {
x : x ,
y : y ,
width : w ,
height : h
} ;
if ( rx != null ) {
attr . rx = rx ;
attr . ry = ry ;
}
}
return this . el ( "rect" , attr ) ;
} ;
/ * \
* Paper . circle
[ method ]
* *
* Draws a circle
* *
- x ( number ) x coordinate of the centre
- y ( number ) y coordinate of the centre
2013-08-22 10:00:40 +00:00
- r ( number ) radius
2013-10-14 11:59:34 +00:00
= ( object ) the ` circle ` element
2013-08-22 10:00:40 +00:00
* *
> Usage
| var c = paper . circle ( 50 , 50 , 40 ) ;
\ * /
2013-08-05 08:04:30 +00:00
proto . circle = function ( cx , cy , r ) {
2013-11-25 01:00:34 +00:00
var attr ;
2014-04-18 00:31:07 +00:00
if ( is ( cx , "object" ) && cx == "[object Object]" ) {
2013-11-25 01:00:34 +00:00
attr = cx ;
2013-08-05 08:04:30 +00:00
} else if ( cx != null ) {
2013-11-25 01:00:34 +00:00
attr = {
2013-08-05 08:04:30 +00:00
cx : cx ,
cy : cy ,
r : r
2013-11-25 01:00:34 +00:00
} ;
2013-08-05 08:04:30 +00:00
}
2013-11-25 01:00:34 +00:00
return this . el ( "circle" , attr ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-10-14 11:59:34 +00:00
2014-05-07 08:37:05 +00:00
var preload = ( function ( ) {
function onerror ( ) {
this . parentNode . removeChild ( this ) ;
}
return function ( src , f ) {
var img = glob . doc . createElement ( "img" ) ,
body = glob . doc . body ;
img . style . cssText = "position:absolute;left:-9999em;top:-9999em" ;
img . onload = function ( ) {
f . call ( img ) ;
img . onload = img . onerror = null ;
body . removeChild ( img ) ;
} ;
img . onerror = onerror ;
body . appendChild ( img ) ;
img . src = src ;
} ;
} ( ) ) ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . image
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Places an image on the surface
2013-08-22 10:00:40 +00:00
* *
- src ( string ) URI of the source image
2013-10-14 11:59:34 +00:00
- x ( number ) x offset position
- y ( number ) y offset position
2013-08-22 10:00:40 +00:00
- width ( number ) width of the image
- height ( number ) height of the image
2013-10-14 11:59:34 +00:00
= ( object ) the ` image ` element
* or
2013-11-25 01:00:34 +00:00
= ( object ) Snap element object with type ` image `
2013-08-22 10:00:40 +00:00
* *
> Usage
| var c = paper . image ( "apple.png" , 10 , 10 , 80 , 80 ) ;
\ * /
2013-08-05 08:04:30 +00:00
proto . image = function ( src , x , y , width , height ) {
2014-05-07 08:37:05 +00:00
var el = this . el ( "image" ) ;
2013-08-05 08:04:30 +00:00
if ( is ( src , "object" ) && "src" in src ) {
el . attr ( src ) ;
} else if ( src != null ) {
var set = {
"xlink:href" : src ,
preserveAspectRatio : "none"
} ;
if ( x != null && y != null ) {
set . x = x ;
set . y = y ;
}
if ( width != null && height != null ) {
set . width = width ;
set . height = height ;
} else {
preload ( src , function ( ) {
2014-05-07 08:37:05 +00:00
Snap . _ . $ ( el . node , {
2013-08-05 08:04:30 +00:00
width : this . offsetWidth ,
height : this . offsetHeight
} ) ;
} ) ;
}
2014-05-07 08:37:05 +00:00
Snap . _ . $ ( el . node , set ) ;
2013-08-05 08:04:30 +00:00
}
return el ;
} ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . ellipse
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Draws an ellipse
2013-08-22 10:00:40 +00:00
* *
- x ( number ) x coordinate of the centre
- y ( number ) y coordinate of the centre
- rx ( number ) horizontal radius
- ry ( number ) vertical radius
2013-10-14 11:59:34 +00:00
= ( object ) the ` ellipse ` element
2013-08-22 10:00:40 +00:00
* *
> Usage
| var c = paper . ellipse ( 50 , 50 , 40 , 20 ) ;
\ * /
2013-08-05 08:04:30 +00:00
proto . ellipse = function ( cx , cy , rx , ry ) {
2014-05-07 08:37:05 +00:00
var attr ;
2014-04-18 00:31:07 +00:00
if ( is ( cx , "object" ) && cx == "[object Object]" ) {
2014-05-07 08:37:05 +00:00
attr = cx ;
2013-08-05 08:04:30 +00:00
} else if ( cx != null ) {
2014-05-07 08:37:05 +00:00
attr = {
2013-08-05 08:04:30 +00:00
cx : cx ,
cy : cy ,
rx : rx ,
ry : ry
2014-05-07 08:37:05 +00:00
} ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
return this . el ( "ellipse" , attr ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-10-14 11:59:34 +00:00
// SIERRA Paper.path(): Unclear from the link what a Catmull-Rom curveto is, and why it would make life any easier.
2013-08-22 10:00:40 +00:00
/ * \
* Paper . path
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Creates a ` <path> ` element using the given string as the path ' s definition
- pathString ( string ) # optional path string in SVG format
* Path string consists of one - letter commands , followed by comma seprarated arguments in numerical form . Example :
2013-08-22 10:00:40 +00:00
| "M10,20L30,40"
2013-10-14 11:59:34 +00:00
* This example features two commands : ` M ` , with arguments ` (10, 20) ` and ` L ` with arguments ` (30, 40) ` . Uppercase letter commands express coordinates in absolute terms , while lowercase commands express them in relative terms from the most recently declared coordinates .
2013-08-22 10:00:40 +00:00
*
# < p > Here is short list of commands available , for more details see < 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 path string format < /a> or <a href="https:/ / developer . mozilla . org / en / SVG / Tutorial / Paths " > article about path strings at MDN < / a > . < / p >
# < table > < thead > < tr > < th > Command < / t h > < t h > N a m e < / t h > < t h > P a r a m e t e r s < / t h > < / t r > < / t h e a d > < t b o d y >
# < tr > < td > M < / t d > < t d > m o v e t o < / t d > < t d > ( x y ) + < / t d > < / t r >
# < tr > < td > Z < / t d > < t d > c l o s e p a t h < / t d > < t d > ( n o n e ) < / t d > < / t r >
# < tr > < td > L < / t d > < t d > l i n e t o < / t d > < t d > ( x y ) + < / t d > < / t r >
# < tr > < td > H < / t d > < t d > h o r i z o n t a l l i n e t o < / t d > < t d > x + < / t d > < / t r >
# < tr > < td > V < / t d > < t d > v e r t i c a l l i n e t o < / t d > < t d > y + < / t d > < / t r >
# < tr > < td > C < / t d > < t d > c u r v e t o < / t d > < t d > ( x 1 y 1 x 2 y 2 x y ) + < / t d > < / t r >
# < tr > < td > S < / t d > < t d > s m o o t h c u r v e t o < / t d > < t d > ( x 2 y 2 x y ) + < / t d > < / t r >
# < tr > < td > Q < / t d > < t d > q u a d r a t i c B é z i e r c u r v e t o < / t d > < t d > ( x 1 y 1 x y ) + < / t d > < / t r >
# < tr > < td > T < / t d > < t d > s m o o t h q u a d r a t i c B é z i e r c u r v e t o < / t d > < t d > ( x y ) + < / t d > < / t r >
# < tr > < td > A < / t d > < t d > e l l i p t i c a l a r c < / t d > < t d > ( r x r y x - a x i s - r o t a t i o n l a r g e - a r c - f l a g s w e e p - f l a g x y ) + < / t d > < / t r >
# < tr > < td > R < /td><td><a href="http:/ / en . wikipedia . org / wiki / Catmull – Rom _spline # Catmull . E2 . 80.93 Rom _spline " > Catmull - Rom curveto < / a > * < / t d > < t d > x 1 y 1 ( x y ) + < / t d > < / t r > < / t b o d y > < / t a b l e >
2013-10-14 11:59:34 +00:00
* * _Catmull - Rom curveto _ is a not standard SVG command and added to make life easier .
* Note : there is a special case when a path consists of only three commands : ` M10,10R…z ` . In this case the path connects back to its starting point .
2013-08-22 10:00:40 +00:00
> Usage
| var c = paper . path ( "M10 10L90 90" ) ;
| // draw a diagonal line:
| // move to 10,10, line to 90,90
\ * /
2013-08-05 08:04:30 +00:00
proto . path = function ( d ) {
2014-05-07 08:37:05 +00:00
var attr ;
2013-09-17 06:33:21 +00:00
if ( is ( d , "object" ) && ! is ( d , "array" ) ) {
2014-05-07 08:37:05 +00:00
attr = d ;
2013-08-05 08:04:30 +00:00
} else if ( d ) {
2014-05-07 08:37:05 +00:00
attr = { d : d } ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
return this . el ( "path" , attr ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . g
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Creates a group element
2013-08-22 10:00:40 +00:00
* *
2013-10-14 11:59:34 +00:00
- varargs ( … ) # optional elements to nest within the group
= ( object ) the ` g ` element
2013-08-22 10:00:40 +00:00
* *
> Usage
| var c1 = paper . circle ( ) ,
| c2 = paper . rect ( ) ,
2013-10-14 11:59:34 +00:00
| g = paper . g ( c2 , c1 ) ; // note that the order of elements is different
2013-08-22 10:00:40 +00:00
* or
| var c1 = paper . circle ( ) ,
| c2 = paper . rect ( ) ,
| g = paper . g ( ) ;
| g . add ( c2 , c1 ) ;
\ * /
/ * \
* Paper . group
[ method ]
* *
* See @ Paper . g
\ * /
2013-09-09 07:36:48 +00:00
proto . group = proto . g = function ( first ) {
2014-05-07 08:37:05 +00:00
var attr ,
el = this . el ( "g" ) ;
2013-09-09 07:36:48 +00:00
if ( arguments . length == 1 && first && ! first . type ) {
el . attr ( first ) ;
} else if ( arguments . length ) {
el . add ( Array . prototype . slice . call ( arguments , 0 ) ) ;
2013-08-05 08:04:30 +00:00
}
return el ;
} ;
2014-04-22 07:12:11 +00:00
/ * \
* Paper . svg
[ method ]
* *
* Creates a nested SVG element .
2014-05-06 00:13:22 +00:00
- x ( number ) @ optional X of the element
- y ( number ) @ optional Y of the element
2014-04-22 07:12:11 +00:00
- width ( number ) @ optional width of the element
- height ( number ) @ optional height of the element
2014-05-06 00:13:22 +00:00
- vbx ( number ) @ optional viewbox X
- vby ( number ) @ optional viewbox Y
- vbw ( number ) @ optional viewbox width
- vbh ( number ) @ optional viewbox height
2014-04-22 07:12:11 +00:00
* *
= ( object ) the ` svg ` element
* *
\ * /
2014-05-06 00:13:22 +00:00
proto . svg = function ( x , y , width , height , vbx , vby , vbw , vbh ) {
2014-05-07 08:37:05 +00:00
var attrs = { } ;
2014-05-06 00:13:22 +00:00
if ( is ( x , "object" ) && y == null ) {
attrs = x ;
} else {
if ( x != null ) {
attrs . x = x ;
}
if ( y != null ) {
attrs . y = y ;
}
if ( width != null ) {
attrs . width = width ;
}
if ( height != null ) {
attrs . height = height ;
}
if ( vbx != null && vby != null && vbw != null && vbh != null ) {
attrs . viewBox = [ vbx , vby , vbw , vbh ] ;
}
2014-04-22 07:12:11 +00:00
}
2014-05-07 08:37:05 +00:00
return this . el ( "svg" , attrs ) ;
2014-05-06 00:13:22 +00:00
} ;
/ * \
* Paper . mask
[ method ]
* *
* Equivalent in behaviour to @ Paper . g , except it ’ s a mask .
* *
= ( object ) the ` mask ` element
* *
\ * /
proto . mask = function ( first ) {
2014-05-07 08:37:05 +00:00
var attr ,
el = this . el ( "mask" ) ;
2014-05-06 00:13:22 +00:00
if ( arguments . length == 1 && first && ! first . type ) {
el . attr ( first ) ;
} else if ( arguments . length ) {
el . add ( Array . prototype . slice . call ( arguments , 0 ) ) ;
2014-04-22 07:12:11 +00:00
}
2014-05-06 00:13:22 +00:00
return el ;
} ;
/ * \
* Paper . ptrn
[ method ]
* *
2014-06-13 03:48:24 +00:00
* Equivalent in behaviour to @ Paper . g , except it ’ s a pattern .
2014-05-06 00:13:22 +00:00
- x ( number ) @ optional X of the element
- y ( number ) @ optional Y of the element
- width ( number ) @ optional width of the element
- height ( number ) @ optional height of the element
- vbx ( number ) @ optional viewbox X
- vby ( number ) @ optional viewbox Y
- vbw ( number ) @ optional viewbox width
- vbh ( number ) @ optional viewbox height
* *
2014-06-13 03:48:24 +00:00
= ( object ) the ` pattern ` element
2014-05-06 00:13:22 +00:00
* *
\ * /
proto . ptrn = function ( x , y , width , height , vx , vy , vw , vh ) {
2014-05-07 08:37:05 +00:00
if ( is ( x , "object" ) ) {
var attr = x ;
2014-05-06 00:13:22 +00:00
} else {
2014-08-25 06:52:37 +00:00
attr = { patternUnits : "userSpaceOnUse" } ;
if ( x ) {
2014-05-07 08:37:05 +00:00
attr . x = x ;
}
2014-08-25 06:52:37 +00:00
if ( y ) {
2014-05-07 08:37:05 +00:00
attr . y = y ;
}
if ( width != null ) {
attr . width = width ;
}
if ( height != null ) {
attr . height = height ;
}
2014-05-15 06:58:04 +00:00
if ( vx != null && vy != null && vw != null && vh != null ) {
attr . viewBox = [ vx , vy , vw , vh ] ;
2014-10-28 10:48:17 +00:00
} else {
attr . viewBox = [ x || 0 , y || 0 , width || 0 , height || 0 ] ;
2014-05-06 00:13:22 +00:00
}
}
2014-05-07 08:37:05 +00:00
return this . el ( "pattern" , attr ) ;
2014-04-22 07:12:11 +00:00
} ;
2014-04-22 09:09:21 +00:00
/ * \
* Paper . use
[ method ]
* *
* Creates a < use > element .
- id ( string ) @ optional id of element to link
* or
- id ( Element ) @ optional element to link
* *
= ( object ) the ` use ` element
* *
\ * /
proto . use = function ( id ) {
2014-05-06 00:13:22 +00:00
if ( id != null ) {
if ( id instanceof Element ) {
if ( ! id . attr ( "id" ) ) {
2014-08-04 11:22:04 +00:00
id . attr ( { id : Snap . _ . id ( id ) } ) ;
2014-05-06 00:13:22 +00:00
}
id = id . attr ( "id" ) ;
2014-04-22 09:09:21 +00:00
}
2014-08-13 12:46:40 +00:00
if ( String ( id ) . charAt ( ) == "#" ) {
id = id . substring ( 1 ) ;
}
2014-08-04 11:22:04 +00:00
return this . el ( "use" , { "xlink:href" : "#" + id } ) ;
2014-05-06 00:13:22 +00:00
} else {
return Element . prototype . use . call ( this ) ;
2014-04-22 09:09:21 +00:00
}
} ;
2014-08-04 11:22:04 +00:00
/ * \
* Paper . symbol
[ method ]
* *
* Creates a < symbol > element .
- vbx ( number ) @ optional viewbox X
- vby ( number ) @ optional viewbox Y
- vbw ( number ) @ optional viewbox width
- vbh ( number ) @ optional viewbox height
= ( object ) the ` symbol ` element
* *
\ * /
proto . symbol = function ( vx , vy , vw , vh ) {
var attr = { } ;
if ( vx != null && vy != null && vw != null && vh != null ) {
attr . viewBox = [ vx , vy , vw , vh ] ;
}
return this . el ( "symbol" , attr ) ;
} ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . text
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Draws a text string
2013-08-22 10:00:40 +00:00
* *
- x ( number ) x coordinate position
- y ( number ) y coordinate position
2013-10-14 11:59:34 +00:00
- text ( string | array ) The text string to draw or array of strings to nest within separate ` <tspan> ` elements
= ( object ) the ` text ` element
2013-08-22 10:00:40 +00:00
* *
> Usage
2013-09-25 05:52:57 +00:00
| var t1 = paper . text ( 50 , 50 , "Snap" ) ;
| var t2 = paper . text ( 50 , 50 , [ "S" , "n" , "a" , "p" ] ) ;
2013-12-23 01:26:40 +00:00
| // Text path usage
| t1 . attr ( { textpath : "M10,10L100,100" } ) ;
| // or
| var pth = paper . path ( "M10,10L100,100" ) ;
| t1 . attr ( { textpath : pth } ) ;
2013-08-22 10:00:40 +00:00
\ * /
2013-08-05 08:04:30 +00:00
proto . text = function ( x , y , text ) {
2014-05-07 08:37:05 +00:00
var attr = { } ;
2013-08-05 08:04:30 +00:00
if ( is ( x , "object" ) ) {
2014-05-07 08:37:05 +00:00
attr = x ;
2013-08-05 08:04:30 +00:00
} else if ( x != null ) {
2014-05-07 08:37:05 +00:00
attr = {
2013-08-05 08:04:30 +00:00
x : x ,
y : y ,
text : text || ""
2014-05-07 08:37:05 +00:00
} ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
return this . el ( "text" , attr ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . line
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Draws a line
2013-08-22 10:00:40 +00:00
* *
- x1 ( number ) x coordinate position of the start
- y1 ( number ) y coordinate position of the start
- x2 ( number ) x coordinate position of the end
- y2 ( number ) y coordinate position of the end
2013-10-14 11:59:34 +00:00
= ( object ) the ` line ` element
2013-08-22 10:00:40 +00:00
* *
> Usage
| var t1 = paper . line ( 50 , 50 , 100 , 100 ) ;
\ * /
2013-08-05 08:04:30 +00:00
proto . line = function ( x1 , y1 , x2 , y2 ) {
2014-05-07 08:37:05 +00:00
var attr = { } ;
2013-08-05 08:04:30 +00:00
if ( is ( x1 , "object" ) ) {
2014-05-07 08:37:05 +00:00
attr = x1 ;
2013-08-05 08:04:30 +00:00
} else if ( x1 != null ) {
2014-05-07 08:37:05 +00:00
attr = {
2013-08-05 08:04:30 +00:00
x1 : x1 ,
x2 : x2 ,
y1 : y1 ,
y2 : y2
2014-05-07 08:37:05 +00:00
} ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
return this . el ( "line" , attr ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . polyline
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Draws a polyline
2013-08-22 10:00:40 +00:00
* *
- points ( array ) array of points
* or
- varargs ( … ) points
2013-10-14 11:59:34 +00:00
= ( object ) the ` polyline ` element
2013-08-22 10:00:40 +00:00
* *
> Usage
| var p1 = paper . polyline ( [ 10 , 10 , 100 , 100 ] ) ;
| var p2 = paper . polyline ( 10 , 10 , 100 , 100 ) ;
\ * /
2013-08-05 08:04:30 +00:00
proto . polyline = function ( points ) {
if ( arguments . length > 1 ) {
points = Array . prototype . slice . call ( arguments , 0 ) ;
}
2014-05-07 08:37:05 +00:00
var attr = { } ;
2013-08-05 08:04:30 +00:00
if ( is ( points , "object" ) && ! is ( points , "array" ) ) {
2014-05-07 08:37:05 +00:00
attr = points ;
2013-08-05 08:04:30 +00:00
} else if ( points != null ) {
2014-05-07 08:37:05 +00:00
attr = { points : points } ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
return this . el ( "polyline" , attr ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . polygon
[ method ]
* *
* Draws a polygon . See @ Paper . polyline
\ * /
2013-08-05 08:04:30 +00:00
proto . polygon = function ( points ) {
if ( arguments . length > 1 ) {
points = Array . prototype . slice . call ( arguments , 0 ) ;
}
2014-05-07 08:37:05 +00:00
var attr = { } ;
2013-08-05 08:04:30 +00:00
if ( is ( points , "object" ) && ! is ( points , "array" ) ) {
2014-05-07 08:37:05 +00:00
attr = points ;
2013-08-05 08:04:30 +00:00
} else if ( points != null ) {
2014-05-07 08:37:05 +00:00
attr = { points : points } ;
2013-08-05 08:04:30 +00:00
}
2014-05-07 08:37:05 +00:00
return this . el ( "polygon" , attr ) ;
2013-08-05 08:04:30 +00:00
} ;
// gradients
( function ( ) {
2014-05-07 08:37:05 +00:00
var $ = Snap . _ . $ ;
// gradients' helpers
2017-01-24 02:08:13 +00:00
/ * \
2017-02-05 01:17:21 +00:00
* Element . stops
2017-01-24 02:08:13 +00:00
[ method ]
* *
* Only for gradients !
* Returns array of gradient stops elements .
= ( array ) the stops array .
\ * /
2014-05-07 08:37:05 +00:00
function Gstops ( ) {
return this . selectAll ( "stop" ) ;
}
2017-01-24 02:08:13 +00:00
/ * \
2017-02-05 01:17:21 +00:00
* Element . addStop
2017-01-24 02:08:13 +00:00
[ method ]
* *
* Only for gradients !
* Adds another stop to the gradient .
- color ( string ) stops color
- offset ( number ) stops offset 0. . 100
= ( object ) gradient element
\ * /
2014-05-07 08:37:05 +00:00
function GaddStop ( color , offset ) {
var stop = $ ( "stop" ) ,
attr = {
offset : + offset + "%"
} ;
color = Snap . color ( color ) ;
2017-01-24 02:08:13 +00:00
attr [ "stop-color" ] = color . hex ;
2014-05-07 08:37:05 +00:00
if ( color . opacity < 1 ) {
attr [ "stop-opacity" ] = color . opacity ;
}
$ ( stop , attr ) ;
2017-01-24 02:08:13 +00:00
var stops = this . stops ( ) ,
inserted ;
for ( var i = 0 ; i < stops . length ; i ++ ) {
2017-01-24 02:32:41 +00:00
var stopOffset = parseFloat ( stops [ i ] . attr ( "offset" ) ) ;
if ( stopOffset > offset ) {
2017-01-24 02:08:13 +00:00
this . node . insertBefore ( stop , stops [ i ] . node ) ;
inserted = true ;
break ;
}
}
if ( ! inserted ) {
this . node . appendChild ( stop ) ;
}
2014-05-07 08:37:05 +00:00
return this ;
}
function GgetBBox ( ) {
if ( this . type == "linearGradient" ) {
var x1 = $ ( this . node , "x1" ) || 0 ,
x2 = $ ( this . node , "x2" ) || 1 ,
y1 = $ ( this . node , "y1" ) || 0 ,
y2 = $ ( this . node , "y2" ) || 0 ;
return Snap . _ . box ( x1 , y1 , math . abs ( x2 - x1 ) , math . abs ( y2 - y1 ) ) ;
} else {
var cx = this . node . cx || . 5 ,
cy = this . node . cy || . 5 ,
r = this . node . r || 0 ;
return Snap . _ . box ( cx - r , cy - r , r * 2 , r * 2 ) ;
}
}
2017-01-24 02:08:13 +00:00
/ * \
2017-02-05 01:17:21 +00:00
* Element . setStops
2017-01-24 02:08:13 +00:00
[ method ]
* *
* Only for gradients !
* Updates stops of the gradient based on passed gradient descriptor . See @ Ppaer . gradient
- str ( string ) gradient descriptor part after ` () ` .
= ( object ) gradient element
| var g = paper . gradient ( "l(0, 0, 1, 1)#000-#f00-#fff" ) ;
| g . setStops ( "#fff-#000-#f00-#fc0" ) ;
\ * /
function GsetStops ( str ) {
var grad = str ,
stops = this . stops ( ) ;
if ( typeof str == "string" ) {
grad = eve ( "snap.util.grad.parse" , null , "l(0,0,0,1)" + str ) . firstDefined ( ) . stops ;
}
if ( ! Snap . is ( grad , "array" ) ) {
return ;
}
for ( var i = 0 ; i < stops . length ; i ++ ) {
if ( grad [ i ] ) {
var color = Snap . color ( grad [ i ] . color ) ,
attr = { "offset" : grad [ i ] . offset + "%" } ;
attr [ "stop-color" ] = color . hex ;
if ( color . opacity < 1 ) {
attr [ "stop-opacity" ] = color . opacity ;
}
stops [ i ] . attr ( attr ) ;
} else {
stops [ i ] . remove ( ) ;
}
}
for ( i = stops . length ; i < grad . length ; i ++ ) {
this . addStop ( grad [ i ] . color , grad [ i ] . offset ) ;
}
return this ;
}
2014-05-07 08:37:05 +00:00
function gradient ( defs , str ) {
2014-05-23 11:03:03 +00:00
var grad = eve ( "snap.util.grad.parse" , null , str ) . firstDefined ( ) ,
2014-05-07 08:37:05 +00:00
el ;
if ( ! grad ) {
return null ;
}
grad . params . unshift ( defs ) ;
if ( grad . type . toLowerCase ( ) == "l" ) {
el = gradientLinear . apply ( 0 , grad . params ) ;
} else {
el = gradientRadial . apply ( 0 , grad . params ) ;
}
if ( grad . type != grad . type . toLowerCase ( ) ) {
$ ( el . node , {
gradientUnits : "userSpaceOnUse"
} ) ;
}
var stops = grad . stops ,
2017-01-24 02:08:13 +00:00
len = stops . length ;
for ( var i = 0 ; i < len ; i ++ ) {
2014-05-07 08:37:05 +00:00
var stop = stops [ i ] ;
el . addStop ( stop . color , stop . offset ) ;
}
return el ;
}
function gradientLinear ( defs , x1 , y1 , x2 , y2 ) {
var el = Snap . _ . make ( "linearGradient" , defs ) ;
el . stops = Gstops ;
el . addStop = GaddStop ;
el . getBBox = GgetBBox ;
2017-01-24 02:08:13 +00:00
el . setStops = GsetStops ;
2014-05-07 08:37:05 +00:00
if ( x1 != null ) {
$ ( el . node , {
x1 : x1 ,
y1 : y1 ,
x2 : x2 ,
y2 : y2
} ) ;
}
return el ;
}
function gradientRadial ( defs , cx , cy , r , fx , fy ) {
var el = Snap . _ . make ( "radialGradient" , defs ) ;
el . stops = Gstops ;
el . addStop = GaddStop ;
el . getBBox = GgetBBox ;
if ( cx != null ) {
$ ( el . node , {
cx : cx ,
cy : cy ,
r : r
} ) ;
}
if ( fx != null && fy != null ) {
$ ( el . node , {
fx : fx ,
fy : fy
} ) ;
}
return el ;
}
/ * \
* Paper . gradient
[ method ]
* *
* Creates a gradient element
* *
- gradient ( string ) gradient descriptor
> Gradient Descriptor
* The gradient descriptor is an expression formatted as
* follows : ` <type>(<coords>)<colors> ` . The ` <type> ` can be
* either linear or radial . The uppercase ` L ` or ` R ` letters
2013-10-14 11:59:34 +00:00
* indicate absolute coordinates offset from the SVG surface .
* Lowercase ` l ` or ` r ` letters indicate coordinates
* calculated relative to the element to which the gradient is
* applied . Coordinates specify a linear gradient vector as
* ` x1 ` , ` y1 ` , ` x2 ` , ` y2 ` , or a radial gradient as ` cx ` , ` cy ` ,
* ` r ` and optional ` fx ` , ` fy ` specifying a focal point away
* from the center of the circle . Specify ` <colors> ` as a list
* of dash - separated CSS color values . Each color may be
* followed by a custom offset value , separated with a colon
* character .
> Examples
2013-08-22 10:00:40 +00:00
* Linear gradient , relative from top - left corner to bottom - right
2013-10-14 11:59:34 +00:00
* corner , from black through red to white :
| var g = paper . gradient ( "l(0, 0, 1, 1)#000-#f00-#fff" ) ;
2013-08-22 10:00:40 +00:00
* Linear gradient , absolute from ( 0 , 0 ) to ( 100 , 100 ) , from black
2013-10-14 11:59:34 +00:00
* through red at 25 % to white :
2014-01-03 01:23:53 +00:00
| var g = paper . gradient ( "L(0, 0, 100, 100)#000-#f00:25-#fff" ) ;
2013-08-22 10:00:40 +00:00
* Radial gradient , relative from the center of the element with radius
2013-10-14 11:59:34 +00:00
* half the width , from black to white :
| var g = paper . gradient ( "r(0.5, 0.5, 0.5)#000-#fff" ) ;
* To apply the gradient :
2013-08-22 10:00:40 +00:00
| paper . circle ( 50 , 50 , 40 ) . attr ( {
| fill : g
| } ) ;
2013-10-14 11:59:34 +00:00
= ( object ) the ` gradient ` element
2013-08-22 10:00:40 +00:00
\ * /
2013-08-05 08:04:30 +00:00
proto . gradient = function ( str ) {
2013-09-19 11:03:24 +00:00
return gradient ( this . defs , str ) ;
2013-08-05 08:04:30 +00:00
} ;
proto . gradientLinear = function ( x1 , y1 , x2 , y2 ) {
2013-09-19 11:03:24 +00:00
return gradientLinear ( this . defs , x1 , y1 , x2 , y2 ) ;
2013-08-05 08:04:30 +00:00
} ;
proto . gradientRadial = function ( cx , cy , r , fx , fy ) {
2013-09-19 11:03:24 +00:00
return gradientRadial ( this . defs , cx , cy , r , fx , fy ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-09-05 00:10:45 +00:00
/ * \
* Paper . toString
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns SVG code for the @ Paper
= ( string ) SVG code for the @ Paper
2013-09-05 00:10:45 +00:00
\ * /
proto . toString = function ( ) {
2014-05-07 08:37:05 +00:00
var doc = this . node . ownerDocument ,
f = doc . createDocumentFragment ( ) ,
d = doc . createElement ( "div" ) ,
2013-09-05 00:10:45 +00:00
svg = this . node . cloneNode ( true ) ,
res ;
f . appendChild ( d ) ;
d . appendChild ( svg ) ;
2014-05-07 08:37:05 +00:00
Snap . _ . $ ( svg , { xmlns : "http://www.w3.org/2000/svg" } ) ;
2013-09-05 00:10:45 +00:00
res = d . innerHTML ;
f . removeChild ( f . firstChild ) ;
return res ;
} ;
2014-08-13 12:46:40 +00:00
/ * \
* Paper . toDataURL
[ method ]
* *
* Returns SVG code for the @ Paper as Data URI string .
= ( string ) Data URI string
\ * /
proto . toDataURL = function ( ) {
if ( window && window . btoa ) {
return "data:image/svg+xml;base64," + btoa ( unescape ( encodeURIComponent ( this ) ) ) ;
}
} ;
2013-10-20 15:46:25 +00:00
/ * \
* Paper . clear
[ method ]
* *
* Removes all child nodes of the paper , except < defs > .
\ * /
proto . clear = function ( ) {
var node = this . node . firstChild ,
next ;
while ( node ) {
next = node . nextSibling ;
if ( node . tagName != "defs" ) {
node . parentNode . removeChild ( node ) ;
2014-05-07 08:37:05 +00:00
} else {
proto . clear . call ( { node : node } ) ;
2013-10-20 15:46:25 +00:00
}
node = next ;
}
} ;
2013-08-05 08:04:30 +00:00
} ( ) ) ;
} ) ;
2014-08-03 22:59:28 +00:00
2013-08-15 08:29:47 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2016-08-01 01:37:11 +00:00
//
2013-08-15 08:29:47 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2016-08-01 01:37:11 +00:00
//
2013-08-15 08:29:47 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2016-08-01 01:37:11 +00:00
//
2013-08-15 08:29:47 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-09-25 05:52:57 +00:00
Snap . plugin ( function ( Snap , Element , Paper , glob ) {
2013-08-05 08:04:30 +00:00
var elproto = Element . prototype ,
2013-09-25 05:52:57 +00:00
is = Snap . is ,
clone = Snap . _ . clone ,
2013-08-05 08:04:30 +00:00
has = "hasOwnProperty" ,
p2s = /,?([a-z]),?/gi ,
toFloat = parseFloat ,
math = Math ,
PI = math . PI ,
mmin = math . min ,
mmax = math . max ,
pow = math . pow ,
abs = math . abs ;
function paths ( ps ) {
var p = paths . ps = paths . ps || { } ;
if ( p [ ps ] ) {
p [ ps ] . sleep = 100 ;
} else {
p [ ps ] = {
sleep : 100
} ;
}
setTimeout ( function ( ) {
for ( var key in p ) if ( p [ has ] ( key ) && key != ps ) {
p [ key ] . sleep -- ;
! p [ key ] . sleep && delete p [ key ] ;
}
} ) ;
return p [ ps ] ;
}
function box ( x , y , width , height ) {
if ( x == null ) {
x = y = width = height = 0 ;
}
if ( y == null ) {
y = x . y ;
width = x . width ;
height = x . height ;
x = x . x ;
}
return {
x : x ,
y : y ,
width : width ,
w : width ,
height : height ,
h : height ,
x2 : x + width ,
y2 : y + height ,
cx : x + width / 2 ,
cy : y + height / 2 ,
r1 : math . min ( width , height ) / 2 ,
r2 : math . max ( width , height ) / 2 ,
r0 : math . sqrt ( width * width + height * height ) / 2 ,
path : rectPath ( x , y , width , height ) ,
vb : [ x , y , width , height ] . join ( " " )
} ;
}
function toString ( ) {
return this . join ( "," ) . replace ( p2s , "$1" ) ;
}
function pathClone ( pathArray ) {
var res = clone ( pathArray ) ;
res . toString = toString ;
return res ;
}
function getPointAtSegmentLength ( p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y , length ) {
if ( length == null ) {
return bezlen ( p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y ) ;
} else {
return findDotsAtSegment ( p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y ,
getTotLen ( p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y , length ) ) ;
}
}
function getLengthFactory ( istotal , subpath ) {
function O ( val ) {
return + ( + val ) . toFixed ( 3 ) ;
}
2013-09-25 05:52:57 +00:00
return Snap . _ . cacher ( function ( path , length , onlystart ) {
2013-09-05 13:24:16 +00:00
if ( path instanceof Element ) {
path = path . attr ( "d" ) ;
}
2013-08-05 08:04:30 +00:00
path = path2curve ( path ) ;
var x , y , p , l , sp = "" , subpaths = { } , point ,
len = 0 ;
for ( var i = 0 , ii = path . length ; i < ii ; i ++ ) {
p = path [ i ] ;
if ( p [ 0 ] == "M" ) {
x = + p [ 1 ] ;
y = + p [ 2 ] ;
} else {
l = getPointAtSegmentLength ( x , y , p [ 1 ] , p [ 2 ] , p [ 3 ] , p [ 4 ] , p [ 5 ] , p [ 6 ] ) ;
if ( len + l > length ) {
if ( subpath && ! subpaths . start ) {
point = getPointAtSegmentLength ( x , y , p [ 1 ] , p [ 2 ] , p [ 3 ] , p [ 4 ] , p [ 5 ] , p [ 6 ] , length - len ) ;
sp += [
"C" + O ( point . start . x ) ,
O ( point . start . y ) ,
O ( point . m . x ) ,
O ( point . m . y ) ,
O ( point . x ) ,
O ( point . y )
] ;
if ( onlystart ) { return sp ; }
subpaths . start = sp ;
sp = [
"M" + O ( point . x ) ,
O ( point . y ) + "C" + O ( point . n . x ) ,
O ( point . n . y ) ,
O ( point . end . x ) ,
O ( point . end . y ) ,
O ( p [ 5 ] ) ,
O ( p [ 6 ] )
] . join ( ) ;
len += l ;
x = + p [ 5 ] ;
y = + p [ 6 ] ;
continue ;
}
if ( ! istotal && ! subpath ) {
point = getPointAtSegmentLength ( x , y , p [ 1 ] , p [ 2 ] , p [ 3 ] , p [ 4 ] , p [ 5 ] , p [ 6 ] , length - len ) ;
return point ;
}
}
len += l ;
x = + p [ 5 ] ;
y = + p [ 6 ] ;
}
sp += p . shift ( ) + p ;
}
subpaths . end = sp ;
point = istotal ? len : subpath ? subpaths : findDotsAtSegment ( x , y , p [ 0 ] , p [ 1 ] , p [ 2 ] , p [ 3 ] , p [ 4 ] , p [ 5 ] , 1 ) ;
return point ;
2013-09-25 05:52:57 +00:00
} , null , Snap . _ . clone ) ;
2013-08-05 08:04:30 +00:00
}
var getTotalLength = getLengthFactory ( 1 ) ,
getPointAtLength = getLengthFactory ( ) ,
getSubpathsAtLength = getLengthFactory ( 0 , 1 ) ;
function findDotsAtSegment ( p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y , t ) {
var t1 = 1 - t ,
t13 = pow ( t1 , 3 ) ,
t12 = pow ( t1 , 2 ) ,
t2 = t * t ,
t3 = t2 * t ,
x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x ,
y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y ,
mx = p1x + 2 * t * ( c1x - p1x ) + t2 * ( c2x - 2 * c1x + p1x ) ,
my = p1y + 2 * t * ( c1y - p1y ) + t2 * ( c2y - 2 * c1y + p1y ) ,
nx = c1x + 2 * t * ( c2x - c1x ) + t2 * ( p2x - 2 * c2x + c1x ) ,
ny = c1y + 2 * t * ( c2y - c1y ) + t2 * ( p2y - 2 * c2y + c1y ) ,
ax = t1 * p1x + t * c1x ,
ay = t1 * p1y + t * c1y ,
cx = t1 * c2x + t * p2x ,
cy = t1 * c2y + t * p2y ,
2017-01-24 02:32:41 +00:00
alpha = 90 - math . atan2 ( mx - nx , my - ny ) * 180 / PI ;
2013-08-05 08:04:30 +00:00
// (mx > nx || my < ny) && (alpha += 180);
return {
x : x ,
y : y ,
m : { x : mx , y : my } ,
n : { x : nx , y : ny } ,
start : { x : ax , y : ay } ,
end : { x : cx , y : cy } ,
alpha : alpha
} ;
}
function bezierBBox ( p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y ) {
2013-09-25 05:52:57 +00:00
if ( ! Snap . is ( p1x , "array" ) ) {
2013-08-05 08:04:30 +00:00
p1x = [ p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y ] ;
}
var bbox = curveDim . apply ( null , p1x ) ;
return box (
bbox . min . x ,
bbox . min . y ,
bbox . max . x - bbox . min . x ,
bbox . max . y - bbox . min . y
) ;
}
function isPointInsideBBox ( bbox , x , y ) {
return x >= bbox . x &&
x <= bbox . x + bbox . width &&
y >= bbox . y &&
y <= bbox . y + bbox . height ;
}
function isBBoxIntersect ( bbox1 , bbox2 ) {
bbox1 = box ( bbox1 ) ;
bbox2 = box ( bbox2 ) ;
return isPointInsideBBox ( bbox2 , bbox1 . x , bbox1 . y )
|| isPointInsideBBox ( bbox2 , bbox1 . x2 , bbox1 . y )
|| isPointInsideBBox ( bbox2 , bbox1 . x , bbox1 . y2 )
|| isPointInsideBBox ( bbox2 , bbox1 . x2 , bbox1 . y2 )
|| isPointInsideBBox ( bbox1 , bbox2 . x , bbox2 . y )
|| isPointInsideBBox ( bbox1 , bbox2 . x2 , bbox2 . y )
|| isPointInsideBBox ( bbox1 , bbox2 . x , bbox2 . y2 )
|| isPointInsideBBox ( bbox1 , bbox2 . x2 , bbox2 . y2 )
|| ( bbox1 . x < bbox2 . x2 && bbox1 . x > bbox2 . x
|| bbox2 . x < bbox1 . x2 && bbox2 . x > bbox1 . x )
&& ( bbox1 . y < bbox2 . y2 && bbox1 . y > bbox2 . y
|| bbox2 . y < bbox1 . y2 && bbox2 . y > bbox1 . y ) ;
}
function base3 ( t , p1 , p2 , p3 , p4 ) {
var t1 = - 3 * p1 + 9 * p2 - 9 * p3 + 3 * p4 ,
t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3 ;
return t * t2 - 3 * p1 + 3 * p2 ;
}
function bezlen ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 , z ) {
if ( z == null ) {
z = 1 ;
}
z = z > 1 ? 1 : z < 0 ? 0 : z ;
var z2 = z / 2 ,
n = 12 ,
2013-08-09 12:13:22 +00:00
Tvalues = [ - . 1252 , . 1252 , - . 3678 , . 3678 , - . 5873 , . 5873 , - . 7699 , . 7699 , - . 9041 , . 9041 , - . 9816 , . 9816 ] ,
2013-08-05 08:04:30 +00:00
Cvalues = [ 0.2491 , 0.2491 , 0.2335 , 0.2335 , 0.2032 , 0.2032 , 0.1601 , 0.1601 , 0.1069 , 0.1069 , 0.0472 , 0.0472 ] ,
sum = 0 ;
for ( var i = 0 ; i < n ; i ++ ) {
var ct = z2 * Tvalues [ i ] + z2 ,
xbase = base3 ( ct , x1 , x2 , x3 , x4 ) ,
ybase = base3 ( ct , y1 , y2 , y3 , y4 ) ,
comb = xbase * xbase + ybase * ybase ;
sum += Cvalues [ i ] * math . sqrt ( comb ) ;
}
return z2 * sum ;
}
function getTotLen ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 , ll ) {
if ( ll < 0 || bezlen ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 ) < ll ) {
return ;
}
var t = 1 ,
step = t / 2 ,
t2 = t - step ,
l ,
e = . 01 ;
l = bezlen ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 , t2 ) ;
while ( abs ( l - ll ) > e ) {
step /= 2 ;
t2 += ( l < ll ? 1 : - 1 ) * step ;
l = bezlen ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 , t2 ) ;
}
return t2 ;
}
function intersect ( x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 ) {
if (
mmax ( x1 , x2 ) < mmin ( x3 , x4 ) ||
mmin ( x1 , x2 ) > mmax ( x3 , x4 ) ||
mmax ( y1 , y2 ) < mmin ( y3 , y4 ) ||
mmin ( y1 , y2 ) > mmax ( y3 , y4 )
) {
return ;
}
var nx = ( x1 * y2 - y1 * x2 ) * ( x3 - x4 ) - ( x1 - x2 ) * ( x3 * y4 - y3 * x4 ) ,
ny = ( x1 * y2 - y1 * x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 * y4 - y3 * x4 ) ,
denominator = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 ) ;
if ( ! denominator ) {
return ;
}
var px = nx / denominator ,
py = ny / denominator ,
px2 = + px . toFixed ( 2 ) ,
py2 = + py . toFixed ( 2 ) ;
if (
px2 < + mmin ( x1 , x2 ) . toFixed ( 2 ) ||
px2 > + mmax ( x1 , x2 ) . toFixed ( 2 ) ||
px2 < + mmin ( x3 , x4 ) . toFixed ( 2 ) ||
px2 > + mmax ( x3 , x4 ) . toFixed ( 2 ) ||
py2 < + mmin ( y1 , y2 ) . toFixed ( 2 ) ||
py2 > + mmax ( y1 , y2 ) . toFixed ( 2 ) ||
py2 < + mmin ( y3 , y4 ) . toFixed ( 2 ) ||
py2 > + mmax ( y3 , y4 ) . toFixed ( 2 )
) {
return ;
}
return { x : px , y : py } ;
}
function inter ( bez1 , bez2 ) {
return interHelper ( bez1 , bez2 ) ;
}
function interCount ( bez1 , bez2 ) {
return interHelper ( bez1 , bez2 , 1 ) ;
}
function interHelper ( bez1 , bez2 , justCount ) {
var bbox1 = bezierBBox ( bez1 ) ,
bbox2 = bezierBBox ( bez2 ) ;
if ( ! isBBoxIntersect ( bbox1 , bbox2 ) ) {
return justCount ? 0 : [ ] ;
}
var l1 = bezlen . apply ( 0 , bez1 ) ,
l2 = bezlen . apply ( 0 , bez2 ) ,
2014-05-23 11:36:04 +00:00
n1 = ~ ~ ( l1 / 8 ) ,
n2 = ~ ~ ( l2 / 8 ) ,
2013-08-05 08:04:30 +00:00
dots1 = [ ] ,
dots2 = [ ] ,
xy = { } ,
res = justCount ? 0 : [ ] ;
for ( var i = 0 ; i < n1 + 1 ; i ++ ) {
var p = findDotsAtSegment . apply ( 0 , bez1 . concat ( i / n1 ) ) ;
dots1 . push ( { x : p . x , y : p . y , t : i / n1 } ) ;
}
for ( i = 0 ; i < n2 + 1 ; i ++ ) {
p = findDotsAtSegment . apply ( 0 , bez2 . concat ( i / n2 ) ) ;
dots2 . push ( { x : p . x , y : p . y , t : i / n2 } ) ;
}
for ( i = 0 ; i < n1 ; i ++ ) {
for ( var j = 0 ; j < n2 ; j ++ ) {
var di = dots1 [ i ] ,
di1 = dots1 [ i + 1 ] ,
dj = dots2 [ j ] ,
dj1 = dots2 [ j + 1 ] ,
2014-05-23 11:36:04 +00:00
ci = abs ( di1 . x - di . x ) < . 001 ? "y" : "x" ,
cj = abs ( dj1 . x - dj . x ) < . 001 ? "y" : "x" ,
2013-08-05 08:04:30 +00:00
is = intersect ( di . x , di . y , di1 . x , di1 . y , dj . x , dj . y , dj1 . x , dj1 . y ) ;
if ( is ) {
if ( xy [ is . x . toFixed ( 4 ) ] == is . y . toFixed ( 4 ) ) {
continue ;
}
xy [ is . x . toFixed ( 4 ) ] = is . y . toFixed ( 4 ) ;
var t1 = di . t + abs ( ( is [ ci ] - di [ ci ] ) / ( di1 [ ci ] - di [ ci ] ) ) * ( di1 . t - di . t ) ,
t2 = dj . t + abs ( ( is [ cj ] - dj [ cj ] ) / ( dj1 [ cj ] - dj [ cj ] ) ) * ( dj1 . t - dj . t ) ;
if ( t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1 ) {
if ( justCount ) {
res ++ ;
} else {
res . push ( {
x : is . x ,
y : is . y ,
t1 : t1 ,
t2 : t2
} ) ;
}
}
}
}
}
return res ;
}
function pathIntersection ( path1 , path2 ) {
return interPathHelper ( path1 , path2 ) ;
}
function pathIntersectionNumber ( path1 , path2 ) {
return interPathHelper ( path1 , path2 , 1 ) ;
}
function interPathHelper ( path1 , path2 , justCount ) {
path1 = path2curve ( path1 ) ;
path2 = path2curve ( path2 ) ;
var x1 , y1 , x2 , y2 , x1m , y1m , x2m , y2m , bez1 , bez2 ,
res = justCount ? 0 : [ ] ;
for ( var i = 0 , ii = path1 . length ; i < ii ; i ++ ) {
var pi = path1 [ i ] ;
if ( pi [ 0 ] == "M" ) {
x1 = x1m = pi [ 1 ] ;
y1 = y1m = pi [ 2 ] ;
} else {
if ( pi [ 0 ] == "C" ) {
bez1 = [ x1 , y1 ] . concat ( pi . slice ( 1 ) ) ;
x1 = bez1 [ 6 ] ;
y1 = bez1 [ 7 ] ;
} else {
bez1 = [ x1 , y1 , x1 , y1 , x1m , y1m , x1m , y1m ] ;
x1 = x1m ;
y1 = y1m ;
}
for ( var j = 0 , jj = path2 . length ; j < jj ; j ++ ) {
var pj = path2 [ j ] ;
if ( pj [ 0 ] == "M" ) {
x2 = x2m = pj [ 1 ] ;
y2 = y2m = pj [ 2 ] ;
} else {
if ( pj [ 0 ] == "C" ) {
bez2 = [ x2 , y2 ] . concat ( pj . slice ( 1 ) ) ;
x2 = bez2 [ 6 ] ;
y2 = bez2 [ 7 ] ;
} else {
bez2 = [ x2 , y2 , x2 , y2 , x2m , y2m , x2m , y2m ] ;
x2 = x2m ;
y2 = y2m ;
}
var intr = interHelper ( bez1 , bez2 , justCount ) ;
if ( justCount ) {
res += intr ;
} else {
for ( var k = 0 , kk = intr . length ; k < kk ; k ++ ) {
intr [ k ] . segment1 = i ;
intr [ k ] . segment2 = j ;
intr [ k ] . bez1 = bez1 ;
intr [ k ] . bez2 = bez2 ;
}
res = res . concat ( intr ) ;
}
}
}
}
}
return res ;
}
function isPointInsidePath ( path , x , y ) {
var bbox = pathBBox ( path ) ;
return isPointInsideBBox ( bbox , x , y ) &&
interPathHelper ( path , [ [ "M" , x , y ] , [ "H" , bbox . x2 + 10 ] ] , 1 ) % 2 == 1 ;
}
function pathBBox ( path ) {
var pth = paths ( path ) ;
if ( pth . bbox ) {
return clone ( pth . bbox ) ;
}
if ( ! path ) {
return box ( ) ;
}
path = path2curve ( path ) ;
2016-08-01 01:37:11 +00:00
var x = 0 ,
2013-08-05 08:04:30 +00:00
y = 0 ,
X = [ ] ,
Y = [ ] ,
p ;
for ( var i = 0 , ii = path . length ; i < ii ; i ++ ) {
p = path [ i ] ;
if ( p [ 0 ] == "M" ) {
x = p [ 1 ] ;
y = p [ 2 ] ;
X . push ( x ) ;
Y . push ( y ) ;
} else {
var dim = curveDim ( x , y , p [ 1 ] , p [ 2 ] , p [ 3 ] , p [ 4 ] , p [ 5 ] , p [ 6 ] ) ;
X = X . concat ( dim . min . x , dim . max . x ) ;
Y = Y . concat ( dim . min . y , dim . max . y ) ;
x = p [ 5 ] ;
y = p [ 6 ] ;
}
}
var xmin = mmin . apply ( 0 , X ) ,
ymin = mmin . apply ( 0 , Y ) ,
xmax = mmax . apply ( 0 , X ) ,
ymax = mmax . apply ( 0 , Y ) ,
bb = box ( xmin , ymin , xmax - xmin , ymax - ymin ) ;
pth . bbox = clone ( bb ) ;
return bb ;
}
function rectPath ( x , y , w , h , r ) {
if ( r ) {
return [
2017-01-24 02:32:41 +00:00
[ "M" , + x + + r , y ] ,
2013-08-05 08:04:30 +00:00
[ "l" , w - r * 2 , 0 ] ,
[ "a" , r , r , 0 , 0 , 1 , r , r ] ,
[ "l" , 0 , h - r * 2 ] ,
[ "a" , r , r , 0 , 0 , 1 , - r , r ] ,
[ "l" , r * 2 - w , 0 ] ,
[ "a" , r , r , 0 , 0 , 1 , - r , - r ] ,
[ "l" , 0 , r * 2 - h ] ,
[ "a" , r , r , 0 , 0 , 1 , r , - r ] ,
[ "z" ]
] ;
}
var res = [ [ "M" , x , y ] , [ "l" , w , 0 ] , [ "l" , 0 , h ] , [ "l" , - w , 0 ] , [ "z" ] ] ;
res . toString = toString ;
return res ;
}
function ellipsePath ( x , y , rx , ry , a ) {
if ( a == null && ry == null ) {
ry = rx ;
}
2014-01-02 08:43:26 +00:00
x = + x ;
y = + y ;
rx = + rx ;
ry = + ry ;
2013-08-05 08:04:30 +00:00
if ( a != null ) {
var rad = Math . PI / 180 ,
x1 = x + rx * Math . cos ( - ry * rad ) ,
x2 = x + rx * Math . cos ( - a * rad ) ,
y1 = y + rx * Math . sin ( - ry * rad ) ,
y2 = y + rx * Math . sin ( - a * rad ) ,
res = [ [ "M" , x1 , y1 ] , [ "A" , rx , rx , 0 , + ( a - ry > 180 ) , 0 , x2 , y2 ] ] ;
} else {
res = [
[ "M" , x , y ] ,
[ "m" , 0 , - ry ] ,
[ "a" , rx , ry , 0 , 1 , 1 , 0 , 2 * ry ] ,
[ "a" , rx , ry , 0 , 1 , 1 , 0 , - 2 * ry ] ,
[ "z" ]
] ;
}
res . toString = toString ;
return res ;
}
2013-09-25 05:52:57 +00:00
var unit2px = Snap . _unit2px ,
2013-09-10 00:22:05 +00:00
getPath = {
2013-08-05 08:04:30 +00:00
path : function ( el ) {
return el . attr ( "path" ) ;
} ,
circle : function ( el ) {
var attr = unit2px ( el ) ;
return ellipsePath ( attr . cx , attr . cy , attr . r ) ;
} ,
ellipse : function ( el ) {
var attr = unit2px ( el ) ;
2014-04-18 00:31:07 +00:00
return ellipsePath ( attr . cx || 0 , attr . cy || 0 , attr . rx , attr . ry ) ;
2013-08-05 08:04:30 +00:00
} ,
rect : function ( el ) {
var attr = unit2px ( el ) ;
2014-04-18 00:31:07 +00:00
return rectPath ( attr . x || 0 , attr . y || 0 , attr . width , attr . height , attr . rx , attr . ry ) ;
2013-08-05 08:04:30 +00:00
} ,
image : function ( el ) {
var attr = unit2px ( el ) ;
2014-04-18 00:31:07 +00:00
return rectPath ( attr . x || 0 , attr . y || 0 , attr . width , attr . height ) ;
2013-08-05 08:04:30 +00:00
} ,
2013-11-27 02:20:50 +00:00
line : function ( el ) {
2014-04-18 00:31:07 +00:00
return "M" + [ el . attr ( "x1" ) || 0 , el . attr ( "y1" ) || 0 , el . attr ( "x2" ) , el . attr ( "y2" ) ] ;
2013-11-27 02:20:50 +00:00
} ,
2013-10-09 09:06:18 +00:00
polyline : function ( el ) {
return "M" + el . attr ( "points" ) ;
} ,
polygon : function ( el ) {
return "M" + el . attr ( "points" ) + "z" ;
2013-10-25 22:53:09 +00:00
} ,
deflt : function ( el ) {
var bbox = el . node . getBBox ( ) ;
return rectPath ( bbox . x , bbox . y , bbox . width , bbox . height ) ;
2013-08-05 08:04:30 +00:00
}
} ;
function pathToRelative ( pathArray ) {
2013-09-19 11:03:24 +00:00
var pth = paths ( pathArray ) ,
lowerCase = String . prototype . toLowerCase ;
2013-08-05 08:04:30 +00:00
if ( pth . rel ) {
return pathClone ( pth . rel ) ;
}
2013-09-25 05:52:57 +00:00
if ( ! Snap . is ( pathArray , "array" ) || ! Snap . is ( pathArray && pathArray [ 0 ] , "array" ) ) {
pathArray = Snap . parsePathString ( pathArray ) ;
2013-08-05 08:04:30 +00:00
}
var res = [ ] ,
x = 0 ,
y = 0 ,
mx = 0 ,
my = 0 ,
start = 0 ;
if ( pathArray [ 0 ] [ 0 ] == "M" ) {
x = pathArray [ 0 ] [ 1 ] ;
y = pathArray [ 0 ] [ 2 ] ;
mx = x ;
my = y ;
start ++ ;
res . push ( [ "M" , x , y ] ) ;
}
for ( var i = start , ii = pathArray . length ; i < ii ; i ++ ) {
var r = res [ i ] = [ ] ,
pa = pathArray [ i ] ;
if ( pa [ 0 ] != lowerCase . call ( pa [ 0 ] ) ) {
r [ 0 ] = lowerCase . call ( pa [ 0 ] ) ;
switch ( r [ 0 ] ) {
case "a" :
r [ 1 ] = pa [ 1 ] ;
r [ 2 ] = pa [ 2 ] ;
r [ 3 ] = pa [ 3 ] ;
r [ 4 ] = pa [ 4 ] ;
r [ 5 ] = pa [ 5 ] ;
r [ 6 ] = + ( pa [ 6 ] - x ) . toFixed ( 3 ) ;
r [ 7 ] = + ( pa [ 7 ] - y ) . toFixed ( 3 ) ;
break ;
case "v" :
r [ 1 ] = + ( pa [ 1 ] - y ) . toFixed ( 3 ) ;
break ;
case "m" :
mx = pa [ 1 ] ;
my = pa [ 2 ] ;
default :
for ( var j = 1 , jj = pa . length ; j < jj ; j ++ ) {
2017-01-24 02:32:41 +00:00
r [ j ] = + ( pa [ j ] - ( j % 2 ? x : y ) ) . toFixed ( 3 ) ;
2013-08-05 08:04:30 +00:00
}
}
} else {
r = res [ i ] = [ ] ;
if ( pa [ 0 ] == "m" ) {
mx = pa [ 1 ] + x ;
my = pa [ 2 ] + y ;
}
for ( var k = 0 , kk = pa . length ; k < kk ; k ++ ) {
res [ i ] [ k ] = pa [ k ] ;
}
}
var len = res [ i ] . length ;
switch ( res [ i ] [ 0 ] ) {
case "z" :
x = mx ;
y = my ;
break ;
case "h" :
x += + res [ i ] [ len - 1 ] ;
break ;
case "v" :
y += + res [ i ] [ len - 1 ] ;
break ;
default :
x += + res [ i ] [ len - 2 ] ;
y += + res [ i ] [ len - 1 ] ;
}
}
res . toString = toString ;
pth . rel = pathClone ( res ) ;
return res ;
}
function pathToAbsolute ( pathArray ) {
var pth = paths ( pathArray ) ;
if ( pth . abs ) {
return pathClone ( pth . abs ) ;
}
if ( ! is ( pathArray , "array" ) || ! is ( pathArray && pathArray [ 0 ] , "array" ) ) { // rough assumption
2013-09-25 05:52:57 +00:00
pathArray = Snap . parsePathString ( pathArray ) ;
2013-08-05 08:04:30 +00:00
}
if ( ! pathArray || ! pathArray . length ) {
return [ [ "M" , 0 , 0 ] ] ;
}
var res = [ ] ,
x = 0 ,
y = 0 ,
mx = 0 ,
my = 0 ,
start = 0 ,
pa0 ;
if ( pathArray [ 0 ] [ 0 ] == "M" ) {
x = + pathArray [ 0 ] [ 1 ] ;
y = + pathArray [ 0 ] [ 2 ] ;
mx = x ;
my = y ;
start ++ ;
res [ 0 ] = [ "M" , x , y ] ;
}
var crz = pathArray . length == 3 &&
pathArray [ 0 ] [ 0 ] == "M" &&
pathArray [ 1 ] [ 0 ] . toUpperCase ( ) == "R" &&
pathArray [ 2 ] [ 0 ] . toUpperCase ( ) == "Z" ;
for ( var r , pa , i = start , ii = pathArray . length ; i < ii ; i ++ ) {
res . push ( r = [ ] ) ;
pa = pathArray [ i ] ;
pa0 = pa [ 0 ] ;
if ( pa0 != pa0 . toUpperCase ( ) ) {
r [ 0 ] = pa0 . toUpperCase ( ) ;
switch ( r [ 0 ] ) {
case "A" :
r [ 1 ] = pa [ 1 ] ;
r [ 2 ] = pa [ 2 ] ;
r [ 3 ] = pa [ 3 ] ;
r [ 4 ] = pa [ 4 ] ;
r [ 5 ] = pa [ 5 ] ;
2014-01-02 08:43:26 +00:00
r [ 6 ] = + pa [ 6 ] + x ;
r [ 7 ] = + pa [ 7 ] + y ;
2013-08-05 08:04:30 +00:00
break ;
case "V" :
r [ 1 ] = + pa [ 1 ] + y ;
break ;
case "H" :
r [ 1 ] = + pa [ 1 ] + x ;
break ;
case "R" :
var dots = [ x , y ] . concat ( pa . slice ( 1 ) ) ;
for ( var j = 2 , jj = dots . length ; j < jj ; j ++ ) {
dots [ j ] = + dots [ j ] + x ;
dots [ ++ j ] = + dots [ j ] + y ;
}
res . pop ( ) ;
res = res . concat ( catmullRom2bezier ( dots , crz ) ) ;
break ;
case "O" :
res . pop ( ) ;
dots = ellipsePath ( x , y , pa [ 1 ] , pa [ 2 ] ) ;
dots . push ( dots [ 0 ] ) ;
res = res . concat ( dots ) ;
break ;
case "U" :
res . pop ( ) ;
res = res . concat ( ellipsePath ( x , y , pa [ 1 ] , pa [ 2 ] , pa [ 3 ] ) ) ;
r = [ "U" ] . concat ( res [ res . length - 1 ] . slice ( - 2 ) ) ;
break ;
case "M" :
mx = + pa [ 1 ] + x ;
my = + pa [ 2 ] + y ;
default :
for ( j = 1 , jj = pa . length ; j < jj ; j ++ ) {
2017-01-24 02:32:41 +00:00
r [ j ] = + pa [ j ] + ( j % 2 ? x : y ) ;
2013-08-05 08:04:30 +00:00
}
}
} else if ( pa0 == "R" ) {
dots = [ x , y ] . concat ( pa . slice ( 1 ) ) ;
res . pop ( ) ;
res = res . concat ( catmullRom2bezier ( dots , crz ) ) ;
r = [ "R" ] . concat ( pa . slice ( - 2 ) ) ;
} else if ( pa0 == "O" ) {
res . pop ( ) ;
dots = ellipsePath ( x , y , pa [ 1 ] , pa [ 2 ] ) ;
dots . push ( dots [ 0 ] ) ;
res = res . concat ( dots ) ;
} else if ( pa0 == "U" ) {
res . pop ( ) ;
res = res . concat ( ellipsePath ( x , y , pa [ 1 ] , pa [ 2 ] , pa [ 3 ] ) ) ;
r = [ "U" ] . concat ( res [ res . length - 1 ] . slice ( - 2 ) ) ;
} else {
for ( var k = 0 , kk = pa . length ; k < kk ; k ++ ) {
r [ k ] = pa [ k ] ;
}
}
pa0 = pa0 . toUpperCase ( ) ;
if ( pa0 != "O" ) {
switch ( r [ 0 ] ) {
case "Z" :
2014-01-02 08:43:26 +00:00
x = + mx ;
y = + my ;
2013-08-05 08:04:30 +00:00
break ;
case "H" :
x = r [ 1 ] ;
break ;
case "V" :
y = r [ 1 ] ;
break ;
case "M" :
mx = r [ r . length - 2 ] ;
my = r [ r . length - 1 ] ;
default :
x = r [ r . length - 2 ] ;
y = r [ r . length - 1 ] ;
}
}
}
res . toString = toString ;
pth . abs = pathClone ( res ) ;
return res ;
}
function l2c ( x1 , y1 , x2 , y2 ) {
return [ x1 , y1 , x2 , y2 , x2 , y2 ] ;
}
function q2c ( x1 , y1 , ax , ay , x2 , y2 ) {
var _13 = 1 / 3 ,
_23 = 2 / 3 ;
return [
_13 * x1 + _23 * ax ,
_13 * y1 + _23 * ay ,
_13 * x2 + _23 * ax ,
_13 * y2 + _23 * ay ,
x2 ,
y2
] ;
}
function a2c ( x1 , y1 , rx , ry , angle , large _arc _flag , sweep _flag , x2 , y2 , recursive ) {
// for more information of where this math came from visit:
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
var _120 = PI * 120 / 180 ,
rad = PI / 180 * ( + angle || 0 ) ,
res = [ ] ,
xy ,
2013-09-25 05:52:57 +00:00
rotate = Snap . _ . cacher ( function ( x , y , rad ) {
2013-08-05 08:04:30 +00:00
var X = x * math . cos ( rad ) - y * math . sin ( rad ) ,
Y = x * math . sin ( rad ) + y * math . cos ( rad ) ;
return { x : X , y : Y } ;
} ) ;
2016-08-01 01:37:11 +00:00
if ( ! rx || ! ry ) {
return [ x1 , y1 , x2 , y2 , x2 , y2 ] ;
}
2013-08-05 08:04:30 +00:00
if ( ! recursive ) {
xy = rotate ( x1 , y1 , - rad ) ;
x1 = xy . x ;
y1 = xy . y ;
xy = rotate ( x2 , y2 , - rad ) ;
x2 = xy . x ;
y2 = xy . y ;
var cos = math . cos ( PI / 180 * angle ) ,
sin = math . sin ( PI / 180 * angle ) ,
x = ( x1 - x2 ) / 2 ,
y = ( y1 - y2 ) / 2 ;
2017-01-24 02:32:41 +00:00
var h = x * x / ( rx * rx ) + y * y / ( ry * ry ) ;
2013-08-05 08:04:30 +00:00
if ( h > 1 ) {
h = math . sqrt ( h ) ;
rx = h * rx ;
ry = h * ry ;
}
var rx2 = rx * rx ,
ry2 = ry * ry ,
k = ( large _arc _flag == sweep _flag ? - 1 : 1 ) *
math . sqrt ( abs ( ( rx2 * ry2 - rx2 * y * y - ry2 * x * x ) / ( rx2 * y * y + ry2 * x * x ) ) ) ,
cx = k * rx * y / ry + ( x1 + x2 ) / 2 ,
cy = k * - ry * x / rx + ( y1 + y2 ) / 2 ,
f1 = math . asin ( ( ( y1 - cy ) / ry ) . toFixed ( 9 ) ) ,
f2 = math . asin ( ( ( y2 - cy ) / ry ) . toFixed ( 9 ) ) ;
f1 = x1 < cx ? PI - f1 : f1 ;
f2 = x2 < cx ? PI - f2 : f2 ;
f1 < 0 && ( f1 = PI * 2 + f1 ) ;
f2 < 0 && ( f2 = PI * 2 + f2 ) ;
if ( sweep _flag && f1 > f2 ) {
f1 = f1 - PI * 2 ;
}
if ( ! sweep _flag && f2 > f1 ) {
f2 = f2 - PI * 2 ;
}
} else {
f1 = recursive [ 0 ] ;
f2 = recursive [ 1 ] ;
cx = recursive [ 2 ] ;
cy = recursive [ 3 ] ;
}
var df = f2 - f1 ;
if ( abs ( df ) > _120 ) {
var f2old = f2 ,
x2old = x2 ,
y2old = y2 ;
f2 = f1 + _120 * ( sweep _flag && f2 > f1 ? 1 : - 1 ) ;
x2 = cx + rx * math . cos ( f2 ) ;
y2 = cy + ry * math . sin ( f2 ) ;
res = a2c ( x2 , y2 , rx , ry , angle , 0 , sweep _flag , x2old , y2old , [ f2 , f2old , cx , cy ] ) ;
}
df = f2 - f1 ;
var c1 = math . cos ( f1 ) ,
s1 = math . sin ( f1 ) ,
c2 = math . cos ( f2 ) ,
s2 = math . sin ( f2 ) ,
t = math . tan ( df / 4 ) ,
hx = 4 / 3 * rx * t ,
hy = 4 / 3 * ry * t ,
m1 = [ x1 , y1 ] ,
m2 = [ x1 + hx * s1 , y1 - hy * c1 ] ,
m3 = [ x2 + hx * s2 , y2 - hy * c2 ] ,
m4 = [ x2 , y2 ] ;
m2 [ 0 ] = 2 * m1 [ 0 ] - m2 [ 0 ] ;
m2 [ 1 ] = 2 * m1 [ 1 ] - m2 [ 1 ] ;
if ( recursive ) {
return [ m2 , m3 , m4 ] . concat ( res ) ;
} else {
res = [ m2 , m3 , m4 ] . concat ( res ) . join ( ) . split ( "," ) ;
var newres = [ ] ;
for ( var i = 0 , ii = res . length ; i < ii ; i ++ ) {
newres [ i ] = i % 2 ? rotate ( res [ i - 1 ] , res [ i ] , rad ) . y : rotate ( res [ i ] , res [ i + 1 ] , rad ) . x ;
}
return newres ;
}
}
function findDotAtSegment ( p1x , p1y , c1x , c1y , c2x , c2y , p2x , p2y , t ) {
var t1 = 1 - t ;
return {
x : pow ( t1 , 3 ) * p1x + pow ( t1 , 2 ) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow ( t , 3 ) * p2x ,
y : pow ( t1 , 3 ) * p1y + pow ( t1 , 2 ) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow ( t , 3 ) * p2y
} ;
}
2016-08-01 01:37:11 +00:00
2014-03-06 23:45:24 +00:00
// Returns bounding box of cubic bezier curve.
// Source: http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
// Original version: NISHIO Hirokazu
// Modifications: https://github.com/timo22345
function curveDim ( x0 , y0 , x1 , y1 , x2 , y2 , x3 , y3 ) {
var tvalues = [ ] ,
bounds = [ [ ] , [ ] ] ,
a , b , c , t , t1 , t2 , b2ac , sqrtb2ac ;
for ( var i = 0 ; i < 2 ; ++ i ) {
if ( i == 0 ) {
b = 6 * x0 - 12 * x1 + 6 * x2 ;
a = - 3 * x0 + 9 * x1 - 9 * x2 + 3 * x3 ;
c = 3 * x1 - 3 * x0 ;
} else {
b = 6 * y0 - 12 * y1 + 6 * y2 ;
a = - 3 * y0 + 9 * y1 - 9 * y2 + 3 * y3 ;
c = 3 * y1 - 3 * y0 ;
}
if ( abs ( a ) < 1e-12 ) {
if ( abs ( b ) < 1e-12 ) {
continue ;
}
t = - c / b ;
if ( 0 < t && t < 1 ) {
tvalues . push ( t ) ;
}
continue ;
}
b2ac = b * b - 4 * c * a ;
sqrtb2ac = math . sqrt ( b2ac ) ;
if ( b2ac < 0 ) {
continue ;
}
t1 = ( - b + sqrtb2ac ) / ( 2 * a ) ;
if ( 0 < t1 && t1 < 1 ) {
tvalues . push ( t1 ) ;
}
t2 = ( - b - sqrtb2ac ) / ( 2 * a ) ;
if ( 0 < t2 && t2 < 1 ) {
tvalues . push ( t2 ) ;
}
}
var x , y , j = tvalues . length ,
jlen = j ,
mt ;
while ( j -- ) {
t = tvalues [ j ] ;
mt = 1 - t ;
2017-01-24 02:32:41 +00:00
bounds [ 0 ] [ j ] = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3 ;
bounds [ 1 ] [ j ] = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3 ;
2014-03-06 23:45:24 +00:00
}
bounds [ 0 ] [ jlen ] = x0 ;
bounds [ 1 ] [ jlen ] = y0 ;
bounds [ 0 ] [ jlen + 1 ] = x3 ;
bounds [ 1 ] [ jlen + 1 ] = y3 ;
bounds [ 0 ] . length = bounds [ 1 ] . length = jlen + 2 ;
return {
min : { x : mmin . apply ( 0 , bounds [ 0 ] ) , y : mmin . apply ( 0 , bounds [ 1 ] ) } ,
max : { x : mmax . apply ( 0 , bounds [ 0 ] ) , y : mmax . apply ( 0 , bounds [ 1 ] ) }
} ;
}
2013-08-05 08:04:30 +00:00
function path2curve ( path , path2 ) {
var pth = ! path2 && paths ( path ) ;
if ( ! path2 && pth . curve ) {
return pathClone ( pth . curve ) ;
}
var p = pathToAbsolute ( path ) ,
p2 = path2 && pathToAbsolute ( path2 ) ,
attrs = { x : 0 , y : 0 , bx : 0 , by : 0 , X : 0 , Y : 0 , qx : null , qy : null } ,
attrs2 = { x : 0 , y : 0 , bx : 0 , by : 0 , X : 0 , Y : 0 , qx : null , qy : null } ,
2014-03-06 23:45:24 +00:00
processPath = function ( path , d , pcom ) {
2013-08-05 08:04:30 +00:00
var nx , ny ;
if ( ! path ) {
return [ "C" , d . x , d . y , d . x , d . y , d . x , d . y ] ;
}
2014-03-06 23:45:24 +00:00
! ( path [ 0 ] in { T : 1 , Q : 1 } ) && ( d . qx = d . qy = null ) ;
2013-08-05 08:04:30 +00:00
switch ( path [ 0 ] ) {
case "M" :
d . X = path [ 1 ] ;
d . Y = path [ 2 ] ;
break ;
case "A" :
2014-04-18 00:31:07 +00:00
path = [ "C" ] . concat ( a2c . apply ( 0 , [ d . x , d . y ] . concat ( path . slice ( 1 ) ) ) ) ;
2013-08-05 08:04:30 +00:00
break ;
case "S" :
2014-03-06 23:45:24 +00:00
if ( pcom == "C" || pcom == "S" ) { // In "S" case we have to take into account, if the previous command is C/S.
nx = d . x * 2 - d . bx ; // And reflect the previous
ny = d . y * 2 - d . by ; // command's control point relative to the current point.
}
else { // or some else or nothing
nx = d . x ;
ny = d . y ;
}
2013-08-05 08:04:30 +00:00
path = [ "C" , nx , ny ] . concat ( path . slice ( 1 ) ) ;
break ;
case "T" :
2014-03-06 23:45:24 +00:00
if ( pcom == "Q" || pcom == "T" ) { // In "T" case we have to take into account, if the previous command is Q/T.
d . qx = d . x * 2 - d . qx ; // And make a reflection similar
d . qy = d . y * 2 - d . qy ; // to case "S".
}
else { // or something else or nothing
d . qx = d . x ;
d . qy = d . y ;
}
2013-08-05 08:04:30 +00:00
path = [ "C" ] . concat ( q2c ( d . x , d . y , d . qx , d . qy , path [ 1 ] , path [ 2 ] ) ) ;
break ;
case "Q" :
d . qx = path [ 1 ] ;
d . qy = path [ 2 ] ;
path = [ "C" ] . concat ( q2c ( d . x , d . y , path [ 1 ] , path [ 2 ] , path [ 3 ] , path [ 4 ] ) ) ;
break ;
case "L" :
path = [ "C" ] . concat ( l2c ( d . x , d . y , path [ 1 ] , path [ 2 ] ) ) ;
break ;
case "H" :
path = [ "C" ] . concat ( l2c ( d . x , d . y , path [ 1 ] , d . y ) ) ;
break ;
case "V" :
path = [ "C" ] . concat ( l2c ( d . x , d . y , d . x , path [ 1 ] ) ) ;
break ;
case "Z" :
path = [ "C" ] . concat ( l2c ( d . x , d . y , d . X , d . Y ) ) ;
break ;
}
return path ;
} ,
fixArc = function ( pp , i ) {
if ( pp [ i ] . length > 7 ) {
pp [ i ] . shift ( ) ;
var pi = pp [ i ] ;
while ( pi . length ) {
2014-03-06 23:45:24 +00:00
pcoms1 [ i ] = "A" ; // if created multiple C:s, their original seg is saved
p2 && ( pcoms2 [ i ] = "A" ) ; // the same as above
2013-08-05 08:04:30 +00:00
pp . splice ( i ++ , 0 , [ "C" ] . concat ( pi . splice ( 0 , 6 ) ) ) ;
}
pp . splice ( i , 1 ) ;
ii = mmax ( p . length , p2 && p2 . length || 0 ) ;
}
} ,
fixM = function ( path1 , path2 , a1 , a2 , i ) {
if ( path1 && path2 && path1 [ i ] [ 0 ] == "M" && path2 [ i ] [ 0 ] != "M" ) {
path2 . splice ( i , 0 , [ "M" , a2 . x , a2 . y ] ) ;
a1 . bx = 0 ;
a1 . by = 0 ;
a1 . x = path1 [ i ] [ 1 ] ;
a1 . y = path1 [ i ] [ 2 ] ;
ii = mmax ( p . length , p2 && p2 . length || 0 ) ;
}
2014-03-06 23:45:24 +00:00
} ,
pcoms1 = [ ] , // path commands of original path p
pcoms2 = [ ] , // path commands of original path p2
pfirst = "" , // temporary holder for original path command
pcom = "" ; // holder for previous path command of original path
2013-08-05 08:04:30 +00:00
for ( var i = 0 , ii = mmax ( p . length , p2 && p2 . length || 0 ) ; i < ii ; i ++ ) {
2014-03-06 23:45:24 +00:00
p [ i ] && ( pfirst = p [ i ] [ 0 ] ) ; // save current path command
if ( pfirst != "C" ) // C is not saved yet, because it may be result of conversion
{
pcoms1 [ i ] = pfirst ; // Save current path command
i && ( pcom = pcoms1 [ i - 1 ] ) ; // Get previous path command pcom
}
p [ i ] = processPath ( p [ i ] , attrs , pcom ) ; // Previous path command is inputted to processPath
if ( pcoms1 [ i ] != "A" && pfirst == "C" ) pcoms1 [ i ] = "C" ; // A is the only command
// which may produce multiple C:s
// so we have to make sure that C is also C in original path
fixArc ( p , i ) ; // fixArc adds also the right amount of A:s to pcoms1
if ( p2 ) { // the same procedures is done to p2
p2 [ i ] && ( pfirst = p2 [ i ] [ 0 ] ) ;
if ( pfirst != "C" ) {
pcoms2 [ i ] = pfirst ;
i && ( pcom = pcoms2 [ i - 1 ] ) ;
}
p2 [ i ] = processPath ( p2 [ i ] , attrs2 , pcom ) ;
if ( pcoms2 [ i ] != "A" && pfirst == "C" ) {
pcoms2 [ i ] = "C" ;
}
fixArc ( p2 , i ) ;
}
2013-08-05 08:04:30 +00:00
fixM ( p , p2 , attrs , attrs2 , i ) ;
fixM ( p2 , p , attrs2 , attrs , i ) ;
var seg = p [ i ] ,
seg2 = p2 && p2 [ i ] ,
seglen = seg . length ,
seg2len = p2 && seg2 . length ;
attrs . x = seg [ seglen - 2 ] ;
attrs . y = seg [ seglen - 1 ] ;
attrs . bx = toFloat ( seg [ seglen - 4 ] ) || attrs . x ;
attrs . by = toFloat ( seg [ seglen - 3 ] ) || attrs . y ;
attrs2 . bx = p2 && ( toFloat ( seg2 [ seg2len - 4 ] ) || attrs2 . x ) ;
attrs2 . by = p2 && ( toFloat ( seg2 [ seg2len - 3 ] ) || attrs2 . y ) ;
attrs2 . x = p2 && seg2 [ seg2len - 2 ] ;
attrs2 . y = p2 && seg2 [ seg2len - 1 ] ;
}
if ( ! p2 ) {
pth . curve = pathClone ( p ) ;
}
return p2 ? [ p , p2 ] : p ;
}
function mapPath ( path , matrix ) {
if ( ! matrix ) {
return path ;
}
var x , y , i , j , ii , jj , pathi ;
path = path2curve ( path ) ;
for ( i = 0 , ii = path . length ; i < ii ; i ++ ) {
pathi = path [ i ] ;
for ( j = 1 , jj = pathi . length ; j < jj ; j += 2 ) {
x = matrix . x ( pathi [ j ] , pathi [ j + 1 ] ) ;
y = matrix . y ( pathi [ j ] , pathi [ j + 1 ] ) ;
pathi [ j ] = x ;
pathi [ j + 1 ] = y ;
}
}
return path ;
}
// http://schepers.cc/getting-to-the-point
function catmullRom2bezier ( crp , z ) {
var d = [ ] ;
for ( var i = 0 , iLen = crp . length ; iLen - 2 * ! z > i ; i += 2 ) {
var p = [
{ x : + crp [ i - 2 ] , y : + crp [ i - 1 ] } ,
{ x : + crp [ i ] , y : + crp [ i + 1 ] } ,
{ x : + crp [ i + 2 ] , y : + crp [ i + 3 ] } ,
{ x : + crp [ i + 4 ] , y : + crp [ i + 5 ] }
] ;
if ( z ) {
if ( ! i ) {
p [ 0 ] = { x : + crp [ iLen - 2 ] , y : + crp [ iLen - 1 ] } ;
} else if ( iLen - 4 == i ) {
p [ 3 ] = { x : + crp [ 0 ] , y : + crp [ 1 ] } ;
} else if ( iLen - 2 == i ) {
p [ 2 ] = { x : + crp [ 0 ] , y : + crp [ 1 ] } ;
p [ 3 ] = { x : + crp [ 2 ] , y : + crp [ 3 ] } ;
}
} else {
if ( iLen - 4 == i ) {
p [ 3 ] = p [ 2 ] ;
} else if ( ! i ) {
p [ 0 ] = { x : + crp [ i ] , y : + crp [ i + 1 ] } ;
}
}
d . push ( [ "C" ,
( - p [ 0 ] . x + 6 * p [ 1 ] . x + p [ 2 ] . x ) / 6 ,
( - p [ 0 ] . y + 6 * p [ 1 ] . y + p [ 2 ] . y ) / 6 ,
( p [ 1 ] . x + 6 * p [ 2 ] . x - p [ 3 ] . x ) / 6 ,
( p [ 1 ] . y + 6 * p [ 2 ] . y - p [ 3 ] . y ) / 6 ,
p [ 2 ] . x ,
p [ 2 ] . y
] ) ;
}
return d ;
}
// export
2013-09-25 05:52:57 +00:00
Snap . path = paths ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . getTotalLength
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns the length of the given path in pixels
2013-08-05 08:04:30 +00:00
* *
2013-10-14 11:59:34 +00:00
- path ( string ) SVG path string
2013-08-05 08:04:30 +00:00
* *
2013-10-14 11:59:34 +00:00
= ( number ) length
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . getTotalLength = getTotalLength ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . getPointAtLength
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns the coordinates of the point located at the given length along the given path
2013-08-05 08:04:30 +00:00
* *
- path ( string ) SVG path string
2013-10-14 11:59:34 +00:00
- length ( number ) length , in pixels , from the start of the path , excluding non - rendering jumps
2013-08-05 08:04:30 +00:00
* *
= ( object ) representation of the point :
o {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate ,
o y : ( number ) y coordinate ,
2013-08-05 08:04:30 +00:00
o alpha : ( number ) angle of derivative
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . getPointAtLength = getPointAtLength ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . getSubpath
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns the subpath of a given path between given start and end lengths
2013-08-05 08:04:30 +00:00
* *
- path ( string ) SVG path string
2013-10-14 11:59:34 +00:00
- from ( number ) length , in pixels , from the start of the path to the start of the segment
- to ( number ) length , in pixels , from the start of the path to the end of the segment
2013-08-05 08:04:30 +00:00
* *
2013-10-14 11:59:34 +00:00
= ( string ) path string definition for the segment
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . getSubpath = function ( path , from , to ) {
2013-08-05 08:04:30 +00:00
if ( this . getTotalLength ( path ) - to < 1e-6 ) {
return getSubpathsAtLength ( path , from ) . end ;
}
var a = getSubpathsAtLength ( path , to , 1 ) ;
return from ? getSubpathsAtLength ( a , from ) . end : a ;
} ;
/ * \
* Element . getTotalLength
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns the length of the path in pixels ( only works for ` path ` elements )
= ( number ) length
2013-08-05 08:04:30 +00:00
\ * /
elproto . getTotalLength = function ( ) {
if ( this . node . getTotalLength ) {
return this . node . getTotalLength ( ) ;
}
} ;
2013-10-14 11:59:34 +00:00
// SIERRA Element.getPointAtLength()/Element.getTotalLength(): If a <path> is broken into different segments, is the jump distance to the new coordinates set by the _M_ or _m_ commands calculated as part of the path's total length?
2013-08-05 08:04:30 +00:00
/ * \
* Element . getPointAtLength
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns coordinates of the point located at the given length on the given path ( only works for ` path ` elements )
2013-08-05 08:04:30 +00:00
* *
2013-10-14 11:59:34 +00:00
- length ( number ) length , in pixels , from the start of the path , excluding non - rendering jumps
2013-08-05 08:04:30 +00:00
* *
= ( object ) representation of the point :
o {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate ,
o y : ( number ) y coordinate ,
2013-08-05 08:04:30 +00:00
o alpha : ( number ) angle of derivative
o }
\ * /
elproto . getPointAtLength = function ( length ) {
return getPointAtLength ( this . attr ( "d" ) , length ) ;
} ;
2013-10-14 11:59:34 +00:00
// SIERRA Element.getSubpath(): Similar to the problem for Element.getPointAtLength(). Unclear how this would work for a segmented path. Overall, the concept of _subpath_ and what I'm calling a _segment_ (series of non-_M_ or _Z_ commands) is unclear.
2013-08-05 08:04:30 +00:00
/ * \
* Element . getSubpath
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns subpath of a given element from given start and end lengths ( only works for ` path ` elements )
2013-08-05 08:04:30 +00:00
* *
2013-10-14 11:59:34 +00:00
- from ( number ) length , in pixels , from the start of the path to the start of the segment
- to ( number ) length , in pixels , from the start of the path to the end of the segment
2013-08-05 08:04:30 +00:00
* *
2013-10-14 11:59:34 +00:00
= ( string ) path string definition for the segment
2013-08-05 08:04:30 +00:00
\ * /
elproto . getSubpath = function ( from , to ) {
2013-09-25 05:52:57 +00:00
return Snap . path . getSubpath ( this . attr ( "d" ) , from , to ) ;
2013-08-05 08:04:30 +00:00
} ;
2013-09-25 05:52:57 +00:00
Snap . _ . box = box ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . findDotsAtSegment
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Finds dot coordinates on the given cubic beziér curve at the given t
2013-08-05 08:04:30 +00:00
- p1x ( number ) x of the first point of the curve
- p1y ( number ) y of the first point of the curve
- c1x ( number ) x of the first anchor of the curve
- c1y ( number ) y of the first anchor of the curve
- c2x ( number ) x of the second anchor of the curve
- c2y ( number ) y of the second anchor of the curve
- p2x ( number ) x of the second point of the curve
- p2y ( number ) y of the second point of the curve
- t ( number ) position on the curve ( 0. . 1 )
= ( object ) point information in format :
o {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate of the point ,
o y : ( number ) y coordinate of the point ,
2013-08-05 08:04:30 +00:00
o m : {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate of the left anchor ,
2013-08-05 08:04:30 +00:00
o y : ( number ) y coordinate of the left anchor
2013-10-14 11:59:34 +00:00
o } ,
2013-08-05 08:04:30 +00:00
o n : {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate of the right anchor ,
2013-08-05 08:04:30 +00:00
o y : ( number ) y coordinate of the right anchor
2013-10-14 11:59:34 +00:00
o } ,
2013-08-05 08:04:30 +00:00
o start : {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate of the start of the curve ,
2013-08-05 08:04:30 +00:00
o y : ( number ) y coordinate of the start of the curve
2013-10-14 11:59:34 +00:00
o } ,
2013-08-05 08:04:30 +00:00
o end : {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate of the end of the curve ,
2013-08-05 08:04:30 +00:00
o y : ( number ) y coordinate of the end of the curve
2013-10-14 11:59:34 +00:00
o } ,
2013-08-05 08:04:30 +00:00
o alpha : ( number ) angle of the curve derivative at the point
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . findDotsAtSegment = findDotsAtSegment ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . bezierBBox
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Returns the bounding box of a given cubic beziér curve
2013-08-05 08:04:30 +00:00
- p1x ( number ) x of the first point of the curve
- p1y ( number ) y of the first point of the curve
- c1x ( number ) x of the first anchor of the curve
- c1y ( number ) y of the first anchor of the curve
- c2x ( number ) x of the second anchor of the curve
- c2y ( number ) y of the second anchor of the curve
- p2x ( number ) x of the second point of the curve
- p2y ( number ) y of the second point of the curve
* or
2013-10-14 11:59:34 +00:00
- bez ( array ) array of six points for beziér curve
2013-10-15 00:12:33 +00:00
= ( object ) bounding box
2013-08-05 08:04:30 +00:00
o {
2013-10-15 00:12:33 +00:00
o x : ( number ) x coordinate of the left top point of the box ,
o y : ( number ) y coordinate of the left top point of the box ,
o x2 : ( number ) x coordinate of the right bottom point of the box ,
o y2 : ( number ) y coordinate of the right bottom point of the box ,
o width : ( number ) width of the box ,
o height : ( number ) height of the box
2013-08-05 08:04:30 +00:00
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . bezierBBox = bezierBBox ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . isPointInsideBBox
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Returns ` true ` if given point is inside bounding box
2013-08-05 08:04:30 +00:00
- bbox ( string ) bounding box
- x ( string ) x coordinate of the point
- y ( string ) y coordinate of the point
2013-10-14 11:59:34 +00:00
= ( boolean ) ` true ` if point is inside
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . isPointInsideBBox = isPointInsideBBox ;
2014-10-28 10:48:17 +00:00
Snap . closest = function ( x , y , X , Y ) {
var r = 100 ,
b = box ( x - r / 2 , y - r / 2 , r , r ) ,
inside = [ ] ,
getter = X [ 0 ] . hasOwnProperty ( "x" ) ? function ( i ) {
return {
x : X [ i ] . x ,
y : X [ i ] . y
} ;
} : function ( i ) {
return {
x : X [ i ] ,
y : Y [ i ]
} ;
} ,
found = 0 ;
while ( r <= 1e6 && ! found ) {
for ( var i = 0 , ii = X . length ; i < ii ; i ++ ) {
var xy = getter ( i ) ;
if ( isPointInsideBBox ( b , xy . x , xy . y ) ) {
found ++ ;
inside . push ( xy ) ;
break ;
}
}
if ( ! found ) {
r *= 2 ;
b = box ( x - r / 2 , y - r / 2 , r , r )
}
}
if ( r == 1e6 ) {
return ;
}
var len = Infinity ,
res ;
for ( i = 0 , ii = inside . length ; i < ii ; i ++ ) {
var l = Snap . len ( x , y , inside [ i ] . x , inside [ i ] . y ) ;
if ( len > l ) {
len = l ;
inside [ i ] . len = l ;
res = inside [ i ] ;
}
}
return res ;
} ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . isBBoxIntersect
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
* Returns ` true ` if two bounding boxes intersect
- bbox1 ( string ) first bounding box
- bbox2 ( string ) second bounding box
2013-10-14 11:59:34 +00:00
= ( boolean ) ` true ` if bounding boxes intersect
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . isBBoxIntersect = isBBoxIntersect ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . intersection
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
* Finds intersections of two paths
- path1 ( string ) path string
- path2 ( string ) path string
= ( array ) dots of intersection
o [
o {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate of the point ,
o y : ( number ) y coordinate of the point ,
o t1 : ( number ) t value for segment of path1 ,
o t2 : ( number ) t value for segment of path2 ,
o segment1 : ( number ) order number for segment of path1 ,
o segment2 : ( number ) order number for segment of path2 ,
o bez1 : ( array ) eight coordinates representing beziér curve for the segment of path1 ,
2013-08-05 08:04:30 +00:00
o bez2 : ( array ) eight coordinates representing beziér curve for the segment of path2
o }
o ]
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . intersection = pathIntersection ;
Snap . path . intersectionNumber = pathIntersectionNumber ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . isPointInside
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-15 00:12:33 +00:00
* Returns ` true ` if given point is inside a given closed path .
*
* Note : fill mode doesn ’ t affect the result of this method .
2013-08-05 08:04:30 +00:00
- path ( string ) path string
- x ( number ) x of the point
- y ( number ) y of the point
2013-10-14 11:59:34 +00:00
= ( boolean ) ` true ` if point is inside the path
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . isPointInside = isPointInsidePath ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . getBBox
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Returns the bounding box of a given path
2013-08-05 08:04:30 +00:00
- path ( string ) path string
= ( object ) bounding box
o {
2013-10-14 11:59:34 +00:00
o x : ( number ) x coordinate of the left top point of the box ,
o y : ( number ) y coordinate of the left top point of the box ,
o x2 : ( number ) x coordinate of the right bottom point of the box ,
o y2 : ( number ) y coordinate of the right bottom point of the box ,
o width : ( number ) width of the box ,
2013-08-05 08:04:30 +00:00
o height : ( number ) height of the box
o }
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . getBBox = pathBBox ;
Snap . path . get = getPath ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . toRelative
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Converts path coordinates into relative values
2013-08-05 08:04:30 +00:00
- path ( string ) path string
= ( array ) path string
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . toRelative = pathToRelative ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . toAbsolute
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Converts path coordinates into absolute values
2013-08-05 08:04:30 +00:00
- path ( string ) path string
= ( array ) path string
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . toAbsolute = pathToAbsolute ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . toCubic
2013-08-05 08:04:30 +00:00
[ method ]
* *
* Utility method
* *
2013-10-14 11:59:34 +00:00
* Converts path to a new path where all segments are cubic beziér curves
2013-08-05 08:04:30 +00:00
- pathString ( string | array ) path string or array of segments
2013-10-14 11:59:34 +00:00
= ( array ) array of segments
2013-08-05 08:04:30 +00:00
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . toCubic = path2curve ;
2013-08-05 08:04:30 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . path . map
2013-08-05 08:04:30 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Transform the path string with the given matrix
2013-08-05 08:04:30 +00:00
- path ( string ) path string
- matrix ( object ) see @ Matrix
= ( string ) transformed path string
\ * /
2013-09-25 05:52:57 +00:00
Snap . path . map = mapPath ;
Snap . path . toString = toString ;
Snap . path . clone = pathClone ;
2013-08-05 08:04:30 +00:00
} ) ;
2015-04-02 11:06:19 +00:00
2013-08-15 08:29:47 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2017-02-03 23:39:45 +00:00
//
2013-08-15 08:29:47 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2017-02-03 23:39:45 +00:00
//
2013-08-15 08:29:47 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2017-02-03 23:39:45 +00:00
//
2013-08-15 08:29:47 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-09-25 05:52:57 +00:00
Snap . plugin ( function ( Snap , Element , Paper , glob ) {
2013-08-05 08:04:30 +00:00
var mmax = Math . max ,
mmin = Math . min ;
// Set
var Set = function ( items ) {
this . items = [ ] ;
2014-05-08 04:21:19 +00:00
this . bindings = { } ;
2013-08-05 08:04:30 +00:00
this . length = 0 ;
this . type = "set" ;
if ( items ) {
for ( var i = 0 , ii = items . length ; i < ii ; i ++ ) {
if ( items [ i ] ) {
this [ this . items . length ] = this . items [ this . items . length ] = items [ i ] ;
this . length ++ ;
}
}
}
} ,
setproto = Set . prototype ;
/ * \
* Set . push
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds each argument to the current set
2013-08-05 08:04:30 +00:00
= ( object ) original element
\ * /
setproto . push = function ( ) {
var item ,
len ;
for ( var i = 0 , ii = arguments . length ; i < ii ; i ++ ) {
item = arguments [ i ] ;
if ( item ) {
len = this . items . length ;
this [ len ] = this . items [ len ] = item ;
this . length ++ ;
}
}
return this ;
} ;
/ * \
* Set . pop
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes last element and returns it
2013-08-05 08:04:30 +00:00
= ( object ) element
\ * /
setproto . pop = function ( ) {
this . length && delete this [ this . length -- ] ;
return this . items . pop ( ) ;
} ;
/ * \
* Set . forEach
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Executes given function for each element in the set
2013-08-05 08:04:30 +00:00
*
2013-10-14 11:59:34 +00:00
* If the function returns ` false ` , the loop stops running .
2013-08-05 08:04:30 +00:00
* *
- callback ( function ) function to run
- thisArg ( object ) context object for the callback
= ( object ) Set object
\ * /
setproto . forEach = function ( callback , thisArg ) {
for ( var i = 0 , ii = this . items . length ; i < ii ; i ++ ) {
if ( callback . call ( thisArg , this . items [ i ] , i ) === false ) {
return this ;
}
}
return this ;
} ;
2014-05-15 06:58:04 +00:00
/ * \
* Set . animate
[ method ]
* *
* Animates each element in set in sync .
*
* *
- attrs ( object ) key - value pairs of destination attributes
- duration ( number ) duration of the animation in milliseconds
- easing ( function ) # optional easing function from @ mina or custom
- callback ( function ) # optional callback function that executes when the animation ends
* or
- animation ( array ) array of animation parameter for each element in set in format ` [attrs, duration, easing, callback] `
> Usage
| // animate all elements in set to radius 10
| set . animate ( { r : 10 } , 500 , mina . easein ) ;
| // or
| // animate first element to radius 10, but second to radius 20 and in different time
| set . animate ( [ { r : 10 } , 500 , mina . easein ] , [ { r : 20 } , 1500 , mina . easein ] ) ;
= ( Element ) the current element
\ * /
2014-05-06 00:13:22 +00:00
setproto . animate = function ( attrs , ms , easing , callback ) {
if ( typeof easing == "function" && ! easing . length ) {
callback = easing ;
easing = mina . linear ;
}
if ( attrs instanceof Snap . _ . Animation ) {
callback = attrs . callback ;
easing = attrs . easing ;
ms = easing . dur ;
attrs = attrs . attr ;
}
2014-05-15 06:58:04 +00:00
var args = arguments ;
if ( Snap . is ( attrs , "array" ) && Snap . is ( args [ args . length - 1 ] , "array" ) ) {
var each = true ;
}
2014-05-06 00:13:22 +00:00
var begin ,
handler = function ( ) {
if ( begin ) {
this . b = begin ;
} else {
begin = this . b ;
}
} ,
cb = 0 ,
2015-04-07 02:06:45 +00:00
set = this ,
2014-05-06 00:13:22 +00:00
callbacker = callback && function ( ) {
2015-04-07 02:06:45 +00:00
if ( ++ cb == set . length ) {
2014-05-06 00:13:22 +00:00
callback . call ( this ) ;
}
} ;
2014-05-15 06:58:04 +00:00
return this . forEach ( function ( el , i ) {
2014-05-06 00:13:22 +00:00
eve . once ( "snap.animcreated." + el . id , handler ) ;
2014-05-15 06:58:04 +00:00
if ( each ) {
args [ i ] && el . animate . apply ( el , args [ i ] ) ;
} else {
el . animate ( attrs , ms , easing , callbacker ) ;
}
2014-05-06 00:13:22 +00:00
} ) ;
} ;
2017-02-03 23:39:45 +00:00
/ * \
* Set . remove
[ method ]
* *
* Removes all children of the set .
*
= ( object ) Set object
\ * /
2013-11-20 00:42:25 +00:00
setproto . remove = function ( ) {
while ( this . length ) {
this . pop ( ) . remove ( ) ;
}
return this ;
} ;
2014-05-08 04:21:19 +00:00
/ * \
* Set . bind
[ method ]
* *
* Specifies how to handle a specific attribute when applied
* to a set .
*
* *
- attr ( string ) attribute name
- callback ( function ) function to run
* or
- attr ( string ) attribute name
- element ( Element ) specific element in the set to apply the attribute to
* or
- attr ( string ) attribute name
- element ( Element ) specific element in the set to apply the attribute to
- eattr ( string ) attribute on the element to bind the attribute to
= ( object ) Set object
\ * /
setproto . bind = function ( attr , a , b ) {
var data = { } ;
if ( typeof a == "function" ) {
this . bindings [ attr ] = a ;
} else {
var aname = b || attr ;
this . bindings [ attr ] = function ( v ) {
data [ aname ] = v ;
a . attr ( data ) ;
} ;
}
return this ;
} ;
2017-02-03 23:39:45 +00:00
/ * \
* Set . attr
[ method ]
* *
* Equivalent of @ Element . attr .
= ( object ) Set object
\ * /
2013-08-05 08:04:30 +00:00
setproto . attr = function ( value ) {
2014-05-08 04:21:19 +00:00
var unbound = { } ;
for ( var k in value ) {
if ( this . bindings [ k ] ) {
this . bindings [ k ] ( value [ k ] ) ;
} else {
unbound [ k ] = value [ k ] ;
}
}
2013-08-05 08:04:30 +00:00
for ( var i = 0 , ii = this . items . length ; i < ii ; i ++ ) {
2014-05-08 04:21:19 +00:00
this . items [ i ] . attr ( unbound ) ;
2013-08-05 08:04:30 +00:00
}
return this ;
} ;
/ * \
* Set . clear
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes all elements from the set
2013-08-05 08:04:30 +00:00
\ * /
setproto . clear = function ( ) {
while ( this . length ) {
this . pop ( ) ;
}
} ;
/ * \
* Set . splice
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes range of elements from the set
2013-08-05 08:04:30 +00:00
* *
- index ( number ) position of the deletion
- count ( number ) number of element to remove
- insertion … ( object ) # optional elements to insert
= ( object ) set elements that were deleted
\ * /
setproto . splice = function ( index , count , insertion ) {
index = index < 0 ? mmax ( this . length + index , 0 ) : index ;
count = mmax ( 0 , mmin ( this . length - index , count ) ) ;
var tail = [ ] ,
todel = [ ] ,
args = [ ] ,
i ;
for ( i = 2 ; i < arguments . length ; i ++ ) {
args . push ( arguments [ i ] ) ;
}
for ( i = 0 ; i < count ; i ++ ) {
todel . push ( this [ index + i ] ) ;
}
for ( ; i < this . length - index ; i ++ ) {
tail . push ( this [ index + i ] ) ;
}
var arglen = args . length ;
for ( i = 0 ; i < arglen + tail . length ; i ++ ) {
this . items [ index + i ] = this [ index + i ] = i < arglen ? args [ i ] : tail [ i - arglen ] ;
}
i = this . items . length = this . length -= count - arglen ;
while ( this [ i ] ) {
delete this [ i ++ ] ;
}
return new Set ( todel ) ;
} ;
/ * \
* Set . exclude
[ method ]
* *
* Removes given element from the set
* *
- element ( object ) element to remove
2013-10-14 11:59:34 +00:00
= ( boolean ) ` true ` if object was found and removed from the set
2013-08-05 08:04:30 +00:00
\ * /
setproto . exclude = function ( el ) {
for ( var i = 0 , ii = this . length ; i < ii ; i ++ ) if ( this [ i ] == el ) {
this . splice ( i , 1 ) ;
return true ;
}
2013-09-19 11:03:24 +00:00
return false ;
2013-08-05 08:04:30 +00:00
} ;
2017-02-03 23:39:45 +00:00
/ * \
* Set . insertAfter
[ method ]
* *
* Inserts set elements after given element .
* *
- element ( object ) set will be inserted after this element
= ( object ) Set object
\ * /
2013-08-05 08:04:30 +00:00
setproto . insertAfter = function ( el ) {
var i = this . items . length ;
while ( i -- ) {
this . items [ i ] . insertAfter ( el ) ;
}
return this ;
} ;
2017-02-03 23:39:45 +00:00
/ * \
* Set . getBBox
[ method ]
* *
* Union of all bboxes of the set . See @ Element . getBBox .
= ( object ) bounding box descriptor . See @ Element . getBBox .
\ * /
2013-08-05 08:04:30 +00:00
setproto . getBBox = function ( ) {
var x = [ ] ,
y = [ ] ,
x2 = [ ] ,
y2 = [ ] ;
for ( var i = this . items . length ; i -- ; ) if ( ! this . items [ i ] . removed ) {
var box = this . items [ i ] . getBBox ( ) ;
x . push ( box . x ) ;
y . push ( box . y ) ;
x2 . push ( box . x + box . width ) ;
y2 . push ( box . y + box . height ) ;
}
x = mmin . apply ( 0 , x ) ;
y = mmin . apply ( 0 , y ) ;
x2 = mmax . apply ( 0 , x2 ) ;
y2 = mmax . apply ( 0 , y2 ) ;
return {
x : x ,
y : y ,
x2 : x2 ,
y2 : y2 ,
width : x2 - x ,
height : y2 - y ,
cx : x + ( x2 - x ) / 2 ,
cy : y + ( y2 - y ) / 2
} ;
} ;
2017-02-03 23:39:45 +00:00
/ * \
* Set . insertAfter
[ method ]
* *
* Creates a clone of the set .
* *
= ( object ) New Set object
\ * /
2013-08-05 08:04:30 +00:00
setproto . clone = function ( s ) {
s = new Set ;
for ( var i = 0 , ii = this . items . length ; i < ii ; i ++ ) {
s . push ( this . items [ i ] . clone ( ) ) ;
}
return s ;
} ;
setproto . toString = function ( ) {
2013-09-25 05:52:57 +00:00
return "Snap\u2018s set" ;
2013-08-05 08:04:30 +00:00
} ;
setproto . type = "set" ;
// export
2017-02-03 23:39:45 +00:00
/ * \
* Snap . Set
[ property ]
* *
* Set constructor .
\ * /
2014-08-13 12:46:40 +00:00
Snap . Set = Set ;
2017-02-03 23:39:45 +00:00
/ * \
* Snap . set
[ method ]
* *
* Creates a set and fills it with list of arguments .
* *
= ( object ) New Set object
| var r = paper . rect ( 0 , 0 , 10 , 10 ) ,
| s1 = Snap . set ( ) , // empty set
| s2 = Snap . set ( r , paper . circle ( 100 , 100 , 20 ) ) ; // prefilled set
\ * /
2013-09-25 05:52:57 +00:00
Snap . set = function ( ) {
2013-08-05 08:04:30 +00:00
var set = new Set ;
if ( arguments . length ) {
set . push . apply ( set , Array . prototype . slice . call ( arguments , 0 ) ) ;
}
return set ;
} ;
} ) ;
2014-05-08 04:21:19 +00:00
2013-08-15 08:29:47 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2016-12-14 00:40:56 +00:00
//
2013-08-15 08:29:47 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2016-12-14 00:40:56 +00:00
//
2013-08-15 08:29:47 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2016-12-14 00:40:56 +00:00
//
2013-08-15 08:29:47 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-09-25 05:52:57 +00:00
Snap . plugin ( function ( Snap , Element , Paper , glob ) {
2013-08-05 08:04:30 +00:00
var names = { } ,
2016-12-29 05:13:00 +00:00
reUnit = /[%a-z]+$/i ,
2013-08-05 08:04:30 +00:00
Str = String ;
names . stroke = names . fill = "colour" ;
function getEmpty ( item ) {
var l = item [ 0 ] ;
switch ( l . toLowerCase ( ) ) {
case "t" : return [ l , 0 , 0 ] ;
case "m" : return [ l , 1 , 0 , 0 , 1 , 0 , 0 ] ;
case "r" : if ( item . length == 4 ) {
return [ l , 0 , item [ 2 ] , item [ 3 ] ] ;
} else {
return [ l , 0 ] ;
}
case "s" : if ( item . length == 5 ) {
return [ l , 1 , 1 , item [ 3 ] , item [ 4 ] ] ;
} else if ( item . length == 3 ) {
return [ l , 1 , 1 ] ;
} else {
return [ l , 1 ] ;
}
}
}
2013-09-28 12:25:29 +00:00
function equaliseTransform ( t1 , t2 , getBBox ) {
2016-12-22 00:33:43 +00:00
t1 = t1 || new Snap . Matrix ;
t2 = t2 || new Snap . Matrix ;
2016-12-14 00:40:56 +00:00
t1 = Snap . parseTransformString ( t1 . toTransformString ( ) ) || [ ] ;
t2 = Snap . parseTransformString ( t2 . toTransformString ( ) ) || [ ] ;
2013-08-05 08:04:30 +00:00
var maxlength = Math . max ( t1 . length , t2 . length ) ,
from = [ ] ,
to = [ ] ,
i = 0 , j , jj ,
tt1 , tt2 ;
for ( ; i < maxlength ; i ++ ) {
tt1 = t1 [ i ] || getEmpty ( t2 [ i ] ) ;
tt2 = t2 [ i ] || getEmpty ( tt1 ) ;
2017-01-24 02:32:41 +00:00
if ( tt1 [ 0 ] != tt2 [ 0 ] ||
tt1 [ 0 ] . toLowerCase ( ) == "r" && ( tt1 [ 2 ] != tt2 [ 2 ] || tt1 [ 3 ] != tt2 [ 3 ] ) ||
tt1 [ 0 ] . toLowerCase ( ) == "s" && ( tt1 [ 3 ] != tt2 [ 3 ] || tt1 [ 4 ] != tt2 [ 4 ] )
2013-08-05 08:04:30 +00:00
) {
2013-09-28 12:25:29 +00:00
t1 = Snap . _ . transform2matrix ( t1 , getBBox ( ) ) ;
t2 = Snap . _ . transform2matrix ( t2 , getBBox ( ) ) ;
from = [ [ "m" , t1 . a , t1 . b , t1 . c , t1 . d , t1 . e , t1 . f ] ] ;
to = [ [ "m" , t2 . a , t2 . b , t2 . c , t2 . d , t2 . e , t2 . f ] ] ;
break ;
2013-08-05 08:04:30 +00:00
}
from [ i ] = [ ] ;
to [ i ] = [ ] ;
for ( j = 0 , jj = Math . max ( tt1 . length , tt2 . length ) ; j < jj ; j ++ ) {
j in tt1 && ( from [ i ] [ j ] = tt1 [ j ] ) ;
j in tt2 && ( to [ i ] [ j ] = tt2 [ j ] ) ;
}
}
return {
from : path2array ( from ) ,
to : path2array ( to ) ,
f : getPath ( from )
} ;
}
function getNumber ( val ) {
return val ;
}
function getUnit ( unit ) {
return function ( val ) {
return + val . toFixed ( 3 ) + unit ;
} ;
}
2015-04-02 11:06:19 +00:00
function getViewBox ( val ) {
return val . join ( " " ) ;
}
2013-08-05 08:04:30 +00:00
function getColour ( clr ) {
2017-01-02 23:34:35 +00:00
return Snap . rgb ( clr [ 0 ] , clr [ 1 ] , clr [ 2 ] , clr [ 3 ] ) ;
2013-08-05 08:04:30 +00:00
}
function getPath ( path ) {
var k = 0 , i , ii , j , jj , out , a , b = [ ] ;
for ( i = 0 , ii = path . length ; i < ii ; i ++ ) {
out = "[" ;
a = [ '"' + path [ i ] [ 0 ] + '"' ] ;
for ( j = 1 , jj = path [ i ] . length ; j < jj ; j ++ ) {
2017-01-24 02:32:41 +00:00
a [ j ] = "val[" + k ++ + "]" ;
2013-08-05 08:04:30 +00:00
}
out += a + "]" ;
b [ i ] = out ;
}
2013-09-25 05:52:57 +00:00
return Function ( "val" , "return Snap.path.toString.call([" + b + "])" ) ;
2013-08-05 08:04:30 +00:00
}
function path2array ( path ) {
var out = [ ] ;
for ( var i = 0 , ii = path . length ; i < ii ; i ++ ) {
for ( var j = 1 , jj = path [ i ] . length ; j < jj ; j ++ ) {
out . push ( path [ i ] [ j ] ) ;
}
}
return out ;
}
2015-04-02 11:06:19 +00:00
function isNumeric ( obj ) {
2016-12-29 05:13:00 +00:00
return isFinite ( obj ) ;
2015-04-02 11:06:19 +00:00
}
function arrayEqual ( arr1 , arr2 ) {
if ( ! Snap . is ( arr1 , "array" ) || ! Snap . is ( arr2 , "array" ) ) {
return false ;
}
return arr1 . toString ( ) == arr2 . toString ( ) ;
}
2013-08-05 08:04:30 +00:00
Element . prototype . equal = function ( name , b ) {
2014-05-23 11:03:03 +00:00
return eve ( "snap.util.equal" , this , name , b ) . firstDefined ( ) ;
2014-05-15 06:58:04 +00:00
} ;
eve . on ( "snap.util.equal" , function ( name , b ) {
2013-09-28 12:25:29 +00:00
var A , B , a = Str ( this . attr ( name ) || "" ) ,
el = this ;
2013-08-05 08:04:30 +00:00
if ( names [ name ] == "colour" ) {
2013-09-25 05:52:57 +00:00
A = Snap . color ( a ) ;
B = Snap . color ( b ) ;
2013-08-05 08:04:30 +00:00
return {
from : [ A . r , A . g , A . b , A . opacity ] ,
to : [ B . r , B . g , B . b , B . opacity ] ,
f : getColour
} ;
}
2015-04-02 11:06:19 +00:00
if ( name == "viewBox" ) {
A = this . attr ( name ) . vb . split ( " " ) . map ( Number ) ;
B = b . split ( " " ) . map ( Number ) ;
return {
from : A ,
to : B ,
f : getViewBox
} ;
}
2013-08-05 08:04:30 +00:00
if ( name == "transform" || name == "gradientTransform" || name == "patternTransform" ) {
2016-12-14 00:40:56 +00:00
if ( typeof b == "string" ) {
b = Str ( b ) . replace ( /\.{3}|\u2026/g , a ) ;
}
a = this . matrix ;
2013-11-25 01:00:34 +00:00
if ( ! Snap . _ . rgTransform . test ( b ) ) {
2016-12-22 00:33:43 +00:00
b = Snap . _ . transform2matrix ( Snap . _ . svgTransform2string ( b ) , this . getBBox ( ) ) ;
2016-12-14 00:40:56 +00:00
} else {
2016-12-22 00:33:43 +00:00
b = Snap . _ . transform2matrix ( b , this . getBBox ( ) ) ;
2013-11-25 01:00:34 +00:00
}
2013-09-28 12:25:29 +00:00
return equaliseTransform ( a , b , function ( ) {
return el . getBBox ( 1 ) ;
} ) ;
2013-08-05 08:04:30 +00:00
}
if ( name == "d" || name == "path" ) {
2013-09-25 05:52:57 +00:00
A = Snap . path . toCubic ( a , b ) ;
2013-08-05 08:04:30 +00:00
return {
from : path2array ( A [ 0 ] ) ,
to : path2array ( A [ 1 ] ) ,
f : getPath ( A [ 0 ] )
} ;
}
2013-11-25 01:00:34 +00:00
if ( name == "points" ) {
2014-05-15 06:58:04 +00:00
A = Str ( a ) . split ( Snap . _ . separator ) ;
B = Str ( b ) . split ( Snap . _ . separator ) ;
2013-11-25 01:00:34 +00:00
return {
from : A ,
to : B ,
f : function ( val ) { return val ; }
} ;
}
2016-08-01 01:37:11 +00:00
if ( isNumeric ( a ) && isNumeric ( b ) ) {
return {
from : parseFloat ( a ) ,
to : parseFloat ( b ) ,
f : getNumber
} ;
}
2015-04-02 11:06:19 +00:00
var aUnit = a . match ( reUnit ) ,
bUnit = Str ( b ) . match ( reUnit ) ;
if ( aUnit && arrayEqual ( aUnit , bUnit ) ) {
2013-08-05 08:04:30 +00:00
return {
from : parseFloat ( a ) ,
to : parseFloat ( b ) ,
f : getUnit ( aUnit )
} ;
} else {
return {
from : this . asPX ( name ) ,
to : this . asPX ( name , b ) ,
f : getNumber
} ;
}
2014-05-15 06:58:04 +00:00
} ) ;
2013-08-05 08:04:30 +00:00
} ) ;
2015-04-02 11:38:56 +00:00
2013-08-15 08:29:47 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2016-12-29 05:13:00 +00:00
//
2013-08-15 08:29:47 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2016-12-29 05:13:00 +00:00
//
2013-08-15 08:29:47 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2016-12-29 05:13:00 +00:00
//
2013-08-15 08:29:47 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-09-25 05:52:57 +00:00
Snap . plugin ( function ( Snap , Element , Paper , glob ) {
2013-08-05 08:04:30 +00:00
var elproto = Element . prototype ,
has = "hasOwnProperty" ,
supportsTouch = "createTouch" in glob . doc ,
events = [
"click" , "dblclick" , "mousedown" , "mousemove" , "mouseout" ,
"mouseover" , "mouseup" , "touchstart" , "touchmove" , "touchend" ,
"touchcancel"
] ,
touchMap = {
mousedown : "touchstart" ,
mousemove : "touchmove" ,
mouseup : "touchend"
} ,
2014-05-23 11:36:04 +00:00
getScroll = function ( xy , el ) {
var name = xy == "y" ? "scrollTop" : "scrollLeft" ,
2014-05-27 13:57:03 +00:00
doc = el && el . node ? el . node . ownerDocument : glob . doc ;
2014-05-23 11:36:04 +00:00
return doc [ name in doc . documentElement ? "documentElement" : "body" ] [ name ] ;
2013-08-05 08:04:30 +00:00
} ,
preventDefault = function ( ) {
this . returnValue = false ;
} ,
preventTouch = function ( ) {
return this . originalEvent . preventDefault ( ) ;
} ,
stopPropagation = function ( ) {
this . cancelBubble = true ;
} ,
stopTouch = function ( ) {
return this . originalEvent . stopPropagation ( ) ;
} ,
2015-04-02 11:38:56 +00:00
addEvent = function ( obj , type , fn , element ) {
var realName = supportsTouch && touchMap [ type ] ? touchMap [ type ] : type ,
f = function ( e ) {
var scrollY = getScroll ( "y" , element ) ,
scrollX = getScroll ( "x" , element ) ;
if ( supportsTouch && touchMap [ has ] ( type ) ) {
for ( var i = 0 , ii = e . targetTouches && e . targetTouches . length ; i < ii ; i ++ ) {
if ( e . targetTouches [ i ] . target == obj || obj . contains ( e . targetTouches [ i ] . target ) ) {
var olde = e ;
e = e . targetTouches [ i ] ;
e . originalEvent = olde ;
e . preventDefault = preventTouch ;
e . stopPropagation = stopTouch ;
break ;
2013-08-05 08:04:30 +00:00
}
2015-04-02 11:38:56 +00:00
}
2013-12-23 01:26:40 +00:00
}
2015-04-02 11:38:56 +00:00
var x = e . clientX + scrollX ,
y = e . clientY + scrollY ;
return fn . call ( element , e , x , y ) ;
} ;
2013-12-23 01:26:40 +00:00
2015-04-02 11:38:56 +00:00
if ( type !== realName ) {
obj . addEventListener ( type , f , false ) ;
}
2013-12-23 01:26:40 +00:00
2015-04-02 11:38:56 +00:00
obj . addEventListener ( realName , f , false ) ;
2013-12-23 01:26:40 +00:00
2015-04-02 11:38:56 +00:00
return function ( ) {
if ( type !== realName ) {
obj . removeEventListener ( type , f , false ) ;
}
obj . removeEventListener ( realName , f , false ) ;
return true ;
} ;
} ,
2013-08-05 08:04:30 +00:00
drag = [ ] ,
dragMove = function ( e ) {
var x = e . clientX ,
y = e . clientY ,
scrollY = getScroll ( "y" ) ,
scrollX = getScroll ( "x" ) ,
dragi ,
j = drag . length ;
while ( j -- ) {
dragi = drag [ j ] ;
if ( supportsTouch ) {
2013-12-23 01:26:40 +00:00
var i = e . touches && e . touches . length ,
2013-08-05 08:04:30 +00:00
touch ;
while ( i -- ) {
touch = e . touches [ i ] ;
2013-12-23 01:26:40 +00:00
if ( touch . identifier == dragi . el . _drag . id || dragi . el . node . contains ( touch . target ) ) {
2013-08-05 08:04:30 +00:00
x = touch . clientX ;
y = touch . clientY ;
( e . originalEvent ? e . originalEvent : e ) . preventDefault ( ) ;
break ;
}
}
} else {
e . preventDefault ( ) ;
}
var node = dragi . el . node ,
o ,
next = node . nextSibling ,
parent = node . parentNode ,
display = node . style . display ;
// glob.win.opera && parent.removeChild(node);
// node.style.display = "none";
// o = dragi.el.paper.getElementByPoint(x, y);
// node.style.display = display;
// glob.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));
2013-09-25 05:52:57 +00:00
// o && eve("snap.drag.over." + dragi.el.id, dragi.el, o);
2013-08-05 08:04:30 +00:00
x += scrollX ;
y += scrollY ;
2013-09-25 05:52:57 +00:00
eve ( "snap.drag.move." + dragi . el . id , dragi . move _scope || dragi . el , x - dragi . el . _drag . x , y - dragi . el . _drag . y , x , y , e ) ;
2013-08-05 08:04:30 +00:00
}
} ,
dragUp = function ( e ) {
2013-09-25 05:52:57 +00:00
Snap . unmousemove ( dragMove ) . unmouseup ( dragUp ) ;
2013-08-05 08:04:30 +00:00
var i = drag . length ,
dragi ;
while ( i -- ) {
dragi = drag [ i ] ;
dragi . el . _drag = { } ;
2013-09-25 05:52:57 +00:00
eve ( "snap.drag.end." + dragi . el . id , dragi . end _scope || dragi . start _scope || dragi . move _scope || dragi . el , e ) ;
2014-10-28 10:48:17 +00:00
eve . off ( "snap.drag.*." + dragi . el . id ) ;
2013-08-05 08:04:30 +00:00
}
drag = [ ] ;
} ;
/ * \
* Element . click
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a click event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . unclick
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a click event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . dblclick
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a double click event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . undblclick
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a double click event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . mousedown
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a mousedown event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . unmousedown
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a mousedown event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . mousemove
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a mousemove event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . unmousemove
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a mousemove event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . mouseout
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a mouseout event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . unmouseout
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a mouseout event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . mouseover
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a mouseover event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . unmouseover
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a mouseover event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . mouseup
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a mouseup event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . unmouseup
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a mouseup event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . touchstart
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a touchstart event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . untouchstart
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a touchstart event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . touchmove
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a touchmove event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . untouchmove
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a touchmove event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . touchend
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a touchend event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . untouchend
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a touchend event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
2016-12-29 05:13:00 +00:00
2013-08-05 08:04:30 +00:00
/ * \
* Element . touchcancel
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds a touchcancel event handler to the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
/ * \
* Element . untouchcancel
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes a touchcancel event handler from the element
2013-08-05 08:04:30 +00:00
- handler ( function ) handler for the event
= ( object ) @ Element
\ * /
for ( var i = events . length ; i -- ; ) {
( function ( eventName ) {
2013-09-25 05:52:57 +00:00
Snap [ eventName ] = elproto [ eventName ] = function ( fn , scope ) {
if ( Snap . is ( fn , "function" ) ) {
2013-08-05 08:04:30 +00:00
this . events = this . events || [ ] ;
this . events . push ( {
name : eventName ,
f : fn ,
2014-05-25 07:52:40 +00:00
unbind : addEvent ( this . node || document , eventName , fn , scope || this )
2013-08-05 08:04:30 +00:00
} ) ;
2014-10-28 10:48:17 +00:00
} else {
for ( var i = 0 , ii = this . events . length ; i < ii ; i ++ ) if ( this . events [ i ] . name == eventName ) {
try {
this . events [ i ] . f . call ( this ) ;
} catch ( e ) { }
}
2013-08-05 08:04:30 +00:00
}
return this ;
} ;
2013-09-25 05:52:57 +00:00
Snap [ "un" + eventName ] =
2013-09-12 02:56:46 +00:00
elproto [ "un" + eventName ] = function ( fn ) {
2013-08-05 08:04:30 +00:00
var events = this . events || [ ] ,
l = events . length ;
2013-09-12 02:56:46 +00:00
while ( l -- ) if ( events [ l ] . name == eventName &&
( events [ l ] . f == fn || ! fn ) ) {
2013-08-05 08:04:30 +00:00
events [ l ] . unbind ( ) ;
events . splice ( l , 1 ) ;
! events . length && delete this . events ;
return this ;
}
return this ;
} ;
} ) ( events [ i ] ) ;
}
/ * \
* Element . hover
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds hover event handlers to the element
2013-08-05 08:04:30 +00:00
- f _in ( function ) handler for hover in
- f _out ( function ) handler for hover out
- icontext ( object ) # optional context for hover in handler
- ocontext ( object ) # optional context for hover out handler
= ( object ) @ Element
\ * /
elproto . hover = function ( f _in , f _out , scope _in , scope _out ) {
return this . mouseover ( f _in , scope _in ) . mouseout ( f _out , scope _out || scope _in ) ;
} ;
/ * \
* Element . unhover
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes hover event handlers from the element
2013-08-05 08:04:30 +00:00
- f _in ( function ) handler for hover in
- f _out ( function ) handler for hover out
= ( object ) @ Element
\ * /
elproto . unhover = function ( f _in , f _out ) {
return this . unmouseover ( f _in ) . unmouseout ( f _out ) ;
} ;
var draggable = [ ] ;
2013-10-14 11:59:34 +00:00
// SIERRA unclear what _context_ refers to for starting, ending, moving the drag gesture.
// SIERRA Element.drag(): _x position of the mouse_: Where are the x/y values offset from?
// SIERRA Element.drag(): much of this member's doc appears to be duplicated for some reason.
// SIERRA Unclear about this sentence: _Additionally following drag events will be triggered: drag.start.<id> on start, drag.end.<id> on end and drag.move.<id> on every move._ Is there a global _drag_ object to which you can assign handlers keyed by an element's ID?
2013-08-05 08:04:30 +00:00
/ * \
* Element . drag
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Adds event handlers for an element ' s drag gesture
* *
2013-08-05 08:04:30 +00:00
- onmove ( function ) handler for moving
- onstart ( function ) handler for drag start
- onend ( function ) handler for drag end
- mcontext ( object ) # optional context for moving handler
- scontext ( object ) # optional context for drag start handler
- econtext ( object ) # optional context for drag end handler
2016-12-29 05:13:00 +00:00
* Additionaly following ` drag ` events are triggered : ` drag.start.<id> ` on start ,
* ` drag.end.<id> ` on end and ` drag.move.<id> ` on every move . When element is dragged over another element
2013-10-14 11:59:34 +00:00
* ` drag.over.<id> ` fires as well .
2013-08-05 08:04:30 +00:00
*
2013-10-14 11:59:34 +00:00
* Start event and start handler are called in specified context or in context of the element with following parameters :
2013-08-05 08:04:30 +00:00
o x ( number ) x position of the mouse
o y ( number ) y position of the mouse
o event ( object ) DOM event object
2013-10-14 11:59:34 +00:00
* Move event and move handler are called in specified context or in context of the element with following parameters :
2013-08-05 08:04:30 +00:00
o dx ( number ) shift by x from the start point
o dy ( number ) shift by y from the start point
o x ( number ) x position of the mouse
o y ( number ) y position of the mouse
o event ( object ) DOM event object
2013-10-14 11:59:34 +00:00
* End event and end handler are called in specified context or in context of the element with following parameters :
2013-08-05 08:04:30 +00:00
o event ( object ) DOM event object
= ( object ) @ Element
\ * /
elproto . drag = function ( onmove , onstart , onend , move _scope , start _scope , end _scope ) {
2014-10-28 10:48:17 +00:00
var el = this ;
2013-08-05 08:04:30 +00:00
if ( ! arguments . length ) {
var origTransform ;
2014-10-28 10:48:17 +00:00
return el . drag ( function ( dx , dy ) {
2013-08-05 08:04:30 +00:00
this . attr ( {
transform : origTransform + ( origTransform ? "T" : "t" ) + [ dx , dy ]
} ) ;
} , function ( ) {
origTransform = this . transform ( ) . local ;
} ) ;
}
2013-12-23 01:26:40 +00:00
function start ( e , x , y ) {
2013-08-05 08:04:30 +00:00
( e . originalEvent || e ) . preventDefault ( ) ;
2014-10-28 10:48:17 +00:00
el . _drag . x = x ;
el . _drag . y = y ;
el . _drag . id = e . identifier ;
2013-09-25 05:52:57 +00:00
! drag . length && Snap . mousemove ( dragMove ) . mouseup ( dragUp ) ;
2014-10-28 10:48:17 +00:00
drag . push ( { el : el , move _scope : move _scope , start _scope : start _scope , end _scope : end _scope } ) ;
onstart && eve . on ( "snap.drag.start." + el . id , onstart ) ;
onmove && eve . on ( "snap.drag.move." + el . id , onmove ) ;
onend && eve . on ( "snap.drag.end." + el . id , onend ) ;
eve ( "snap.drag.start." + el . id , start _scope || move _scope || el , x , y , e ) ;
}
function init ( e , x , y ) {
eve ( "snap.draginit." + el . id , el , e , x , y ) ;
}
eve . on ( "snap.draginit." + el . id , start ) ;
el . _drag = { } ;
draggable . push ( { el : el , start : start , init : init } ) ;
el . mousedown ( init ) ;
return el ;
2013-08-05 08:04:30 +00:00
} ;
2013-09-12 02:56:46 +00:00
/ *
2013-08-05 08:04:30 +00:00
* Element . onDragOver
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Shortcut to assign event handler for ` drag.over.<id> ` event , where ` id ` is the element ' s ` id ` ( see @ Element . id )
2013-08-05 08:04:30 +00:00
- f ( function ) handler for event , first argument would be the element you are dragging over
\ * /
2013-09-12 02:56:46 +00:00
// elproto.onDragOver = function (f) {
2013-09-25 05:52:57 +00:00
// f ? eve.on("snap.drag.over." + this.id, f) : eve.unbind("snap.drag.over." + this.id);
2013-09-12 02:56:46 +00:00
// };
2013-08-05 08:04:30 +00:00
/ * \
* Element . undrag
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Removes all drag event handlers from the given element
2013-08-05 08:04:30 +00:00
\ * /
elproto . undrag = function ( ) {
var i = draggable . length ;
while ( i -- ) if ( draggable [ i ] . el == this ) {
2014-10-28 10:48:17 +00:00
this . unmousedown ( draggable [ i ] . init ) ;
2013-08-05 08:04:30 +00:00
draggable . splice ( i , 1 ) ;
2013-09-25 05:52:57 +00:00
eve . unbind ( "snap.drag.*." + this . id ) ;
2014-10-28 10:48:17 +00:00
eve . unbind ( "snap.draginit." + this . id ) ;
2013-08-05 08:04:30 +00:00
}
2013-09-25 05:52:57 +00:00
! draggable . length && Snap . unmousemove ( dragMove ) . unmouseup ( dragUp ) ;
2013-09-12 02:56:46 +00:00
return this ;
2013-08-05 08:04:30 +00:00
} ;
2013-08-15 08:29:47 +00:00
} ) ;
2015-04-02 11:06:19 +00:00
2013-08-15 08:29:47 +00:00
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
2017-01-02 23:49:09 +00:00
//
2013-08-15 08:29:47 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2017-01-02 23:49:09 +00:00
//
2013-08-15 08:29:47 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2017-01-02 23:49:09 +00:00
//
2013-08-15 08:29:47 +00:00
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-09-25 05:52:57 +00:00
Snap . plugin ( function ( Snap , Element , Paper , glob ) {
2013-08-15 08:29:47 +00:00
var elproto = Element . prototype ,
pproto = Paper . prototype ,
rgurl = /^\s*url\((.+)\)/ ,
Str = String ,
2013-09-25 05:52:57 +00:00
$ = Snap . _ . $ ;
Snap . filter = { } ;
2013-08-22 10:00:40 +00:00
/ * \
* Paper . filter
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Creates a ` <filter> ` element
2013-08-22 10:00:40 +00:00
* *
2013-10-14 11:59:34 +00:00
- filstr ( string ) SVG fragment of filter provided as a string
2013-08-22 10:00:40 +00:00
= ( object ) @ Element
2013-10-14 11:59:34 +00:00
* Note : It is recommended to use filters embedded into the page inside an empty SVG element .
2013-08-22 10:00:40 +00:00
> Usage
| var f = paper . filter ( '<feGaussianBlur stdDeviation="2"/>' ) ,
| c = paper . circle ( 10 , 10 , 10 ) . attr ( {
| filter : f
| } ) ;
\ * /
2013-08-15 08:29:47 +00:00
pproto . filter = function ( filstr ) {
2013-09-25 05:52:57 +00:00
var paper = this ;
if ( paper . type != "svg" ) {
paper = paper . paper ;
}
var f = Snap . parse ( Str ( filstr ) ) ,
id = Snap . _ . id ( ) ,
width = paper . node . offsetWidth ,
height = paper . node . offsetHeight ,
2013-08-15 08:29:47 +00:00
filter = $ ( "filter" ) ;
$ ( filter , {
id : id ,
2013-11-20 01:29:50 +00:00
filterUnits : "userSpaceOnUse"
2013-08-15 08:29:47 +00:00
} ) ;
filter . appendChild ( f . node ) ;
2013-09-25 05:52:57 +00:00
paper . defs . appendChild ( filter ) ;
2013-08-15 08:29:47 +00:00
return new Element ( filter ) ;
} ;
2017-01-02 23:49:09 +00:00
2013-09-25 05:52:57 +00:00
eve . on ( "snap.util.getattr.filter" , function ( ) {
2013-08-15 08:29:47 +00:00
eve . stop ( ) ;
var p = $ ( this . node , "filter" ) ;
if ( p ) {
var match = Str ( p ) . match ( rgurl ) ;
2013-09-25 05:52:57 +00:00
return match && Snap . select ( match [ 1 ] ) ;
2013-08-15 08:29:47 +00:00
}
} ) ;
2013-09-25 05:52:57 +00:00
eve . on ( "snap.util.attr.filter" , function ( value ) {
2013-08-15 08:29:47 +00:00
if ( value instanceof Element && value . type == "filter" ) {
eve . stop ( ) ;
var id = value . node . id ;
if ( ! id ) {
$ ( value . node , { id : value . id } ) ;
id = value . id ;
}
$ ( this . node , {
2013-12-23 01:26:40 +00:00
filter : Snap . url ( id )
2013-08-15 08:29:47 +00:00
} ) ;
}
2013-09-05 00:10:45 +00:00
if ( ! value || value == "none" ) {
2013-08-15 08:29:47 +00:00
eve . stop ( ) ;
this . node . removeAttribute ( "filter" ) ;
}
} ) ;
2013-08-22 10:00:40 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . blur
2013-08-22 10:00:40 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the blur filter
2013-08-22 10:00:40 +00:00
* *
2013-10-14 11:59:34 +00:00
- x ( number ) amount of horizontal blur , in pixels
- y ( number ) # optional amount of vertical blur , in pixels
2013-08-22 10:00:40 +00:00
= ( string ) filter representation
> Usage
2013-09-25 05:52:57 +00:00
| var f = paper . filter ( Snap . filter . blur ( 5 , 10 ) ) ,
2013-08-22 10:00:40 +00:00
| c = paper . circle ( 10 , 10 , 10 ) . attr ( {
| filter : f
| } ) ;
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . blur = function ( x , y ) {
2013-08-15 08:29:47 +00:00
if ( x == null ) {
x = 2 ;
}
var def = y == null ? x : [ x , y ] ;
2013-09-25 05:52:57 +00:00
return Snap . format ( '\<feGaussianBlur stdDeviation="{def}"/>' , {
2013-08-15 08:29:47 +00:00
def : def
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . blur . toString = function ( ) {
2013-08-15 08:29:47 +00:00
return this ( ) ;
} ;
2013-08-22 10:00:40 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . shadow
2013-08-22 10:00:40 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the shadow filter
2013-08-22 10:00:40 +00:00
* *
2014-01-13 02:06:26 +00:00
- dx ( number ) # optional horizontal shift of the shadow , in pixels
- dy ( number ) # optional vertical shift of the shadow , in pixels
2013-10-14 11:59:34 +00:00
- blur ( number ) # optional amount of blur
- color ( string ) # optional color of the shadow
2014-01-13 02:06:26 +00:00
- opacity ( number ) # optional ` 0..1 ` opacity of the shadow
* or
- dx ( number ) # optional horizontal shift of the shadow , in pixels
- dy ( number ) # optional vertical shift of the shadow , in pixels
- color ( string ) # optional color of the shadow
- opacity ( number ) # optional ` 0..1 ` opacity of the shadow
* which makes blur default to ` 4 ` . Or
- dx ( number ) # optional horizontal shift of the shadow , in pixels
- dy ( number ) # optional vertical shift of the shadow , in pixels
- opacity ( number ) # optional ` 0..1 ` opacity of the shadow
2013-08-22 10:00:40 +00:00
= ( string ) filter representation
> Usage
2017-01-02 23:49:09 +00:00
| var f = paper . filter ( Snap . filter . shadow ( 0 , 2 , . 3 ) ) ,
2013-08-22 10:00:40 +00:00
| c = paper . circle ( 10 , 10 , 10 ) . attr ( {
| filter : f
| } ) ;
\ * /
2014-01-13 02:06:26 +00:00
Snap . filter . shadow = function ( dx , dy , blur , color , opacity ) {
2017-01-02 23:49:09 +00:00
if ( opacity == null ) {
if ( color == null ) {
opacity = blur ;
blur = 4 ;
color = "#000" ;
} else {
opacity = color ;
2017-02-02 01:51:35 +00:00
color = blur ;
2017-01-02 23:49:09 +00:00
blur = 4 ;
}
2014-01-13 02:06:26 +00:00
}
2013-08-15 08:29:47 +00:00
if ( blur == null ) {
2013-09-05 00:10:45 +00:00
blur = 4 ;
2013-08-15 08:29:47 +00:00
}
2014-01-13 02:06:26 +00:00
if ( opacity == null ) {
opacity = 1 ;
2013-09-19 11:03:24 +00:00
}
2013-08-15 08:29:47 +00:00
if ( dx == null ) {
dx = 0 ;
2013-09-05 00:10:45 +00:00
dy = 2 ;
2013-08-15 08:29:47 +00:00
}
if ( dy == null ) {
dy = dx ;
}
2013-09-25 05:52:57 +00:00
color = Snap . color ( color ) ;
2014-01-13 02:06:26 +00:00
return Snap . format ( '<feGaussianBlur in="SourceAlpha" stdDeviation="{blur}"/><feOffset dx="{dx}" dy="{dy}" result="offsetblur"/><feFlood flood-color="{color}"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="{opacity}"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>' , {
2013-09-10 02:22:49 +00:00
color : color ,
2013-08-15 08:29:47 +00:00
dx : dx ,
dy : dy ,
2014-01-13 02:06:26 +00:00
blur : blur ,
opacity : opacity
2013-08-15 08:29:47 +00:00
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . shadow . toString = function ( ) {
2013-08-15 08:29:47 +00:00
return this ( ) ;
} ;
2013-09-10 02:22:49 +00:00
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . grayscale
2013-09-10 02:22:49 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the grayscale filter
2013-09-10 02:22:49 +00:00
* *
2013-10-14 11:59:34 +00:00
- amount ( number ) amount of filter ( ` 0..1 ` )
2013-09-10 02:22:49 +00:00
= ( string ) filter representation
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . grayscale = function ( amount ) {
2013-09-10 02:22:49 +00:00
if ( amount == null ) {
amount = 1 ;
}
2013-09-25 05:52:57 +00:00
return Snap . format ( '<feColorMatrix type="matrix" values="{a} {b} {c} 0 0 {d} {e} {f} 0 0 {g} {b} {h} 0 0 0 0 0 1 0"/>' , {
2013-09-10 02:22:49 +00:00
a : 0.2126 + 0.7874 * ( 1 - amount ) ,
b : 0.7152 - 0.7152 * ( 1 - amount ) ,
c : 0.0722 - 0.0722 * ( 1 - amount ) ,
d : 0.2126 - 0.2126 * ( 1 - amount ) ,
e : 0.7152 + 0.2848 * ( 1 - amount ) ,
f : 0.0722 - 0.0722 * ( 1 - amount ) ,
g : 0.2126 - 0.2126 * ( 1 - amount ) ,
h : 0.0722 + 0.9278 * ( 1 - amount )
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . grayscale . toString = function ( ) {
2013-09-10 02:22:49 +00:00
return this ( ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . sepia
2013-09-10 02:22:49 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the sepia filter
2013-09-10 02:22:49 +00:00
* *
2013-10-14 11:59:34 +00:00
- amount ( number ) amount of filter ( ` 0..1 ` )
2013-09-10 02:22:49 +00:00
= ( string ) filter representation
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . sepia = function ( amount ) {
2013-09-10 02:22:49 +00:00
if ( amount == null ) {
amount = 1 ;
}
2013-09-25 05:52:57 +00:00
return Snap . format ( '<feColorMatrix type="matrix" values="{a} {b} {c} 0 0 {d} {e} {f} 0 0 {g} {h} {i} 0 0 0 0 0 1 0"/>' , {
2013-09-10 02:22:49 +00:00
a : 0.393 + 0.607 * ( 1 - amount ) ,
b : 0.769 - 0.769 * ( 1 - amount ) ,
c : 0.189 - 0.189 * ( 1 - amount ) ,
d : 0.349 - 0.349 * ( 1 - amount ) ,
e : 0.686 + 0.314 * ( 1 - amount ) ,
f : 0.168 - 0.168 * ( 1 - amount ) ,
g : 0.272 - 0.272 * ( 1 - amount ) ,
h : 0.534 - 0.534 * ( 1 - amount ) ,
i : 0.131 + 0.869 * ( 1 - amount )
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . sepia . toString = function ( ) {
2013-09-10 02:22:49 +00:00
return this ( ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . saturate
2013-09-10 02:22:49 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the saturate filter
2013-09-10 02:22:49 +00:00
* *
2013-10-14 11:59:34 +00:00
- amount ( number ) amount of filter ( ` 0..1 ` )
2013-09-10 02:22:49 +00:00
= ( string ) filter representation
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . saturate = function ( amount ) {
2013-09-10 02:22:49 +00:00
if ( amount == null ) {
amount = 1 ;
}
2013-09-25 05:52:57 +00:00
return Snap . format ( '<feColorMatrix type="saturate" values="{amount}"/>' , {
2013-09-10 02:22:49 +00:00
amount : 1 - amount
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . saturate . toString = function ( ) {
2013-09-10 02:22:49 +00:00
return this ( ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . hueRotate
2013-09-10 02:22:49 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the hue - rotate filter
2013-09-10 02:22:49 +00:00
* *
2013-10-14 11:59:34 +00:00
- angle ( number ) angle of rotation
2013-09-10 02:22:49 +00:00
= ( string ) filter representation
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . hueRotate = function ( angle ) {
2013-09-10 02:22:49 +00:00
angle = angle || 0 ;
2013-09-25 05:52:57 +00:00
return Snap . format ( '<feColorMatrix type="hueRotate" values="{angle}"/>' , {
2013-09-10 02:22:49 +00:00
angle : angle
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . hueRotate . toString = function ( ) {
2013-09-10 02:22:49 +00:00
return this ( ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . invert
2013-09-10 02:22:49 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the invert filter
2013-09-10 02:22:49 +00:00
* *
2013-10-14 11:59:34 +00:00
- amount ( number ) amount of filter ( ` 0..1 ` )
2013-09-10 02:22:49 +00:00
= ( string ) filter representation
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . invert = function ( amount ) {
2013-09-10 02:22:49 +00:00
if ( amount == null ) {
amount = 1 ;
}
2015-04-02 11:06:19 +00:00
// <feColorMatrix type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" color-interpolation-filters="sRGB"/>
2013-09-25 05:52:57 +00:00
return Snap . format ( '<feComponentTransfer><feFuncR type="table" tableValues="{amount} {amount2}"/><feFuncG type="table" tableValues="{amount} {amount2}"/><feFuncB type="table" tableValues="{amount} {amount2}"/></feComponentTransfer>' , {
2013-09-10 02:22:49 +00:00
amount : amount ,
amount2 : 1 - amount
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . invert . toString = function ( ) {
2013-09-10 02:22:49 +00:00
return this ( ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . brightness
2013-09-10 02:22:49 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the brightness filter
2013-09-10 02:22:49 +00:00
* *
2013-10-14 11:59:34 +00:00
- amount ( number ) amount of filter ( ` 0..1 ` )
2013-09-10 02:22:49 +00:00
= ( string ) filter representation
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . brightness = function ( amount ) {
2013-09-10 02:22:49 +00:00
if ( amount == null ) {
amount = 1 ;
}
2013-09-25 05:52:57 +00:00
return Snap . format ( '<feComponentTransfer><feFuncR type="linear" slope="{amount}"/><feFuncG type="linear" slope="{amount}"/><feFuncB type="linear" slope="{amount}"/></feComponentTransfer>' , {
2013-09-10 02:22:49 +00:00
amount : amount
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . brightness . toString = function ( ) {
2013-09-10 02:22:49 +00:00
return this ( ) ;
} ;
/ * \
2013-09-25 05:52:57 +00:00
* Snap . filter . contrast
2013-09-10 02:22:49 +00:00
[ method ]
* *
2013-10-14 11:59:34 +00:00
* Returns an SVG markup string for the contrast filter
2013-09-10 02:22:49 +00:00
* *
2013-10-14 11:59:34 +00:00
- amount ( number ) amount of filter ( ` 0..1 ` )
2013-09-10 02:22:49 +00:00
= ( string ) filter representation
\ * /
2013-09-25 05:52:57 +00:00
Snap . filter . contrast = function ( amount ) {
2013-09-10 02:22:49 +00:00
if ( amount == null ) {
amount = 1 ;
}
2013-09-25 05:52:57 +00:00
return Snap . format ( '<feComponentTransfer><feFuncR type="linear" slope="{amount}" intercept="{amount2}"/><feFuncG type="linear" slope="{amount}" intercept="{amount2}"/><feFuncB type="linear" slope="{amount}" intercept="{amount2}"/></feComponentTransfer>' , {
2013-09-10 02:22:49 +00:00
amount : amount ,
amount2 : . 5 - amount / 2
} ) ;
} ;
2013-09-25 05:52:57 +00:00
Snap . filter . contrast . toString = function ( ) {
2013-09-10 02:22:49 +00:00
return this ( ) ;
} ;
2013-09-25 05:52:57 +00:00
} ) ;
2014-08-25 06:52:37 +00:00
2014-09-17 07:40:16 +00:00
// Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap . plugin ( function ( Snap , Element , Paper , glob , Fragment ) {
var box = Snap . _ . box ,
is = Snap . is ,
firstLetter = /^[^a-z]*([tbmlrc])/i ,
toString = function ( ) {
return "T" + this . dx + "," + this . dy ;
} ;
/ * \
* Element . getAlign
[ method ]
* *
* Returns shift needed to align the element relatively to given element .
* If no elements specified , parent ` <svg> ` container will be used .
- el ( object ) @ optional alignment element
- way ( string ) one of six values : ` "top" ` , ` "middle" ` , ` "bottom" ` , ` "left" ` , ` "center" ` , ` "right" `
= ( object | string ) Object in format ` {dx: , dy: } ` also has a string representation as a transformation string
> Usage
| el . transform ( el . getAlign ( el2 , "top" ) ) ;
* or
| var dy = el . getAlign ( el2 , "top" ) . dy ;
\ * /
Element . prototype . getAlign = function ( el , way ) {
if ( way == null && is ( el , "string" ) ) {
way = el ;
el = null ;
}
el = el || this . paper ;
var bx = el . getBBox ? el . getBBox ( ) : box ( el ) ,
bb = this . getBBox ( ) ,
out = { } ;
way = way && way . match ( firstLetter ) ;
way = way ? way [ 1 ] . toLowerCase ( ) : "c" ;
switch ( way ) {
case "t" :
out . dx = 0 ;
out . dy = bx . y - bb . y ;
break ;
case "b" :
out . dx = 0 ;
out . dy = bx . y2 - bb . y2 ;
break ;
case "m" :
out . dx = 0 ;
out . dy = bx . cy - bb . cy ;
break ;
case "l" :
out . dx = bx . x - bb . x ;
out . dy = 0 ;
break ;
case "r" :
out . dx = bx . x2 - bb . x2 ;
out . dy = 0 ;
break ;
default :
out . dx = bx . cx - bb . cx ;
out . dy = 0 ;
break ;
}
out . toString = toString ;
return out ;
} ;
/ * \
* Element . align
[ method ]
* *
* Aligns the element relatively to given one via transformation .
* If no elements specified , parent ` <svg> ` container will be used .
- el ( object ) @ optional alignment element
- way ( string ) one of six values : ` "top" ` , ` "middle" ` , ` "bottom" ` , ` "left" ` , ` "center" ` , ` "right" `
= ( object ) this element
> Usage
| el . align ( el2 , "top" ) ;
* or
| el . align ( "middle" ) ;
\ * /
Element . prototype . align = function ( el , way ) {
return this . transform ( "..." + this . getAlign ( el , way ) ) ;
} ;
} ) ;
2014-09-17 07:44:54 +00:00
2017-01-02 23:34:35 +00:00
// Copyright (c) 2017 Adobe Systems Incorporated. All rights reserved.
2016-12-30 00:29:34 +00:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap . plugin ( function ( Snap , Element , Paper , glob ) {
// Colours are from https://www.materialui.co
var red = "#ffebee#ffcdd2#ef9a9a#e57373#ef5350#f44336#e53935#d32f2f#c62828#b71c1c#ff8a80#ff5252#ff1744#d50000" ,
pink = "#FCE4EC#F8BBD0#F48FB1#F06292#EC407A#E91E63#D81B60#C2185B#AD1457#880E4F#FF80AB#FF4081#F50057#C51162" ,
purple = "#F3E5F5#E1BEE7#CE93D8#BA68C8#AB47BC#9C27B0#8E24AA#7B1FA2#6A1B9A#4A148C#EA80FC#E040FB#D500F9#AA00FF" ,
deeppurple = "#EDE7F6#D1C4E9#B39DDB#9575CD#7E57C2#673AB7#5E35B1#512DA8#4527A0#311B92#B388FF#7C4DFF#651FFF#6200EA" ,
indigo = "#E8EAF6#C5CAE9#9FA8DA#7986CB#5C6BC0#3F51B5#3949AB#303F9F#283593#1A237E#8C9EFF#536DFE#3D5AFE#304FFE" ,
blue = "#E3F2FD#BBDEFB#90CAF9#64B5F6#64B5F6#2196F3#1E88E5#1976D2#1565C0#0D47A1#82B1FF#448AFF#2979FF#2962FF" ,
lightblue = "#E1F5FE#B3E5FC#81D4FA#4FC3F7#29B6F6#03A9F4#039BE5#0288D1#0277BD#01579B#80D8FF#40C4FF#00B0FF#0091EA" ,
cyan = "#E0F7FA#B2EBF2#80DEEA#4DD0E1#26C6DA#00BCD4#00ACC1#0097A7#00838F#006064#84FFFF#18FFFF#00E5FF#00B8D4" ,
teal = "#E0F2F1#B2DFDB#80CBC4#4DB6AC#26A69A#009688#00897B#00796B#00695C#004D40#A7FFEB#64FFDA#1DE9B6#00BFA5" ,
green = "#E8F5E9#C8E6C9#A5D6A7#81C784#66BB6A#4CAF50#43A047#388E3C#2E7D32#1B5E20#B9F6CA#69F0AE#00E676#00C853" ,
lightgreen = "#F1F8E9#DCEDC8#C5E1A5#AED581#9CCC65#8BC34A#7CB342#689F38#558B2F#33691E#CCFF90#B2FF59#76FF03#64DD17" ,
lime = "#F9FBE7#F0F4C3#E6EE9C#DCE775#D4E157#CDDC39#C0CA33#AFB42B#9E9D24#827717#F4FF81#EEFF41#C6FF00#AEEA00" ,
yellow = "#FFFDE7#FFF9C4#FFF59D#FFF176#FFEE58#FFEB3B#FDD835#FBC02D#F9A825#F57F17#FFFF8D#FFFF00#FFEA00#FFD600" ,
amber = "#FFF8E1#FFECB3#FFE082#FFD54F#FFCA28#FFC107#FFB300#FFA000#FF8F00#FF6F00#FFE57F#FFD740#FFC400#FFAB00" ,
orange = "#FFF3E0#FFE0B2#FFCC80#FFB74D#FFA726#FF9800#FB8C00#F57C00#EF6C00#E65100#FFD180#FFAB40#FF9100#FF6D00" ,
deeporange = "#FBE9E7#FFCCBC#FFAB91#FF8A65#FF7043#FF5722#F4511E#E64A19#D84315#BF360C#FF9E80#FF6E40#FF3D00#DD2C00" ,
brown = "#EFEBE9#D7CCC8#BCAAA4#A1887F#8D6E63#795548#6D4C41#5D4037#4E342E#3E2723" ,
grey = "#FAFAFA#F5F5F5#EEEEEE#E0E0E0#BDBDBD#9E9E9E#757575#616161#424242#212121" ,
bluegrey = "#ECEFF1#CFD8DC#B0BEC5#90A4AE#78909C#607D8B#546E7A#455A64#37474F#263238" ;
/ * \
* Snap . mui
[ property ]
* *
* Contain Material UI colours .
| Snap ( ) . rect ( 0 , 0 , 10 , 10 ) . attr ( { fill : Snap . mui . deeppurple , stroke : Snap . mui . amber [ 600 ] } ) ;
# For colour reference : < a href = "https://www.materialui.co" > https : //www.materialui.co</a>.
\ * /
Snap . mui = { } ;
/ * \
* Snap . flat
[ property ]
* *
* Contain Flat UI colours .
| Snap ( ) . rect ( 0 , 0 , 10 , 10 ) . attr ( { fill : Snap . flat . carrot , stroke : Snap . flat . wetasphalt } ) ;
# For colour reference : < a href = "https://www.materialui.co" > https : //www.materialui.co</a>.
\ * /
Snap . flat = { } ;
function saveColor ( colors ) {
colors = colors . split ( /(?=#)/ ) ;
var color = new String ( colors [ 5 ] ) ;
color [ 50 ] = colors [ 0 ] ;
color [ 100 ] = colors [ 1 ] ;
color [ 200 ] = colors [ 2 ] ;
color [ 300 ] = colors [ 3 ] ;
color [ 400 ] = colors [ 4 ] ;
color [ 500 ] = colors [ 5 ] ;
color [ 600 ] = colors [ 6 ] ;
color [ 700 ] = colors [ 7 ] ;
color [ 800 ] = colors [ 8 ] ;
color [ 900 ] = colors [ 9 ] ;
if ( colors [ 10 ] ) {
color . A100 = colors [ 10 ] ;
color . A200 = colors [ 11 ] ;
color . A400 = colors [ 12 ] ;
color . A700 = colors [ 13 ] ;
}
return color ;
}
Snap . mui . red = saveColor ( red ) ;
Snap . mui . pink = saveColor ( pink ) ;
Snap . mui . purple = saveColor ( purple ) ;
Snap . mui . deeppurple = saveColor ( deeppurple ) ;
Snap . mui . indigo = saveColor ( indigo ) ;
Snap . mui . blue = saveColor ( blue ) ;
Snap . mui . lightblue = saveColor ( lightblue ) ;
Snap . mui . cyan = saveColor ( cyan ) ;
Snap . mui . teal = saveColor ( teal ) ;
Snap . mui . green = saveColor ( green ) ;
Snap . mui . lightgreen = saveColor ( lightgreen ) ;
Snap . mui . lime = saveColor ( lime ) ;
Snap . mui . yellow = saveColor ( yellow ) ;
Snap . mui . amber = saveColor ( amber ) ;
Snap . mui . orange = saveColor ( orange ) ;
Snap . mui . deeporange = saveColor ( deeporange ) ;
Snap . mui . brown = saveColor ( brown ) ;
Snap . mui . grey = saveColor ( grey ) ;
Snap . mui . bluegrey = saveColor ( bluegrey ) ;
Snap . flat . turquoise = "#1abc9c" ;
Snap . flat . greensea = "#16a085" ;
Snap . flat . sunflower = "#f1c40f" ;
Snap . flat . orange = "#f39c12" ;
Snap . flat . emerland = "#2ecc71" ;
Snap . flat . nephritis = "#27ae60" ;
Snap . flat . carrot = "#e67e22" ;
Snap . flat . pumpkin = "#d35400" ;
Snap . flat . peterriver = "#3498db" ;
Snap . flat . belizehole = "#2980b9" ;
Snap . flat . alizarin = "#e74c3c" ;
Snap . flat . pomegranate = "#c0392b" ;
Snap . flat . amethyst = "#9b59b6" ;
Snap . flat . wisteria = "#8e44ad" ;
Snap . flat . clouds = "#ecf0f1" ;
Snap . flat . silver = "#bdc3c7" ;
Snap . flat . wetasphalt = "#34495e" ;
Snap . flat . midnightblue = "#2c3e50" ;
Snap . flat . concrete = "#95a5a6" ;
Snap . flat . asbestos = "#7f8c8d" ;
/ * \
* Snap . importMUIColors
[ method ]
* *
* Imports Material UI colours into global object .
| Snap . importMUIColors ( ) ;
| Snap ( ) . rect ( 0 , 0 , 10 , 10 ) . attr ( { fill : deeppurple , stroke : amber [ 600 ] } ) ;
# For colour reference : < a href = "https://www.materialui.co" > https : //www.materialui.co</a>.
\ * /
Snap . importMUIColors = function ( ) {
for ( var color in Snap . mui ) {
if ( Snap . mui . hasOwnProperty ( color ) ) {
window [ color ] = Snap . mui [ color ] ;
}
}
} ;
} ) ;
2013-09-25 05:52:57 +00:00
return Snap ;
2016-12-29 05:13:00 +00:00
} ) ) ;