@@ -1521,57 +1521,64 @@ function Canvas({
15211521 // This avoids async rendering issues with image stamps
15221522 const stampsToRender = [ ] ;
15231523
1524- // Render template objects as semi-transparent background
1524+ // Create and render template layer separately so it stays below all drawings
1525+ let templateCanvas = null ;
15251526 if ( currentTemplateObjects && currentTemplateObjects . length > 0 ) {
1526- offscreenContext . save ( ) ;
1527- offscreenContext . globalAlpha = 0.5 ;
1527+ templateCanvas = document . createElement ( 'canvas' ) ;
1528+ templateCanvas . width = canvasWidth ;
1529+ templateCanvas . height = canvasHeight ;
1530+ const templateContext = templateCanvas . getContext ( '2d' ) ;
1531+ templateContext . imageSmoothingEnabled = false ;
1532+
1533+ templateContext . save ( ) ;
1534+ templateContext . globalAlpha = 0.5 ;
15281535
15291536 let renderedCount = 0 ;
15301537 for ( const obj of currentTemplateObjects ) {
15311538 try {
15321539 if ( obj . type === 'line' ) {
1533- offscreenContext . beginPath ( ) ;
1534- offscreenContext . moveTo ( obj . x1 , obj . y1 ) ;
1535- offscreenContext . lineTo ( obj . x2 , obj . y2 ) ;
1536- offscreenContext . strokeStyle = obj . color || '#333' ;
1537- offscreenContext . lineWidth = obj . lineWidth || 2 ;
1538- offscreenContext . stroke ( ) ;
1540+ templateContext . beginPath ( ) ;
1541+ templateContext . moveTo ( obj . x1 , obj . y1 ) ;
1542+ templateContext . lineTo ( obj . x2 , obj . y2 ) ;
1543+ templateContext . strokeStyle = obj . color || '#333' ;
1544+ templateContext . lineWidth = obj . lineWidth || 2 ;
1545+ templateContext . stroke ( ) ;
15391546 renderedCount ++ ;
15401547 } else if ( obj . type === 'rectangle' ) {
1541- offscreenContext . strokeStyle = obj . stroke || '#333' ;
1542- offscreenContext . lineWidth = obj . lineWidth || 2 ;
1548+ templateContext . strokeStyle = obj . stroke || '#333' ;
1549+ templateContext . lineWidth = obj . lineWidth || 2 ;
15431550 if ( obj . fill && obj . fill !== 'transparent' ) {
1544- offscreenContext . fillStyle = obj . fill ;
1545- offscreenContext . fillRect ( obj . x , obj . y , obj . width , obj . height ) ;
1551+ templateContext . fillStyle = obj . fill ;
1552+ templateContext . fillRect ( obj . x , obj . y , obj . width , obj . height ) ;
15461553 }
1547- offscreenContext . strokeRect ( obj . x , obj . y , obj . width , obj . height ) ;
1554+ templateContext . strokeRect ( obj . x , obj . y , obj . width , obj . height ) ;
15481555 renderedCount ++ ;
15491556 } else if ( obj . type === 'circle' ) {
1550- offscreenContext . beginPath ( ) ;
1551- offscreenContext . arc ( obj . cx , obj . cy , obj . radius , 0 , Math . PI * 2 ) ;
1552- offscreenContext . strokeStyle = obj . stroke || '#333' ;
1553- offscreenContext . lineWidth = obj . lineWidth || 2 ;
1557+ templateContext . beginPath ( ) ;
1558+ templateContext . arc ( obj . cx , obj . cy , obj . radius , 0 , Math . PI * 2 ) ;
1559+ templateContext . strokeStyle = obj . stroke || '#333' ;
1560+ templateContext . lineWidth = obj . lineWidth || 2 ;
15541561 if ( obj . fill && obj . fill !== 'transparent' ) {
1555- offscreenContext . fillStyle = obj . fill ;
1556- offscreenContext . fill ( ) ;
1562+ templateContext . fillStyle = obj . fill ;
1563+ templateContext . fill ( ) ;
15571564 }
1558- offscreenContext . stroke ( ) ;
1565+ templateContext . stroke ( ) ;
15591566 renderedCount ++ ;
15601567 } else if ( obj . type === 'ellipse' ) {
1561- offscreenContext . beginPath ( ) ;
1562- offscreenContext . ellipse ( obj . cx , obj . cy , obj . rx , obj . ry , 0 , 0 , Math . PI * 2 ) ;
1563- offscreenContext . strokeStyle = obj . stroke || '#333' ;
1564- offscreenContext . lineWidth = obj . lineWidth || 2 ;
1568+ templateContext . beginPath ( ) ;
1569+ templateContext . ellipse ( obj . cx , obj . cy , obj . rx , obj . ry , 0 , 0 , Math . PI * 2 ) ;
1570+ templateContext . strokeStyle = obj . stroke || '#333' ;
1571+ templateContext . lineWidth = obj . lineWidth || 2 ;
15651572 if ( obj . fill && obj . fill !== 'transparent' ) {
1566- offscreenContext . fillStyle = obj . fill ;
1567- offscreenContext . fill ( ) ;
1573+ templateContext . fillStyle = obj . fill ;
1574+ templateContext . fill ( ) ;
15681575 }
1569- offscreenContext . stroke ( ) ;
1576+ templateContext . stroke ( ) ;
15701577 renderedCount ++ ;
15711578 } else if ( obj . type === 'text' ) {
1572- offscreenContext . fillStyle = obj . color || '#333' ;
1573- offscreenContext . font = `${ obj . bold ? 'bold ' : '' } ${ obj . fontSize || 16 } px Arial` ;
1574- offscreenContext . fillText ( obj . text || '' , obj . x , obj . y ) ;
1579+ templateContext . fillStyle = obj . color || '#333' ;
1580+ templateContext . font = `${ obj . bold ? 'bold ' : '' } ${ obj . fontSize || 16 } px Arial` ;
1581+ templateContext . fillText ( obj . text || '' , obj . x , obj . y ) ;
15751582 renderedCount ++ ;
15761583 } else {
15771584 console . warn ( 'Unknown template object type:' , obj . type ) ;
@@ -1580,11 +1587,15 @@ function Canvas({
15801587 console . warn ( 'Failed to render template object:' , obj , e ) ;
15811588 }
15821589 }
1583- offscreenContext . restore ( ) ;
1590+ templateContext . restore ( ) ;
15841591 } else {
15851592 console . log ( 'No template objects to render' ) ;
15861593 }
15871594
1595+ if ( templateCanvas ) {
1596+ offscreenContext . drawImage ( templateCanvas , 0 , 0 ) ;
1597+ }
1598+
15881599 const cutOriginalIds = new Set ( ) ;
15891600 try {
15901601 combined . forEach ( ( d ) => {
@@ -1686,6 +1697,21 @@ function Canvas({
16861697 } finally {
16871698 offscreenContext . restore ( ) ;
16881699 }
1700+
1701+ // Restore template layer in the cut region so templates remain visible
1702+ if ( templateCanvas ) {
1703+ offscreenContext . drawImage (
1704+ templateCanvas ,
1705+ Math . floor ( r . x ) - 2 ,
1706+ Math . floor ( r . y ) - 2 ,
1707+ Math . ceil ( r . width ) + 4 ,
1708+ Math . ceil ( r . height ) + 4 ,
1709+ Math . floor ( r . x ) - 2 ,
1710+ Math . floor ( r . y ) - 2 ,
1711+ Math . ceil ( r . width ) + 4 ,
1712+ Math . ceil ( r . height ) + 4
1713+ ) ;
1714+ }
16891715 }
16901716
16911717 continue ;
0 commit comments