import { listenWindow } from './utils' ; export class Zoom { el : HTMLElement ; intensity : number ; onzoom : Function ; previous : { cx : number ; cy : number ; distance : number ; } | null = null ; pointers : PointerEvent [ ] = [ ] ; destroy : ( ) => void ; constructor ( container , el , intensity , onzoom ) { this . el = el ; this . intensity = intensity ; this . onzoom = onzoom ; container . addEventListener ( 'wheel' , this . wheel . bind ( this ) ) ; container . addEventListener ( 'pointerdown' , this . down . bind ( this ) ) ; container . addEventListener ( 'dblclick' , this . dblclick . bind ( this ) ) ; const destroyMove = listenWindow ( 'pointermove' , this . move . bind ( this ) ) ; const destroyUp = listenWindow ( 'pointerup' , this . end . bind ( this ) ) ; const destroyCancel = listenWindow ( 'pointercancel' , this . end . bind ( this ) ) ; this . destroy = ( ) => { destroyMove ( ) ; destroyUp ( ) ; destroyCancel ( ) ; } ; } get translating ( ) { return this . pointers . length >= 2 ; } wheel ( e ) { e . preventDefault ( ) ; const rect = this . el . getBoundingClientRect ( ) ; const isNegative = e . deltaY < 0 ; const delta = isNegative ? this . intensity : - this . intensity ; const ox = ( rect . left - e . clientX ) * delta ; const oy = ( rect . top - e . clientY ) * delta ; this . onzoom ( delta , ox , oy , 'wheel' ) ; } touches ( ) { let e = { touches : this . pointers } ; let [ x1 , y1 ] = [ e . touches [ 0 ] . clientX , e . touches [ 0 ] . clientY ] ; let [ x2 , y2 ] = [ e . touches [ 1 ] . clientX , e . touches [ 1 ] . clientY ] ; let distance = Math . sqrt ( Math . pow ( x1 - x2 , 2 ) + Math . pow ( y1 - y2 , 2 ) ) ; return { cx : ( x1 + x2 ) / 2 , cy : ( y1 + y2 ) / 2 , distance } ; } down ( e ) { this . pointers . push ( e ) ; } move ( e ) { this . pointers = this . pointers . map ( p => p . pointerId === e . pointerId ? e : p ) ; if ( ! this . translating ) return ; let rect = this . el . getBoundingClientRect ( ) ; let { cx , cy , distance } = this . touches ( ) ; if ( this . previous !== null ) { let delta = distance / this . previous . distance - 1 ; const ox = ( rect . left - cx ) * delta ; const oy = ( rect . top - cy ) * delta ; this . onzoom ( delta , ox - ( this . previous . cx - cx ) , oy - ( this . previous . cy - cy ) , 'touch' ) ; } this . previous = { cx , cy , distance } ; } end ( e ) { this . previous = null ; this . pointers = this . pointers . filter ( p => p . pointerId !== e . pointerId ) ; } dblclick ( e ) { e . preventDefault ( ) ; const rect = this . el . getBoundingClientRect ( ) ; const delta = 4 * this . intensity ; const ox = ( rect . left - e . clientX ) * delta ; const oy = ( rect . top - e . clientY ) * delta ; this . onzoom ( delta , ox , oy , 'dblclick' ) ; } }