10
10
'use strict' ;
11
11
12
12
var d3 = require ( 'd3' ) ;
13
- var isNumeric = require ( 'fast-isnumeric' ) ;
14
13
15
14
var Color = require ( '../color' ) ;
16
- var Drawing = require ( '../drawing' ) ;
17
15
18
16
var ARROWPATHS = require ( './arrow_paths' ) ;
19
17
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 ;
42
44
43
45
if ( el . nodeName === 'line' ) {
44
46
start = { x : + el3 . attr ( 'x1' ) , y : + el3 . attr ( 'y1' ) } ;
45
47
end = { x : + el3 . attr ( 'x2' ) , y : + el3 . attr ( 'y2' ) } ;
46
48
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 ;
49
51
50
52
startRot = Math . atan2 ( dy , dx ) ;
51
53
endRot = startRot + Math . PI ;
@@ -83,16 +85,19 @@ module.exports = function drawArrowHead(el3, style, ends, mag, standoff) {
83
85
}
84
86
85
87
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
+
88
91
startRot = Math . atan2 ( start0 . y - dstart . y , start0 . x - dstart . x ) ;
89
92
start = el . getPointAtLength ( Math . min ( backOff , pathlen ) ) ;
93
+
90
94
if ( backOff ) dashArray = '0px,' + backOff + 'px,' ;
91
95
}
92
96
93
97
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
+
96
101
endRot = Math . atan2 ( end0 . y - dend . y , end0 . x - dend . x ) ;
97
102
end = el . getPointAtLength ( Math . max ( 0 , pathlen - backOff ) ) ;
98
103
@@ -110,19 +115,19 @@ module.exports = function drawArrowHead(el3, style, ends, mag, standoff) {
110
115
111
116
function drawhead ( p , rot ) {
112
117
if ( ! headStyle . path ) return ;
113
- if ( style > 5 ) rot = 0 ; // don't rotate square or circle
118
+ if ( headStyle . noRotate ) rot = 0 ;
119
+
114
120
d3 . select ( el . parentNode ) . append ( 'path' )
115
121
. attr ( {
116
122
'class' : el3 . attr ( 'class' ) ,
117
123
d : headStyle . path ,
118
124
transform :
119
125
'translate(' + p . x + ',' + p . y + ')' +
120
- 'rotate(' + ( rot * 180 / Math . PI ) + ')' +
126
+ ( rot ? 'rotate(' + ( rot * 180 / Math . PI ) + ')' : '' ) +
121
127
'scale(' + scale + ')'
122
128
} )
123
129
. style ( {
124
- fill : stroke ,
125
- opacity : opacity ,
130
+ fill : Color . rgb ( options . arrowcolor ) ,
126
131
'stroke-width' : 0
127
132
} ) ;
128
133
}
0 commit comments