import * as React from 'react' ; import { attributeRank , attributesRange , cache } from '@/common/attribute' ; import type { ICanvasProps , ICanvasRef } from './ICanvas' ; export * from './ICanvas' ; const imgCache = new Map ( ) ; const [ w , h ] = [ 34 , 34 ] ; export async function loadAsset ( name ) { if ( imgCache . has ( name ) ) return imgCache . get ( name ) ! ; const url = ( await cache ?. [ name ] ) . default ; const p = new Promise ( ( resolve ) => { const image = new Image ( ) ; image . addEventListener ( 'load' , ( ) => { imgCache . set ( name , p ) ; resolve ( image ) ; } ) ; image . src = url ; image . crossOrigin = 'anonymous' ; } ) ; return p ; } export const Canvas = React . forwardRef < ICanvasRef , ICanvasProps > ( ( { attribute , ratio = 1 , style , className } , ref ) => { const canvasRef = React . useRef < HTMLCanvasElement > ( null ) ; const [ width , height ] = React . useMemo ( ( ) => [ w * ratio , h * ratio ] , [ ratio ] ) ; React . useEffect ( ( ) => { const render = async ( ) => { if ( canvasRef . current ) { const ctx = canvasRef . current . getContext ( '2d' ) ; ctx ?. clearRect ( 0 , 0 , width , height ) ; ctx ?. setTransform ( ratio , 0 , 0 , ratio , 0 , 0 ) ; const imgs = await Promise . all ( attributeRank . map ( async ( attr ) => { const attrValue = attribute ?. [ attr ] ; if ( ! attrValue || ! attributesRange [ attr ] . includes ( attrValue ) ) { console . warn ( 'attribute error:' , attribute ) ; return ; } return loadAsset ( `${ attr }_${ attrValue }` ) ; } ) ) ; imgs . forEach ( ( i ) => { if ( i ) ctx ?. drawImage ( i , 0 , 0 ) ; } ) ; } } ; render ( ) ; } , [ attribute , width , height , ratio ] ) ; React . useImperativeHandle ( ref , ( ) => ( { toDataURL : ( type = 'image/png' , quality = 1.0 ) => canvasRef . current ?. toDataURL ( type , quality ) , } ) , [ ] ) ; return ( < canvas ref = { canvasRef } className = { className } width = { width } height = { height } style = { { ... style , width , height , background : 'white' } } />); } ) ; Canvas . displayName = 'Canvas' ;