@@ -20,12 +20,15 @@ var ARROWPATHS = require('./arrow_paths');
20
20
*
21
21
* @param {d3.selection } el3: a d3-selected line or path element
22
22
*
23
- * @param {string } ends: 'start', 'end', or 'start+end' for which ends get arrowheads
23
+ * @param {string } ends: 'none', ' start', 'end', or 'start+end' for which ends get arrowheads
24
24
*
25
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
26
+ * @param {number } options.arrowhead: end head style - see ./arrow_paths
27
+ * @param {number } options.startarrowhead: start head style - see ./arrow_paths
28
+ * @param {number } options.arrowsize: relative size of the end head vs line width
29
+ * @param {number } options.startarrowsize: relative size of the start head vs line width
30
+ * @param {number } options.standoff: distance in px to move the end arrow point from its target
31
+ * @param {number } options.startstandoff: distance in px to move the start arrow point from its target
29
32
* @param {number } options.arrowwidth: width of the arrow line
30
33
* @param {string } options.arrowcolor: color of the arrow line, for the head to match
31
34
* Note that the opacity of this color is ignored, as it's assumed the container
@@ -35,10 +38,14 @@ var ARROWPATHS = require('./arrow_paths');
35
38
module . exports = function drawArrowHead ( el3 , ends , options ) {
36
39
var el = el3 . node ( ) ;
37
40
var headStyle = ARROWPATHS [ options . arrowhead || 0 ] ;
41
+ var startHeadStyle = ARROWPATHS [ options . startarrowhead || 0 ] ;
38
42
var scale = ( options . arrowwidth || 1 ) * options . arrowsize ;
43
+ var startScale = ( options . arrowwidth || 1 ) * options . startarrowsize ;
39
44
var doStart = ends . indexOf ( 'start' ) >= 0 ;
40
45
var doEnd = ends . indexOf ( 'end' ) >= 0 ;
46
+ var doNone = ends . indexOf ( 'none' ) >= 0 ;
41
47
var backOff = headStyle . backoff * scale + options . standoff ;
48
+ var startBackOff = startHeadStyle . backoff * startScale + options . startstandoff ;
42
49
43
50
var start , end , startRot , endRot ;
44
51
@@ -51,6 +58,13 @@ module.exports = function drawArrowHead(el3, ends, options) {
51
58
52
59
startRot = Math . atan2 ( dy , dx ) ;
53
60
endRot = startRot + Math . PI ;
61
+ if ( backOff && startBackOff ) {
62
+ if ( backOff * backOff + startBackOff * startBackOff > dx * dx + dy * dy ) {
63
+ hideLine ( ) ;
64
+ return ;
65
+ }
66
+ }
67
+
54
68
if ( backOff ) {
55
69
if ( backOff * backOff > dx * dx + dy * dy ) {
56
70
hideLine ( ) ;
@@ -59,17 +73,27 @@ module.exports = function drawArrowHead(el3, ends, options) {
59
73
var backOffX = backOff * Math . cos ( startRot ) ,
60
74
backOffY = backOff * Math . sin ( startRot ) ;
61
75
62
- if ( doStart ) {
63
- start . x -= backOffX ;
64
- start . y -= backOffY ;
65
- el3 . attr ( { x1 : start . x , y1 : start . y } ) ;
66
- }
67
- if ( doEnd ) {
76
+ if ( doEnd || doNone ) {
68
77
end . x += backOffX ;
69
78
end . y += backOffY ;
70
79
el3 . attr ( { x2 : end . x , y2 : end . y } ) ;
71
80
}
72
81
}
82
+
83
+ if ( startBackOff ) {
84
+ if ( startBackOff * startBackOff > dx * dx + dy * dy ) {
85
+ hideLine ( ) ;
86
+ return ;
87
+ }
88
+ var startBackOffX = startBackOff * Math . cos ( startRot ) ,
89
+ startbackOffY = startBackOff * Math . sin ( startRot ) ;
90
+
91
+ if ( doStart || doNone ) {
92
+ start . x -= startBackOffX ;
93
+ start . y -= startbackOffY ;
94
+ el3 . attr ( { x1 : start . x , y1 : start . y } ) ;
95
+ }
96
+ }
73
97
}
74
98
else if ( el . nodeName === 'path' ) {
75
99
var pathlen = el . getTotalLength ( ) ,
@@ -79,41 +103,35 @@ module.exports = function drawArrowHead(el3, ends, options) {
79
103
// combine the two
80
104
dashArray = '' ;
81
105
82
- if ( pathlen < backOff ) {
106
+ if ( pathlen < backOff || pathlen < startBackOff || pathlen < backOff + startBackOff ) {
83
107
hideLine ( ) ;
84
108
return ;
85
109
}
86
110
87
- if ( doStart ) {
88
- var start0 = el . getPointAtLength ( 0 ) ;
89
- var dstart = el . getPointAtLength ( 0.1 ) ;
90
111
91
- startRot = Math . atan2 ( start0 . y - dstart . y , start0 . x - dstart . x ) ;
92
- start = el . getPointAtLength ( Math . min ( backOff , pathlen ) ) ;
112
+ var start0 = el . getPointAtLength ( 0 ) ;
113
+ var dstart = el . getPointAtLength ( 0.1 ) ;
93
114
94
- if ( backOff ) dashArray = '0px,' + backOff + 'px,' ;
95
- }
115
+ startRot = Math . atan2 ( start0 . y - dstart . y , start0 . x - dstart . x ) ;
116
+ start = el . getPointAtLength ( Math . min ( startBackOff , pathlen ) ) ;
96
117
97
- if ( doEnd ) {
98
- var end0 = el . getPointAtLength ( pathlen ) ;
99
- var dend = el . getPointAtLength ( pathlen - 0.1 ) ;
118
+ dashArray = '0px,' + startBackOff + 'px,' ;
100
119
101
- endRot = Math . atan2 ( end0 . y - dend . y , end0 . x - dend . x ) ;
102
- end = el . getPointAtLength ( Math . max ( 0 , pathlen - backOff ) ) ;
120
+ var end0 = el . getPointAtLength ( pathlen ) ;
121
+ var dend = el . getPointAtLength ( pathlen - 0.1 ) ;
103
122
104
- if ( backOff ) {
105
- var shortening = dashArray ? 2 * backOff : backOff ;
106
- dashArray += ( pathlen - shortening ) + 'px,' + pathlen + 'px' ;
107
- }
108
- }
109
- else if ( dashArray ) dashArray += pathlen + 'px' ;
123
+ endRot = Math . atan2 ( end0 . y - dend . y , end0 . x - dend . x ) ;
124
+ end = el . getPointAtLength ( Math . max ( 0 , pathlen - backOff ) ) ;
125
+
126
+ var shortening = dashArray ? startBackOff + backOff : backOff ;
127
+ dashArray += ( pathlen - shortening ) + 'px,' + pathlen + 'px' ;
110
128
111
- if ( dashArray ) el3 . style ( 'stroke-dasharray' , dashArray ) ;
129
+ el3 . style ( 'stroke-dasharray' , dashArray ) ;
112
130
}
113
131
114
132
function hideLine ( ) { el3 . style ( 'stroke-dasharray' , '0px,100px' ) ; }
115
133
116
- function drawhead ( p , rot ) {
134
+ function drawhead ( headStyle , p , rot , scale ) {
117
135
if ( ! headStyle . path ) return ;
118
136
if ( headStyle . noRotate ) rot = 0 ;
119
137
@@ -132,6 +150,6 @@ module.exports = function drawArrowHead(el3, ends, options) {
132
150
} ) ;
133
151
}
134
152
135
- if ( doStart ) drawhead ( start , startRot ) ;
136
- if ( doEnd ) drawhead ( end , endRot ) ;
153
+ if ( doStart ) drawhead ( startHeadStyle , start , startRot , startScale ) ;
154
+ if ( doEnd ) drawhead ( headStyle , end , endRot , scale ) ;
137
155
} ;
0 commit comments