import React , { useEffect , useState } from 'react' ; import { ComponentProps , Streamlit , withStreamlitConnection } from "./streamlit" ; import { fabric } from 'fabric' ; interface PythonArgs { canvasWidth : number ; canvasHeight : number ; rectTop : number ; rectLeft : number ; rectWidth : number ; rectHeight : number ; realtimeUpdate : boolean ; boxColor : string ; imageData : Uint8ClampedArray ; lockAspect : boolean ; } const StreamlitCropper = ( props ) => { const [ canvas , setCanvas ] = useState ( new fabric . Canvas ( "" ) ) ; const { canvasWidth , canvasHeight , imageData } = props . args ; var invisCanvas = document . createElement ( "canvas" ) ; var ctx = invisCanvas . getContext ( '2d' ) ; invisCanvas . width = canvasWidth ; invisCanvas . height = canvasHeight ; if ( ctx ) { var idata = ctx . createImageData ( canvasWidth , canvasHeight ) ; idata . data . set ( imageData ) ; ctx . putImageData ( idata , 0 , 0 ) ; var dataUri = invisCanvas . toDataURL ( ) ; } else { var dataUri = "" ; } /**
     * Initialize canvas on mount and add a rectangle
     */ useEffect ( ( ) => { const { rectTop , rectLeft , rectWidth , rectHeight , boxColor , lockAspect } = props . args ; const canvas = new fabric . Canvas ( 'c' , { enableRetinaScaling : false , backgroundImage : dataUri , uniScaleTransform : lockAspect } ) ; var rect = new fabric . Rect ( { left : rectLeft , top : rectTop , fill : '' , width : rectWidth , height : rectHeight , objectCaching : true , stroke : boxColor , strokeWidth : 3 , hasRotatingPoint : false } ) ; canvas . add ( rect ) ; setCanvas ( canvas ) ; Streamlit . setFrameHeight ( ) ; } , [ canvasHeight , canvasWidth ] ) ; /**
     * On update (either realtime or doubleclick), send the coordinates of the rectangle
     * back to streamlit.
     */ useEffect ( ( ) => { const { realtimeUpdate } = props . args ; if ( ! canvas ) { return ; } const handleEvent = ( ) => { canvas . renderAll ( ) ; const coords = canvas . getObjects ( ) [ 0 ] . getBoundingRect ( ) ; Streamlit . setComponentValue ( { coords : coords } ) ; } ; if ( realtimeUpdate ) { canvas . on ( "object:modified" , handleEvent ) ; return ( ) => { canvas . off ( "object:modified" ) ; } ; } else { canvas . on ( "mouse:dblclick" , handleEvent ) ; return ( ) => { canvas . off ( "mouse:dblclick" ) ; } ; } } ) ; return ( < > < canvas id = "c" width = { canvasWidth } height = { canvasHeight } / > < />); } ; export default withStreamlitConnection ( StreamlitCropper ) ;