import { Utils } from '@components/canvas/Utils' ; import { MiBrushRepaintConfig , Tools } from '@components/canvas/Tools' ; import { Stage } from '@components/canvas/Stage' ; import { MiPointConfig } from '@components/canvas/Point' ; import { MiRectConfig } from '@components/canvas/shapes/Rect' ; import { MiTextConfig } from '@components/canvas/tools/Text' ; export abstract class MiLayer { data : MiLayerData [ ] = [ ] ; abstract draw ( ) ; abstract clear ( ... args ) ; } /** 图层数据 */ export interface MiLayerData { tool : string ; move : MiPointConfig ; rotate : number ; scale : number ; origin : MiPointConfig ; visible : boolean ; rect ? : MiRectConfig ; text ? : MiTextConfig ; draw : ( config ? : MiBrushRepaintConfig ) => void ; } export class Layer extends MiLayer { id : string ; idx : number ; index : number | null = null ; hidden : boolean ; thumb = '' ; selected = - 1 ; selection = false ; eraser : { index : number ; selection : boolean ; } = { index : - 1 , selection : false } ; param idx constructor ( idx ? ) { super ( ) ; this . id = Utils . uid ( ) ; const stage = Tools . getStage ( ) , layers = stage . layers , keys = Object . keys ( layers ) ; const last = layers [ keys [ keys . length - 1 ] ] , index = last ? last . idx + 1 : 1 ; this . idx = idx ?? index ; this . hidden = false ; } param ctx param data draw ( ctx ? , data ? ) { if ( data && data . length > 0 ) { for ( let i = 0 , len = data . length ; i < len ; i ++ ) { const cur = data [ i ] ; cur . draw ( { rect : cur . rect , scale : cur . scale ?? 1 , rotate : cur . rotate ?? 0 , move : cur . move , origin : cur . origin , ctx } ) ; } } else { if ( ! this . hidden ) { let selection = { } ; for ( let i = 0 , len = this . data . length ; i < len ; i ++ ) { const cur = this . data [ i ] ; if ( cur . visible ) { const config = { rect : cur . rect , scale : cur . scale ?? 1 , rotate : cur . rotate ?? 0 , move : cur . move , origin : cur . origin , ctx } ; if ( this . index !== null && this . index === i ) { this . selected = i ; if ( cur . tool !== 'text' ) cur . draw ( config ) ; selection = { ... config , selection : true } ; this . selection = false ; } else cur . draw ( config ) ; } } /** 选中框 - 遍历完成后绘制 */ if ( this . selected !== - 1 ) { const data = this . data [ this . selected ] ; data . draw ( selection ) ; this . selected = - 1 ; } /** 橡皮擦选中 */ if ( this . eraser . selection ) { const active = this . data [ this . eraser . index ] as any , tool = Tools . getInstances ( ) [ active . tool ] ; if ( tool ) tool . drawEraserRect ( active . rect , active . move , active . scale , active . origin ) ; } } } } param index clear ( index ? ) { if ( index !== undefined ) { /** 清除图层内的单条数据 */ if ( this . data && this . data [ index ] ) { this . data [ index ] . visible = false ; Tools . setTraces ( { operation : 'eraser' , index } ) ; } } else { /** 清除整个图层数据 */ const indexes = [ ] ; for ( let i = 0 , len = this . data . length ; i < len ; i ++ ) { if ( this . data [ i ] . visible ) { this . data [ i ] . visible = false ; indexes . push ( i ) ; } } if ( indexes . length > 0 ) { Tools . setTraces ( { operation : 'clean' , indexes } ) ; } } /** 重绘 */ this . eraser . index = - 1 ; this . eraser . selection = false ; Tools . getStage ( ) . draw ( true ) ; } param data param width param height thumbnail ( data ? , width ? , height ? ) { const elem = document . getElementById ( this . id ) ; if ( elem ) { const stage = Tools . getStage ( ) , canvas = Utils . createCanvasElement ( ) ; width = width ?? stage . canvas . width ; height = height ?? stage . canvas . height ; canvas . width = width ; canvas . height = height ; const ctx = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; this . draw ( ctx , data ) ; const image = canvas . toDataURL ( ) ; elem . style . backgroundSize = 'cover' ; elem . style . backgroundPosition = 'no-repeat' ; elem . style . backgroundImage = `url(${ image })` ; this . thumb = image ; canvas . remove ( ) ; } } param stage getLayers ( stage ? ) { stage = stage ?? Tools . getStage ( ) ; const ids = Object . keys ( stage . layers ) , data = [ ] ; for ( let i = 0 , len = ids . length ; i < len ; i ++ ) { const layer = stage . layers [ ids [ i ] ] ; data . push ( { id : layer . id , idx : layer . idx , index : layer . index , hidden : layer . hidden , thumb : layer . thumb } ) ; } return data ; } }