import { SheetImage } from "./SheetImage" ; import type { Studio } from ".." ; import type { IPoint , Vector } from "bp/math" ; import type { Design } from "bp/design" ; /**
 *  Workspace 物件負責管理介於  Viewport 和  Sheet 之間的配置計算；
 * 我們把這個部份稱為工作區域，是一個可以被捲動的空間。
  export abstract class Workspace extends SheetImage { private _spaceHolder : HTMLDivElement ; public $onSheetChange ? : ( x : number , y : number ) => void ; constructor ( studio ) { super ( studio ) ; this . _el . appendChild ( this . _spaceHolder = document . createElement ( "div" ) ) ; this . _spaceHolder . style . zIndex = "-10" ; } public $zoom ( zoom , center ) { let sheet = this . _design ! . sheet ; let offset = this . _offset , scale = this . $scale ; let cx = ( center . x - offset . x ) / scale , cy = ( offset . y - center . y ) / scale ; sheet . _zoom = zoom ; offset = this . _offset ; scale = this . $scale ; this . _scrollTo ( sheet . $scroll . x + cx * scale + offset . x - center . x , sheet . $scroll . y + offset . y - cy * scale - center . y ) ; } public $scrollBy ( design , diff ) { let { x , y } = design . sheet . $scroll ; if ( this . _isXScrollable ) x -= diff . x ; if ( this . _isYScrollable ) y -= diff . y ; this . _scrollTo ( x , y ) ; } /** 設置捲軸的顯示與否、並且傳回當前是否可捲動 */ @ shrewd public $isScrollable ( ) { this . _el . classList . toggle ( "scroll-x" , this . _isXScrollable ) ; this . _el . classList . toggle ( "scroll-y" , this . _isYScrollable ) ; setTimeout ( ( ) => this . _setSize ( ) , 0 ) ; return this . _isXScrollable || this . _isYScrollable ; } /** 傳回全部（包括超出視界範圍的）要輸出的範圍 */ protected _getBound ( ) { let sw = this . _scrollWidth ; let sh = this . _scrollHeight ; let x = ( sw - this . _imgWidth ) / 2 - this . _scroll . x ; let y = ( sh - this . _imgHeight ) / 2 - this . _scroll . y ; return new paper . Rectangle ( x , y , this . _imgWidth , this . _imgHeight ) ; } /** 目前工作區域的捲動偏移 */ @ shrewd protected get _offset ( ) : IPoint { let scroll = { x : this . _scrollWidth , y : this . _scrollHeight } ; let padding = this . _getPadding ( scroll ) ; return { x : padding . x - this . _scroll . x , y : padding . y - this . _scroll . y } ; } protected _createImg ( ) { let img = new Image ( ) ; img . alt = "" ; this . _spaceHolder . appendChild ( img ) ; return img ; } @ shrewd private _onSheetChange ( ) { let sheet = this . _design ?. sheet ; if ( sheet ) { this . _spaceHolder . style . width = this . _scrollWidth + "px" ; this . _spaceHolder . style . height = this . _scrollHeight + "px" ; this . $onSheetChange ?. ( sheet . $scroll . x , sheet . $scroll . y ) ; } } private get _scroll ( ) : IPoint { return this . _design ?. sheet . $scroll ?? { x : 0 , y : 0 } ; } private _scrollTo ( x , y ) { let w = this . _scrollWidth - this . _viewWidth ; let h = this . _scrollHeight - this . _viewHeight ; if ( x < 0 ) x = 0 ; if ( y < 0 ) y = 0 ; if ( x > w ) x = w ; if ( y > h ) y = h ; this . _scroll . x = Math . round ( x ) ; this . _scroll . y = Math . round ( y ) ; } /** 全部的捲動寬度 */ @ shrewd private get _scrollWidth ( ) : number { return Math . max ( this . _imgWidth , this . _viewWidth ) ; } /** 全部的捲動高度 */ @ shrewd private get _scrollHeight ( ) : number { return Math . max ( this . _imgHeight , this . _viewHeight ) ; } @ shrewd private get _isXScrollable ( ) : boolean { return this . _imgWidth > this . _viewWidth + 1 ; } @ shrewd private get _isYScrollable ( ) : boolean { return this . _imgHeight > this . _viewHeight + 1 ; } }