nl_tokens: Efficiently auto - orient an element . This basically implements the orient = auto attribute of markers . The easiest way of understanding on what this does is to imagine the element is an arrowhead . Calling this method on the arrowhead makes it point to the position point while being auto - oriented ( properly rotated ) towards the reference point . target is the element relative to which the transformations are applied . Usually a viewport .
pl_tokens: function ( position , reference , target ) { // Clean-up previously set transformations except the scale. If we didn't clean up the // previous transformations then they'd add up with the old ones. Scale is an exception as // it doesn't add up, consider: `this.scale(2).scale(2).scale(2)`. The result is that the // element is scaled by the factor 2, not 8. var s = this . scale ( ) ; this . attr ( 'transform' , '' ) ; this . scale ( s . sx , s . sy ) ; var svg = this . svg ( ) . node ; var bbox = this . bbox ( false , target ) ; // 1. Translate to origin. var translateToOrigin = svg . createSVGTransform ( ) ; translateToOrigin . setTranslate ( - bbox . x - bbox . width / 2 , - bbox . y - bbox . height / 2 ) ; // 2. Rotate around origin. var rotateAroundOrigin = svg . createSVGTransform ( ) ; var angle = g . point ( position ) . changeInAngle ( position . x - reference . x , position . y - reference . y , reference ) ; rotateAroundOrigin . setRotate ( angle , 0 , 0 ) ; // 3. Translate to the `position` + the offset (half my width) towards the `reference` point. var translateFinal = svg . createSVGTransform ( ) ; var finalPosition = g . point ( position ) . move ( reference , bbox . width / 2 ) ; translateFinal . setTranslate ( <mask> . x + ( position . x - finalPosition . x ) , position . y + ( position . y - finalPosition . y ) ) ; // 4. Apply transformations. var ctm = this . node . getTransformToElement ( target ) ; var transform = svg . createSVGTransform ( ) ; transform . setMatrix ( translateFinal . matrix . multiply ( rotateAroundOrigin . matrix . multiply ( translateToOrigin . matrix . multiply ( ctm ) ) ) ) ; // Instead of directly setting the `matrix()` transform on the element, first, decompose // the matrix into separate transforms. This allows us to use normal Vectorizer methods // as they don't work on matrices. An example of this is to retrieve a scale of an element. // this.node.transform.baseVal.initialize(transform); var decomposition = decomposeMatrix ( transform . matrix ) ; this . translate ( decomposition . translateX , decomposition . translateY ) ; this . rotate ( decomposition . rotation ) ; // Note that scale has been already applied, hence the following line stays commented. (it's here just for reference). //this.scale(decomposition.scaleX, decomposition.scaleY); return this ; }