Skip to content

Commit

Permalink
Add dotsOptions.roundSize
Browse files Browse the repository at this point in the history
  • Loading branch information
kozakdenys committed Oct 17, 2024
1 parent ec26837 commit 30643b9
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 26 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,12 @@ When QR type is svg, the image may not load in certain applications as it is sav

`options.dotsOptions` structure

Property|Type |Default Value|Description
--------|------------------------------------------------------------------------------|-------------|-------------------
color |string |`'#000'` |Color of QR dots
gradient|object | |Gradient of QR dots
type |string (`'rounded' 'dots' 'classy' 'classy-rounded' 'square' 'extra-rounded'`)|`'square'` |Style of QR dots
Property | Type | Default Value |Description
-------- |--------------------------------------------------------------------------------|---------------|-------------------
color | string | `'#000'` |Color of QR dots
gradient | object | |Gradient of QR dots
type | string (`'rounded' 'dots' 'classy' 'classy-rounded' 'square' 'extra-rounded'`) | `'square'` |Style of QR dots
roundSize| boolean | true |Whether to round dots size to integer. `true` value might create extra margin around qr code. If `false`, [shape-rendering="crispEdges"](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering#crispedges) will be applied to SVG element.

`options.backgroundOptions` structure

Expand Down
4 changes: 3 additions & 1 deletion src/core/QROptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface RequiredOptions extends Options {
type: DotType;
color: string;
gradient?: Gradient;
roundSize?: boolean;
};
backgroundOptions: {
round: number;
Expand Down Expand Up @@ -56,7 +57,8 @@ const defaultOptions: RequiredOptions = {
},
dotsOptions: {
type: "square",
color: "#000"
color: "#000",
roundSize: true,
},
backgroundOptions: {
round: 0,
Expand Down
46 changes: 26 additions & 20 deletions src/core/QRSVG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export default class QRSVG {
this._element.setAttribute("width", String(options.width));
this._element.setAttribute("height", String(options.height));
this._element.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
if (!options.dotsOptions.roundSize) {
this._element.setAttribute("shape-rendering", "crispEdges");
}
this._element.setAttribute("viewBox", `0 0 ${options.width} ${options.height}`);
this._defs = this._window.document.createElementNS("http://www.w3.org/2000/svg", "defs");
this._element.appendChild(this._defs);
Expand Down Expand Up @@ -87,7 +90,7 @@ export default class QRSVG {
const count = qr.getModuleCount();
const minSize = Math.min(this._options.width, this._options.height) - this._options.margin * 2;
const realQRSize = this._options.shape === shapeTypes.circle ? minSize / Math.sqrt(2) : minSize;
const dotSize = Math.floor(realQRSize / count);
const dotSize = this._roundSize(realQRSize / count);
let drawImageSize = {
hideXDots: 0,
hideYDots: 0,
Expand Down Expand Up @@ -115,6 +118,7 @@ export default class QRSVG {
});
}

console.log(this._image?.width, this._image?.height)
this.drawBackground();
this.drawDots((row: number, col: number): boolean => {
if (this._options.imageOptions.hideBackgroundDots) {
Expand Down Expand Up @@ -166,8 +170,8 @@ export default class QRSVG {
element.setAttribute("rx", String((height / 2) * options.backgroundOptions.round));
}

element.setAttribute("x", String((options.width - width) / 2));
element.setAttribute("y", String((options.height - height) / 2));
element.setAttribute("x", String(this._roundSize((options.width - width) / 2)));
element.setAttribute("y", String(this._roundSize((options.height - height) / 2)));
element.setAttribute("width", String(width));
element.setAttribute("height", String(height));

Expand Down Expand Up @@ -201,9 +205,9 @@ export default class QRSVG {

const minSize = Math.min(options.width, options.height) - options.margin * 2;
const realQRSize = options.shape === shapeTypes.circle ? minSize / Math.sqrt(2) : minSize;
const dotSize = Math.floor(realQRSize / count);
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
const dotSize = this._roundSize(realQRSize / count);
const xBeginning = this._roundSize((options.width - count * dotSize) / 2);
const yBeginning = this._roundSize((options.height - count * dotSize) / 2);
const dot = new QRDot({
svg: this._element,
type: options.dotsOptions.type,
Expand Down Expand Up @@ -252,12 +256,12 @@ export default class QRSVG {
}

if (options.shape === shapeTypes.circle) {
const additionalDots = Math.floor((minSize / dotSize - count) / 2);
const additionalDots = this._roundSize((minSize / dotSize - count) / 2);
const fakeCount = count + additionalDots * 2;
const xFakeBeginning = xBeginning - additionalDots * dotSize;
const yFakeBeginning = yBeginning - additionalDots * dotSize;
const fakeMatrix: number[][] = [];
const center = Math.floor(fakeCount / 2);
const center = this._roundSize(fakeCount / 2);

for (let row = 0; row < fakeCount; row++) {
fakeMatrix[row] = [];
Expand Down Expand Up @@ -322,11 +326,11 @@ export default class QRSVG {
const count = this._qr.getModuleCount();
const minSize = Math.min(options.width, options.height) - options.margin * 2;
const realQRSize = options.shape === shapeTypes.circle ? minSize / Math.sqrt(2) : minSize;
const dotSize = Math.floor(realQRSize / count);
const dotSize = this._roundSize(realQRSize / count);
const cornersSquareSize = dotSize * 7;
const cornersDotSize = dotSize * 3;
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
const xBeginning = this._roundSize((options.width - count * dotSize) / 2);
const yBeginning = this._roundSize((options.height - count * dotSize) / 2);

[
[0, 0, 0],
Expand Down Expand Up @@ -456,11 +460,6 @@ export default class QRSVG {

imageToBlob(): void {
if (!this._image) return;
// fix blurry svg
if (/(\.svg$)|(^data:image\/svg)/.test(this._options.image ?? "")) {
this._image.width = this._options.width;
this._image.height = this._options.height;
}
if (this._options.imageOptions.saveAsBlob && this._canvas) {
const ctx = this._canvas.getContext("2d");
if (ctx) {
Expand Down Expand Up @@ -519,10 +518,10 @@ export default class QRSVG {
dotSize: number;
}): Promise<void> {
const options = this._options;
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
const dx = xBeginning + options.imageOptions.margin + (count * dotSize - width) / 2;
const dy = yBeginning + options.imageOptions.margin + (count * dotSize - height) / 2;
const xBeginning = this._roundSize((options.width - count * dotSize) / 2);
const yBeginning = this._roundSize((options.height - count * dotSize) / 2);
const dx = xBeginning + this._roundSize(options.imageOptions.margin + (count * dotSize - width) / 2);
const dy = yBeginning + this._roundSize(options.imageOptions.margin + (count * dotSize - height) / 2);
const dw = width - options.imageOptions.margin * 2;
const dh = height - options.imageOptions.margin * 2;

Expand Down Expand Up @@ -635,4 +634,11 @@ export default class QRSVG {

this._element.appendChild(rect);
}

_roundSize = (value: number) => {
if (this._options.dotsOptions.roundSize) {
return Math.floor(value);
}
return value;
}
}

0 comments on commit 30643b9

Please sign in to comment.