import { Workflow } from "../" ; export class EdgePanner { /** ID of the requested animation frame for panning */ private panAnimationFrame ; private workflow : Workflow ; private movementSpeed = 10 ; private scrollMargin = 100 ; /**
     * Current state of collision on both axes, each negative if beyond top/left border,
     * positive if beyond right/bottom, zero if inside the viewport
     */ private collision = { x : 0 , y : 0 } ; private viewportClientRect : ClientRect ; private panningCallback = ( sdx , sdy ) => void 0 ; constructor ( workflow , config = { scrollMargin : 100 , movementSpeed : 10 } ) { const options = Object . assign ( { scrollMargin : 100 , movementSpeed : 10 } , config ) ; this . workflow = workflow ; this . scrollMargin = options . scrollMargin ; this . movementSpeed = options . movementSpeed ; this . viewportClientRect = this . workflow . svgRoot . getBoundingClientRect ( ) ; } /**
     * Calculates if dragged node is at or beyond the point beyond which workflow panning should be triggered.
     * If collision state has changed,  onBoundaryCollisionChange will be triggered.
      triggerCollisionDetection ( x , y , callback ) { const collision = { x : 0 , y : 0 } ; this . panningCallback = callback ; let { left , right , top , bottom } = this . viewportClientRect ; left = left + this . scrollMargin ; right = right - this . scrollMargin ; top = top + this . scrollMargin ; bottom = bottom - this . scrollMargin ; if ( x < left ) { collision . x = x - left ; } else if ( x > right ) { collision . x = x - right ; } if ( y < top ) { collision . y = y - top ; } else if ( y > bottom ) { collision . y = y - bottom ; } if ( Math . sign ( collision . x ) !== Math . sign ( this . collision . x ) || Math . sign ( collision . y ) !== Math . sign ( this . collision . y ) ) { const previous = this . collision ; this . collision = collision ; this . onBoundaryCollisionChange ( collision , previous ) ; } } /**
     * Triggered when  triggerCollisionDetection determines that collision properties have changed.
      private onBoundaryCollisionChange ( current , previous ) { this . stop ( ) ; if ( current . x === 0 && current . y === 0 ) { return ; } this . start ( this . collision ) ; } private start ( direction ) { let startTimestamp ; const scale = this . workflow . scale ; const matrix = this . workflow . workflow . transform . baseVal . getItem ( 0 ) . matrix ; const sixtyFPS = 16.6666 ; const onFrame = ( timestamp ) => { const frameDeltaTime = timestamp - ( startTimestamp || timestamp ) ; startTimestamp = timestamp ; if ( frameDeltaTime !== 0 && ! this . panAnimationFrame ) { startTimestamp = undefined ; return ; } const moveX = Math . sign ( direction . x ) * this . movementSpeed * frameDeltaTime / sixtyFPS ; const moveY = Math . sign ( direction . y ) * this . movementSpeed * frameDeltaTime / sixtyFPS ; matrix . e -= moveX ; matrix . f -= moveY ; const frameDiffX = moveX / scale ; const frameDiffY = moveY / scale ; this . panningCallback ( frameDiffX , frameDiffY ) ; this . panAnimationFrame = window . requestAnimationFrame ( onFrame ) ; } ; this . panAnimationFrame = window . requestAnimationFrame ( onFrame ) ; } stop ( ) { window . cancelAnimationFrame ( this . panAnimationFrame ) ; this . panAnimationFrame = undefined ; } }