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