1010'use strict' ; 
1111
1212var  d3  =  require ( 'd3' ) ; 
13- var  isNumeric  =  require ( 'fast-isnumeric' ) ; 
1413
1514var  Color  =  require ( '../color' ) ; 
16- var  Drawing  =  require ( '../drawing' ) ; 
1715
1816var  ARROWPATHS  =  require ( './arrow_paths' ) ; 
1917
20- // add arrowhead(s) to a path or line d3 element el3 
21- // style: 1-6, first 5 are pointers, 6 is circle, 7 is square, 8 is none 
22- // ends is 'start', 'end' (default), 'start+end' 
23- // mag is magnification vs. default (default 1) 
24- 
25- module . exports  =  function  drawArrowHead ( el3 ,  style ,  ends ,  mag ,  standoff )  { 
26-     if ( ! isNumeric ( mag ) )  mag  =  1 ; 
27-     var  el  =  el3 . node ( ) , 
28-         headStyle  =  ARROWPATHS [ style || 0 ] ; 
29- 
30-     if ( typeof  ends  !==  'string'  ||  ! ends )  ends  =  'end' ; 
31- 
32-     var  scale  =  ( Drawing . getPx ( el3 ,  'stroke-width' )  ||  1 )  *  mag , 
33-         stroke  =  el3 . style ( 'stroke' )  ||  Color . defaultLine , 
34-         opacity  =  el3 . style ( 'stroke-opacity' )  ||  1 , 
35-         doStart  =  ends . indexOf ( 'start' )  >=  0 , 
36-         doEnd  =  ends . indexOf ( 'end' )  >=  0 , 
37-         backOff  =  headStyle . backoff  *  scale  +  standoff , 
38-         start , 
39-         end , 
40-         startRot , 
41-         endRot ; 
18+ /** 
19+  * Add arrowhead(s) to a path or line element 
20+  * 
21+  * @param  {d3.selection } el3: a d3-selected line or path element 
22+  * 
23+  * @param  {string } ends: 'start', 'end', or 'start+end' for which ends get arrowheads 
24+  * 
25+  * @param  {object } options: style information. Must have all the following: 
26+  * @param  {number } options.arrowhead: head style - see ./arrow_paths 
27+  * @param  {number } options.arrowsize: relative size of the head vs line width 
28+  * @param  {number } options.standoff: distance in px to move the arrow point from its target 
29+  * @param  {number } options.arrowwidth: width of the arrow line 
30+  * @param  {string } options.arrowcolor: color of the arrow line, for the head to match 
31+  *     Note that the opacity of this color is ignored, as it's assumed the container 
32+  *     of both the line and head has opacity applied to it so there isn't greater opacity 
33+  *     where they overlap. 
34+  */ 
35+ module . exports  =  function  drawArrowHead ( el3 ,  ends ,  options )  { 
36+     var  el  =  el3 . node ( ) ; 
37+     var  headStyle  =  ARROWPATHS [ options . arrowhead  ||  0 ] ; 
38+     var  scale  =  ( options . arrowwidth  ||  1 )  *  options . arrowsize ; 
39+     var  doStart  =  ends . indexOf ( 'start' )  >=  0 ; 
40+     var  doEnd  =  ends . indexOf ( 'end' )  >=  0 ; 
41+     var  backOff  =  headStyle . backoff  *  scale  +  options . standoff ; 
42+ 
43+     var  start ,  end ,  startRot ,  endRot ; 
4244
4345    if ( el . nodeName  ===  'line' )  { 
4446        start  =  { x : + el3 . attr ( 'x1' ) ,  y : + el3 . attr ( 'y1' ) } ; 
4547        end  =  { x : + el3 . attr ( 'x2' ) ,  y : + el3 . attr ( 'y2' ) } ; 
4648
47-         var  dx  =  start . x  -  end . x , 
48-              dy  =  start . y  -  end . y ; 
49+         var  dx  =  start . x  -  end . x ; 
50+         var  dy  =  start . y  -  end . y ; 
4951
5052        startRot  =  Math . atan2 ( dy ,  dx ) ; 
5153        endRot  =  startRot  +  Math . PI ; 
@@ -83,16 +85,19 @@ module.exports = function drawArrowHead(el3, style, ends, mag, standoff) {
8385        } 
8486
8587        if ( doStart )  { 
86-             var  start0  =  el . getPointAtLength ( 0 ) , 
87-                 dstart  =  el . getPointAtLength ( 0.1 ) ; 
88+             var  start0  =  el . getPointAtLength ( 0 ) ; 
89+             var  dstart  =  el . getPointAtLength ( 0.1 ) ; 
90+ 
8891            startRot  =  Math . atan2 ( start0 . y  -  dstart . y ,  start0 . x  -  dstart . x ) ; 
8992            start  =  el . getPointAtLength ( Math . min ( backOff ,  pathlen ) ) ; 
93+ 
9094            if ( backOff )  dashArray  =  '0px,'  +  backOff  +  'px,' ; 
9195        } 
9296
9397        if ( doEnd )  { 
94-             var  end0  =  el . getPointAtLength ( pathlen ) , 
95-                 dend  =  el . getPointAtLength ( pathlen  -  0.1 ) ; 
98+             var  end0  =  el . getPointAtLength ( pathlen ) ; 
99+             var  dend  =  el . getPointAtLength ( pathlen  -  0.1 ) ; 
100+ 
96101            endRot  =  Math . atan2 ( end0 . y  -  dend . y ,  end0 . x  -  dend . x ) ; 
97102            end  =  el . getPointAtLength ( Math . max ( 0 ,  pathlen  -  backOff ) ) ; 
98103
@@ -110,19 +115,19 @@ module.exports = function drawArrowHead(el3, style, ends, mag, standoff) {
110115
111116    function  drawhead ( p ,  rot )  { 
112117        if ( ! headStyle . path )  return ; 
113-         if ( style  >  5 )  rot  =  0 ;  // don't rotate square or circle 
118+         if ( headStyle . noRotate )  rot  =  0 ; 
119+ 
114120        d3 . select ( el . parentNode ) . append ( 'path' ) 
115121            . attr ( { 
116122                'class' : el3 . attr ( 'class' ) , 
117123                d : headStyle . path , 
118124                transform :
119125                    'translate('  +  p . x  +  ','  +  p . y  +  ')'  + 
120-                     'rotate('  +  ( rot  *  180  /  Math . PI )  +  ')'  + 
126+                     ( rot  ?  'rotate('  +  ( rot  *  180  /  Math . PI )  +  ')'  :  '' )  + 
121127                    'scale('  +  scale  +  ')' 
122128            } ) 
123129            . style ( { 
124-                 fill : stroke , 
125-                 opacity : opacity , 
130+                 fill : Color . rgb ( options . arrowcolor ) , 
126131                'stroke-width' : 0 
127132            } ) ; 
128133    } 
0 commit comments