@@ -14,7 +14,9 @@ export const ERROR_LEVEL_MAP: { [index in 'L' | 'M' | 'Q' | 'H']: qrcodegen.QrCo
14
14
15
15
const DEFAULT_SIZE = 160 ;
16
16
const DEFAULT_SCALE = 10 ;
17
+ const DEFAULT_PADDING = 10 ;
17
18
const DEFAULT_COLOR = '#000000' ;
19
+ const DEFAULT_BACKGROUND_COLOR = '#FFFFFF' ;
18
20
const DEFAULT_ICONSIZE = 40 ;
19
21
const DEFAULT_LEVEL : keyof typeof ERROR_LEVEL_MAP = 'M' ;
20
22
@@ -33,30 +35,35 @@ export function drawCanvas(
33
35
value : qrcodegen . QrCode | null ,
34
36
size = DEFAULT_SIZE ,
35
37
scale = DEFAULT_SCALE ,
38
+ padding : number | number [ ] = DEFAULT_PADDING ,
36
39
color = DEFAULT_COLOR ,
40
+ backgroundColor = DEFAULT_BACKGROUND_COLOR ,
37
41
iconSize = DEFAULT_ICONSIZE ,
38
42
icon ?: string
39
43
) : void {
40
44
const ctx = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ;
45
+ const formattedPadding = formatPadding ( padding ) ;
41
46
canvas . style . width = `${ size } px` ;
42
47
canvas . style . height = `${ size } px` ;
43
48
if ( ! value ) {
44
49
ctx . fillStyle = 'rgba(0, 0, 0, 0)' ;
45
50
ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
46
51
return ;
47
52
}
48
- canvas . width = value . size * scale ;
49
- canvas . height = value . size * scale ;
53
+ canvas . width = value . size * scale + formattedPadding [ 1 ] + formattedPadding [ 3 ] ;
54
+ canvas . height = value . size * scale + formattedPadding [ 0 ] + formattedPadding [ 2 ] ;
50
55
if ( ! icon ) {
51
- drawCanvasColor ( ctx , value , scale , color ) ;
56
+ drawCanvasBackground ( ctx , canvas . width , canvas . height , scale , backgroundColor ) ;
57
+ drawCanvasColor ( ctx , value , scale , formattedPadding , backgroundColor , color ) ;
52
58
} else {
53
59
const iconImg = new Image ( ) ;
54
60
iconImg . src = icon ;
55
61
iconImg . crossOrigin = 'anonymous' ;
56
62
iconImg . width = iconSize * ( canvas . width / size ) ;
57
63
iconImg . height = iconSize * ( canvas . width / size ) ;
58
64
iconImg . onload = ( ) => {
59
- drawCanvasColor ( ctx , value , scale , color ) ;
65
+ drawCanvasBackground ( ctx , canvas . width , canvas . height , scale , backgroundColor ) ;
66
+ drawCanvasColor ( ctx , value , scale , formattedPadding , backgroundColor , color ) ;
60
67
const iconCoordinate = canvas . width / 2 - ( iconSize * ( canvas . width / size ) ) / 2 ;
61
68
62
69
ctx . fillRect ( iconCoordinate , iconCoordinate , iconSize * ( canvas . width / size ) , iconSize * ( canvas . width / size ) ) ;
@@ -68,20 +75,51 @@ export function drawCanvas(
68
75
iconSize * ( canvas . width / size )
69
76
) ;
70
77
} ;
71
- iconImg . onerror = ( ) => drawCanvasColor ( ctx , value , scale , color ) ;
78
+ iconImg . onerror = ( ) => {
79
+ drawCanvasBackground ( ctx , canvas . width , canvas . height , scale , backgroundColor ) ;
80
+ drawCanvasColor ( ctx , value , scale , formattedPadding , backgroundColor , color ) ;
81
+ } ;
72
82
}
73
83
}
74
84
75
85
export function drawCanvasColor (
76
86
ctx : CanvasRenderingContext2D ,
77
87
value : qrcodegen . QrCode ,
78
88
scale : number ,
89
+ padding : number [ ] ,
90
+ backgroundColor : string ,
79
91
color : string
80
92
) : void {
81
93
for ( let y = 0 ; y < value . size ; y ++ ) {
82
94
for ( let x = 0 ; x < value . size ; x ++ ) {
83
- ctx . fillStyle = value . getModule ( x , y ) ? color : 'rgba(0, 0, 0, 0)' ;
95
+ ctx . fillStyle = value . getModule ( x , y ) ? color : backgroundColor ;
96
+ ctx . fillRect ( padding [ 3 ] + x * scale , padding [ 0 ] + y * scale , scale , scale ) ;
97
+ }
98
+ }
99
+ }
100
+
101
+ export function drawCanvasBackground (
102
+ ctx : CanvasRenderingContext2D ,
103
+ width : number ,
104
+ height : number ,
105
+ scale : number ,
106
+ backgroundColor : string
107
+ ) : void {
108
+ for ( let y = 0 ; y < height ; y ++ ) {
109
+ for ( let x = 0 ; x < width ; x ++ ) {
110
+ ctx . fillStyle = backgroundColor ;
84
111
ctx . fillRect ( x * scale , y * scale , scale , scale ) ;
85
112
}
86
113
}
87
114
}
115
+
116
+ export function formatPadding ( padding : number | number [ ] ) : number [ ] {
117
+ if ( Array . isArray ( padding ) ) {
118
+ // Build an array of 4 elements and repeat values from padding as necessary to set the value of the array
119
+ return Array ( 4 )
120
+ . fill ( 0 )
121
+ . map ( ( _ , index ) => padding [ index % padding . length ] ) ;
122
+ } else {
123
+ return [ padding , padding , padding , padding ] ;
124
+ }
125
+ }
0 commit comments