From e70e16922d3dc13fa5ade2cf0cdb699cd12af27f Mon Sep 17 00:00:00 2001 From: MILAD RAZA <56252911+milad-raza-developer@users.noreply.github.com> Date: Mon, 12 Aug 2024 02:31:37 -0700 Subject: [PATCH] add eyeframes and eyeballs --- src/.DS_Store | Bin 0 -> 6148 bytes src/assets/.DS_Store | Bin 6148 -> 6148 bytes src/constants/cornerDotTypes.ts | 12 +- src/constants/cornerSquareTypes.ts | 10 +- src/constants/dotTypes.ts | 3 +- src/core/QRCanvas.ts | 46 +- src/core/QRCodeStyling.test.js | 59 +- src/core/QRCodeStyling.ts | 23 +- src/core/QROptions.ts | 2 - src/core/QRSVG.ts | 108 +--- src/figures/.DS_Store | Bin 0 -> 6148 bytes src/figures/cornerDot/canvas/QRCornerDot.ts | 441 +++++++++++++- src/figures/cornerDot/svg/QRCornerDot.ts | 557 ++++++++++++++++- .../cornerSquare/svg/QRCornerSquare.ts | 560 +++++++++++++++++- src/figures/dot/svg/QRDot.ts | 18 +- src/index.html | 107 ++-- src/types/index.ts | 37 +- 17 files changed, 1648 insertions(+), 335 deletions(-) create mode 100644 src/.DS_Store create mode 100644 src/figures/.DS_Store diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..351cd19ec92be2eb4bc877c7dc6d595ac8bcb5c6 GIT binary patch literal 6148 zcmeHLJxc>Y5S`VFMgCzi)n+ej!e2az>PL55j|bV9 z_OCI~nXyh3jxhzTP>VtufXN7q1{pTA@tz-La(cK*IOWXO52wt2jH-U;gE@%YB4*?=JUon z6!6W2xO!ZZS;bG*PYUD@Q_2cjQmlS2SSa0b1dep2xnOOCch^Yqo5q5pv zC+EhnXR{U86uRCi;1qBQBnt5Q;G;1H8e@fW=|Crs06-6JX}FhbB+zFEFwht)ga;;6 zDo~{geZ&wd9e!WO1sY?8DxHL^jCpirp-(76uh7Dm;Uofuu6GJJ1#ATt)yER=|A({B z|8|o5

lU%#{MdtJbO&Jd)m9GY`jmt&dhmW8=73p-e%iw_|z3TQUEyAPr+a-v9%R Tu|jxY?uUSs!F5i7KULrhVMxwN literal 0 HcmV?d00001 diff --git a/src/assets/.DS_Store b/src/assets/.DS_Store index 71d2fbc179f1d46f098ee0c29c01f826e2c4f1d2..d9337fccc11364611cb20ec1d46cac9cf6616b7e 100644 GIT binary patch delta 194 zcmZoMXfc=|#>B)qu~2NHo+2aL#DLw46_^+q*(UQazNybiHw;eB&n;j81C7-{iiM$s zA(f$+p(Hoo#U&{xKM5$t@wPF+Z->Y+M^yO~yz&JZ$YxIf*#I}YEVw8yCqHlVf5r(c io7p+|Ie;$QEXeeoc{0CB`mu~2NHo+2aD#DLwC4MbQb^E18NT);e?Wn)7H<7Rdaeh#3T&5g|8 WnJ4p$SaL7`0V4wg)8+t?EzAIu8xdgu diff --git a/src/constants/cornerDotTypes.ts b/src/constants/cornerDotTypes.ts index f5c7b5bf..f6b548db 100644 --- a/src/constants/cornerDotTypes.ts +++ b/src/constants/cornerDotTypes.ts @@ -2,5 +2,15 @@ import { CornerDotTypes } from "../types"; export default { dot: "dot", - square: "square" + square: "square", + star: "star", + plus: "plus", + squareRounded: "square-rounded", + rightBottomSquare: "square-right-bottom", + leaf: "leaf", + leftTopCircle: "circle-left-top", + rightBottomCircle: "circle-right-bottom", + diamond: "diamond", + cross: "cross", + rhombus: "rhombus" } as CornerDotTypes; diff --git a/src/constants/cornerSquareTypes.ts b/src/constants/cornerSquareTypes.ts index ac67ec28..8d1db1af 100644 --- a/src/constants/cornerSquareTypes.ts +++ b/src/constants/cornerSquareTypes.ts @@ -3,5 +3,13 @@ import { CornerSquareTypes } from "../types"; export default { dot: "dot", square: "square", - extraRounded: "extra-rounded" + dottedSquare:"dotted-square", + extraRounded: "extra-rounded", + rightBottomSquare: "right-bottom-square", + leftTopSquare: "left-top-square", + leftTopCircle: "circle-left-top", + rightBottomCircle: "circle-right-bottom", + circleInSquare: "circle-in-square", + peanut: "peanut", + // paragonal: "paragonal", } as CornerSquareTypes; diff --git a/src/constants/dotTypes.ts b/src/constants/dotTypes.ts index 26d4f498..3e062313 100644 --- a/src/constants/dotTypes.ts +++ b/src/constants/dotTypes.ts @@ -6,5 +6,6 @@ export default { classy: "classy", classyRounded: "classy-rounded", square: "square", - extraRounded: "extra-rounded" + extraRounded: "extra-rounded", + star: "star", } as DotTypes; diff --git a/src/core/QRCanvas.ts b/src/core/QRCanvas.ts index 8426983f..d76b67fa 100644 --- a/src/core/QRCanvas.ts +++ b/src/core/QRCanvas.ts @@ -5,7 +5,7 @@ import QRCornerSquare from "../figures/cornerSquare/canvas/QRCornerSquare"; import QRCornerDot from "../figures/cornerDot/canvas/QRCornerDot"; import { RequiredOptions } from "./QROptions"; import gradientTypes from "../constants/gradientTypes"; -import { QRCode, Gradient, FilterFunction, Canvas } from "../types"; +import { QRCode, Gradient, FilterFunction } from "../types"; const squareMask = [ [1, 1, 1, 1, 1, 1, 1], @@ -28,18 +28,14 @@ const dotMask = [ ]; export default class QRCanvas { - _canvas: Canvas; + _canvas: HTMLCanvasElement; _options: RequiredOptions; _qr?: QRCode; _image?: HTMLImageElement; //TODO don't pass all options to this class constructor(options: RequiredOptions) { - if (options.nodeCanvas?.createCanvas) { - this._canvas = options.nodeCanvas.createCanvas(options.width, options.height); - } else { - this._canvas = document.createElement("canvas"); - } + this._canvas = document.createElement("canvas"); this._canvas.width = options.width; this._canvas.height = options.height; this._options = options; @@ -57,7 +53,7 @@ export default class QRCanvas { return this._canvas.height; } - getCanvas(): Canvas { + getCanvas(): HTMLCanvasElement { return this._canvas; } @@ -361,37 +357,21 @@ export default class QRCanvas { loadImage(): Promise { return new Promise((resolve, reject) => { const options = this._options; + const image = new Image(); if (!options.image) { return reject("Image is not defined"); } - if (options.nodeCanvas?.loadImage) { - options.nodeCanvas - .loadImage(options.image) - .then((image: HTMLImageElement) => { - // fix blurry svg - if (/(\.svg$)|(^data:image\/svg)/.test(options.image ?? "")) { - image.width = this._options.width; - image.height = this._options.height; - } - this._image = image; - resolve(); - }) - .catch(reject); - } else { - const image = new Image(); - - if (typeof options.imageOptions.crossOrigin === "string") { - image.crossOrigin = options.imageOptions.crossOrigin; - } - - this._image = image; - image.onload = (): void => { - resolve(); - }; - image.src = options.image; + if (typeof options.imageOptions.crossOrigin === "string") { + image.crossOrigin = options.imageOptions.crossOrigin; } + + this._image = image; + image.onload = (): void => { + resolve(); + }; + image.src = options.image; }); } diff --git a/src/core/QRCodeStyling.test.js b/src/core/QRCodeStyling.test.js index 80714a2e..d71876a1 100644 --- a/src/core/QRCodeStyling.test.js +++ b/src/core/QRCodeStyling.test.js @@ -1,15 +1,13 @@ import QRCodeStyling from "./QRCodeStyling"; import fs from "fs"; import path from "path"; -import nodeCanvas from "canvas"; -import { JSDOM } from "jsdom"; describe("Test QRCodeStyling class", () => { beforeAll(() => { global.document.body.innerHTML = "

"; }); - it("The README example should work correctly", (done) => { + it("The README example should work correctly", done => { const expectedQRCodeFile = fs.readFileSync( path.resolve(__dirname, "../assets/test/image_from_readme.png"), "base64" @@ -39,59 +37,4 @@ describe("Test QRCodeStyling class", () => { done(); }); }); - - it("Compatible with node-canvas", (done) => { - const expectedQRCodeFile = fs.readFileSync( - path.resolve(__dirname, "../assets/test/image_from_readme.png"), - "base64" - ); - const qrCode = new QRCodeStyling({ - nodeCanvas, - width: 300, - height: 300, - data: "TEST", - image: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAEUlEQVR42mNk+M+AARiHsiAAcCIKAYwFoQ8AAAAASUVORK5CYII=", - dotsOptions: { - color: "#4267b2", - type: "rounded" - }, - backgroundOptions: { - color: "#e9ebee" - } - }); - qrCode.getRawData("png").then((buffer) => { - const uri = `data:image/png;base64,${buffer.toString("base64")}`; - expect(uri).toEqual(expect.stringContaining(expectedQRCodeFile)); - done(); - }); - }); - - it("Compatible with jsdom", (done) => { - const expectedQRCodeFile = fs.readFileSync( - path.resolve(__dirname, "../assets/test/image_from_readme.svg"), - "base64" - ); - const qrCode = new QRCodeStyling({ - jsdom: JSDOM, - type: "svg", - width: 300, - height: 300, - data: "TEST", - image: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAEUlEQVR42mNk+M+AARiHsiAAcCIKAYwFoQ8AAAAASUVORK5CYII=", - dotsOptions: { - color: "#4267b2", - type: "rounded" - }, - backgroundOptions: { - color: "#e9ebee" - } - }); - qrCode.getRawData("svg").then((buffer) => { - const svgString = buffer.toString("base64"); - expect(svgString).toEqual(expect.stringContaining(expectedQRCodeFile)); - done(); - }); - }); }); diff --git a/src/core/QRCodeStyling.ts b/src/core/QRCodeStyling.ts index 8c9c4ccc..3454d09e 100644 --- a/src/core/QRCodeStyling.ts +++ b/src/core/QRCodeStyling.ts @@ -113,35 +113,24 @@ export default class QRCodeStyling { this._container = container; } - async getRawData(extension: Extension = "png"): Promise { + async getRawData(extension: Extension = "png"): Promise { if (!this._qr) throw "QR code is empty"; const element = await this._getQRStylingElement(extension); if (extension.toLowerCase() === "svg") { - const serializer = new ((element as unknown) as QRSVG)._window.XMLSerializer(); + const serializer = new XMLSerializer(); const source = serializer.serializeToString(((element as unknown) as QRSVG).getElement()); - const svgString = `\r\n${source}`; - if (typeof Blob !== "undefined" && !this._options.jsdom) { - return new Blob([svgString], { type: "image/svg+xml" }); - } else { - return Buffer.from(svgString); - } + return new Blob(['\r\n' + source], { type: "image/svg+xml" }); } else { - return new Promise((resolve) => { - const canvas = ((element as unknown) as QRCanvas).getCanvas(); - if (canvas.toBuffer) { - resolve(canvas.toBuffer(`image/${extension}`)); - } else { - canvas.toBlob(resolve, `image/${extension}`, 1); - } - }); + return new Promise((resolve) => + ((element as unknown) as QRCanvas).getCanvas().toBlob(resolve, `image/${extension}`, 1) + ); } } async download(downloadOptions?: Partial | string): Promise { if (!this._qr) throw "QR code is empty"; - if (typeof Blob === "undefined") throw "Cannot download in Node.js, call getRawData instead."; let extension = "png" as Extension; let name = "qr"; diff --git a/src/core/QROptions.ts b/src/core/QROptions.ts index a2ffe250..dca57f86 100644 --- a/src/core/QROptions.ts +++ b/src/core/QROptions.ts @@ -15,7 +15,6 @@ export interface RequiredOptions extends Options { errorCorrectionLevel: ErrorCorrectionLevel; }; imageOptions: { - saveAsBlob: boolean; hideBackgroundDots: boolean; imageSize: number; crossOrigin?: string; @@ -44,7 +43,6 @@ const defaultOptions: RequiredOptions = { errorCorrectionLevel: errorCorrectionLevels.Q }, imageOptions: { - saveAsBlob: false, hideBackgroundDots: true, imageSize: 0.4, crossOrigin: undefined, diff --git a/src/core/QRSVG.ts b/src/core/QRSVG.ts index 29bd6ad7..93656a0a 100644 --- a/src/core/QRSVG.ts +++ b/src/core/QRSVG.ts @@ -5,9 +5,7 @@ import QRCornerSquare from "../figures/cornerSquare/svg/QRCornerSquare"; import QRCornerDot from "../figures/cornerDot/svg/QRCornerDot"; import { RequiredOptions } from "./QROptions"; import gradientTypes from "../constants/gradientTypes"; -import { QRCode, FilterFunction, Gradient, Window, Canvas } from "../types"; - -declare const window: Window; +import { QRCode, FilterFunction, Gradient } from "../types"; const squareMask = [ [1, 1, 1, 1, 1, 1, 1], @@ -30,8 +28,6 @@ const dotMask = [ ]; export default class QRSVG { - _canvas?: Canvas; - _window: Window; _element: SVGElement; _defs: SVGElement; _dotsClipPath?: SVGElement; @@ -40,32 +36,15 @@ export default class QRSVG { _options: RequiredOptions; _qr?: QRCode; _image?: HTMLImageElement; - _imageUri?: string; //TODO don't pass all options to this class constructor(options: RequiredOptions) { - if (options.jsdom) { - this._window = new options.jsdom("", { resources: "usable" }).window; - } else { - this._window = window; - } - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "svg"); + this._element = document.createElementNS("http://www.w3.org/2000/svg", "svg"); this._element.setAttribute("width", String(options.width)); this._element.setAttribute("height", String(options.height)); - this._defs = this._window.document.createElementNS("http://www.w3.org/2000/svg", "defs"); + this._defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); this._element.appendChild(this._defs); - if (options.imageOptions.saveAsBlob) { - if (options.nodeCanvas?.createCanvas) { - this._canvas = options.nodeCanvas.createCanvas(options.width, options.height); - } else { - this._canvas = document.createElement("canvas"); - } - this._canvas.width = options.width; - this._canvas.height = options.height; - } - this._imageUri = options.image; - this._options = options; } @@ -85,7 +64,7 @@ export default class QRSVG { const oldElement = this._element; this._element = oldElement.cloneNode(false) as SVGElement; oldElement?.parentNode?.replaceChild(this._element, oldElement); - this._defs = this._window.document.createElementNS("http://www.w3.org/2000/svg", "defs"); + this._defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); this._element.appendChild(this._defs); } @@ -106,7 +85,6 @@ export default class QRSVG { //We need it to get image size await this.loadImage(); if (!this._image) return; - this.imageToBlob(); const { imageOptions, qrOptions } = this._options; const coverLevel = imageOptions.imageSize * errorCorrectionPercents[qrOptions.errorCorrectionLevel]; const maxHiddenDots = Math.floor(coverLevel * count * count); @@ -190,13 +168,9 @@ export default class QRSVG { const dotSize = Math.floor(minSize / count); 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, - window: this._window - }); + const dot = new QRDot({ svg: this._element, type: options.dotsOptions.type }); - this._dotsClipPath = this._window.document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); + this._dotsClipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); this._dotsClipPath.setAttribute("id", "clip-path-dot-color"); this._defs.appendChild(this._dotsClipPath); @@ -269,7 +243,7 @@ export default class QRSVG { let cornersDotClipPath = this._dotsClipPath; if (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) { - cornersSquareClipPath = this._window.document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); + cornersSquareClipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); cornersSquareClipPath.setAttribute("id", `clip-path-corners-square-color-${column}-${row}`); this._defs.appendChild(cornersSquareClipPath); this._cornersSquareClipPath = this._cornersDotClipPath = cornersDotClipPath = cornersSquareClipPath; @@ -287,11 +261,7 @@ export default class QRSVG { } if (options.cornersSquareOptions?.type) { - const cornersSquare = new QRCornerSquare({ - svg: this._element, - type: options.cornersSquareOptions.type, - window: this._window - }); + const cornersSquare = new QRCornerSquare({ svg: this._element, type: options.cornersSquareOptions.type }); cornersSquare.draw(x, y, cornersSquareSize, rotation); @@ -299,11 +269,7 @@ export default class QRSVG { cornersSquareClipPath.appendChild(cornersSquare._element); } } else { - const dot = new QRDot({ - svg: this._element, - type: options.dotsOptions.type, - window: this._window - }); + const dot = new QRDot({ svg: this._element, type: options.dotsOptions.type }); for (let i = 0; i < squareMask.length; i++) { for (let j = 0; j < squareMask[i].length; j++) { @@ -326,7 +292,7 @@ export default class QRSVG { } if (options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) { - cornersDotClipPath = this._window.document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); + cornersDotClipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"); cornersDotClipPath.setAttribute("id", `clip-path-corners-dot-color-${column}-${row}`); this._defs.appendChild(cornersDotClipPath); this._cornersDotClipPath = cornersDotClipPath; @@ -344,11 +310,7 @@ export default class QRSVG { } if (options.cornersDotOptions?.type) { - const cornersDot = new QRCornerDot({ - svg: this._element, - type: options.cornersDotOptions.type, - window: this._window - }); + const cornersDot = new QRCornerDot({ svg: this._element, type: options.cornersDotOptions.type }); cornersDot.draw(x + dotSize * 2, y + dotSize * 2, cornersDotSize, rotation); @@ -356,11 +318,7 @@ export default class QRSVG { cornersDotClipPath.appendChild(cornersDot._element); } } else { - const dot = new QRDot({ - svg: this._element, - type: options.dotsOptions.type, - window: this._window - }); + const dot = new QRDot({ svg: this._element, type: options.dotsOptions.type }); for (let i = 0; i < dotMask.length; i++) { for (let j = 0; j < dotMask[i].length; j++) { @@ -384,38 +342,10 @@ 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) { - ctx.drawImage(this._image, 0, 0, this._canvas.width, this._canvas.height); - this._imageUri = this._canvas.toDataURL("image/png"); - console.log(this._imageUri); - } - } - } - loadImage(): Promise { return new Promise((resolve, reject) => { const options = this._options; - - if (options.nodeCanvas?.loadImage && options.image) { - options.nodeCanvas - .loadImage(options.image) - .then((image: HTMLImageElement) => { - this._image = image; - resolve(); - }) - .catch(reject); - return; - } - const image = new this._window.Image(); + const image = new Image(); if (!options.image) { return reject("Image is not defined"); @@ -452,8 +382,8 @@ export default class QRSVG { const dw = width - options.imageOptions.margin * 2; const dh = height - options.imageOptions.margin * 2; - const image = this._window.document.createElementNS("http://www.w3.org/2000/svg", "image"); - image.setAttribute("href", this._imageUri || ""); + const image = document.createElementNS("http://www.w3.org/2000/svg", "image"); + image.setAttribute("href", options.image || ""); image.setAttribute("x", String(dx)); image.setAttribute("y", String(dy)); image.setAttribute("width", `${dw}px`); @@ -482,7 +412,7 @@ export default class QRSVG { name: string; }): void { const size = width > height ? width : height; - const rect = this._window.document.createElementNS("http://www.w3.org/2000/svg", "rect"); + const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); rect.setAttribute("x", String(x)); rect.setAttribute("y", String(y)); rect.setAttribute("height", String(height)); @@ -492,7 +422,7 @@ export default class QRSVG { if (options) { let gradient: SVGElement; if (options.type === gradientTypes.radial) { - gradient = this._window.document.createElementNS("http://www.w3.org/2000/svg", "radialGradient"); + gradient = document.createElementNS("http://www.w3.org/2000/svg", "radialGradient"); gradient.setAttribute("id", name); gradient.setAttribute("gradientUnits", "userSpaceOnUse"); gradient.setAttribute("fx", String(x + width / 2)); @@ -533,7 +463,7 @@ export default class QRSVG { x1 = x1 - width / 2 / Math.tan(rotation); } - gradient = this._window.document.createElementNS("http://www.w3.org/2000/svg", "linearGradient"); + gradient = document.createElementNS("http://www.w3.org/2000/svg", "linearGradient"); gradient.setAttribute("id", name); gradient.setAttribute("gradientUnits", "userSpaceOnUse"); gradient.setAttribute("x1", String(Math.round(x0))); @@ -543,7 +473,7 @@ export default class QRSVG { } options.colorStops.forEach(({ offset, color }: { offset: number; color: string }) => { - const stop = this._window.document.createElementNS("http://www.w3.org/2000/svg", "stop"); + const stop = document.createElementNS("http://www.w3.org/2000/svg", "stop"); stop.setAttribute("offset", `${100 * offset}%`); stop.setAttribute("stop-color", color); gradient.appendChild(stop); diff --git a/src/figures/.DS_Store b/src/figures/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c3c2041b32f2f9f109829c8eea2ed61dcbb0fcf9 GIT binary patch literal 6148 zcmeHKu}%U(5S;}Ih!hkSmir0PTb$%^zMZ*O;I_uboY!xE7jZSo<}fQY(q##Rr_4&!@C6?_y)FZ!Z%32ycbjtgEyOIdkL^s% zDSNLtXP_x;(M}pRx0;Yf|P$|IQ2M=dV6idPI=|B^% z0Kg80gP}j*4$vzmilrcCU`|qjlIrw|;Upd7UgHwQQc%*#>E*-e&Q5PAF6@r=eF!I) z2wH0jm;!YL+VVKy`hT(i{$EeBCsV)__*V+JPMW17ypq<|#>;W7_3$yAjpIteDg~WT giV@4D_yisd { context.arc(0, 0, size / 2, 0, Math.PI * 2); - } + }, }); } @@ -57,7 +103,338 @@ export default class QRCornerDot { ...args, draw: () => { context.rect(-size / 2, -size / 2, size, size); - } + }, + }); + } + + _basicRoundedSquare(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + const radius = size / 5; // Adjust the radius as needed + + this._rotateFigure({ + ...args, + draw: () => { + const halfSize = size / 2; + context.beginPath(); + context.moveTo(-halfSize + radius, -halfSize); + context.lineTo(halfSize - radius, -halfSize); + context.arcTo( + halfSize, + -halfSize, + halfSize, + -halfSize + radius, + radius + ); + context.lineTo(halfSize, halfSize - radius); + context.arcTo(halfSize, halfSize, halfSize - radius, halfSize, radius); + context.lineTo(-halfSize + radius, halfSize); + context.arcTo( + -halfSize, + halfSize, + -halfSize, + halfSize - radius, + radius + ); + context.lineTo(-halfSize, -halfSize + radius); + context.arcTo( + -halfSize, + -halfSize, + -halfSize + radius, + -halfSize, + radius + ); + context.closePath(); + }, + }); + } + + _basicRoundedSquareRightBottomEdge(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + const radius = size / 5; // Adjust the radius as needed + + this._rotateFigure({ + ...args, + draw: () => { + const halfSize = size / 2; + context.beginPath(); + context.moveTo(-halfSize + radius, -halfSize); + context.lineTo(halfSize - radius, -halfSize); + context.arcTo( + halfSize, + -halfSize, + halfSize, + -halfSize + radius, + radius + ); + context.lineTo(halfSize, -halfSize + radius); + context.lineTo(halfSize, halfSize); + context.lineTo(halfSize - radius, halfSize); + context.arcTo( + halfSize - radius, + halfSize, + halfSize - radius, + halfSize - radius, + radius + ); + context.lineTo(-halfSize + radius, halfSize); + context.arcTo( + -halfSize, + halfSize, + -halfSize, + halfSize - radius, + radius + ); + context.lineTo(-halfSize, -halfSize + radius); + context.arcTo( + -halfSize, + -halfSize, + -halfSize + radius, + -halfSize, + radius + ); + context.closePath(); + }, + }); + } + + _basicLeaf(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + const extension = size / 4; // Adjust the extension as needed + const cornerRadius = size / 10; // Adjust the corner radius as needed + + this._rotateFigure({ + ...args, + draw: () => { + context.beginPath(); + context.moveTo(-size / 2.2 - extension, -size / 2.2 - extension); // Start at the top left corner + context.lineTo(size / 2.2, -size / 2.2); // Draw top edge + context.lineTo(size / 2.2, size / 2.2); // Draw right edge + context.lineTo(-size / 2.2, size / 2.2); // Draw bottom edge + + // Draw rounded left top corner + context.arc( + -size / 2.2 - extension + cornerRadius, + -size / 2.2 + cornerRadius - extension, + cornerRadius, + Math.PI, + Math.PI * 1.5 + ); + + context.closePath(); + + context.fill(); + }, + }); + } + + _basicCircleLeftTopEdge(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + const radius = size / 2; // Radius of the rounded corners + const cornerSize = radius / 32; // Size of the flat top-left corner + + this._rotateFigure({ + ...args, + draw: () => { + const halfSize = size / 2; + + // Draw the full rounded square + context.beginPath(); + + // Move to the starting point of the top-right corner + context.moveTo(-halfSize + cornerSize, -halfSize); + + // Draw the top-right corner + context.lineTo(halfSize - radius, -halfSize); + context.arcTo( + halfSize, + -halfSize, + halfSize, + -halfSize + radius, + radius + ); + + // Draw the right side + context.lineTo(halfSize, halfSize - radius); + context.arcTo(halfSize, halfSize, halfSize - radius, halfSize, radius); + + // Draw the bottom side + context.lineTo(-halfSize + radius, halfSize); + context.arcTo( + -halfSize, + halfSize, + -halfSize, + halfSize - radius, + radius + ); + + // Draw the left side + context.lineTo(-halfSize, -halfSize + cornerSize); + + // Draw the flat top-left corner + context.lineTo(-halfSize + cornerSize, -halfSize); + + context.closePath(); + // context.fillStyle = '#000'; // Set color for the rounded square + context.fill(); + }, + }); + } + + _basicCircleRightBottomEdge(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + const radius = size / 2; // Radius of the rounded corners + const cornerSize = radius / 32; // Size of the flat right-bottom corner + + this._rotateFigure({ + ...args, + draw: () => { + const halfSize = size / 2; + + // Draw the full rounded square + context.beginPath(); + + // Move to the starting point of the top-left corner + context.moveTo(-halfSize, -halfSize + cornerSize); + + // Draw the top-left corner + context.lineTo(-halfSize + radius, -halfSize); + context.arcTo( + -halfSize, + -halfSize, + -halfSize, + -halfSize + radius, + radius + ); + + // Draw the top side + context.lineTo(halfSize - radius, -halfSize); + context.arcTo( + halfSize, + -halfSize, + halfSize, + -halfSize + radius, + radius + ); + + // Draw the right side + context.lineTo(halfSize, halfSize - cornerSize); + + // Draw the flat right-bottom corner + context.lineTo(halfSize, halfSize); + context.lineTo(halfSize - cornerSize, halfSize); + + // Draw the bottom side + context.lineTo(-halfSize + radius, halfSize); + context.arcTo( + -halfSize, + halfSize, + -halfSize, + halfSize - radius, + radius + ); + + context.closePath(); + // context.fillStyle = '#000'; // Set color for the rounded square + context.fill(); + }, + }); + } + + _basicDiamond(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + const halfSize = size / 2; // Half the size of the diamond + + this._rotateFigure({ + ...args, + draw: () => { + context.beginPath(); + + // Move to the top point of the diamond + context.moveTo(0, -halfSize); + + // Draw the right point + context.lineTo(halfSize, 0); + + // Draw the bottom point + context.lineTo(0, halfSize); + + // Draw the left point + context.lineTo(-halfSize, 0); + + // Close the path to the top point + context.closePath(); + + // context.fillStyle = "#000"; // Set color for the diamond + context.fill(); + }, + }); + } + + _basicStar(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + + const numPoints = 5; + const outerRadius = size / 2; + const innerRadius = outerRadius / 2.5; + const step = Math.PI / numPoints; + + this._rotateFigure({ + ...args, + draw: () => { + context.beginPath(); + for (let i = 0; i < 2 * numPoints; i++) { + const radius = i % 2 === 0 ? outerRadius : innerRadius; + const angle = i * step; + context.lineTo(radius * Math.cos(angle), radius * Math.sin(angle)); + } + context.closePath(); + }, + }); + } + + _basicPlus(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + + const thickness = size / 5; + const halfThickness = thickness / 2; + const halfSize = size / 2; + + this._rotateFigure({ + ...args, + draw: () => { + context.beginPath(); + context.rect(-halfThickness, -halfSize, thickness, size); // vertical rectangle + context.rect(-halfSize, -halfThickness, size, thickness); // horizontal rectangle + context.closePath(); + }, + }); + } + + _basicCross(args: BasicFigureDrawArgsCanvas): void { + const { size, context } = args; + const lineWidth = size / 4; // Width of the cross lines + const halfSize = size / 2; // Half the size of the cross + + this._rotateFigure({ + ...args, + draw: () => { + context.save(); // Save the current state + context.translate(0, 0); // Move to the center + context.rotate(Math.PI / 4); // Rotate 45 degrees (pi/4 radians) + + context.beginPath(); + + // Draw the horizontal line of the cross + context.rect(-halfSize, -lineWidth / 2, size, lineWidth); + + // Draw the vertical line of the cross + context.rect(-lineWidth / 2, -halfSize, lineWidth, size); + + context.fillStyle = '#000'; // Set c//olor for the cross + context.fill(); + + context.restore(); // Restore the state + }, }); } @@ -68,4 +445,58 @@ export default class QRCornerDot { _drawSquare({ x, y, size, context, rotation }: DrawArgsCanvas): void { this._basicSquare({ x, y, size, context, rotation }); } + + _drawStar({ x, y, size, context, rotation }: DrawArgsCanvas): void { + this._basicStar({ x, y, size, context, rotation }); + } + + _drawPlus({ x, y, size, context, rotation }: DrawArgsCanvas): void { + this._basicPlus({ x, y, size, context, rotation }); + } + + _drawCross({ x, y, size, context, rotation }: DrawArgsCanvas): void { + this._basicCross({ x, y, size, context, rotation }); + } + + _drawDiamond({ x, y, size, context, rotation }: DrawArgsCanvas): void { + this._basicDiamond({ x, y, size, context, rotation }); + } + + _drawSquareRounded({ x, y, size, context, rotation }: DrawArgsCanvas): void { + this._basicRoundedSquare({ x, y, size, context, rotation }); + } + + _drawSquareRoundedRightBottomEdge({ + x, + y, + size, + context, + rotation, + }: DrawArgsCanvas): void { + this._basicRoundedSquareRightBottomEdge({ x, y, size, context, rotation }); + } + + _drawLeaf({ x, y, size, context, rotation }: DrawArgsCanvas): void { + this._basicLeaf({ x, y, size, context, rotation }); + } + + _drawCircleLeftTopEdge({ + x, + y, + size, + context, + rotation, + }: DrawArgsCanvas): void { + this._basicCircleLeftTopEdge({ x, y, size, context, rotation }); + } + + _drawCircleRightBottomEdge({ + x, + y, + size, + context, + rotation, + }: DrawArgsCanvas): void { + this._basicCircleRightBottomEdge({ x, y, size, context, rotation }); + } } diff --git a/src/figures/cornerDot/svg/QRCornerDot.ts b/src/figures/cornerDot/svg/QRCornerDot.ts index ea42fb93..7390b1fe 100644 --- a/src/figures/cornerDot/svg/QRCornerDot.ts +++ b/src/figures/cornerDot/svg/QRCornerDot.ts @@ -1,16 +1,20 @@ import cornerDotTypes from "../../../constants/cornerDotTypes"; -import { CornerDotType, RotateFigureArgs, BasicFigureDrawArgs, DrawArgs, Window } from "../../../types"; +import { + CornerDotType, + RotateFigureArgs, + BasicFigureDrawArgs, + DrawArgs, +} from "../../../types"; export default class QRCornerDot { - _element?: SVGElement; _svg: SVGElement; _type: CornerDotType; - _window: Window; + _element: SVGElement | null; - constructor({ svg, type, window }: { svg: SVGElement; type: CornerDotType; window: Window }) { + constructor({ svg, type }: { svg: SVGElement; type: CornerDotType }) { this._svg = svg; this._type = type; - this._window = window; + this._element = null; } draw(x: number, y: number, size: number, rotation: number): void { @@ -21,6 +25,36 @@ export default class QRCornerDot { case cornerDotTypes.square: drawFunction = this._drawSquare; break; + case cornerDotTypes.star: + drawFunction = this._drawStar; + break; + case cornerDotTypes.squareRounded: + drawFunction = this._drawSquareRounded; + break; + case cornerDotTypes.rightBottomSquare: + drawFunction = this._drawSquareRoundedRightBottomEdge; + break; + case cornerDotTypes.plus: + drawFunction = this._drawPlus; + break; + case cornerDotTypes.cross: + drawFunction = this._drawCross; + break; + case cornerDotTypes.rhombus: + drawFunction = this._drawRhombus; + break; + case cornerDotTypes.leaf: + drawFunction = this._drawLead; + break; + case cornerDotTypes.leftTopCircle: + drawFunction = this._drawCircleLeftTopEdge; + break; + case cornerDotTypes.rightBottomCircle: + drawFunction = this._drawCircleRightBottomEdge; + break; + case cornerDotTypes.diamond: + drawFunction = this._drawDiamond; + break; case cornerDotTypes.dot: default: drawFunction = this._drawDot; @@ -34,7 +68,13 @@ export default class QRCornerDot { const cy = y + size / 2; draw(); - this._element?.setAttribute("transform", `rotate(${(180 * rotation) / Math.PI},${cx},${cy})`); + const lastChild = this._svg.lastChild as SVGElement | null; + if (lastChild) { + lastChild.setAttribute( + "transform", + `rotate(${(180 * rotation) / Math.PI},${cx},${cy})` + ); + } } _basicDot(args: BasicFigureDrawArgs): void { @@ -43,11 +83,15 @@ export default class QRCornerDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "circle"); - this._element.setAttribute("cx", String(x + size / 2)); - this._element.setAttribute("cy", String(y + size / 2)); - this._element.setAttribute("r", String(size / 2)); - } + const circle = document.createElementNS( + "http://www.w3.org/2000/svg", + "circle" + ); + circle.setAttribute("cx", String(x + size / 2)); + circle.setAttribute("cy", String(y + size / 2)); + circle.setAttribute("r", String(size / 2)); + this._svg.appendChild(circle); + }, }); } @@ -57,12 +101,453 @@ export default class QRCornerDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "rect"); - this._element.setAttribute("x", String(x)); - this._element.setAttribute("y", String(y)); - this._element.setAttribute("width", String(size)); - this._element.setAttribute("height", String(size)); - } + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + rect.setAttribute("x", String(x)); + rect.setAttribute("y", String(y)); + rect.setAttribute("width", String(size)); + rect.setAttribute("height", String(size)); + this._svg.appendChild(rect); + }, + }); + } + + _basicRoundedSquare(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 5; // Adjust the radius as needed + + this._rotateFigure({ + ...args, + draw: () => { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + rect.setAttribute("x", String(x)); + rect.setAttribute("y", String(y)); + rect.setAttribute("width", String(size)); + rect.setAttribute("height", String(size)); + rect.setAttribute("rx", String(radius)); + rect.setAttribute("ry", String(radius)); + this._svg.appendChild(rect); + }, + }); + } + + _basicRoundedSquareRightBottomEdge(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 5; // Adjust the radius as needed + + this._rotateFigure({ + ...args, + draw: () => { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + rect.setAttribute("x", String(x)); + rect.setAttribute("y", String(y)); + rect.setAttribute("width", String(size)); + rect.setAttribute("height", String(size)); + rect.setAttribute("rx", String(radius)); + rect.setAttribute("ry", String(radius)); + + // Create a small rectangle to cover the bottom right corner + const flatCornerRect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + flatCornerRect.setAttribute("x", String(x + size - radius)); + flatCornerRect.setAttribute("y", String(y + size - radius)); + flatCornerRect.setAttribute("width", String(radius)); + flatCornerRect.setAttribute("height", String(radius)); + + this._svg.appendChild(rect); + this._svg.appendChild(flatCornerRect); + }, + }); + } + + _basicLeaf(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const extension = size / 4; // Adjust the extension as needed + const cornerRadius = size / 10; // Adjust the corner radius as needed + + this._rotateFigure({ + ...args, + draw: () => { + const path = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + const d = ` + M ${x - size / 2.2 - extension},${ + y - size / 2.2 - extension + } // Move to the top left corner + L ${x + size / 2.2},${y - size / 2.2} // Draw top edge + L ${x + size / 2.2},${y + size / 2.2} // Draw right edge + L ${x - size / 2.2},${y + size / 2.2} // Draw bottom edge + A ${cornerRadius},${cornerRadius} 0 0 1 ${ + x - size / 2.2 - extension + cornerRadius + },${y - size / 2.2 + cornerRadius} // Draw rounded left top corner + Z // Close the path + ` + .replace(/\/\/.*$/gm, "") + .trim(); // Remove comments and trim whitespace + path.setAttribute("d", d); + this._svg.appendChild(path); + }, + }); + } + + // _basicCircleLeftTopEdge(args: BasicFigureDrawArgs): void { + // const { size, x, y } = args; + // const radius = size / 2; + + // this._rotateFigure({ + // ...args, + // draw: () => { + // const circle = document.createElementNS( + // "http://www.w3.org/2000/svg", + // "circle" + // ); + + // // Adjust the attributes to position the circle with a flat top left corner + // circle.setAttribute("cx", String(x + radius)); // Adjusted to radius for left edge + // circle.setAttribute("cy", String(y + radius)); // Adjusted to radius for top edge + // circle.setAttribute("r", String(radius)); // Use radius as the size + + // this._svg.appendChild(circle); + // }, + // }); + // } + + _basicCircleLeftTopEdge(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 2; + + this._rotateFigure({ + ...args, + draw: () => { + // Create a circle for the curved part + const circle = document.createElementNS( + "http://www.w3.org/2000/svg", + "circle" + ); + circle.setAttribute("cx", String(x + radius)); + circle.setAttribute("cy", String(y + radius)); + circle.setAttribute("r", String(radius)); + + // Create a rectangle for the flat corner + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + rect.setAttribute("x", String(x)); + rect.setAttribute("y", String(y)); + rect.setAttribute("width", String(radius)); + rect.setAttribute("height", String(radius)); + + // Add both shapes to the SVG + this._svg.appendChild(circle); + this._svg.appendChild(rect); + }, + }); + } + + _basicCircleRightBottomEdge(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 2; + + this._rotateFigure({ + ...args, + draw: () => { + // Create a circle for the curved part + const circle = document.createElementNS( + "http://www.w3.org/2000/svg", + "circle" + ); + circle.setAttribute("cx", String(x + radius)); + circle.setAttribute("cy", String(y + radius)); + circle.setAttribute("r", String(radius)); + + // Create a rectangle for the flat bottom-right corner + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + rect.setAttribute("x", String(x + radius)); + rect.setAttribute("y", String(y + radius)); + rect.setAttribute("width", String(radius)); + rect.setAttribute("height", String(radius)); + + // Add both shapes to the SVG + this._svg.appendChild(circle); + this._svg.appendChild(rect); + }, + }); + } + + // _basicExtendedSquare(args: BasicFigureDrawArgs): void { + // const { size, x, y } = args; + // const extension = size / 6; // Adjust the extension as needed + + // this._rotateFigure({ + // ...args, + // draw: () => { + // const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + // rect.setAttribute("x", String(x - extension)); + // rect.setAttribute("y", String(y - extension)); + // rect.setAttribute("width", String(size + extension)); + // rect.setAttribute("height", String(size + extension)); + // this._svg.appendChild(rect); + // } + // }); + // } + + _basicDiamond(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + + this._rotateFigure({ + ...args, + draw: () => { + const polygon = document.createElementNS( + "http://www.w3.org/2000/svg", + "polygon" + ); + polygon.setAttribute( + "points", + ` + ${x + size / 2}, ${y} + ${x + size}, ${y + size / 2} + ${x + size / 2}, ${y + size} + ${x}, ${y + size / 2} + ` + ); + this._svg.appendChild(polygon); + }, + }); + } + + _basicStar(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + + const numPoints = 5; + const outerRadius = size / 2; + const innerRadius = outerRadius / 2.5; + const step = Math.PI / numPoints; + + this._rotateFigure({ + ...args, + draw: () => { + const points = []; + for (let i = 0; i < 2 * numPoints; i++) { + const radius = i % 2 === 0 ? outerRadius : innerRadius; + const angle = i * step; + const px = x + size / 2 + radius * Math.cos(angle); + const py = y + size / 2 + radius * Math.sin(angle); + points.push(`${px},${py}`); + } + + const polygon = document.createElementNS( + "http://www.w3.org/2000/svg", + "polygon" + ); + polygon.setAttribute("points", points.join(" ")); + this._svg.appendChild(polygon); + }, + }); + } + + _basicPlus(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + + const thickness = size / 5; + const halfThickness = thickness / 2; + const halfSize = size / 2; + + this._rotateFigure({ + ...args, + draw: () => { + const group = document.createElementNS( + "http://www.w3.org/2000/svg", + "g" + ); + + const verticalRect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + verticalRect.setAttribute("x", String(x + halfSize - halfThickness)); + verticalRect.setAttribute("y", String(y)); + verticalRect.setAttribute("width", String(thickness)); + verticalRect.setAttribute("height", String(size)); + group.appendChild(verticalRect); + + const horizontalRect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + horizontalRect.setAttribute("x", String(x)); + horizontalRect.setAttribute("y", String(y + halfSize - halfThickness)); + horizontalRect.setAttribute("width", String(size)); + horizontalRect.setAttribute("height", String(thickness)); + group.appendChild(horizontalRect); + + this._svg.appendChild(group); + }, + }); + } + + _basicCross(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + + const thickness = size / 2.5; + const halfThickness = thickness / 2; + const halfSize = size / 2; + + this._rotateFigure({ + ...args, + draw: () => { + const group = document.createElementNS( + "http://www.w3.org/2000/svg", + "g" + ); + + const verticalRect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + verticalRect.setAttribute("x", String(x + halfSize - halfThickness)); + verticalRect.setAttribute("y", String(y)); + verticalRect.setAttribute("width", String(thickness)); + verticalRect.setAttribute("height", String(size)); + verticalRect.setAttribute( + "transform", + `rotate(45 ${x + halfSize} ${y + halfSize})` + ); + verticalRect.setAttribute("rx", String(thickness / 2)); // add this line + group.appendChild(verticalRect); + + const horizontalRect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + horizontalRect.setAttribute("x", String(x)); + horizontalRect.setAttribute("y", String(y + halfSize - halfThickness)); + horizontalRect.setAttribute("width", String(size)); + horizontalRect.setAttribute("height", String(thickness)); + horizontalRect.setAttribute( + "transform", + `rotate(45 ${x + halfSize} ${y + halfSize})` + ); + horizontalRect.setAttribute("rx", String(thickness / 2)); // add this line + group.appendChild(horizontalRect); + + this._svg.appendChild(group); + }, + }); + } + + _basicRhombus(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + + const thickness = size / 1.8; + const halfThickness = thickness / 2; + const halfSize = size / 2; + + this._rotateFigure({ + ...args, + draw: () => { + const group = document.createElementNS( + "http://www.w3.org/2000/svg", + "g" + ); + + // group.setAttribute("transform", `rotate(45 ${x + halfSize} ${y + halfSize})`); + + const verticalRect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + verticalRect.setAttribute("x", String(x + halfSize - halfThickness)); + verticalRect.setAttribute("y", String(y)); + verticalRect.setAttribute("width", String(thickness)); + verticalRect.setAttribute("height", String(size)); + + const verticalTopTriangle = document.createElementNS( + "http://www.w3.org/2000/svg", + "polygon" + ); + verticalTopTriangle.setAttribute( + "points", + ` + ${x + halfSize - halfThickness},${y} + ${x + halfSize},${y - halfThickness} + ${x + halfSize + halfThickness},${y} + ` + ); + + const verticalBottomTriangle = document.createElementNS( + "http://www.w3.org/2000/svg", + "polygon" + ); + verticalBottomTriangle.setAttribute( + "points", + ` + ${x + halfSize - halfThickness},${y + size} + ${x + halfSize + halfThickness},${y + size} + ${x + halfSize},${y + size + halfThickness} + ` + ); + + group.appendChild(verticalRect); + group.appendChild(verticalTopTriangle); + group.appendChild(verticalBottomTriangle); + + const horizontalRect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + horizontalRect.setAttribute("x", String(x)); + horizontalRect.setAttribute("y", String(y + halfSize - halfThickness)); + horizontalRect.setAttribute("width", String(size)); + horizontalRect.setAttribute("height", String(thickness)); + + const horizontalLeftTriangle = document.createElementNS( + "http://www.w3.org/2000/svg", + "polygon" + ); + horizontalLeftTriangle.setAttribute( + "points", + ` + ${x},${y + halfSize - halfThickness} + ${x - halfThickness},${y + halfSize} + ${x},${y + halfSize + halfThickness} + ` + ); + + const horizontalRightTriangle = document.createElementNS( + "http://www.w3.org/2000/svg", + "polygon" + ); + horizontalRightTriangle.setAttribute( + "points", + ` + ${x + size},${y + halfSize - halfThickness} + ${x + size + halfThickness},${y + halfSize} + ${x + size},${y + halfSize + halfThickness} + ` + ); + + group.appendChild(horizontalRect); + group.appendChild(horizontalLeftTriangle); + group.appendChild(horizontalRightTriangle); + + this._svg.appendChild(group); + }, }); } @@ -73,4 +558,42 @@ export default class QRCornerDot { _drawSquare({ x, y, size, rotation }: DrawArgs): void { this._basicSquare({ x, y, size, rotation }); } + + _drawStar({ x, y, size, rotation }: DrawArgs): void { + this._basicStar({ x, y, size, rotation }); + } + + _drawPlus({ x, y, size, rotation }: DrawArgs): void { + this._basicPlus({ x, y, size, rotation }); + } + + _drawSquareRounded({ x, y, size, rotation }: DrawArgs): void { + this._basicRoundedSquare({ x, y, size, rotation }); + } + + _drawSquareRoundedRightBottomEdge({ x, y, size, rotation }: DrawArgs): void { + this._basicRoundedSquareRightBottomEdge({ x, y, size, rotation }); + } + + _drawLead({ x, y, size, rotation }: DrawArgs): void { + this._basicLeaf({ x, y, size, rotation }); + } + + _drawCircleLeftTopEdge({ x, y, size, rotation }: DrawArgs): void { + this._basicCircleLeftTopEdge({ x, y, size, rotation }); + } + _drawCircleRightBottomEdge({ x, y, size, rotation }: DrawArgs): void { + this._basicCircleRightBottomEdge({ x, y, size, rotation }); + } + + _drawDiamond({ x, y, size, rotation }: DrawArgs): void { + this._basicDiamond({ x, y, size, rotation }); + } + _drawCross({ x, y, size, rotation }: DrawArgs): void { + this._basicCross({ x, y, size, rotation }); + } + + _drawRhombus({ x, y, size, rotation }: DrawArgs): void { + this._basicRhombus({ x, y, size, rotation }); + } } diff --git a/src/figures/cornerSquare/svg/QRCornerSquare.ts b/src/figures/cornerSquare/svg/QRCornerSquare.ts index f8e05126..39a39444 100644 --- a/src/figures/cornerSquare/svg/QRCornerSquare.ts +++ b/src/figures/cornerSquare/svg/QRCornerSquare.ts @@ -1,16 +1,19 @@ import cornerSquareTypes from "../../../constants/cornerSquareTypes"; -import { CornerSquareType, DrawArgs, BasicFigureDrawArgs, RotateFigureArgs, Window } from "../../../types"; +import { + CornerSquareType, + DrawArgs, + BasicFigureDrawArgs, + RotateFigureArgs, +} from "../../../types"; export default class QRCornerSquare { _element?: SVGElement; _svg: SVGElement; _type: CornerSquareType; - _window: Window; - constructor({ svg, type, window }: { svg: SVGElement; type: CornerSquareType; window: Window }) { + constructor({ svg, type }: { svg: SVGElement; type: CornerSquareType }) { this._svg = svg; this._type = type; - this._window = window; } draw(x: number, y: number, size: number, rotation: number): void { @@ -24,6 +27,30 @@ export default class QRCornerSquare { case cornerSquareTypes.extraRounded: drawFunction = this._drawExtraRounded; break; + case cornerSquareTypes.dottedSquare: + drawFunction = this._drawDottedSquare; + break; + case cornerSquareTypes.rightBottomSquare: + drawFunction = this._drawRoundedSquareRightBottomEdge; + break; + case cornerSquareTypes.leftTopSquare: + drawFunction = this._drawRoundedSquareLeftTopEdge; + break; + case cornerSquareTypes.leftTopCircle: + drawFunction = this._drawCircleLeftTopFlat; + break; + case cornerSquareTypes.rightBottomCircle: + drawFunction = this._drawCircleRightBottomFlat; + break; + case cornerSquareTypes.peanut: + drawFunction = this._drawPeanutShape; + break; + case cornerSquareTypes.circleInSquare: + drawFunction = this._drawCircleInSquare; + break; + // case cornerSquareTypes.paragonal: + // drawFunction = this._drawParagonalShape; + // break; case cornerSquareTypes.dot: default: drawFunction = this._drawDot; @@ -37,7 +64,10 @@ export default class QRCornerSquare { const cy = y + size / 2; draw(); - this._element?.setAttribute("transform", `rotate(${(180 * rotation) / Math.PI},${cx},${cy})`); + this._element?.setAttribute( + "transform", + `rotate(${(180 * rotation) / Math.PI},${cx},${cy})` + ); } _basicDot(args: BasicFigureDrawArgs): void { @@ -47,7 +77,10 @@ export default class QRCornerSquare { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "path"); + this._element = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); this._element.setAttribute("clip-rule", "evenodd"); this._element.setAttribute( "d", @@ -58,7 +91,7 @@ export default class QRCornerSquare { `a ${size / 2 - dotSize} ${size / 2 - dotSize} 0 1 1 -0.1 0` + // a innerRadius, innerRadius, 0, 1, 1, -1, 0 // Draw inner arc, but don't close it `Z` // Z // Close the inner ring. Actually will still work without, but inner ring will have one unit missing in stroke ); - } + }, }); } @@ -69,7 +102,10 @@ export default class QRCornerSquare { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "path"); + this._element = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); this._element.setAttribute("clip-rule", "evenodd"); this._element.setAttribute( "d", @@ -84,7 +120,7 @@ export default class QRCornerSquare { `h ${-size + 2 * dotSize}` + `z` ); - } + }, }); } @@ -95,33 +131,489 @@ export default class QRCornerSquare { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "path"); + this._element = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); this._element.setAttribute("clip-rule", "evenodd"); this._element.setAttribute( "d", `M ${x} ${y + 2.5 * dotSize}` + `v ${2 * dotSize}` + - `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${dotSize * 2.5} ${dotSize * 2.5}` + + `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${dotSize * 2.5} ${ + dotSize * 2.5 + }` + `h ${2 * dotSize}` + - `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${dotSize * 2.5} ${-dotSize * 2.5}` + + `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${dotSize * 2.5} ${ + -dotSize * 2.5 + }` + `v ${-2 * dotSize}` + - `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${-dotSize * 2.5}` + + `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${ + -dotSize * 2.5 + }` + `h ${-2 * dotSize}` + - `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${dotSize * 2.5}` + + `a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${ + dotSize * 2.5 + }` + `M ${x + 2.5 * dotSize} ${y + dotSize}` + `h ${2 * dotSize}` + - `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${dotSize * 1.5}` + + `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${ + dotSize * 1.5 + }` + `v ${2 * dotSize}` + - `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${-dotSize * 1.5} ${dotSize * 1.5}` + + `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${-dotSize * 1.5} ${ + dotSize * 1.5 + }` + `h ${-2 * dotSize}` + - `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${-dotSize * 1.5} ${-dotSize * 1.5}` + + `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${-dotSize * 1.5} ${ + -dotSize * 1.5 + }` + `v ${-2 * dotSize}` + - `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${-dotSize * 1.5}` + `a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${ + -dotSize * 1.5 + }` + ); + }, + }); + } + + _basicDottedSquare(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const squareSize = size / 7; + const gap = squareSize * 1.2; + + this._rotateFigure({ + ...args, + draw: () => { + this._element = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + this._element.setAttribute("clip-rule", "evenodd"); + this._element.setAttribute("fill", "#000"); // Add this line to fill the squares + + let pathData = ""; + // Top edge + for (let i = 0; i <= size - squareSize; i += gap) { + pathData += `M ${ + x + i + } ${y} h ${squareSize} v ${squareSize} h -${squareSize} z `; + } + // Right edge + for (let i = 0; i <= size - squareSize; i += gap) { + pathData += `M ${x + size - squareSize} ${ + y + i + } h ${squareSize} v ${squareSize} h -${squareSize} z `; + } + // Bottom edge + for (let i = 0; i <= size - squareSize; i += gap) { + pathData += `M ${x + size - i - squareSize} ${ + y + size - squareSize + } h ${squareSize} v ${squareSize} h -${squareSize} z `; + } + // Left edge + for (let i = 0; i <= size - squareSize; i += gap) { + pathData += `M ${x} ${ + y + size - i - squareSize + } h ${squareSize} v ${squareSize} h -${squareSize} z `; + } + // Top-left corner + pathData += `M ${x} ${y} h ${squareSize} v ${squareSize} h -${squareSize} z `; + // Top-right corner + pathData += `M ${ + x + size - squareSize + } ${y} h ${squareSize} v ${squareSize} h -${squareSize} z `; + // Bottom-right corner + pathData += `M ${x + size - squareSize} ${ + y + size - squareSize + } h ${squareSize} v ${squareSize} h -${squareSize} z `; + // Bottom-left corner + pathData += `M ${x} ${ + y + size - squareSize + } h ${squareSize} v ${squareSize} h -${squareSize} z `; + + this._element.setAttribute("d", pathData); + }, + }); + } + + _basicRoundedSquareRightBottomEdge(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 4; // Adjust this value to control the rounding radius + const innerSquareSize = size / 1.4; // Size of the inner square + const innerSquareRadius = innerSquareSize / 4; // Radius for the inner square + const innerX = x + (size - innerSquareSize) / 2; // X position for the inner square + const innerY = y + (size - innerSquareSize) / 2; // Y position for the inner square + + this._rotateFigure({ + ...args, + draw: () => { + // Create the main shape path + const path = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + path.setAttribute("clip-rule", "evenodd"); + path.setAttribute( + "d", + `M ${x + radius} ${y}` + // Start at the top-left rounded corner + `H ${x + size - radius}` + // Draw a horizontal line to the right + `a ${radius} ${radius} 0 0 1 ${radius} ${radius}` + // Draw the top-right arc + `V ${y + size - radius}` + // Draw a vertical line down to the bottom-right flat edge + `H ${x + size}` + // Move to the bottom-right flat edge + `V ${y + size}` + // Draw a vertical line down to the bottom + `H ${x + radius}` + // Draw a horizontal line to the left + `a ${radius} ${radius} 0 0 1 -${radius} -${radius}` + // Draw the bottom-left arc + `V ${y + radius}` + // Draw a vertical line up to the starting point + `a ${radius} ${radius} 0 0 1 ${radius} -${radius}` + // Draw the top-left arc + `Z` // Close the path + ); + path.setAttribute("fill", "white"); // Set fill to white + path.setAttribute("stroke", "black"); // Set the stroke color + path.setAttribute("stroke-width", "1"); // Set the stroke width + this._element = path; + + // Create the inner square path + const innerPath = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + innerPath.setAttribute("clip-rule", "evenodd"); + innerPath.setAttribute( + "d", + `M ${innerX + innerSquareRadius} ${innerY}` + // Start at the top-left rounded corner + `H ${innerX + innerSquareSize - innerSquareRadius}` + // Draw a horizontal line to the right + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 ${innerSquareRadius} ${innerSquareRadius}` + // Draw the top-right arc + `V ${innerY + innerSquareSize - innerSquareRadius}` + // Draw a vertical line down to the bottom-right flat edge + `H ${innerX + innerSquareSize}` + // Move to the bottom-right flat edge + `V ${innerY + innerSquareSize}` + // Draw a vertical line down to the bottom + `H ${innerX + innerSquareRadius}` + // Draw a horizontal line to the left + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 -${innerSquareRadius} -${innerSquareRadius}` + // Draw the bottom-left arc + `V ${innerY + innerSquareRadius}` + // Draw a vertical line up to the starting point + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 ${innerSquareRadius} -${innerSquareRadius}` + // Draw the top-left arc + `Z` // Close the path + ); + innerPath.setAttribute("fill", "white"); // Set fill to white for the inner square + innerPath.setAttribute("stroke", "black"); // Set the stroke color + innerPath.setAttribute("stroke-width", "1"); // Set the stroke width + + // Append the elements to the SVG container + const svgContainer = document.querySelector("svg"); // Adjust this selector to match your SVG container + if (svgContainer) { + svgContainer.appendChild(this._element); + svgContainer.appendChild(innerPath); + } + }, + }); + } + + _basicRoundedSquareLeftTopEdge(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 4; // Adjust this value to control the rounding radius + const innerSquareSize = size / 1.4; // Size of the inner square + const innerSquareRadius = innerSquareSize / 4; // Radius for the inner square + const innerX = x + (size - innerSquareSize) / 2; // X position for the inner square + const innerY = y + (size - innerSquareSize) / 2; // Y position for the inner square + + this._rotateFigure({ + ...args, + draw: () => { + // Create the main shape path + const path = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + path.setAttribute("clip-rule", "evenodd"); + path.setAttribute( + "d", + `M ${x + radius} ${y}` + // Start at the top-left flat edge + `H ${x + size - radius}` + // Draw a horizontal line to the right + `a ${radius} ${radius} 0 0 1 ${radius} ${radius}` + // Draw the top-right arc + `V ${y + size - radius}` + // Draw a vertical line down to the bottom-right + `a ${radius} ${radius} 0 0 1 -${radius} ${radius}` + // Draw the bottom-right arc + `H ${x + radius}` + // Draw a horizontal line to the left + `a ${radius} ${radius} 0 0 1 -${radius} -${radius}` + // Draw the bottom-left arc + `V ${y + radius}` + // Draw a vertical line up to the starting point + `H ${x}` + // Draw a horizontal line to the left to the starting point + `V ${y}` + // Move up to the top to ensure the flat corner is complete + `Z` // Close the path + ); + path.setAttribute("fill", "white"); // Set fill to white + path.setAttribute("stroke", "black"); // Set the stroke color + path.setAttribute("stroke-width", "1"); // Set the stroke width + this._element = path; + + // Create the inner square path + const innerPath = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + innerPath.setAttribute("clip-rule", "evenodd"); + innerPath.setAttribute( + "d", + `M ${innerX + innerSquareRadius} ${innerY}` + // Start at the top-left flat edge + `H ${innerX + innerSquareSize - innerSquareRadius}` + // Draw a horizontal line to the right + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 ${innerSquareRadius} ${innerSquareRadius}` + // Draw the top-right arc + `V ${innerY + innerSquareSize - innerSquareRadius}` + // Draw a vertical line down to the bottom-right + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 -${innerSquareRadius} ${innerSquareRadius}` + // Draw the bottom-right arc + `H ${innerX + innerSquareRadius}` + // Draw a horizontal line to the left + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 -${innerSquareRadius} -${innerSquareRadius}` + // Draw the bottom-left arc + `V ${innerY + innerSquareRadius}` + // Draw a vertical line up to the starting point + `H ${innerX}` + // Draw a horizontal line to the left to the starting point + `V ${innerY}` + // Move up to the top to ensure the flat corner is complete + `Z` // Close the path ); - } + innerPath.setAttribute("fill", "white"); // Set fill to white for the inner square + innerPath.setAttribute("stroke", "black"); // Set the stroke color + innerPath.setAttribute("stroke-width", "1"); // Set the stroke width + + // Append the elements to the SVG container + const svgContainer = document.querySelector("svg"); // Adjust this selector to match your SVG container + if (svgContainer) { + svgContainer.appendChild(this._element); + svgContainer.appendChild(innerPath); + } + }, }); } + _basicCircleInSquare(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const borderWidth = size / 7; // Adjust the border width as needed + const circleRadius = size / 2 - borderWidth / 2; + + this._rotateFigure({ + ...args, + draw: () => { + this._element = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + this._element.setAttribute("fill", "none"); + this._element.setAttribute( + "d", + `M ${x} ${y}` + + `h ${size}` + + `v ${size}` + + `h ${-size}` + + `z` + // Outer square border + `M ${x + size / 2}, ${y + size / 2}` + + `m -${circleRadius}, 0` + + `a ${circleRadius},${circleRadius} 0 1,0 ${2 * circleRadius},0` + + `a ${circleRadius},${circleRadius} 0 1,0 -${2 * circleRadius},0` // Circle in the center + ); + }, + }); + } + + _basicLeftTopCircle(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 2; + const flatEdgeLength = size / 16; // Adjust this value as needed to control the length of the flat edge + const smallDotRadius = radius / 1.4; // Adjust this value to control the size of the small dot + + this._rotateFigure({ + ...args, + draw: () => { + // Create the main shape path + const path = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + path.setAttribute("clip-rule", "evenodd"); + path.setAttribute( + "d", + `M ${x + flatEdgeLength} ${y}` + // Start at the top-left flat edge + `H ${x + size - radius}` + // Draw a horizontal line to the right + `a ${radius} ${radius} 0 0 1 ${radius} ${radius}` + // Draw the top-right arc + `V ${y + size - radius}` + // Draw a vertical line down to the bottom-right + `a ${radius} ${radius} 0 0 1 -${radius} ${radius}` + // Draw the bottom-right arc + `H ${x + radius}` + // Draw a horizontal line to the left + `a ${radius} ${radius} 0 0 1 -${radius} -${radius}` + // Draw the bottom-left arc + `V ${y + flatEdgeLength}` + // Draw a vertical line up to the starting point to close the path + `a ${radius} ${radius} 0 0 1 ${radius} -${radius}` + // Draw the top-left arc + `Z` // Close the path + ); + path.setAttribute("fill", "none"); // No fill + path.setAttribute("stroke", "black"); // Set the stroke color + path.setAttribute("stroke-width", "1"); // Set the stroke width + this._element = path; + + // Create the white rounded dot with flat corner + const smallDot = document.createElementNS( + "http://www.w3.org/2000/svg", + "circle" + ); + smallDot.setAttribute("cx", `${x + radius}`); // Center x + smallDot.setAttribute("cy", `${y + radius}`); // Center y + smallDot.setAttribute("r", `${smallDotRadius}`); // Radius of the white circle + smallDot.setAttribute("fill", "white"); // White fill + smallDot.setAttribute("stroke", "none"); // No stroke + + // Append both elements to the SVG container + const svgContainer = document.querySelector("svg"); // Adjust this selector to match your SVG container + if (svgContainer) { + svgContainer.appendChild(this._element); + svgContainer.appendChild(smallDot); + } + }, + }); + } + + _basicRightBottomCircle(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 2; + const flatEdgeLength = size / 16; // Adjust this value as needed to control the length of the flat edge + const smallDotRadius = radius / 1.4; // Adjust this value to control the size of the small dot + + this._rotateFigure({ + ...args, + draw: () => { + // Create the main shape path + const path = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + path.setAttribute("clip-rule", "evenodd"); + path.setAttribute( + "d", + `M ${x} ${y + radius}` + // Start at the top-left arc + `a ${radius} ${radius} 0 0 1 ${radius} -${radius}` + // Draw the top-left arc + `H ${x + size - radius}` + // Draw a horizontal line to the right + `a ${radius} ${radius} 0 0 1 ${radius} ${radius}` + // Draw the top-right arc + `V ${y + size - radius}` + // Draw a vertical line down to the bottom-right flat edge + `H ${x + size - flatEdgeLength}` + // Draw a horizontal line to the left to the flat edge + `V ${y + size}` + // Draw a vertical line down to the bottom + `H ${x + radius}` + // Draw a horizontal line to the left + `a ${radius} ${radius} 0 0 1 -${radius} -${radius}` + // Draw the bottom-left arc + `Z` // Close the path + ); + path.setAttribute("fill", "none"); // No fill + path.setAttribute("stroke", "black"); // Set the stroke color + path.setAttribute("stroke-width", "1"); // Set the stroke width + this._element = path; + + // Create the white rounded dot with flat corner + const smallDot = document.createElementNS( + "http://www.w3.org/2000/svg", + "circle" + ); + smallDot.setAttribute("cx", `${x + radius}`); // Center x + smallDot.setAttribute("cy", `${y + radius}`); // Center y + smallDot.setAttribute("r", `${smallDotRadius}`); // Radius of the white circle + smallDot.setAttribute("fill", "white"); // White fill + smallDot.setAttribute("stroke", "none"); // No stroke + + // Append both elements to the SVG container + const svgContainer = document.querySelector("svg"); // Adjust this selector to match your SVG container + if (svgContainer) { + svgContainer.appendChild(this._element); + svgContainer.appendChild(smallDot); + } + }, + }); + } + + _basicPeanutShape(args: BasicFigureDrawArgs): void { + const { size, x, y } = args; + const radius = size / 3.7; // Adjust this value to control the rounding radius + const innerSquareSize = size / 1.4; // Size of the inner square + const innerSquareRadius = innerSquareSize / 3.7; // Radius for the inner square + const innerX = x + (size - innerSquareSize) / 2; // X position for the inner square + const innerY = y + (size - innerSquareSize) / 2; // Y position for the inner square + + this._rotateFigure({ + ...args, + draw: () => { + // Create the main shape path + const path = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + path.setAttribute("clip-rule", "evenodd"); + path.setAttribute( + "d", + `M ${x + radius} ${y}` + // Start at the top-left flat edge + `H ${x + size - radius}` + // Draw a horizontal line to the right + `a ${radius} ${radius} 0 0 1 ${radius} ${radius}` + // Draw the top-right arc + `V ${y + size - radius}` + // Draw a vertical line down to the bottom-right flat edge + `H ${x + size}` + // Move to the bottom-right flat edge + `V ${y + size}` + // Draw a vertical line down to the bottom + `H ${x + radius}` + // Draw a horizontal line to the left + `a ${radius} ${radius} 0 0 1 -${radius} -${radius}` + // Draw the bottom-left arc + `V ${y + radius}` + // Draw a vertical line up to the starting point + `H ${x}` + // Move to the top-left flat edge + `V ${y}` + // Draw a vertical line up to the top + `Z` // Close the path + ); + path.setAttribute("fill", "white"); // Set fill to white + path.setAttribute("stroke", "black"); // Set the stroke color + path.setAttribute("stroke-width", "1"); // Set the stroke width + this._element = path; + + // Create the inner square path + const innerPath = document.createElementNS( + "http://www.w3.org/2000/svg", + "path" + ); + innerPath.setAttribute("clip-rule", "evenodd"); + innerPath.setAttribute( + "d", + `M ${innerX + innerSquareRadius} ${innerY}` + // Start at the top-left flat edge + `H ${innerX + innerSquareSize - innerSquareRadius}` + // Draw a horizontal line to the right + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 ${innerSquareRadius} ${innerSquareRadius}` + // Draw the top-right arc + `V ${innerY + innerSquareSize - innerSquareRadius}` + // Draw a vertical line down to the bottom-right flat edge + `H ${innerX + innerSquareSize}` + // Move to the bottom-right flat edge + `V ${innerY + innerSquareSize}` + // Draw a vertical line down to the bottom + `H ${innerX + innerSquareRadius}` + // Draw a horizontal line to the left + `a ${innerSquareRadius} ${innerSquareRadius} 0 0 1 -${innerSquareRadius} -${innerSquareRadius}` + // Draw the bottom-left arc + `V ${innerY + innerSquareRadius}` + // Draw a vertical line up to the starting point + `H ${innerX}` + // Move to the top-left flat edge + `V ${innerY}` + // Draw a vertical line up to the top + `Z` // Close the path + ); + innerPath.setAttribute("fill", "white"); // Set fill to white for the inner square + innerPath.setAttribute("stroke", "black"); // Set the stroke color + innerPath.setAttribute("stroke-width", "1"); // Set the stroke width + + // Append the elements to the SVG container + const svgContainer = document.querySelector("svg"); // Adjust this selector to match your SVG container + if (svgContainer) { + svgContainer.appendChild(this._element); + svgContainer.appendChild(innerPath); + } + }, + }); + } + + // _basicParagonalShape(args: BasicFigureDrawArgs): void { + // const { size, x, y } = args; + + // this._rotateFigure({ + // ...args, + // draw: () => { + // const element = document.createElementNS("http://www.w3.org/2000/svg", "path"); + // element.setAttribute("clip-rule", "evenodd"); + // element.setAttribute( + // "d", + // `M ${x + size * 0.2} ${y}` + // Move to the top-left corner + // `L ${x + size * 0.8} ${y}` + // Draw line to top-right corner + // `L ${x + size * 0.9} ${y + size * 0.3}` + // Draw line to right-middle corner + // `L ${x + size * 0.7} ${y + size}` + // Draw line to bottom-right corner + // `L ${x + size * 0.3} ${y + size}` + // Draw line to bottom-left corner + // `L ${x + size * 0.1} ${y + size * 0.7}` + // Draw line to left-middle corner + // `Z` // Close the shape + // ); + // element.setAttribute("fill", "black"); // Set fill color to black + + // // Append the shape to the parent element + // args.parent.appendChild(element); + // }, + // }); + // } + + + _drawDot({ x, y, size, rotation }: DrawArgs): void { this._basicDot({ x, y, size, rotation }); } @@ -133,4 +625,34 @@ export default class QRCornerSquare { _drawExtraRounded({ x, y, size, rotation }: DrawArgs): void { this._basicExtraRounded({ x, y, size, rotation }); } + + _drawDottedSquare({ x, y, size, rotation }: DrawArgs): void { + this._basicDottedSquare({ x, y, size, rotation }); + } + + _drawRoundedSquareRightBottomEdge({ x, y, size, rotation }: DrawArgs): void { + this._basicRoundedSquareRightBottomEdge({ x, y, size, rotation }); + } + + _drawRoundedSquareLeftTopEdge({ x, y, size, rotation }: DrawArgs): void { + this._basicRoundedSquareLeftTopEdge({ x, y, size, rotation }); + } + + _drawCircleInSquare({ x, y, size, rotation }: DrawArgs): void { + this._basicCircleInSquare({ x, y, size, rotation }); + } + + _drawCircleLeftTopFlat({ x, y, size, rotation }: DrawArgs): void { + this._basicLeftTopCircle({ x, y, size, rotation }); + } + + _drawCircleRightBottomFlat({ x, y, size, rotation }: DrawArgs): void { + this._basicRightBottomCircle({ x, y, size, rotation }); + } + _drawPeanutShape({ x, y, size, rotation }: DrawArgs): void { + this._basicPeanutShape({ x, y, size, rotation }); + } + // _drawParagonalShape({ x, y, size, rotation }: DrawArgs): void { + // this._basicParagonalShape({ x, y, size, rotation }); + // } } diff --git a/src/figures/dot/svg/QRDot.ts b/src/figures/dot/svg/QRDot.ts index 161cb1a7..e12cddf5 100644 --- a/src/figures/dot/svg/QRDot.ts +++ b/src/figures/dot/svg/QRDot.ts @@ -1,16 +1,14 @@ import dotTypes from "../../../constants/dotTypes"; -import { DotType, GetNeighbor, DrawArgs, BasicFigureDrawArgs, RotateFigureArgs, Window } from "../../../types"; +import { DotType, GetNeighbor, DrawArgs, BasicFigureDrawArgs, RotateFigureArgs } from "../../../types"; export default class QRDot { _element?: SVGElement; _svg: SVGElement; _type: DotType; - _window: Window; - constructor({ svg, type, window }: { svg: SVGElement; type: DotType; window: Window }) { + constructor({ svg, type }: { svg: SVGElement; type: DotType }) { this._svg = svg; this._type = type; - this._window = window; } draw(x: number, y: number, size: number, getNeighbor: GetNeighbor): void { @@ -55,7 +53,7 @@ export default class QRDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "circle"); + this._element = document.createElementNS("http://www.w3.org/2000/svg", "circle"); this._element.setAttribute("cx", String(x + size / 2)); this._element.setAttribute("cy", String(y + size / 2)); this._element.setAttribute("r", String(size / 2)); @@ -69,7 +67,7 @@ export default class QRDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "rect"); + this._element = document.createElementNS("http://www.w3.org/2000/svg", "rect"); this._element.setAttribute("x", String(x)); this._element.setAttribute("y", String(y)); this._element.setAttribute("width", String(size)); @@ -85,7 +83,7 @@ export default class QRDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "path"); + this._element = document.createElementNS("http://www.w3.org/2000/svg", "path"); this._element.setAttribute( "d", `M ${x} ${y}` + //go to top left position @@ -104,7 +102,7 @@ export default class QRDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "path"); + this._element = document.createElementNS("http://www.w3.org/2000/svg", "path"); this._element.setAttribute( "d", `M ${x} ${y}` + //go to top left position @@ -124,7 +122,7 @@ export default class QRDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "path"); + this._element = document.createElementNS("http://www.w3.org/2000/svg", "path"); this._element.setAttribute( "d", `M ${x} ${y}` + //go to top left position @@ -143,7 +141,7 @@ export default class QRDot { this._rotateFigure({ ...args, draw: () => { - this._element = this._window.document.createElementNS("http://www.w3.org/2000/svg", "path"); + this._element = document.createElementNS("http://www.w3.org/2000/svg", "path"); this._element.setAttribute( "d", `M ${x} ${y}` + //go to left top position diff --git a/src/index.html b/src/index.html index 44dcc685..6467627e 100644 --- a/src/index.html +++ b/src/index.html @@ -1,55 +1,66 @@ - - - QR Code Styling - - -
-
- - + // qrCode2.download() + + diff --git a/src/types/index.ts b/src/types/index.ts index b0d59e7a..f255c0cf 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -3,41 +3,13 @@ export interface UnknownObject { [key: string]: any; } -export type DotType = "dots" | "rounded" | "classy" | "classy-rounded" | "square" | "extra-rounded"; -export type CornerDotType = "dot" | "square"; -export type CornerSquareType = "dot" | "square" | "extra-rounded"; +export type DotType = "dots" | "rounded" | "classy" | "classy-rounded" | "square" | "extra-rounded" | "star" ; +export type CornerDotType = "dot" | "square" | "star" | "plus" | "square-rounded" | "leaf" | "circle-left-top" | "circle-right-bottom" | "square-right-bottom" | "diamond" | "cross" | "rhombus" +export type CornerSquareType = "dot" | "square" | "extra-rounded" | "dotted-square" | "right-bottom-square" | "left-top-square" | "circle-in-square" | "circle-left-top" | "circle-right-bottom" | "peanut" | "paragonal"; export type Extension = "svg" | "png" | "jpeg" | "webp"; export type GradientType = "radial" | "linear"; export type DrawType = "canvas" | "svg"; -export interface Canvas extends HTMLCanvasElement { - toBuffer?: (type: string) => Buffer; - createCanvas?: (width: number, height: number) => Canvas; - loadImage?: (image: string) => Promise; -} - -export interface Window { - Image: typeof HTMLImageElement; - XMLSerializer: typeof XMLSerializer; - document: Document; -} -declare const window: Window; - -interface JsDomOptions { - resources: string; -} -export class JSDom { - window: Window; - _options: JsDomOptions; - _input: string; - - constructor(input: string, options: JsDomOptions) { - this._options = options; - this._input = input; - this.window = window; - } -} - export type Gradient = { type: GradientType; rotation?: number; @@ -133,15 +105,12 @@ export type Options = { margin?: number; data?: string; image?: string; - nodeCanvas?: Canvas; - jsdom?: typeof JSDom; qrOptions?: { typeNumber?: TypeNumber; mode?: Mode; errorCorrectionLevel?: ErrorCorrectionLevel; }; imageOptions?: { - saveAsBlob?: boolean; hideBackgroundDots?: boolean; imageSize?: number; crossOrigin?: string;