@@ -2503,121 +2503,123 @@ var JSONResponse = {
2503
2503
2504
2504
// Draw bboxes
2505
2505
var bboxes = JSONResponse . getBboxes ( detection ) || [ ]
2506
- bboxes ?. forEach ( ( item , index ) => {
2507
- const isHovered = index === hoverBoxId ;
2508
- const visible = ! visiblePaths || visiblePaths . length <= 0 || visiblePaths . includes ( item . path || item . id ) ;
2509
- if ( ! visible ) {
2510
- return ;
2511
- }
2512
-
2513
- var [ x , y , w , h , d ] = JSONResponse . getXYWHD ( JSONResponse . getBbox ( item ) || [ ] ) ;
2514
- const isRate = Math . abs ( x ) < 1 && Math . abs ( y ) < 1 && Math . abs ( w ) < 1 && Math . abs ( h ) < 1 ;
2515
- x = isRate ? x * width : x * xRate ;
2516
- y = isRate ? y * height : y * yRate ;
2517
- w = isRate ? w * width : w * xRate ;
2518
- h = isRate ? h * height : h * yRate ;
2519
- const angle = item . degree || item . rotate || item . angle || item . perspective || d || 0 ;
2520
-
2521
- var color = item . color ;
2522
- if ( options . styleOverride ) {
2523
- const override = options . styleOverride ( item , item [ '@before' ] ) ;
2524
- if ( override && override . color ) {
2525
- color = override . color ;
2526
- }
2527
- }
2528
-
2529
- const [ r , g , b , a ] = color || [ 0 , 255 , 0 , 255 ] ;
2530
- const rgba = `rgba(${ r } , ${ g } , ${ b } , ${ hoverBoxId != null || ! isHovered ? 0.3 : Math . min ( 0.5 , a < 1 ? a : a / 255 ) } )` ;
2531
-
2532
- const reversedRgba = `rgba(${ 255 - r } , ${ 255 - g } , ${ 255 - b } ` , $ { isHovered || hoverBoxId == null ? 1 : 0.3 } ) `;
2533
- // const luma = 0.299 * r + 0.587 * g + 0.114 * b;
2534
- const backgroundFill = rgba; // 还是有些看不清 luma > 186 ? 'rgba(0, 0, 0, 0.5)' : 'rgba(255, 255, 255, 0.5)';
2535
-
2536
- ctx.strokeStyle = isHovered ? reversedRgba : rgba;
2537
- ctx.fillStyle = rgba;
2538
-
2539
- // Draw horizontal box
2540
- ctx.strokeRect(x, y, w, h);
2541
-
2542
- // Optionally draw rotated box
2543
- if (rotateBoxes && angle !== 0) {
2544
- ctx.save();
2545
- ctx.translate(x + w / 2, y + h / 2);
2546
- ctx.rotate((angle * Math.PI) / 180);
2547
- ctx.strokeRect(-w / 2, -h / 2, w, h);
2548
- ctx.restore();
2549
- }
2550
-
2551
- if (hoverBoxId != null && ! isHovered) {
2552
- return
2553
- }
2554
-
2555
- // Label
2556
- const label = (isDiff ? (item['@before'] ? '- ' : '+ ') : '') + ` $ { item . ocr || item . label || '' } - $ { item . id || '' } ${( ( JSONResponse . getScore ( item ) || 0 ) * 100 ) . toFixed ( 0 ) } % $ { angle == 0 ? '' : ' ' + Math . round ( angle ) + '°' } `;
2557
- // ctx.font = 'bold 36px';
2558
- // const size = ctx.measureText(label);
2559
- // const textHeight = size.height || height*0.1; // Math.max(height*0.1, size.height);
2560
- // 让字号约为 canvas 高度的 2%,并限定 12~48px
2561
- ctx . font = `bold ${ fontSize } px sans-serif` ;
2562
- const size = ctx . measureText ( label ) ;
2563
- // 自动从 font 里提取 px 字号
2564
- const fontMatch = ctx . font . match ( / ( \d + ) p x / ) ;
2565
- const textHeight = fontMatch ? parseInt ( fontMatch [ 1 ] ) : 36 ; // fallback 到 36px
2566
- const textWidth = size . width ; // *textHeight/size.height;
2567
- const padding = 2 ;
2568
-
2569
- let positions = [
2570
- [ x , y - textHeight - padding ] ,
2571
- [ x + w - textWidth , y - textHeight - padding ] ,
2572
- [ x , y + h + padding ] ,
2573
- [ x + w - textWidth , y + h + padding ]
2574
- ] ;
2575
-
2576
- let labelX = x , labelY = y - textHeight - padding ;
2577
- for ( const [ lx , ly ] of positions ) {
2578
- const overlaps = placedLabels . some ( ( { x : ox , y : oy , w : ow , h : oh } ) =>
2579
- lx < ox + ow && lx + textWidth > ox && ly < oy + oh && ly + textHeight > oy
2580
- ) ;
2581
- if ( ! overlaps && lx >= 0 && ly >= 0 && lx + textWidth <= canvas . width && ly + textHeight <= canvas . height ) {
2582
- labelX = lx ;
2583
- labelY = ly ;
2584
- break ;
2585
- }
2586
- }
2506
+ if ( bboxes instanceof Array ) {
2507
+ bboxes ?. forEach ( ( item , index ) => {
2508
+ const isHovered = index === hoverBoxId ;
2509
+ const visible = ! visiblePaths || visiblePaths . length <= 0 || visiblePaths . includes ( item . path || item . id ) ;
2510
+ if ( ! visible ) {
2511
+ return ;
2512
+ }
2587
2513
2588
- placedLabels . push ( { x : labelX , y : labelY , w : textWidth , h : textHeight } ) ;
2514
+ var [ x , y , w , h , d ] = JSONResponse . getXYWHD ( JSONResponse . getBbox ( item ) || [ ] ) ;
2515
+ const isRate = Math . abs ( x ) < 1 && Math . abs ( y ) < 1 && Math . abs ( w ) < 1 && Math . abs ( h ) < 1 ;
2516
+ x = isRate ? x * width : x * xRate ;
2517
+ y = isRate ? y * height : y * yRate ;
2518
+ w = isRate ? w * width : w * xRate ;
2519
+ h = isRate ? h * height : h * yRate ;
2520
+ const angle = item . degree || item . rotate || item . angle || item . perspective || d || 0 ;
2521
+
2522
+ var color = item . color ;
2523
+ if ( options . styleOverride ) {
2524
+ const override = options . styleOverride ( item , item [ '@before' ] ) ;
2525
+ if ( override && override . color ) {
2526
+ color = override . color ;
2527
+ }
2528
+ }
2589
2529
2590
- ctx . save ( ) ;
2591
- if ( rotateText && angle !== 0 ) {
2592
- ctx . translate ( labelX + textWidth / 2 , labelY + textHeight / 2 ) ;
2593
- ctx . rotate ( ( angle * Math . PI ) / 180 ) ;
2594
- ctx . translate ( - textWidth / 2 , - textHeight / 2 ) ;
2595
- labelX = 0 ;
2596
- labelY = 0 ;
2597
- }
2530
+ const [ r , g , b , a ] = color || [ 0 , 255 , 0 , 255 ] ;
2531
+ const rgba = `rgba(${ r } , ${ g } , ${ b } , ${ hoverBoxId != null || ! isHovered ? 0.3 : Math . min ( 0.5 , a < 1 ? a : a / 255 ) } )` ;
2598
2532
2599
- if ( showLabelBackground ) {
2600
- ctx . fillStyle = backgroundFill ;
2601
- ctx . fillRect ( labelX - 2 , labelY - 1 , textWidth + 4 , textHeight + 2 ) ;
2602
- }
2533
+ const reversedRgba = `rgba(${ 255 - r } , ${ 255 - g } , ${ 255 - b } , ${ isHovered || hoverBoxId == null ? 1 : 0.3 } )` ;
2534
+ // const luma = 0.299 * r + 0.587 * g + 0.114 * b;
2535
+ const backgroundFill = rgba ; // 还是有些看不清 luma > 186 ? 'rgba(0, 0, 0, 0.5)' : 'rgba(255, 255, 255, 0.5)';
2603
2536
2604
- ctx . fillStyle = showLabelBackground ? reversedRgba : rgba ;
2605
- ctx . fillText ( label , labelX , labelY ) ;
2606
- ctx . restore ( ) ;
2537
+ ctx . strokeStyle = isHovered ? reversedRgba : rgba ;
2538
+ ctx . fillStyle = rgba ;
2607
2539
2608
- if ( markable && item [ '@before' ] != true ) {
2609
- const isWrong = wrongs . indexOf ( isDiff ? item [ '@index' ] : index ) >= 0 ; // item.correct === false;
2610
- // 绘制 √ 和 ×
2611
- ctx . font = `bold ${ fontSize } px sans-serif` ;
2612
- // ctx.fillStyle = isWrong ? 'red' : 'green';
2613
- ctx . fillStyle = isWrong ? 'red' : 'green' ;
2614
- const checkX = labelX + textWidth + 4 ;
2615
- const checkY = labelY ;
2616
- ctx . fillText ( isWrong ? '×' : '√' , checkX , checkY ) ;
2617
- }
2540
+ // Draw horizontal box
2541
+ ctx . strokeRect ( x , y , w , h ) ;
2618
2542
2619
- JSONResponse . drawDetections ( canvas , item , options , img , ctx ) ;
2620
- } ) ;
2543
+ // Optionally draw rotated box
2544
+ if ( rotateBoxes && angle !== 0 ) {
2545
+ ctx . save ( ) ;
2546
+ ctx . translate ( x + w / 2 , y + h / 2 ) ;
2547
+ ctx . rotate ( ( angle * Math . PI ) / 180 ) ;
2548
+ ctx . strokeRect ( - w / 2 , - h / 2 , w , h ) ;
2549
+ ctx . restore ( ) ;
2550
+ }
2551
+
2552
+ if ( hoverBoxId != null && ! isHovered ) {
2553
+ return
2554
+ }
2555
+
2556
+ // Label
2557
+ const label = ( isDiff ? ( item [ '@before' ] ? '- ' : '+ ' ) : '' ) + `${ item . ocr || item . label || '' } -${ item . id || '' } ${ ( ( JSONResponse . getScore ( item ) || 0 ) * 100 ) . toFixed ( 0 ) } %${ angle == 0 ? '' : ' ' + Math . round ( angle ) + '°' } ` ;
2558
+ // ctx.font = 'bold 36px';
2559
+ // const size = ctx.measureText(label);
2560
+ // const textHeight = size.height || height*0.1; // Math.max(height*0.1, size.height);
2561
+ // 让字号约为 canvas 高度的 2%,并限定 12~48px
2562
+ ctx . font = `bold ${ fontSize } px sans-serif` ;
2563
+ const size = ctx . measureText ( label ) ;
2564
+ // 自动从 font 里提取 px 字号
2565
+ const fontMatch = ctx . font . match ( / ( \d + ) p x / ) ;
2566
+ const textHeight = fontMatch ? parseInt ( fontMatch [ 1 ] ) : 36 ; // fallback 到 36px
2567
+ const textWidth = size . width ; // *textHeight/size.height;
2568
+ const padding = 2 ;
2569
+
2570
+ let positions = [
2571
+ [ x , y - textHeight - padding ] ,
2572
+ [ x + w - textWidth , y - textHeight - padding ] ,
2573
+ [ x , y + h + padding ] ,
2574
+ [ x + w - textWidth , y + h + padding ]
2575
+ ] ;
2576
+
2577
+ let labelX = x , labelY = y - textHeight - padding ;
2578
+ for ( const [ lx , ly ] of positions ) {
2579
+ const overlaps = placedLabels . some ( ( { x : ox , y : oy , w : ow , h : oh } ) =>
2580
+ lx < ox + ow && lx + textWidth > ox && ly < oy + oh && ly + textHeight > oy
2581
+ ) ;
2582
+ if ( ! overlaps && lx >= 0 && ly >= 0 && lx + textWidth <= canvas . width && ly + textHeight <= canvas . height ) {
2583
+ labelX = lx ;
2584
+ labelY = ly ;
2585
+ break ;
2586
+ }
2587
+ }
2588
+
2589
+ placedLabels . push ( { x : labelX , y : labelY , w : textWidth , h : textHeight } ) ;
2590
+
2591
+ ctx . save ( ) ;
2592
+ if ( rotateText && angle !== 0 ) {
2593
+ ctx . translate ( labelX + textWidth / 2 , labelY + textHeight / 2 ) ;
2594
+ ctx . rotate ( ( angle * Math . PI ) / 180 ) ;
2595
+ ctx . translate ( - textWidth / 2 , - textHeight / 2 ) ;
2596
+ labelX = 0 ;
2597
+ labelY = 0 ;
2598
+ }
2599
+
2600
+ if ( showLabelBackground ) {
2601
+ ctx . fillStyle = backgroundFill ;
2602
+ ctx . fillRect ( labelX - 2 , labelY - 1 , textWidth + 4 , textHeight + 2 ) ;
2603
+ }
2604
+
2605
+ ctx . fillStyle = showLabelBackground ? reversedRgba : rgba ;
2606
+ ctx . fillText ( label , labelX , labelY ) ;
2607
+ ctx . restore ( ) ;
2608
+
2609
+ if ( markable && item [ '@before' ] != true ) {
2610
+ const isWrong = wrongs . indexOf ( isDiff ? item [ '@index' ] : index ) >= 0 ; // item.correct === false;
2611
+ // 绘制 √ 和 ×
2612
+ ctx . font = `bold ${ fontSize } px sans-serif` ;
2613
+ // ctx.fillStyle = isWrong ? 'red' : 'green';
2614
+ ctx . fillStyle = isWrong ? 'red' : 'green' ;
2615
+ const checkX = labelX + textWidth + 4 ;
2616
+ const checkY = labelY ;
2617
+ ctx . fillText ( isWrong ? '×' : '√' , checkX , checkY ) ;
2618
+ }
2619
+
2620
+ JSONResponse . drawDetections ( canvas , item , options , img , ctx ) ;
2621
+ } ) ;
2622
+ }
2621
2623
2622
2624
// Draw lines
2623
2625
var lines = JSONResponse . getLines ( detection ) ;
0 commit comments