@@ -5,7 +5,7 @@ import { ReactScanInternals } from '../index';
55import { getLabelText } from '../utils' ;
66import { isOutlineUnstable , throttle } from './utils' ;
77import { log } from './log' ;
8- import { recalcOutlineColor } from './perf-observer' ;
8+ // import { recalcOutlineColor } from './perf-observer';
99
1010export interface PendingOutline {
1111 rect : DOMRect ;
@@ -31,13 +31,26 @@ export interface PaintedOutline {
3131
3232export const MONO_FONT =
3333 'Menlo,Consolas,Monaco,Liberation Mono,Lucida Console,monospace' ;
34+ const DEFAULT_THROTTLE_TIME = 8 ; // 2 frames
3435export const colorRef = { current : '115,97,230' } ;
3536
3637export const getOutlineKey = ( outline : PendingOutline ) : string => {
3738 return `${ outline . rect . top } -${ outline . rect . left } -${ outline . rect . width } -${ outline . rect . height } ` ;
3839} ;
3940
41+ const getRectCache = new WeakMap <
42+ HTMLElement ,
43+ { rect : DOMRect ; timestamp : number }
44+ > ( ) ;
45+
4046export const getRect = ( domNode : HTMLElement ) : DOMRect | null => {
47+ const cachedRect = getRectCache . get ( domNode ) ;
48+ if (
49+ cachedRect &&
50+ performance . now ( ) - cachedRect . timestamp < DEFAULT_THROTTLE_TIME
51+ ) {
52+ return cachedRect . rect ;
53+ }
4154 const style = window . getComputedStyle ( domNode ) ;
4255 if (
4356 style . display === 'none' ||
@@ -47,18 +60,19 @@ export const getRect = (domNode: HTMLElement): DOMRect | null => {
4760 return null ;
4861 }
4962
50- // if (!document.documentElement.contains(domNode)) return null;
51-
5263 const rect = domNode . getBoundingClientRect ( ) ;
64+
5365 const isVisible =
5466 rect . top >= 0 ||
5567 rect . left >= 0 ||
5668 rect . bottom <= window . innerHeight ||
5769 rect . right <= window . innerWidth ;
5870
59- if ( ! isVisible ) return null ;
71+ if ( ! isVisible || ! rect . width || ! rect . height ) {
72+ return null ;
73+ }
6074
61- if ( ! rect . height || ! rect . width ) return null ;
75+ getRectCache . set ( domNode , { rect, timestamp : performance . now ( ) } ) ;
6276
6377 return rect ;
6478} ;
@@ -114,7 +128,7 @@ export const mergeOutlines = (outlines: PendingOutline[]) => {
114128} ;
115129
116130export const recalcOutlines = throttle ( ( ) => {
117- const { scheduledOutlines, activeOutlinesMap } = ReactScanInternals ;
131+ const { scheduledOutlines, activeOutlines } = ReactScanInternals ;
118132
119133 for ( let i = scheduledOutlines . length - 1 ; i >= 0 ; i -- ) {
120134 const outline = scheduledOutlines [ i ] ;
@@ -126,21 +140,18 @@ export const recalcOutlines = throttle(() => {
126140 outline . rect = rect ;
127141 }
128142
129- const activeOutlines = Array . from ( activeOutlinesMap . values ( ) ) ;
130-
131143 for ( let i = activeOutlines . length - 1 ; i >= 0 ; i -- ) {
132144 const activeOutline = activeOutlines [ i ] ;
133145 if ( ! activeOutline ) continue ;
134146 const { outline } = activeOutline ;
135147 const rect = getRect ( outline . domNode ) ;
136148 if ( ! rect ) {
137- activeOutlinesMap . delete ( getOutlineKey ( outline ) ) ;
138- activeOutline . resolve ( ) ;
149+ activeOutlines . splice ( i , 1 ) ;
139150 continue ;
140151 }
141152 outline . rect = rect ;
142153 }
143- } , 16 ) ; // 1 frame
154+ } , DEFAULT_THROTTLE_TIME ) ;
144155
145156export const flushOutlines = (
146157 ctx : CanvasRenderingContext2D ,
@@ -157,7 +168,7 @@ export const flushOutlines = (
157168
158169 requestAnimationFrame ( ( ) => {
159170 if ( perfObserver ) {
160- recalcOutlineColor ( perfObserver . takeRecords ( ) ) ;
171+ // recalcOutlineColor(perfObserver.takeRecords());
161172 }
162173 recalcOutlines ( ) ;
163174 void ( async ( ) => {
@@ -212,8 +223,7 @@ export const paintOutline = (
212223) => {
213224 return new Promise < void > ( ( resolve ) => {
214225 const unstable = isOutlineUnstable ( outline ) ;
215- const totalFrames = unstable ? 30 : 10 ;
216- const frame = 0 ;
226+ const totalFrames = unstable ? 60 : 5 ;
217227 const alpha = 0.8 ;
218228
219229 const { options } = ReactScanInternals ;
@@ -222,13 +232,12 @@ export const paintOutline = (
222232 log ( outline . renders ) ;
223233 }
224234
225- const outlineKey = getOutlineKey ( outline ) ;
226- const existingActiveOutline =
227- ReactScanInternals . activeOutlinesMap . get ( outlineKey ) ;
235+ const key = getOutlineKey ( outline ) ;
236+ const existingActiveOutline = ReactScanInternals . activeOutlines . find (
237+ ( activeOutline ) => getOutlineKey ( activeOutline . outline ) === key ,
238+ ) ;
228239
229- const renderCount = existingActiveOutline
230- ? existingActiveOutline . outline . renders . length + outline . renders . length
231- : outline . renders . length ;
240+ const renderCount = outline . renders . length ;
232241 const maxRenders = ReactScanInternals . options . maxRenders ;
233242 const t = Math . min ( renderCount / ( maxRenders ?? 20 ) , 1 ) ;
234243
@@ -243,19 +252,17 @@ export const paintOutline = (
243252
244253 if ( existingActiveOutline ) {
245254 existingActiveOutline . outline . renders . push ( ...outline . renders ) ;
246- existingActiveOutline . frame = frame ;
255+ existingActiveOutline . outline . rect = outline . rect ;
256+ existingActiveOutline . frame = 0 ;
247257 existingActiveOutline . totalFrames = totalFrames ;
248258 existingActiveOutline . alpha = alpha ;
249259 existingActiveOutline . text = getLabelText (
250260 existingActiveOutline . outline . renders ,
251261 ) ;
252262 existingActiveOutline . color = color ;
253- existingActiveOutline . resolve = ( ) => {
254- resolve ( ) ;
255- options . onPaintFinish ?.( existingActiveOutline . outline ) ;
256- } ;
257263 } else {
258- ReactScanInternals . activeOutlinesMap . set ( outlineKey , {
264+ const frame = 0 ;
265+ ReactScanInternals . activeOutlines . push ( {
259266 outline,
260267 alpha,
261268 frame,
@@ -270,50 +277,75 @@ export const paintOutline = (
270277 }
271278
272279 if ( ! animationFrameId ) {
273- fadeOutOutline ( ctx ) ;
280+ animationFrameId = requestAnimationFrame ( ( ) => fadeOutOutline ( ctx ) ) ;
274281 }
275282 } ) ;
276283} ;
277284
278285export const fadeOutOutline = ( ctx : CanvasRenderingContext2D ) => {
279- const { activeOutlinesMap } = ReactScanInternals ;
286+ const { activeOutlines } = ReactScanInternals ;
280287
281- ctx . save ( ) ;
282- ctx . resetTransform ( ) ;
283288 ctx . clearRect ( 0 , 0 , ctx . canvas . width , ctx . canvas . height ) ;
284- ctx . restore ( ) ;
285289
286- const activeOutlines = Array . from ( activeOutlinesMap . values ( ) ) ;
290+ const combinedPath = new Path2D ( ) ;
287291
288- for ( let i = 0 , len = activeOutlines . length ; i < len ; i ++ ) {
292+ let maxStrokeAlpha = 0 ;
293+ let maxFillAlpha = 0 ;
294+
295+ const pendingLabeledOutlines : PaintedOutline [ ] = [ ] ;
296+
297+ for ( let i = activeOutlines . length - 1 ; i >= 0 ; i -- ) {
289298 const activeOutline = activeOutlines [ i ] ;
290- const { outline, frame, totalFrames, color } = activeOutline ;
299+ if ( ! activeOutline ) continue ;
300+ const { outline, frame, totalFrames } = activeOutline ;
301+ // const newRect = getRect(outline.domNode);
302+ // if (newRect) {
303+ // outline.rect = newRect;
304+ // }
291305 const { rect } = outline ;
292306 const unstable = isOutlineUnstable ( outline ) ;
293307
294308 const alphaScalar = unstable ? 0.8 : 0.2 ;
295309
296310 activeOutline . alpha = alphaScalar * ( 1 - frame / totalFrames ) ;
297311
298- const strokeAlpha = activeOutline . alpha ;
299- const fillAlpha = activeOutline . alpha * 0.1 ;
312+ maxStrokeAlpha = Math . max ( maxStrokeAlpha , activeOutline . alpha ) ;
313+ maxFillAlpha = Math . max ( maxFillAlpha , activeOutline . alpha * 0.1 ) ;
300314
301- 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 ( ) ;
315+ combinedPath . rect ( rect . x , rect . y , rect . width , rect . height ) ;
316+
317+ if ( unstable ) {
318+ pendingLabeledOutlines . push ( {
319+ alpha : activeOutline . alpha ,
320+ outline,
321+ text : activeOutline . text ,
322+ } ) ;
323+ }
324+
325+ activeOutline . frame ++ ;
326+
327+ if ( activeOutline . frame > activeOutline . totalFrames ) {
328+ activeOutlines . splice ( i , 1 ) ;
329+ }
330+ }
331+
332+ ctx . save ( ) ;
333+
334+ ctx . strokeStyle = `rgba(${ colorRef . current } , ${ maxStrokeAlpha } )` ;
335+ ctx . lineWidth = 1 ;
336+ ctx . fillStyle = `rgba(${ colorRef . current } , ${ maxFillAlpha } )` ;
337+
338+ ctx . stroke ( combinedPath ) ;
339+ ctx . fill ( combinedPath ) ;
312340
313- if ( unstable && activeOutline . text ) {
314- const { text } = activeOutline ;
315- ctx . save ( ) ;
341+ ctx . restore ( ) ;
316342
343+ for ( let i = 0 , len = pendingLabeledOutlines . length ; i < len ; i ++ ) {
344+ const { alpha, outline, text } = pendingLabeledOutlines [ i ] ;
345+ const { rect } = outline ;
346+ ctx . save ( ) ;
347+
348+ if ( text ) {
317349 ctx . font = `10px ${ MONO_FONT } ` ;
318350 const textMetrics = ctx . measureText ( text ) ;
319351 const textWidth = textMetrics . width ;
@@ -322,26 +354,19 @@ export const fadeOutOutline = (ctx: CanvasRenderingContext2D) => {
322354 const labelX : number = rect . x ;
323355 const labelY : number = rect . y - textHeight - 4 ;
324356
325- ctx . fillStyle = `rgba(${ color . r } ,${ color . g } , ${ color . b } , ${ strokeAlpha } )` ;
357+ ctx . fillStyle = `rgba(${ colorRef . current } ,${ alpha } )` ;
326358 ctx . fillRect ( labelX , labelY , textWidth + 4 , textHeight + 4 ) ;
327359
328- ctx . fillStyle = `rgba(255,255,255,${ strokeAlpha } )` ;
360+ ctx . fillStyle = `rgba(255,255,255,${ alpha } )` ;
329361 ctx . fillText ( text , labelX + 2 , labelY + textHeight ) ;
330-
331- ctx . restore ( ) ;
332362 }
333363
334- activeOutline . frame ++ ;
335-
336- if ( activeOutline . frame > activeOutline . totalFrames ) {
337- activeOutlinesMap . delete ( getOutlineKey ( outline ) ) ;
338- activeOutline . resolve ( ) ;
339- }
364+ ctx . restore ( ) ;
340365 }
341366
342- if ( activeOutlinesMap . size === 0 ) {
343- animationFrameId = null ;
344- } else {
367+ if ( activeOutlines . length ) {
345368 animationFrameId = requestAnimationFrame ( ( ) => fadeOutOutline ( ctx ) ) ;
369+ } else {
370+ animationFrameId = null ;
346371 }
347372} ;
0 commit comments