@@ -20,6 +20,7 @@ export interface ActiveOutline {
2020 totalFrames : number ;
2121 resolve : ( ) => void ;
2222 text : string | null ;
23+ color : { r : number ; g : number ; b : number } ;
2324}
2425
2526export interface PaintedOutline {
@@ -114,6 +115,7 @@ export const mergeOutlines = (outlines: PendingOutline[]) => {
114115
115116export const recalcOutlines = throttle ( ( ) => {
116117 const { scheduledOutlines, activeOutlinesMap } = ReactScanInternals ;
118+
117119 for ( let i = scheduledOutlines . length - 1 ; i >= 0 ; i -- ) {
118120 const outline = scheduledOutlines [ i ] ;
119121 const rect = getRect ( outline . domNode ) ;
@@ -126,13 +128,14 @@ export const recalcOutlines = throttle(() => {
126128
127129 const activeOutlines = Array . from ( activeOutlinesMap . values ( ) ) ;
128130
129- for ( let i = 0 , len = activeOutlines . length ; i < len ; i ++ ) {
131+ for ( let i = activeOutlines . length - 1 ; i >= 0 ; i -- ) {
130132 const activeOutline = activeOutlines [ i ] ;
133+ if ( ! activeOutline ) continue ;
131134 const { outline } = activeOutline ;
132135 const rect = getRect ( outline . domNode ) ;
133136 if ( ! rect ) {
134- activeOutlines . splice ( i , 1 ) ;
135137 activeOutlinesMap . delete ( getOutlineKey ( outline ) ) ;
138+ activeOutline . resolve ( ) ;
136139 continue ;
137140 }
138141 outline . rect = rect ;
@@ -209,13 +212,10 @@ export const paintOutline = (
209212) => {
210213 return new Promise < void > ( ( resolve ) => {
211214 const unstable = isOutlineUnstable ( outline ) ;
212-
213215 const totalFrames = unstable ? 30 : 10 ;
214216 const frame = 0 ;
215217 const alpha = 0.8 ;
216218
217- const text : string | null = getLabelText ( outline . renders ) ;
218-
219219 const { options } = ReactScanInternals ;
220220 options . onPaintStart ?.( outline ) ;
221221 if ( options . log ) {
@@ -226,6 +226,21 @@ export const paintOutline = (
226226 const existingActiveOutline =
227227 ReactScanInternals . activeOutlinesMap . get ( outlineKey ) ;
228228
229+ const renderCount = existingActiveOutline
230+ ? existingActiveOutline . outline . renders . length + outline . renders . length
231+ : outline . renders . length ;
232+ const maxRenders = ReactScanInternals . options . maxRenders ;
233+ const t = Math . min ( renderCount / ( maxRenders ?? 20 ) , 1 ) ;
234+
235+ const startColor = { r : 115 , g : 97 , b : 230 } ;
236+ const endColor = { r : 185 , g : 49 , b : 115 } ;
237+
238+ const r = Math . round ( startColor . r + t * ( endColor . r - startColor . r ) ) ;
239+ const g = Math . round ( startColor . g + t * ( endColor . g - startColor . g ) ) ;
240+ const b = Math . round ( startColor . b + t * ( endColor . b - startColor . b ) ) ;
241+
242+ const color = { r, g, b } ;
243+
229244 if ( existingActiveOutline ) {
230245 existingActiveOutline . outline . renders . push ( ...outline . renders ) ;
231246 existingActiveOutline . frame = frame ;
@@ -234,6 +249,7 @@ export const paintOutline = (
234249 existingActiveOutline . text = getLabelText (
235250 existingActiveOutline . outline . renders ,
236251 ) ;
252+ existingActiveOutline . color = color ;
237253 existingActiveOutline . resolve = ( ) => {
238254 resolve ( ) ;
239255 options . onPaintFinish ?.( existingActiveOutline . outline ) ;
@@ -248,7 +264,8 @@ export const paintOutline = (
248264 resolve ( ) ;
249265 options . onPaintFinish ?.( outline ) ;
250266 } ,
251- text,
267+ text : getLabelText ( outline . renders ) ,
268+ color,
252269 } ) ;
253270 }
254271
@@ -261,65 +278,42 @@ export const paintOutline = (
261278export const fadeOutOutline = ( ctx : CanvasRenderingContext2D ) => {
262279 const { activeOutlinesMap } = ReactScanInternals ;
263280
281+ ctx . save ( ) ;
282+ ctx . resetTransform ( ) ;
264283 ctx . clearRect ( 0 , 0 , ctx . canvas . width , ctx . canvas . height ) ;
265-
266- const combinedPath = new Path2D ( ) ;
267-
268- let maxStrokeAlpha = 0 ;
269- let maxFillAlpha = 0 ;
270-
271- const pendingLabeledOutlines : PaintedOutline [ ] = [ ] ;
284+ ctx . restore ( ) ;
272285
273286 const activeOutlines = Array . from ( activeOutlinesMap . values ( ) ) ;
274287
275288 for ( let i = 0 , len = activeOutlines . length ; i < len ; i ++ ) {
276289 const activeOutline = activeOutlines [ i ] ;
277- const { outline, frame, totalFrames } = activeOutline ;
290+ const { outline, frame, totalFrames, color } = activeOutline ;
278291 const { rect } = outline ;
279292 const unstable = isOutlineUnstable ( outline ) ;
280293
281294 const alphaScalar = unstable ? 0.8 : 0.2 ;
282295
283296 activeOutline . alpha = alphaScalar * ( 1 - frame / totalFrames ) ;
284297
285- maxStrokeAlpha = Math . max ( maxStrokeAlpha , activeOutline . alpha ) ;
286- maxFillAlpha = Math . max ( maxFillAlpha , activeOutline . alpha * 0.1 ) ;
287-
288- combinedPath . rect ( rect . x , rect . y , rect . width , rect . height ) ;
289-
290- if ( unstable ) {
291- pendingLabeledOutlines . push ( {
292- alpha : activeOutline . alpha ,
293- outline,
294- text : activeOutline . text ,
295- } ) ;
296- }
297-
298- activeOutline . frame ++ ;
299-
300- if ( activeOutline . frame > activeOutline . totalFrames ) {
301- activeOutlinesMap . delete ( getOutlineKey ( outline ) ) ;
302- activeOutline . resolve ( ) ;
303- }
304- }
305-
306- ctx . save ( ) ;
307-
308- ctx . strokeStyle = `rgba(${ colorRef . current } , ${ maxStrokeAlpha } )` ;
309- ctx . lineWidth = 1 ;
310- ctx . fillStyle = `rgba(${ colorRef . current } , ${ maxFillAlpha } )` ;
298+ const strokeAlpha = activeOutline . alpha ;
299+ const fillAlpha = activeOutline . alpha * 0.1 ;
311300
312- ctx . stroke ( combinedPath ) ;
313- ctx . fill ( combinedPath ) ;
314-
315- ctx . restore ( ) ;
316-
317- for ( let i = 0 , len = pendingLabeledOutlines . length ; i < len ; i ++ ) {
318- const { alpha, outline, text } = pendingLabeledOutlines [ i ] ;
319- const { rect } = outline ;
320301 ctx . save ( ) ;
302+ ctx . strokeStyle = `rgba(${ color . r } ,${ color . g } ,${ color . b } ,${ strokeAlpha } )` ;
303+ ctx . lineWidth = 1 ;
304+ ctx . fillStyle = `rgba(${ color . r } ,${ color . g } ,${ color . b } ,${ fillAlpha } )` ;
305+
306+ ctx . beginPath ( ) ;
307+ ctx . rect ( rect . x , rect . y , rect . width , rect . height ) ;
308+ ctx . stroke ( ) ;
309+ ctx . fill ( ) ;
310+ ctx . closePath ( ) ;
311+ ctx . restore ( ) ;
312+
313+ if ( unstable && activeOutline . text ) {
314+ const { text } = activeOutline ;
315+ ctx . save ( ) ;
321316
322- if ( text ) {
323317 ctx . font = `10px ${ MONO_FONT } ` ;
324318 const textMetrics = ctx . measureText ( text ) ;
325319 const textWidth = textMetrics . width ;
@@ -328,19 +322,26 @@ export const fadeOutOutline = (ctx: CanvasRenderingContext2D) => {
328322 const labelX : number = rect . x ;
329323 const labelY : number = rect . y - textHeight - 4 ;
330324
331- ctx . fillStyle = `rgba(${ colorRef . current } ,${ alpha } )` ;
325+ ctx . fillStyle = `rgba(${ color . r } ,${ color . g } , ${ color . b } , ${ strokeAlpha } )` ;
332326 ctx . fillRect ( labelX , labelY , textWidth + 4 , textHeight + 4 ) ;
333327
334- ctx . fillStyle = `rgba(255,255,255,${ alpha } )` ;
328+ ctx . fillStyle = `rgba(255,255,255,${ strokeAlpha } )` ;
335329 ctx . fillText ( text , labelX + 2 , labelY + textHeight ) ;
330+
331+ ctx . restore ( ) ;
336332 }
337333
338- ctx . restore ( ) ;
334+ activeOutline . frame ++ ;
335+
336+ if ( activeOutline . frame > activeOutline . totalFrames ) {
337+ activeOutlinesMap . delete ( getOutlineKey ( outline ) ) ;
338+ activeOutline . resolve ( ) ;
339+ }
339340 }
340341
341- if ( activeOutlines . length ) {
342- animationFrameId = requestAnimationFrame ( ( ) => fadeOutOutline ( ctx ) ) ;
343- } else {
342+ if ( activeOutlinesMap . size === 0 ) {
344343 animationFrameId = null ;
344+ } else {
345+ animationFrameId = requestAnimationFrame ( ( ) => fadeOutOutline ( ctx ) ) ;
345346 }
346347} ;
0 commit comments