@@ -98,7 +98,7 @@ export const Canvas = () => {
9898 }
9999 return null ;
100100 } , [ ] ) ;
101-
101+
102102 // Returns array of handle objects: { x, y, dir }
103103 const getHandlesForShape = useCallback (
104104 ( shape ) => {
@@ -229,45 +229,45 @@ export const Canvas = () => {
229229 ctx . strokeStyle = shape . color ;
230230 drawPath ( 0 ) ;
231231 ctx . setLineDash ( [ ] ) ;
232- } else if ( brush === 'paint' ) {
233- ctx . lineCap = "round" ;
234- ctx . lineJoin = "round" ;
235-
236- const baseWidth = Math . max ( shape . width , 1.5 ) ; // Ensure a minimum body
237- const layers = 8 ;
238-
239- for ( let i = 0 ; i < layers ; i ++ ) {
240- const opacity = 0.18 + Math . random ( ) * 0.12 ;
241- const color = tinycolor ( shape . color )
242- . brighten ( ( Math . random ( ) - 0.5 ) * 2.5 )
243- . setAlpha ( opacity )
244- . toRgbString ( ) ;
245-
246- ctx . strokeStyle = color ;
247- ctx . globalAlpha = 0.9 ;
248- const widthFactor = baseWidth < 4 ? 3.8 : 2.2 ;
249- ctx . lineWidth = baseWidth * ( widthFactor + i * 0.2 ) ;
250-
251- drawPath ( 0 ) ;
252- }
253-
254- ctx . globalAlpha = 0.25 ;
255- ctx . lineWidth = baseWidth * ( baseWidth < 4 ? 4.8 : 3.2 ) ;
256- ctx . strokeStyle = tinycolor ( shape . color )
257- . lighten ( 3 )
258- . setAlpha ( 0.25 )
259- . toRgbString ( ) ;
260- drawPath ( 0 ) ;
261-
262- ctx . globalAlpha = 0.95 ;
263- ctx . lineWidth = baseWidth * ( baseWidth < 4 ? 3.4 : 2.4 ) ;
264- ctx . strokeStyle = shape . color ;
265- drawPath ( 0 ) ;
266-
267- ctx . globalAlpha = 1 ;
268- ctx . lineWidth = shape . width ;
269- } else if ( brush === "crayon" ) {
270- const pts = shape . path ;
232+ } else if ( brush === 'paint' ) {
233+ ctx . lineCap = "round" ;
234+ ctx . lineJoin = "round" ;
235+
236+ const baseWidth = Math . max ( shape . width , 1.5 ) ; // Ensure a minimum body
237+ const layers = 8 ;
238+
239+ for ( let i = 0 ; i < layers ; i ++ ) {
240+ const opacity = 0.18 + Math . random ( ) * 0.12 ;
241+ const color = tinycolor ( shape . color )
242+ . brighten ( ( Math . random ( ) - 0.5 ) * 2.5 )
243+ . setAlpha ( opacity )
244+ . toRgbString ( ) ;
245+
246+ ctx . strokeStyle = color ;
247+ ctx . globalAlpha = 0.9 ;
248+ const widthFactor = baseWidth < 4 ? 3.8 : 2.2 ;
249+ ctx . lineWidth = baseWidth * ( widthFactor + i * 0.2 ) ;
250+
251+ drawPath ( 0 ) ;
252+ }
253+
254+ ctx . globalAlpha = 0.25 ;
255+ ctx . lineWidth = baseWidth * ( baseWidth < 4 ? 4.8 : 3.2 ) ;
256+ ctx . strokeStyle = tinycolor ( shape . color )
257+ . lighten ( 3 )
258+ . setAlpha ( 0.25 )
259+ . toRgbString ( ) ;
260+ drawPath ( 0 ) ;
261+
262+ ctx . globalAlpha = 0.95 ;
263+ ctx . lineWidth = baseWidth * ( baseWidth < 4 ? 3.4 : 2.4 ) ;
264+ ctx . strokeStyle = shape . color ;
265+ drawPath ( 0 ) ;
266+
267+ ctx . globalAlpha = 1 ;
268+ ctx . lineWidth = shape . width ;
269+ } else if ( brush === "crayon" ) {
270+ const pts = shape . path ;
271271 if ( pts . length >= 2 ) {
272272 ctx . save ( ) ;
273273 ctx . globalCompositeOperation = 'source-over' ;
@@ -375,61 +375,61 @@ export const Canvas = () => {
375375 ctx . lineWidth = shape . width ;
376376 ctx . strokeStyle = shape . color ;
377377 } else if ( brush === "oil-pastel" ) {
378- ctx . lineCap = "round" ;
379- ctx . lineJoin = "round" ;
378+ ctx . lineCap = "round" ;
379+ ctx . lineJoin = "round" ;
380380
381- const baseWidth = Math . max ( shape . width , 2 ) ;
382- const seed = shape . _seed || 1 ; // use shape seed for consistent randomness
383- const rng = mulberry32 ( seed ) ;
381+ const baseWidth = Math . max ( shape . width , 2 ) ;
382+ const seed = shape . _seed || 1 ; // use shape seed for consistent randomness
383+ const rng = mulberry32 ( seed ) ;
384384
385- for ( let layer = 0 ; layer < 6 ; layer ++ ) {
386- const variation = ( rng ( ) - 0.5 ) * 10 ;
387- const opacity = 0.12 + rng ( ) * 0.1 ;
388- const pastelColor = tinycolor ( shape . color )
389- . brighten ( variation )
390- . setAlpha ( opacity )
391- . toRgbString ( ) ;
385+ for ( let layer = 0 ; layer < 6 ; layer ++ ) {
386+ const variation = ( rng ( ) - 0.5 ) * 10 ;
387+ const opacity = 0.12 + rng ( ) * 0.1 ;
388+ const pastelColor = tinycolor ( shape . color )
389+ . brighten ( variation )
390+ . setAlpha ( opacity )
391+ . toRgbString ( ) ;
392392
393- ctx . strokeStyle = pastelColor ;
394- ctx . lineWidth = baseWidth * ( 1.2 + rng ( ) * 0.6 ) ;
393+ ctx . strokeStyle = pastelColor ;
394+ ctx . lineWidth = baseWidth * ( 1.2 + rng ( ) * 0.6 ) ;
395395
396- ctx . beginPath ( ) ;
397- for ( let i = 0 ; i < shape . path . length - 1 ; i ++ ) {
398- const p1 = shape . path [ i ] ;
399- const p2 = shape . path [ i + 1 ] ;
400- const dx = p2 . x - p1 . x ;
401- const dy = p2 . y - p1 . y ;
402- const steps = Math . ceil ( Math . hypot ( dx , dy ) / 1.5 ) ;
403-
404- const segRng = mulberry32 ( seed ^ ( layer * 999 + i * 31 ) ) ;
405-
406- for ( let s = 0 ; s < steps ; s ++ ) {
407- const t = s / steps ;
408- const x = p1 . x + dx * t + ( segRng ( ) - 0.5 ) * 2.5 ;
409- const y = p1 . y + dy * t + ( segRng ( ) - 0.5 ) * 2.5 ;
410-
411- if ( segRng ( ) > 0.2 ) {
412- ctx . moveTo ( x , y ) ;
413- ctx . lineTo ( x + 0.3 , y + 0.3 ) ;
414- }
415- }
416- }
417- ctx . stroke ( ) ;
418- }
419-
420- ctx . strokeStyle = tinycolor ( shape . color ) . darken ( 12 ) . setAlpha ( 0.25 ) . toRgbString ( ) ;
421- ctx . lineWidth = baseWidth * 1.8 ;
422- ctx . globalAlpha = 0.9 ;
423- drawPath ( 0 ) ;
424- ctx . globalAlpha = 0.7 ;
425- ctx . lineWidth = baseWidth * 2.2 ;
426- ctx . strokeStyle = tinycolor ( shape . color ) . setAlpha ( 0.25 ) . toRgbString ( ) ;
427- drawPath ( 0 ) ;
428-
429- ctx . globalAlpha = 1 ;
430- ctx . lineWidth = shape . width ;
431- } else {
432- //default(solid)
396+ ctx . beginPath ( ) ;
397+ for ( let i = 0 ; i < shape . path . length - 1 ; i ++ ) {
398+ const p1 = shape . path [ i ] ;
399+ const p2 = shape . path [ i + 1 ] ;
400+ const dx = p2 . x - p1 . x ;
401+ const dy = p2 . y - p1 . y ;
402+ const steps = Math . ceil ( Math . hypot ( dx , dy ) / 1.5 ) ;
403+
404+ const segRng = mulberry32 ( seed ^ ( layer * 999 + i * 31 ) ) ;
405+
406+ for ( let s = 0 ; s < steps ; s ++ ) {
407+ const t = s / steps ;
408+ const x = p1 . x + dx * t + ( segRng ( ) - 0.5 ) * 2.5 ;
409+ const y = p1 . y + dy * t + ( segRng ( ) - 0.5 ) * 2.5 ;
410+
411+ if ( segRng ( ) > 0.2 ) {
412+ ctx . moveTo ( x , y ) ;
413+ ctx . lineTo ( x + 0.3 , y + 0.3 ) ;
414+ }
415+ }
416+ }
417+ ctx . stroke ( ) ;
418+ }
419+
420+ ctx . strokeStyle = tinycolor ( shape . color ) . darken ( 12 ) . setAlpha ( 0.25 ) . toRgbString ( ) ;
421+ ctx . lineWidth = baseWidth * 1.8 ;
422+ ctx . globalAlpha = 0.9 ;
423+ drawPath ( 0 ) ;
424+ ctx . globalAlpha = 0.7 ;
425+ ctx . lineWidth = baseWidth * 2.2 ;
426+ ctx . strokeStyle = tinycolor ( shape . color ) . setAlpha ( 0.25 ) . toRgbString ( ) ;
427+ drawPath ( 0 ) ;
428+
429+ ctx . globalAlpha = 1 ;
430+ ctx . lineWidth = shape . width ;
431+ } else {
432+ //default(solid)
433433 ctx . lineWidth = shape . width ;
434434 ctx . strokeStyle = shape . color ;
435435 ctx . setLineDash ( [ ] ) ;
@@ -847,7 +847,18 @@ export const Canvas = () => {
847847 console . warn ( "Unsupported format:" , format ) ;
848848 }
849849 } ;
850-
850+ useEffect ( ( ) => {
851+ const handleGlobalWheel = ( e ) => {
852+ // Block browser zoom if user scrolls with Ctrl/Cmd + trackpad
853+ if ( e . ctrlKey ) {
854+ e . preventDefault ( ) ;
855+ }
856+ } ;
857+ window . addEventListener ( "wheel" , handleGlobalWheel , { passive : false } ) ;
858+ return ( ) => {
859+ window . removeEventListener ( "wheel" , handleGlobalWheel ) ;
860+ } ;
861+ } , [ ] ) ;
851862
852863 return (
853864 < div className = "relative w-full h-screen overflow-hidden bg-canvas" >
0 commit comments