From e6bc25495995eb70efc7b89cf2c2c24de1882fab Mon Sep 17 00:00:00 2001 From: Anastacia-Tesli Date: Mon, 18 Sep 2023 19:52:25 +0300 Subject: [PATCH 1/2] feat: add pages for print --- package-lock.json | 107 ++++++++++++ package.json | 3 + src/components/App/App.tsx | 9 + src/components/MainHero/MainHero.module.scss | 2 +- .../NewSticker/NewSticker.module.scss | 24 ++- .../PreviewForDownLoad.module.scss | 46 +++++ .../PreviewForDownLoad/PreviewForDownLoad.tsx | 163 ++++++++++++++++++ .../pages/AddStickers/AddStickers.module.scss | 11 ++ src/utils/_scss-variables.scss | 2 +- 9 files changed, 362 insertions(+), 5 deletions(-) create mode 100644 src/components/PreviewForDownLoad/PreviewForDownLoad.module.scss create mode 100644 src/components/PreviewForDownLoad/PreviewForDownLoad.tsx diff --git a/package-lock.json b/package-lock.json index f0d9d2ba..0c7b74ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,9 @@ "@types/react-dom": "^18.0.11", "classnames": "^2.3.2", "csstype": "^3.1.2", + "downloadjs": "^1.4.7", "framer-motion": "^10.11.2", + "html2canvas": "^1.4.1", "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -34,6 +36,7 @@ "web-vitals": "^2.1.4" }, "devDependencies": { + "@types/downloadjs": "^1.4.3", "@types/react-slick": "^0.23.10", "@types/react-transition-group": "^4.4.5", "@typescript-eslint/eslint-plugin": "^5.53.0", @@ -3856,6 +3859,12 @@ "@types/node": "*" } }, + "node_modules/@types/downloadjs": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/downloadjs/-/downloadjs-1.4.3.tgz", + "integrity": "sha512-MjJepFle/tLtT2/jmDNth6ZnwWzEhm40L+olE5HKR70ISUCfgT55eqreeHldAzFLY2HDUGsn8zgyto8KygN0CA==", + "dev": true + }, "node_modules/@types/eslint": { "version": "8.21.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.1.tgz", @@ -5529,6 +5538,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -6236,6 +6253,14 @@ "postcss": "^8.4" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", @@ -6959,6 +6984,11 @@ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" }, + "node_modules/downloadjs": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz", + "integrity": "sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==" + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -9173,6 +9203,18 @@ "webpack": "^5.20.0" } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -16445,6 +16487,14 @@ "node": ">=8" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -16842,6 +16892,14 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -20397,6 +20455,12 @@ "@types/node": "*" } }, + "@types/downloadjs": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/downloadjs/-/downloadjs-1.4.3.tgz", + "integrity": "sha512-MjJepFle/tLtT2/jmDNth6ZnwWzEhm40L+olE5HKR70ISUCfgT55eqreeHldAzFLY2HDUGsn8zgyto8KygN0CA==", + "dev": true + }, "@types/eslint": { "version": "8.21.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.1.tgz", @@ -21646,6 +21710,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==" + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -22168,6 +22237,14 @@ "postcss-selector-parser": "^6.0.9" } }, + "css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "requires": { + "utrie": "^1.0.2" + } + }, "css-loader": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", @@ -22689,6 +22766,11 @@ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" }, + "downloadjs": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz", + "integrity": "sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==" + }, "duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -24296,6 +24378,15 @@ "tapable": "^2.0.0" } }, + "html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "requires": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + } + }, "htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -29344,6 +29435,14 @@ "minimatch": "^3.0.4" } }, + "text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "requires": { + "utrie": "^1.0.2" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -29640,6 +29739,14 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, + "utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "requires": { + "base64-arraybuffer": "^1.0.2" + } + }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", diff --git a/package.json b/package.json index 4ed3d984..01b7fa22 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "@types/react-dom": "^18.0.11", "classnames": "^2.3.2", "csstype": "^3.1.2", + "downloadjs": "^1.4.7", "framer-motion": "^10.11.2", + "html2canvas": "^1.4.1", "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -53,6 +55,7 @@ ] }, "devDependencies": { + "@types/downloadjs": "^1.4.3", "@types/react-slick": "^0.23.10", "@types/react-transition-group": "^4.4.5", "@typescript-eslint/eslint-plugin": "^5.53.0", diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx index 1b5a86b9..8ab4a448 100644 --- a/src/components/App/App.tsx +++ b/src/components/App/App.tsx @@ -42,6 +42,7 @@ import { getStickers } from '../../store/stickersSlice'; import { IStickersState } from '../../interfaces/IStickersState'; import styles from './App.module.scss'; +import { PreviewForDownLoad } from '../PreviewForDownLoad/PreviewForDownLoad'; const App: React.FC = () => { const dispatch = useAppDispatch(); @@ -127,6 +128,14 @@ const App: React.FC = () => { } /> + + + + } + /> } /> } /> } /> diff --git a/src/components/MainHero/MainHero.module.scss b/src/components/MainHero/MainHero.module.scss index c8e30194..9ce24443 100644 --- a/src/components/MainHero/MainHero.module.scss +++ b/src/components/MainHero/MainHero.module.scss @@ -57,7 +57,7 @@ } .button { - @media screen and (max-width: 420px) { + @media screen and (max-width: 375px) { width: 100%; padding: 14px 10px; } diff --git a/src/components/NewSticker/NewSticker.module.scss b/src/components/NewSticker/NewSticker.module.scss index 71464585..72e806d7 100644 --- a/src/components/NewSticker/NewSticker.module.scss +++ b/src/components/NewSticker/NewSticker.module.scss @@ -9,6 +9,14 @@ padding: 40px 40px 40px 30px; box-shadow: 3px 3px 10px 0px rgba(212, 73, 0, 0.1); border-radius: 10px; + + @media screen and (max-width: 1010px) { + max-width: 100%; + } + + @media screen and (max-width: 768px) { + padding: 24px 16px; + } } .card_unactive { @@ -66,9 +74,13 @@ grid-template-columns: 255px repeat(1, 1fr); grid-template-rows: repeat(4, max-content); } - @media screen and (max-width: 845px) { + @media screen and (max-width: 768px) { grid-template-columns: repeat(2, 1fr); } + + @media screen and (max-width: 550px) { + grid-template-columns: 1fr; + } } .info_unactive { @@ -85,9 +97,12 @@ @media screen and (max-width: 1010px) { grid-row: 1/1; } - @media screen and (max-width: 845px) { + @media screen and (max-width: 768px) { grid-column: 1/3; } + @media screen and (max-width: 550px) { + grid-column: 1/1; + } } .flex { @@ -110,9 +125,12 @@ @media screen and (max-width: 1010px) { grid-column: 2/3; } - @media screen and (max-width: 845px) { + @media screen and (max-width: 768px) { grid-column: 1/3; } + @media screen and (max-width: 550px) { + grid-column: 1/1; + } } .shapes { display: flex; diff --git a/src/components/PreviewForDownLoad/PreviewForDownLoad.module.scss b/src/components/PreviewForDownLoad/PreviewForDownLoad.module.scss new file mode 100644 index 00000000..060ce57d --- /dev/null +++ b/src/components/PreviewForDownLoad/PreviewForDownLoad.module.scss @@ -0,0 +1,46 @@ +@import '../../utils/_scss-variables.scss'; + +.page { + margin: 30px auto; +} +.button { + margin-left: 120px; +} + +.container { + display: grid; + grid-auto-flow: row dense; + background-color: #fff; + margin: 30px auto; +} + +.border { + box-sizing: border-box; + background-color: #fff; + + &_rounded_square { + border-radius: 5px; + } + + &_circle { + border-radius: 50%; + } + + &_red { + border: 1px solid red; + } +} + +.image { + width: 100%; + height: 100%; + object-fit: cover; + + &_rounded_square { + border-radius: 5px; + } + + &_circle { + border-radius: 50%; + } +} diff --git a/src/components/PreviewForDownLoad/PreviewForDownLoad.tsx b/src/components/PreviewForDownLoad/PreviewForDownLoad.tsx new file mode 100644 index 00000000..7ffd9d6f --- /dev/null +++ b/src/components/PreviewForDownLoad/PreviewForDownLoad.tsx @@ -0,0 +1,163 @@ +import cn from 'classnames'; +import downloadjs from 'downloadjs'; +import html2canvas from 'html2canvas'; + +import { useAppDispatch } from '../../hooks/hooks'; +import { openMessage } from '../../store/popupSlice'; +import { messages } from '../../utils/content/popups'; +import { converter } from '../../utils/converter'; +import { pageSizePx, stickerWhiteBorder } from '../../utils/constants'; +import { useSelector } from 'react-redux'; +import { IStickersState } from '../../interfaces'; +import { generateRandomNumber } from '../../utils/generateRandomNumber'; +import { ButtonWithText } from '../UI'; +import { useState } from 'react'; + +import styles from './PreviewForDownLoad.module.scss'; + +export const pageSizePxOptimal = { + widthPage: pageSizePx.widthPage * 3.11, + heightPage: pageSizePx.heightPage * 3.11, + paddingList: { + top: pageSizePx.paddingList.top * 3.11, + right: pageSizePx.paddingList.right * 3.11, + bottom: pageSizePx.paddingList.bottom * 3.11, + left: pageSizePx.paddingList.left * 3.11, + }, + gapX: pageSizePx.gapX * 3.11, + gapY: pageSizePx.gapY * 3.11, +}; +const PreviewForDownLoad: React.FC = () => { + const dispatch = useAppDispatch(); + const [loading, setLoading] = useState(false); + const borderInPx = converter.mmToPx(stickerWhiteBorder); + const { pages } = useSelector((state: { stickers: IStickersState }) => state.stickers); + + const handleDownload = async () => { + await setLoading(true); + const elements = document.querySelectorAll('.page'); + if (!elements) return; + async function download() { + elements.forEach(async (element) => { + const canvas = await html2canvas(element); + const dataURL = canvas.toDataURL('image/jpeg'); + if (element.classList.contains('red-line')) { + downloadjs(dataURL, 'crop.jpeg', 'image/jpeg'); + } else downloadjs(dataURL, 'stickers.jpeg', 'image/jpeg'); + }); + } + download() + .catch(() => + dispatch( + openMessage({ + text: `${messages.somethingWrong}`, + isError: true, + }), + ), + ) + .finally(() => setTimeout(() => setLoading(false), 2000)); + }; + + return ( +
+ + Скачать макеты + + + {pages.map((elementsPage) => { + const cards = []; + for (let i = 0; i < elementsPage.length; i++) { + for (let j = 0; j < elementsPage[i].count; j++) { + cards.push(elementsPage[i].card); + } + } + return ( + <> +
+ {cards.map((card, index) => { + if (card.id === 'newSticker') { + return null; + } + + return ( +
+ +
+ ); + })} +
+ +
+ {cards.map((card, index) => { + if (card.id === 'newSticker') { + return null; + } + + return ( +
+ ); + })} +
+ + ); + })} +
+ ); +}; + +export { PreviewForDownLoad }; diff --git a/src/components/pages/AddStickers/AddStickers.module.scss b/src/components/pages/AddStickers/AddStickers.module.scss index 20a16788..78c6eac1 100644 --- a/src/components/pages/AddStickers/AddStickers.module.scss +++ b/src/components/pages/AddStickers/AddStickers.module.scss @@ -10,12 +10,23 @@ text-align: left; @include flex(column, center, flex-start); gap: 30px; + + @media screen and (max-width: 1010px) { + max-width: 100%; + } + } + @media screen and (max-width: 1010px) { + max-width: 100%; } } .content { @include flex(column, center, flex-start); gap: 30px; + + @media screen and (max-width: 1010px) { + max-width: 100%; + } } .cards { diff --git a/src/utils/_scss-variables.scss b/src/utils/_scss-variables.scss index 80807de6..563360a0 100644 --- a/src/utils/_scss-variables.scss +++ b/src/utils/_scss-variables.scss @@ -6,7 +6,7 @@ $popup-bg-color: #fff; $desktop-padding: 165px; $tablet-padding: 60px; -$mobile-padding: 24px; +$mobile-padding: 16px; $element-color: #dbe7ff; $element-secondary-color: #fff7f3; From 835803196212d59a29cc78e068db2e14f4b1a821 Mon Sep 17 00:00:00 2001 From: HanmaDaiki Date: Tue, 19 Sep 2023 17:47:14 +0300 Subject: [PATCH 2/2] feat: add converter rgbToCmyk (on work) --- .../PreviewForDownLoad/PreviewForDownLoad.tsx | 17 ++-- src/utils/converter.ts | 82 +++++++++++++++++++ 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/components/PreviewForDownLoad/PreviewForDownLoad.tsx b/src/components/PreviewForDownLoad/PreviewForDownLoad.tsx index 7ffd9d6f..bf105233 100644 --- a/src/components/PreviewForDownLoad/PreviewForDownLoad.tsx +++ b/src/components/PreviewForDownLoad/PreviewForDownLoad.tsx @@ -41,6 +41,11 @@ const PreviewForDownLoad: React.FC = () => { elements.forEach(async (element) => { const canvas = await html2canvas(element); const dataURL = canvas.toDataURL('image/jpeg'); + + const cmykURL = await converter.imageRgbToCmyk(dataURL); + if (typeof cmykURL === 'string') { + downloadjs(cmykURL, 'cmyk.jpeg', 'image/jpeg'); + } if (element.classList.contains('red-line')) { downloadjs(dataURL, 'crop.jpeg', 'image/jpeg'); } else downloadjs(dataURL, 'stickers.jpeg', 'image/jpeg'); @@ -52,8 +57,8 @@ const PreviewForDownLoad: React.FC = () => { openMessage({ text: `${messages.somethingWrong}`, isError: true, - }), - ), + }) + ) ) .finally(() => setTimeout(() => setLoading(false), 2000)); }; @@ -97,10 +102,10 @@ const PreviewForDownLoad: React.FC = () => { height: converter.cmToPx(card.height) * 3.11, padding: borderInPx * 3.11, gridRow: `span ${Math.ceil( - converter.cmToPx(card.height) * 3.11 + pageSizePxOptimal.gapY, + converter.cmToPx(card.height) * 3.11 + pageSizePxOptimal.gapY )}`, gridColumn: `span ${Math.ceil( - converter.cmToPx(card.width) * 3.11 + pageSizePxOptimal.gapX, + converter.cmToPx(card.width) * 3.11 + pageSizePxOptimal.gapX )}`, }} key={`${card.id}${index}`} @@ -142,10 +147,10 @@ const PreviewForDownLoad: React.FC = () => { height: converter.cmToPx(card.height) * 3.11, padding: borderInPx * 3.11, gridRow: `span ${Math.ceil( - converter.cmToPx(card.height) * 3.11 + pageSizePxOptimal.gapY, + converter.cmToPx(card.height) * 3.11 + pageSizePxOptimal.gapY )}`, gridColumn: `span ${Math.ceil( - converter.cmToPx(card.width) * 3.11 + pageSizePxOptimal.gapX, + converter.cmToPx(card.width) * 3.11 + pageSizePxOptimal.gapX )}`, }} key={`${card.id}${index}`} diff --git a/src/utils/converter.ts b/src/utils/converter.ts index 208b6971..f93186a1 100644 --- a/src/utils/converter.ts +++ b/src/utils/converter.ts @@ -22,6 +22,88 @@ class Converter { mmToPx(value: number): number { return value * 3.8; } + colorRgbToCmyk(r: number, g: number, b: number) { + const rs = r / 255; + const gs = g / 255; + const bs = b / 255; + const k = 1 - Math.max(rs, gs, bs); + + if(rs === 0 && gs === 0 && bs === 0) { + return { + c: 0, + m: 0, + y: 0, + k: 1, + }; + } + + const c = (1 - rs - k)/Math.round(1 - k); + const m = (1 - gs - k)/Math.round(1 - k); + const y = (1 - bs - k)/Math.round(1 - k); + + return { + c: c, + m: m, + y: y, + k: k, + }; + } + imageRgbToCmyk(imgSrc: string) { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + if (ctx) { + const image = new Image(); + + image.src = imgSrc; // Замените на путь к вашему RGB-изображению + + return new Promise((resolve, reject) => { + image.onload = function () { + // Установите размер холста в соответствии с размерами изображения + canvas.width = image.width; + canvas.height = image.height; + + // Нарисуйте изображение на холсте + ctx.drawImage(image, 0, 0); + + // Получите данные изображения + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const data = imageData.data; + + // Конвертируйте пиксели RGB в CMYK + for (let i = 0; i < data.length; i += 4) { + const b = data[i]; + const g = data[i + 1]; + const r = data[i + 2]; + const converter = new Converter(); + // Конвертируйте RGB в CMYK + const { c, m, y, k } = converter.colorRgbToCmyk(r, g, b); + + // Установите значения CMYK + data[i] = c; + data[i + 1] = m; + data[i + 2] = y; + data[i + 3] = k; + // Сохраните значение альфа-канала без изменений + } + console.log(imageData) + // Обновите холст с данными CMYK-изображения + ctx.putImageData(imageData, 0, 0); + + // Экспортируйте холст в виде нового изображения + const cmykImage = canvas.toDataURL('image/jpeg'); + + // Используйте CMYK-изображение по необходимости + resolve(cmykImage); + }; + + image.onerror = function () { + reject(new Error('Failed to load the image.')); + }; + }); + } + + return Promise.reject(new Error('Canvas context is not available.')); + } } export const converter = new Converter();