param { number } deg return { number } export const getAngle = ( deg ) : number => { return Math . PI / 180 * deg ; } ; param { number } deg param { number } r return { Array < number > } export const getArcPointerByDeg = ( deg , r ) : [ number , number ] => { return [ + ( Math . cos ( deg ) * r ) . toFixed ( 8 ) , + ( Math . sin ( deg ) * r ) . toFixed ( 8 ) ] ; } ; param { number } x param { number } y return { Array < number > } export const getTangentByPointer = ( x , y ) : Array < number > => { let k = - x / y ; let b = - k * x + y ; return [ k , b ] ; } ; export const drawRadian = ( flag , ctx , r , start , end , direction = true ) => { if ( Math . abs ( end - start ) . toFixed ( 8 ) >= getAngle ( 180 ) . toFixed ( 8 ) ) { let middle = ( end + start ) / 2 ; if ( direction ) { drawRadian ( flag , ctx , r , start , middle , direction ) ; drawRadian ( flag , ctx , r , middle , end , direction ) ; } else { drawRadian ( flag , ctx , r , middle , end , direction ) ; drawRadian ( flag , ctx , r , start , middle , direction ) ; } return false ; } if ( ! direction ) [ start , end ] = [ end , start ] ; const [ x1 , y1 ] = getArcPointerByDeg ( start , r ) ; const [ x2 , y2 ] = getArcPointerByDeg ( end , r ) ; const [ k1 , b1 ] = getTangentByPointer ( x1 , y1 ) ; const [ k2 , b2 ] = getTangentByPointer ( x2 , y2 ) ; let x0 = ( b2 - b1 ) / ( k1 - k2 ) ; let y0 = ( k2 * b1 - k1 * b2 ) / ( k2 - k1 ) ; if ( isNaN ( x0 ) ) { Math . abs ( x1 ) === + r . toFixed ( 8 ) && ( x0 = x1 ) ; Math . abs ( x2 ) === + r . toFixed ( 8 ) && ( x0 = x2 ) ; } if ( k1 === Infinity || k1 === - Infinity ) { y0 = k2 * x0 + b2 ; } else if ( k2 === Infinity || k2 === - Infinity ) { y0 = k1 * x0 + b1 ; } ctx . lineTo ( x1 , y1 ) ; if ( flag . indexOf ( 'MP' ) > 0 ) { ctx . quadraticCurveTo ( x0 , y0 , x2 , y2 ) ; } else { ctx . arcTo ( x0 , y0 , x2 , y2 , r ) ; } } ; export const drawSector = ( flag , ctx , minRadius , maxRadius , start , end , gutter , background ) => { if ( ! gutter ) { ctx . beginPath ( ) ; ctx . fillStyle = background ; ctx . moveTo ( 0 , 0 ) ; ctx . arc ( 0 , 0 , maxRadius , start , end , false ) ; ctx . closePath ( ) ; ctx . fill ( ) ; } else { drawSectorByArcTo ( flag , ctx , minRadius , maxRadius , start , end , gutter , background ) ; } } ; export const drawSectorByArcTo = ( flag , ctx , minRadius , maxRadius , start , end , gutter , background ) => { if ( ! minRadius ) minRadius = gutter ; let maxGutter = getAngle ( 90 / Math . PI / maxRadius * gutter ) ; let minGutter = getAngle ( 90 / Math . PI / minRadius * gutter ) ; let maxStart = start + maxGutter ; let maxEnd = end - maxGutter ; let minStart = start + minGutter ; let minEnd = end - minGutter ; ctx . beginPath ( ) ; ctx . fillStyle = background ; ctx . moveTo ( ... getArcPointerByDeg ( maxStart , maxRadius ) ) ; drawRadian ( flag , ctx , maxRadius , maxStart , maxEnd , true ) ; if ( minEnd > minStart ) { drawRadian ( flag , ctx , minRadius , minStart , minEnd , false ) ; } else { ctx . lineTo ( ... getArcPointerByDeg ( ( start + end ) / 2 , gutter / 2 / Math . abs ( Math . sin ( ( start - end ) / 2 ) ) ) ) ; } ctx . closePath ( ) ; ctx . fill ( ) ; } ; export const drawRoundRect = ( ctx , x , y , w , h , r , color ) => { let min = Math . min ( w , h ) ; if ( r > min / 2 ) r = min / 2 ; ctx . beginPath ( ) ; ctx . fillStyle = color ; ctx . moveTo ( x + r , y ) ; ctx . lineTo ( x + r , y ) ; ctx . lineTo ( x + w - r , y ) ; ctx . quadraticCurveTo ( x + w , y , x + w , y + r ) ; ctx . lineTo ( x + w , y + h - r ) ; ctx . quadraticCurveTo ( x + w , y + h , x + w - r , y + h ) ; ctx . lineTo ( x + r , y + h ) ; ctx . quadraticCurveTo ( x , y + h , x , y + h - r ) ; ctx . lineTo ( x , y + r ) ; ctx . quadraticCurveTo ( x , y , x + r , y ) ; ctx . closePath ( ) ; ctx . fill ( ) ; } ; /**
 * 创建线性渐变色
 */ export const getLinearGradient = ( ctx , x , y , w , h , background ) => { const context = ( /linear-gradient\((.+)\)/ . exec ( background ) as Array < any > ) [ 1 ] . split ( ',' ) . map ( ( text ) => text . trim ( ) ) ; let deg = context . shift ( ) , direction = [ 0 , 0 , 0 , 0 ] ; if ( deg . includes ( 'deg' ) ) { deg = deg . slice ( 0 , - 3 ) % 360 ; const getLenOfTanDeg = ( deg ) => Math . tan ( deg / 180 * Math . PI ) ; if ( deg >= 0 && deg < 45 ) direction = [ x , y + h , x + w , y + h - w * getLenOfTanDeg ( deg - 0 ) ] ; else if ( deg >= 45 && deg < 90 ) direction = [ x , y + h , ( x + w ) - h * getLenOfTanDeg ( deg - 45 ) , y ] ; else if ( deg >= 90 && deg < 135 ) direction = [ x + w , y + h , ( x + w ) - h * getLenOfTanDeg ( deg - 90 ) , y ] ; else if ( deg >= 135 && deg < 180 ) direction = [ x + w , y + h , x , y + w * getLenOfTanDeg ( deg - 135 ) ] ; else if ( deg >= 180 && deg < 225 ) direction = [ x + w , y , x , y + w * getLenOfTanDeg ( deg - 180 ) ] ; else if ( deg >= 225 && deg < 270 ) direction = [ x + w , y , x + h * getLenOfTanDeg ( deg - 225 ) , y + h ] ; else if ( deg >= 270 && deg < 315 ) direction = [ x , y , x + h * getLenOfTanDeg ( deg - 270 ) , y + h ] ; else if ( deg >= 315 && deg < 360 ) direction = [ x , y , x + w , y + h - w * getLenOfTanDeg ( deg - 315 ) ] ; } else if ( deg . includes ( 'top' ) ) direction = [ x , y + h , x , y ] ; else if ( deg . includes ( 'bottom' ) ) direction = [ x , y , x , y + h ] ; else if ( deg . includes ( 'left' ) ) direction = [ x + w , y , x , y ] ; else if ( deg . includes ( 'right' ) ) direction = [ x , y , x + w , y ] ; const gradient = ctx . createLinearGradient ( ... ( direction . map ( n => n >> 0 ) as [ number , number , number , number ] ) ) ; return context . reduce ( ( gradient , item , index ) => { const info = item . split ( ' ' ) ; if ( info . length === 1 ) gradient . addColorStop ( index , info [ 0 ] ) ; else if ( info . length === 2 ) gradient . addColorStop ( ... info ) ; return gradient ; } , gradient ) ; } ;