import { MiTools , Tools } from '@components/canvas/Tools' ; import { Canvas } from '@components/canvas/Canvas' ; import { Point } from '@components/canvas/Point' ; import { MiRectConfig , MiRectPointConfig } from '@components/canvas/shapes/Rect' ; export class Screenshot extends Tools implements MiTools { name = 'screenshot' ; type = 'area' ; start = new Point ( 0 , 0 ) ; rect : MiRectConfig = { x : 0 , y : 0 , width : 0 , height : 0 } ; protected static instance : Screenshot ; param canvas constructor ( canvas ) { super ( canvas ) ; Screenshot . instance = this ; Tools . instances [ this . name ] = this ; } return draw ( ) { /** 过小的区域不下载 */ if ( this . type === 'area' && this . rect . width < 10 && this . rect . height < 10 ) return ; /** 开始截图 */ const time = Date . parse ( new Date ( ) . toString ( ) ) , file = `mi-meeting-screenshot-${ time }.png` , type = 'image/png' , clipCanvas = document . createElement ( 'canvas' ) , screenCanvas = document . createElement ( 'canvas' ) , clipCtx = clipCanvas . getContext ( '2d' ) as CanvasRenderingContext2D , screenCtx = screenCanvas . getContext ( '2d' ) as CanvasRenderingContext2D ; let dataURL = '' , width = this . canvas . width , height = this . canvas . height , canvas ! , ctx ! , image ! ; if ( this . type === 'area' ) { width = this . rect . width ; height = this . rect . height ; canvas = clipCanvas ; ctx = clipCtx ; image = this . ctx . getImageData ( this . rect . x , this . rect . y , this . rect . width , this . rect . height ) ; /** rect 复位 */ this . rect = { x : 0 , y : 0 , width : 0 , height : 0 } ; } else if ( this . type === 'screen' ) { canvas = screenCanvas ; ctx = screenCtx ; image = this . ctx . getImageData ( 0 , 0 , this . canvas . width , this . canvas . height ) ; } canvas . width = width ; canvas . height = height ; ctx . putImageData ( image , 0 , 0 , 0 , 0 , width , height ) ; if ( ! Tools . stage . transparent ) { /** 背景色 */ ctx . globalCompositeOperation = 'destination-over' ; ctx . fillStyle = Tools . stage . background ; ctx . fillRect ( 0 , 0 , width , height ) ; } dataURL = canvas . toDataURL ( type , 1 ) ; this . download ( file , dataURL ) ; } param points param ctx protected drawCropArea ( points , ctx ? ) { ctx = ctx ?? this . getBufferContext ( ) ; ctx . beginPath ( ) ; ctx . moveTo ( points . lt . x , points . lt . y ) ; ctx . lineTo ( points . rt . x , points . rt . y ) ; ctx . lineTo ( points . rb . x , points . rb . y ) ; ctx . lineTo ( points . lb . x , points . lb . y ) ; ctx . closePath ( ) ; ctx . stroke ( ) ; } return static screenshot ( ) { Screenshot . instance . draw ( ) ; } param file param dataURL protected download ( file , dataURL ) { const link = document . createElement ( 'a' ) , blob = this . image2Blob ( dataURL ) ; link . download = file ; link . style . display = 'none' ; link . href = URL . createObjectURL ( blob ) ; document . body . appendChild ( link ) ; link . click ( ) ; link . remove ( ) ; } param dataURL protected image2Blob ( dataURL ) { const parts = dataURL . split ( ';base64,' ) , type = parts [ 0 ] . split ( ':' ) [ 1 ] , raw = window . atob ( parts [ 1 ] ) , length = raw . length , uInt8Array = new Uint8Array ( length ) ; for ( let i = 0 ; i < length ; i ++ ) { uInt8Array [ i ] = raw . charCodeAt ( i ) ; } return new Blob ( [ uInt8Array ] , { type } ) ; } param event protected drawBegin ( event ) { const point = this . createPoint ( event . clientX , event . clientY ) ; if ( this . type === 'area' ) { /** 区域截图 */ this . buffer = this . createBuffer ( 2 , 'rgb(255, 109, 31)' ) ; const ctx = this . getBufferContext ( ) ; ctx . lineDashOffset = 3 ; ctx . setLineDash ( [ 5 ] ) ; this . start = point ; } } param event protected drawUpdate ( event ) { const point = this . createPoint ( event . clientX , event . clientY ) ; if ( this . type === 'area' ) { /** 区域截图 */ const points = this . getPointsBasedOn2Point ( this . start , point , this . rect ) ; this . drawCropArea ( points ) ; } } param event protected drawEnd ( event ) { if ( this . type === 'area' ) this . drawUpdate ( event ) ; this . resetBuffer ( ( ) => { this . draw ( ) ; } ) ; } }