@@ -20,12 +20,15 @@ var ARROWPATHS = require('./arrow_paths');
2020 *
2121 * @param {d3.selection } el3: a d3-selected line or path element
2222 *
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
2424 *
2525 * @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
2932 * @param {number } options.arrowwidth: width of the arrow line
3033 * @param {string } options.arrowcolor: color of the arrow line, for the head to match
3134 * Note that the opacity of this color is ignored, as it's assumed the container
@@ -35,10 +38,14 @@ var ARROWPATHS = require('./arrow_paths');
3538module . exports = function drawArrowHead ( el3 , ends , options ) {
3639 var el = el3 . node ( ) ;
3740 var headStyle = ARROWPATHS [ options . arrowhead || 0 ] ;
41+ var startHeadStyle = ARROWPATHS [ options . startarrowhead || 0 ] ;
3842 var scale = ( options . arrowwidth || 1 ) * options . arrowsize ;
43+ var startScale = ( options . arrowwidth || 1 ) * options . startarrowsize ;
3944 var doStart = ends . indexOf ( 'start' ) >= 0 ;
4045 var doEnd = ends . indexOf ( 'end' ) >= 0 ;
46+ var doNone = ends . indexOf ( 'none' ) >= 0 ;
4147 var backOff = headStyle . backoff * scale + options . standoff ;
48+ var startBackOff = startHeadStyle . backoff * startScale + options . startstandoff ;
4249
4350 var start , end , startRot , endRot ;
4451
@@ -51,6 +58,13 @@ module.exports = function drawArrowHead(el3, ends, options) {
5158
5259 startRot = Math . atan2 ( dy , dx ) ;
5360 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+
5468 if ( backOff ) {
5569 if ( backOff * backOff > dx * dx + dy * dy ) {
5670 hideLine ( ) ;
@@ -59,17 +73,27 @@ module.exports = function drawArrowHead(el3, ends, options) {
5973 var backOffX = backOff * Math . cos ( startRot ) ,
6074 backOffY = backOff * Math . sin ( startRot ) ;
6175
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 ) {
6877 end . x += backOffX ;
6978 end . y += backOffY ;
7079 el3 . attr ( { x2 : end . x , y2 : end . y } ) ;
7180 }
7281 }
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+ }
7397 }
7498 else if ( el . nodeName === 'path' ) {
7599 var pathlen = el . getTotalLength ( ) ,
@@ -79,41 +103,35 @@ module.exports = function drawArrowHead(el3, ends, options) {
79103 // combine the two
80104 dashArray = '' ;
81105
82- if ( pathlen < backOff ) {
106+ if ( pathlen < backOff || pathlen < startBackOff || pathlen < backOff + startBackOff ) {
83107 hideLine ( ) ;
84108 return ;
85109 }
86110
87- if ( doStart ) {
88- var start0 = el . getPointAtLength ( 0 ) ;
89- var dstart = el . getPointAtLength ( 0.1 ) ;
90111
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 ) ;
93114
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 ) ) ;
96117
97- if ( doEnd ) {
98- var end0 = el . getPointAtLength ( pathlen ) ;
99- var dend = el . getPointAtLength ( pathlen - 0.1 ) ;
118+ dashArray = '0px,' + startBackOff + 'px,' ;
100119
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 ) ;
103122
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' ;
110128
111- if ( dashArray ) el3 . style ( 'stroke-dasharray' , dashArray ) ;
129+ el3 . style ( 'stroke-dasharray' , dashArray ) ;
112130 }
113131
114132 function hideLine ( ) { el3 . style ( 'stroke-dasharray' , '0px,100px' ) ; }
115133
116- function drawhead ( p , rot ) {
134+ function drawhead ( headStyle , p , rot , scale ) {
117135 if ( ! headStyle . path ) return ;
118136 if ( headStyle . noRotate ) rot = 0 ;
119137
@@ -132,6 +150,6 @@ module.exports = function drawArrowHead(el3, ends, options) {
132150 } ) ;
133151 }
134152
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 ) ;
137155} ;
0 commit comments