Skip to content

Commit 3b8216e

Browse files
committed
Update.
1 parent 4004903 commit 3b8216e

File tree

5 files changed

+132
-54
lines changed

5 files changed

+132
-54
lines changed

dist/kjua.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/kjua.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,8 @@ module.exports = options => {
77
const settings = Object.assign({}, defaults, options);
88
const qr = qrcode(settings.text, settings.ecLevel, settings.minVersion, settings.quiet);
99

10-
if (settings.render === 'canvas') {
11-
return create_canvas_qrcode(qr, settings, false);
12-
} else if (settings.render === 'image') {
13-
return create_canvas_qrcode(qr, settings, true);
14-
} else if (settings.render === 'svg') {
10+
if (settings.render === 'svg') {
1511
return create_svg_qrcode(qr, settings);
1612
}
17-
18-
return null;
13+
return create_canvas_qrcode(qr, settings, settings.render === 'image');
1914
};

src/lib/create_canvas_qrcode.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ const draw_module_rounded = require('./draw_rounded');
33
const draw_mode = require('./draw_mode');
44

55
const draw_background = (ctx, settings) => {
6-
ctx.fillStyle = settings.back;
7-
ctx.fillRect(0, 0, settings.size, settings.size);
6+
if (settings.back) {
7+
ctx.fillStyle = settings.back;
8+
ctx.fillRect(0, 0, settings.size, settings.size);
9+
}
810
};
911

1012
const draw_module_default = (qr, ctx, settings, width, row, col) => {

src/lib/create_svg_qrcode.js

Lines changed: 105 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
const {create_svg_el, set_attr} = require('./dom');
1+
const {create_svg_el, get_attr} = require('./dom');
22

3-
const wrap_ctx = ctx => {
3+
const create_draw_ctx = ctx => {
44
const rnd = x => Math.round(x * 10) / 10;
5+
const rndo = x => Math.round(x * 10) / 10 + ctx.o;
56
return {
6-
m(x, y) {ctx.p += `M ${rnd(x)} ${rnd(y)} `; return this;},
7-
l(x, y) {ctx.p += `L ${rnd(x)} ${rnd(y)} `; return this;},
8-
a(x, y, rad) {ctx.p += `A ${rnd(rad)} ${rnd(rad)} 0 0 1 ${rnd(x)} ${rnd(y)} `; return this;}
7+
m(x, y) {ctx.p += `M ${rndo(x)} ${rndo(y)} `; return this;},
8+
l(x, y) {ctx.p += `L ${rndo(x)} ${rndo(y)} `; return this;},
9+
a(x, y, rad) {ctx.p += `A ${rnd(rad)} ${rnd(rad)} 0 0 1 ${rndo(x)} ${rndo(y)} `; return this;}
910
};
1011
};
1112

@@ -81,57 +82,129 @@ const draw_mod = (qr, ctx, settings, width, row, col) => {
8182
const dark_sw = is_dark(row_s, col_w);
8283
const dark_w = is_dark(row, col_w);
8384

84-
ctx = wrap_ctx(ctx);
85-
8685
if (dark_center) {
8786
draw_dark(ctx, left, top, right, bottom, radius, !dark_n && !dark_w, !dark_n && !dark_e, !dark_s && !dark_e, !dark_s && !dark_w);
8887
} else {
8988
draw_light(ctx, left, top, right, bottom, radius, dark_n && dark_w && dark_nw, dark_n && dark_e && dark_ne, dark_s && dark_e && dark_se, dark_s && dark_w && dark_sw);
9089
}
9190
};
9291

93-
const draw_modules = (qr, ctx, settings) => {
92+
const create_path = (qr, settings) => {
9493
if (!qr) {
95-
return;
94+
return '';
9695
}
9796

97+
const ctx = {p: '', o: 0};
9898
const mod_count = qr.module_count;
99-
const mod_size = settings.size / mod_count;
99+
let mod_size = settings.size / mod_count;
100+
if (settings.crisp) {
101+
mod_size = Math.floor(mod_size);
102+
ctx.o = Math.floor((settings.size - mod_size * mod_count) / 2);
103+
}
100104

105+
const draw_ctx = create_draw_ctx(ctx);
101106
for (let row = 0; row < mod_count; row += 1) {
102107
for (let col = 0; col < mod_count; col += 1) {
103-
draw_mod(qr, ctx, settings, mod_size, row, col);
108+
draw_mod(qr, draw_ctx, settings, mod_size, row, col);
104109
}
105110
}
111+
112+
return ctx.p;
106113
};
107114

108-
const create_svg_qrcode = (qr, settings) => {
109-
const ctx = {p: ''};
115+
const add_label = (el, settings) => {
116+
console.warn('svg label not implemented yet', el, settings);
117+
const size = settings.size;
118+
const font = 'bold ' + settings.mSize * 0.01 * size + 'px ' + settings.fontname;
119+
120+
const {create_canvas, dpr} = require('./dom');
121+
const ratio = settings.ratio || dpr;
122+
const ctx = create_canvas(size, ratio).getContext('2d');
123+
ctx.strokeStyle = settings.back;
124+
ctx.lineWidth = settings.mSize * 0.01 * size * 0.1;
125+
ctx.fillStyle = settings.fontcolor;
126+
ctx.font = font;
127+
const w = ctx.measureText(settings.label).width;
128+
129+
const sh = settings.mSize * 0.01;
130+
const sw = w / size;
131+
const sl = (1 - sw) * settings.mPosX * 0.01;
132+
const st = (1 - sh) * settings.mPosY * 0.01;
133+
const x = sl * size;
134+
const y = st * size + 0.75 * settings.mSize * 0.01 * size;
135+
136+
const text_el = create_svg_el('text', {
137+
x,
138+
y
139+
});
140+
Object.assign(text_el.style, {
141+
font,
142+
fill: settings.fontcolor,
143+
'paint-order': 'stroke',
144+
stroke: settings.back,
145+
'stroke-width': ctx.lineWidth
146+
});
147+
148+
text_el.textContent = settings.label;
149+
el.appendChild(text_el);
150+
};
110151

111-
draw_modules(qr, ctx, settings);
112-
// draw_mode(ctx, settings);
152+
const add_image = (el, settings) => {
153+
const size = settings.size;
154+
const w = settings.image.naturalWidth || 1;
155+
const h = settings.image.naturalHeight || 1;
156+
const sh = settings.mSize * 0.01;
157+
const sw = sh * w / h;
158+
const sl = (1 - sw) * settings.mPosX * 0.01;
159+
const st = (1 - sh) * settings.mPosY * 0.01;
160+
const x = sl * size;
161+
const y = st * size;
162+
const iw = sw * size;
163+
const ih = sh * size;
164+
165+
const img_el = create_svg_el('image', {
166+
href: get_attr(settings.image, 'src'),
167+
x,
168+
y,
169+
width: iw,
170+
height: ih
171+
});
172+
el.appendChild(img_el);
173+
};
113174

175+
const create_svg_qrcode = (qr, settings) => {
114176
const size = settings.size;
115-
const svg_el = create_svg_el('svg');
116-
set_attr(svg_el, 'xmlns', 'http://www.w3.org/2000/svg');
117-
set_attr(svg_el, 'width', size);
118-
set_attr(svg_el, 'height', size);
119-
set_attr(svg_el, 'viewBox', `0 0 ${size} ${size}`);
177+
const mode = settings.mode;
178+
179+
const svg_el = create_svg_el('svg', {
180+
xmlns: 'http://www.w3.org/2000/svg',
181+
width: size,
182+
height: size,
183+
viewBox: `0 0 ${size} ${size}`
184+
});
120185
svg_el.style.width = `${size}px`;
121186
svg_el.style.height = `${size}px`;
122187

123-
const rect_el = create_svg_el('rect');
124-
set_attr(rect_el, 'x', 0);
125-
set_attr(rect_el, 'y', 0);
126-
set_attr(rect_el, 'width', size);
127-
set_attr(rect_el, 'height', size);
128-
set_attr(rect_el, 'fill', settings.back);
129-
svg_el.appendChild(rect_el);
130-
131-
const path_el = create_svg_el('path');
132-
set_attr(path_el, 'd', ctx.p);
133-
set_attr(path_el, 'fill', settings.fill);
134-
svg_el.appendChild(path_el);
188+
if (settings.back) {
189+
svg_el.appendChild(create_svg_el('rect', {
190+
x: 0,
191+
y: 0,
192+
width: size,
193+
height: size,
194+
fill: settings.back
195+
}));
196+
}
197+
198+
svg_el.appendChild(create_svg_el('path', {
199+
d: create_path(qr, settings),
200+
fill: settings.fill
201+
}));
202+
203+
if (mode === 'label') {
204+
add_label(svg_el, settings);
205+
} else if (mode === 'image') {
206+
add_image(svg_el, settings);
207+
}
135208

136209
return svg_el;
137210
};

src/lib/dom.js

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,42 @@ const dpr = win.devicePixelRatio || 1;
44

55
const SVG_NS = 'http://www.w3.org/2000/svg';
66

7-
const create = name => doc.createElement(name);
8-
const create_svg_el = name => doc.createElementNS(SVG_NS, name);
97
const get_attr = (el, key) => el.getAttribute(key);
10-
const set_attr = (el, key, value) => el.setAttribute(key, value);
8+
const set_attrs = (el, obj) => {
9+
Object.keys(obj || {}).forEach(key => {
10+
el.setAttribute(key, obj[key]);
11+
});
12+
return el;
13+
};
14+
15+
const create_el = (name, obj) => set_attrs(doc.createElement(name), obj);
16+
const create_svg_el = (name, obj) => set_attrs(doc.createElementNS(SVG_NS, name), obj);
1117

1218
const create_canvas = (size, ratio) => {
13-
const canvas = create('canvas');
14-
set_attr(canvas, 'width', size * ratio);
15-
set_attr(canvas, 'height', size * ratio);
19+
const canvas = create_el('canvas', {
20+
width: size * ratio,
21+
height: size * ratio
22+
});
1623
canvas.style.width = `${size}px`;
1724
canvas.style.height = `${size}px`;
1825
return canvas;
1926
};
2027

2128
const canvas_to_img = canvas => {
22-
const img = create('img');
23-
set_attr(img, 'crossorigin', 'anonymous');
24-
set_attr(img, 'src', canvas.toDataURL('image/png'));
25-
set_attr(img, 'width', get_attr(canvas, 'width'));
26-
set_attr(img, 'height', get_attr(canvas, 'height'));
29+
const img = create_el('img', {
30+
crossOrigin: 'anonymous',
31+
src: canvas.toDataURL('image/png'),
32+
width: get_attr(canvas, 'width'),
33+
height: get_attr(canvas, 'height')
34+
});
2735
img.style.width = canvas.style.width;
2836
img.style.height = canvas.style.height;
2937
return img;
3038
};
3139

3240
module.exports = {
3341
create_svg_el,
34-
set_attr,
42+
get_attr,
3543
create_canvas,
3644
canvas_to_img,
3745
dpr

0 commit comments

Comments
 (0)