Skip to content

Commit

Permalink
fix: svg generates with fillsand strokes [credits: DriesVanbilloen]
Browse files Browse the repository at this point in the history
  • Loading branch information
rizypb committed Feb 8, 2024
1 parent c7c320b commit a51cb3e
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 26 deletions.
16 changes: 16 additions & 0 deletions src/core/QRCodeStyling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ export default class QRCodeStyling {
return "";
}

async getRawData(extension: Extension = "png"): Promise<Blob | null> {
if (!this._qr) throw "QR code is empty";
const element = await this._getQRStylingElement();

if (extension.toLowerCase() === "svg") {
const serializer = new XMLSerializer();
const source = serializer.serializeToString((element as unknown as QRSVG).getElement());

return new Blob(['<?xml version="1.0" standalone="no"?>\r\n' + source], { type: "image/svg+xml" });
} else {
return new Promise((resolve) =>
(element as unknown as QRCanvas).getCanvas().toBlob(resolve, `image/${extension}`, 1)
);
}
}

async download(downloadOptions?: Partial<DownloadOptions>): Promise<void> {
if (!this._drawingPromise) return;

Expand Down
104 changes: 78 additions & 26 deletions src/core/QRSVG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ const dotMask = [

export default class QRSVG {
_element: SVGElement;
_style: SVGStyleElement;
_defs: SVGElement;
_dotsClipPath?: SVGElement;
_cornersSquareClipPath?: SVGElement;
_cornersDotClipPath?: SVGElement;
_dots?: SVGElement;
_cornerSquares?: SVGElement;
_corners?: SVGElement;
_cornerDots?: SVGElement;
_options: RequiredOptions;
_qr?: QRCode;
_image?: HTMLImageElement;
Expand All @@ -43,8 +48,7 @@ export default class QRSVG {
this._element.setAttribute("width", String(options.width));
this._element.setAttribute("height", String(options.height));
this._defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
this._element.appendChild(this._defs);

this._style = document.createElementNS("http://www.w3.org/2000/svg", "style");
this._options = options;
}

Expand All @@ -65,6 +69,8 @@ export default class QRSVG {
this._element = oldElement.cloneNode(false) as SVGElement;
oldElement?.parentNode?.replaceChild(this._element, oldElement);
this._defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
this._style = document.createElementNS("http://www.w3.org/2000/svg", "style");
this._element.appendChild(this._style);
this._element.appendChild(this._defs);
}

Expand Down Expand Up @@ -97,6 +103,8 @@ export default class QRSVG {
dotSize
});
}
this._element.appendChild(this._style);
this._element.appendChild(this._defs);

this.clear();
this.drawBackground();
Expand Down Expand Up @@ -137,7 +145,7 @@ export default class QRSVG {
const gradientOptions = options.backgroundOptions?.gradient;
const color = options.backgroundOptions?.color;

if (gradientOptions || color) {
if (gradientOptions) {
this._createColor({
options: gradientOptions,
color: color,
Expand All @@ -148,6 +156,11 @@ export default class QRSVG {
width: options.width,
name: "background-color"
});
} else if (options.backgroundOptions?.color) {
this._createStyle({
color: color,
name: "background-color"
});
}
}
}
Expand All @@ -169,21 +182,30 @@ export default class QRSVG {
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
const dot = new QRDot({ svg: this._element, type: options.dotsOptions.type });

this._dotsClipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
this._dotsClipPath.setAttribute("id", "clip-path-dot-color");
this._defs.appendChild(this._dotsClipPath);

this._createColor({
options: options.dotsOptions?.gradient,
color: options.dotsOptions.color,
additionalRotation: 0,
x: xBeginning,
y: yBeginning,
height: count * dotSize,
width: count * dotSize,
name: "dot-color"
});
if (options.dotsOptions?.gradient) {
this._dotsClipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
this._dotsClipPath.setAttribute("id", "clip-path-dot-color");
this._defs.appendChild(this._dotsClipPath);

this._createColor({
options: options.dotsOptions?.gradient,
color: options.dotsOptions.color,
additionalRotation: 0,
x: xBeginning,
y: yBeginning,
height: count * dotSize,
width: count * dotSize,
name: "dot-color"
});
} else if (options.dotsOptions?.color) {
this._dots = document.createElementNS("http://www.w3.org/2000/svg", "g");
this._dots.setAttribute("class", "dot-color");
this._element.appendChild(this._dots);
this._createStyle({
color: options.dotsOptions.color,
name: "dot-color"
});
}

for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
Expand All @@ -207,6 +229,8 @@ export default class QRSVG {

if (dot._element && this._dotsClipPath) {
this._dotsClipPath.appendChild(dot._element);
} else if (dot._element && this._dots) {
this._dots.appendChild(dot._element);
}
}
}
Expand Down Expand Up @@ -242,7 +266,7 @@ export default class QRSVG {
let cornersSquareClipPath = this._dotsClipPath;
let cornersDotClipPath = this._dotsClipPath;

if (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) {
if (options.cornersSquareOptions?.gradient) {
cornersSquareClipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
cornersSquareClipPath.setAttribute("id", `clip-path-corners-square-color-${column}-${row}`);
this._defs.appendChild(cornersSquareClipPath);
Expand All @@ -258,15 +282,25 @@ export default class QRSVG {
width: cornersSquareSize,
name: `corners-square-color-${column}-${row}`
});
} else {
this._cornerSquares = document.createElementNS("http://www.w3.org/2000/svg", "g");
this._cornerSquares.setAttribute("class", `corners-square-color-${column}-${row}`);
this._element.appendChild(this._cornerSquares);
this._createStyle({
color: options.cornersSquareOptions?.color,
name: `corners-square-color-${column}-${row}`
});
}

if (options.cornersSquareOptions?.type) {
const cornersSquare = new QRCornerSquare({ svg: this._element, type: options.cornersSquareOptions.type });

cornersSquare.draw(x, y, cornersSquareSize, rotation);

if (cornersSquare._element && cornersSquareClipPath) {
if (options.cornersSquareOptions?.gradient && cornersSquare._element && cornersSquareClipPath) {
cornersSquareClipPath.appendChild(cornersSquare._element);
} else if (cornersSquare._element && this._cornerSquares) {
this._cornerSquares.appendChild(cornersSquare._element);
}
} else {
const dot = new QRDot({ svg: this._element, type: options.dotsOptions.type });
Expand All @@ -284,14 +318,16 @@ export default class QRSVG {
(xOffset: number, yOffset: number): boolean => !!squareMask[i + xOffset]?.[j + yOffset]
);

if (dot._element && cornersSquareClipPath) {
cornersSquareClipPath.appendChild(dot._element);
if (dot._element && this._cornersSquareClipPath) {
this._cornersSquareClipPath.appendChild(dot._element);
} else if (dot._element && this._cornerSquares) {
this._cornerSquares.appendChild(dot._element);
}
}
}
}

if (options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) {
if (options.cornersDotOptions?.gradient) {
cornersDotClipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
cornersDotClipPath.setAttribute("id", `clip-path-corners-dot-color-${column}-${row}`);
this._defs.appendChild(cornersDotClipPath);
Expand All @@ -307,15 +343,25 @@ export default class QRSVG {
width: cornersDotSize,
name: `corners-dot-color-${column}-${row}`
});
} else {
this._cornerDots = document.createElementNS("http://www.w3.org/2000/svg", "g");
this._cornerDots.setAttribute("class", `corners-dot-color-${column}-${row}`);
this._element.appendChild(this._cornerDots);
this._createStyle({
color: options.cornersDotOptions?.color,
name: `corners-dot-color-${column}-${row}`
});
}

if (options.cornersDotOptions?.type) {
const cornersDot = new QRCornerDot({ svg: this._element, type: options.cornersDotOptions.type });

cornersDot.draw(x + dotSize * 2, y + dotSize * 2, cornersDotSize, rotation);

if (cornersDot._element && cornersDotClipPath) {
if (options.cornersDotOptions?.gradient && cornersDot._element && cornersDotClipPath) {
cornersDotClipPath.appendChild(cornersDot._element);
} else if (cornersDot._element && this._cornerDots) {
this._cornerDots.appendChild(cornersDot._element);
}
} else {
const dot = new QRDot({ svg: this._element, type: options.dotsOptions.type });
Expand All @@ -333,8 +379,10 @@ export default class QRSVG {
(xOffset: number, yOffset: number): boolean => !!dotMask[i + xOffset]?.[j + yOffset]
);

if (dot._element && cornersDotClipPath) {
cornersDotClipPath.appendChild(dot._element);
if (dot._element && this._cornersDotClipPath) {
this._cornersDotClipPath.appendChild(dot._element);
} else if (dot._element && this._cornerDots) {
this._cornerDots.appendChild(dot._element);
}
}
}
Expand Down Expand Up @@ -487,4 +535,8 @@ export default class QRSVG {

this._element.appendChild(rect);
}

_createStyle({ color, name }: { color?: string; name: string }): void {
this._style.innerHTML += `.${name}{ fill: ${color}; }`;
}
}

0 comments on commit a51cb3e

Please sign in to comment.