From fe53e88d9c3c323bca28b1803256ed424ac992b1 Mon Sep 17 00:00:00 2001 From: ciaochaos <1272777550@qq.com> Date: Fri, 15 May 2020 22:36:00 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/shenma-site-verification.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/shenma-site-verification.txt diff --git a/public/shenma-site-verification.txt b/public/shenma-site-verification.txt new file mode 100644 index 0000000..929a411 --- /dev/null +++ b/public/shenma-site-verification.txt @@ -0,0 +1 @@ +shenma-site-verification:d4fbd6b4291052fe30f66a678aff6481_1589553349 \ No newline at end of file From cf481b9e6bcc2ed441e867b3821254d2c51ff62f Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Sat, 16 May 2020 12:31:10 +0800 Subject: [PATCH 2/9] fixed database --- src/containers/app/PartDownloadViewer.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/containers/app/PartDownloadViewer.js b/src/containers/app/PartDownloadViewer.js index bbb2fac..1db318b 100644 --- a/src/containers/app/PartDownloadViewer.js +++ b/src/containers/app/PartDownloadViewer.js @@ -2,40 +2,36 @@ import { connect } from 'react-redux'; import PartDownload from "../../components/app/PartDownload"; import React from "react"; import {saveImg, saveSvg} from "../../utils/downloader"; -import ReactDOMServer from "react-dom/server"; import {increaseDownloadData, recordDownloadDetail} from "../../api/db"; import {getParamDetailedValue, outerHtml} from "../../utils/util"; -function saveEl(state, type) { - const el = React.createElement(state.rendererType, { - qrcode: state.qrcode, - params: state.paramValue[state.selectedIndex], - setParamInfo: () => {} - }); +function saveDB(state, type) { increaseDownloadData(state.value) recordDownloadDetail({ text: state.textUrl, value: state.value, type: type, params: state.paramInfo[state.selectedIndex].map((item, index) => { - return { - key: item.key, - value: getParamDetailedValue(item, state.paramValue[state.selectedIndex][index]) + const value = getParamDetailedValue(item, state.paramValue[state.selectedIndex][index]) + if (typeof value != "string" || value.length <= 128) { + return { + key: item.key, + value: value + } } }), history: state.history }); - return el; } const mapStateToProps = (state) => ({ value: state.value, onSvgDownload: () => { - // saveSvg(state.value, ReactDOMServer.renderToString(saveEl(state, 'svg'))) saveSvg(state.value, outerHtml(state.selectedIndex)) + saveDB(state, 'svg') }, onJpgDownload: () => { - // return saveImg(state.value, ReactDOMServer.renderToString(saveEl(state, 'jpg')), 1500, 1500) + saveDB(state, 'jpg') return saveImg(state.value, outerHtml(state.selectedIndex), 1500, 1500) } }) From 17d70a4327be952978b37fe4548602ededf06bca Mon Sep 17 00:00:00 2001 From: ciaochaos <1272777550@qq.com> Date: Sun, 17 May 2020 19:53:41 +0800 Subject: [PATCH 3/9] =?UTF-8?q?C2=20=E6=A0=B7=E5=BC=8F=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=9B=9D=E5=85=89=E5=BA=A6=E4=B8=8E=E5=AF=B9=E6=AF=94=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/renderer/RendererResImage.js | 35 ++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/components/renderer/RendererResImage.js b/src/components/renderer/RendererResImage.js index 6633206..7c349f5 100644 --- a/src/components/renderer/RendererResImage.js +++ b/src/components/renderer/RendererResImage.js @@ -9,10 +9,12 @@ function listPoints(qrcode, params) { const nCount = qrcode.getModuleCount(); const typeTable = getTypeTable(qrcode); const pointList = new Array(nCount); - let alignType = params[1]; - let timingType = params[2]; - let otherColor = params[3]; - let posColor = params[4]; + let contrast = params[1]; + let exposure = params[2]; + let alignType = params[3]; + let timingType = params[4]; + let otherColor = params[5]; + let posColor = params[6]; let id = 0; for (let x = 0; x < nCount; x++) { @@ -74,6 +76,16 @@ function getParamInfo() { key: '背景图片', default: data, }, + { + type: ParamTypes.TEXT_EDITOR, + key: '对比度', + default: 0 + }, + { + type: ParamTypes.TEXT_EDITOR, + key: '曝光', + default: 0 + }, { type: ParamTypes.SELECTOR, key: '小定位点样式', @@ -114,7 +126,7 @@ export function getViewBox(qrcode) { return String(-nCount / 5) + ' ' + String(-nCount / 5) + ' ' + String(nCount + nCount / 5 * 2) + ' ' + String(nCount + nCount / 5 * 2); } -function getGrayPointList(imgBase64, size, black, white) { +function getGrayPointList(params, size, black, white) { let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); let img = document.createElement('img'); @@ -122,7 +134,9 @@ function getGrayPointList(imgBase64, size, black, white) { canvas.style.imageRendering = 'pixelated'; size *= 3; - img.src = imgBase64; + img.src = params[0]; + let contrast = params[1]; + let exposure = params[2]; return new Promise(resolve => { img.onload = () => { canvas.width = size; @@ -135,7 +149,7 @@ function getGrayPointList(imgBase64, size, black, white) { let imageData = ctx.getImageData(x, y, 1, 1); let data = imageData.data; let gray = gamma(data[0], data[1], data[2]); - if (Math.random() > gray / 255 && ( x % 3 !== 1 || y % 3 !== 1 ) ) gpl.push(); + if (Math.random() > ((gray / 255) - 0.5) * (contrast + 1) + 0.5 + exposure && ( x % 3 !== 1 || y % 3 !== 1 ) ) gpl.push(); } } resolve(gpl); @@ -144,8 +158,7 @@ function getGrayPointList(imgBase64, size, black, white) { } const RendererResImage = ({qrcode, params, setParamInfo}) => { - let otherColor = params[3]; - let posColor = params[4]; + let otherColor = params[5]; useEffect(() => { setParamInfo(getParamInfo()); @@ -153,8 +166,8 @@ const RendererResImage = ({qrcode, params, setParamInfo}) => { const [gpl, setGPL] = useState([]); useMemo(() => { - getGrayPointList(params[0], qrcode.getModuleCount(), "#S-black", "#S-white").then(res => setGPL(res)); - }, [setGPL, params[0], qrcode]) + getGrayPointList(params, qrcode.getModuleCount(), "#S-black", "#S-white").then(res => setGPL(res)); + }, [setGPL, params[0], params[1], params[2], qrcode]) return ( Date: Sun, 17 May 2020 19:59:41 +0800 Subject: [PATCH 4/9] =?UTF-8?q?C2=20=E6=A0=B7=E5=BC=8F=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=9B=9D=E5=85=89=E5=BA=A6=E4=B8=8E=E5=AF=B9=E6=AF=94=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/renderer/RendererResImage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/renderer/RendererResImage.js b/src/components/renderer/RendererResImage.js index 7c349f5..deb0909 100644 --- a/src/components/renderer/RendererResImage.js +++ b/src/components/renderer/RendererResImage.js @@ -135,8 +135,8 @@ function getGrayPointList(params, size, black, white) { size *= 3; img.src = params[0]; - let contrast = params[1]; - let exposure = params[2]; + let contrast = params[1]/100; + let exposure = params[2]/100; return new Promise(resolve => { img.onload = () => { canvas.width = size; From a0c0055c0f86d7da66ce9acd401d0a824c8eaca9 Mon Sep 17 00:00:00 2001 From: ciaochaos <1272777550@qq.com> Date: Sun, 17 May 2020 20:14:58 +0800 Subject: [PATCH 5/9] =?UTF-8?q?C2=20=E6=A0=B7=E5=BC=8F=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=9B=9D=E5=85=89=E5=BA=A6=E4=B8=8E=E5=AF=B9=E6=AF=94=E5=BA=A6?= =?UTF-8?q?=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/renderer/RendererResImage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/renderer/RendererResImage.js b/src/components/renderer/RendererResImage.js index deb0909..345ec6b 100644 --- a/src/components/renderer/RendererResImage.js +++ b/src/components/renderer/RendererResImage.js @@ -149,7 +149,7 @@ function getGrayPointList(params, size, black, white) { let imageData = ctx.getImageData(x, y, 1, 1); let data = imageData.data; let gray = gamma(data[0], data[1], data[2]); - if (Math.random() > ((gray / 255) - 0.5) * (contrast + 1) + 0.5 + exposure && ( x % 3 !== 1 || y % 3 !== 1 ) ) gpl.push(); + if (Math.random() > ((gray / 255) + exposure - 0.5) * (contrast + 1) + 0.5 && ( x % 3 !== 1 || y % 3 !== 1 ) ) gpl.push(); } } resolve(gpl); From 39ff33e1a2c09bb3d25a02c7933bb9baa7684352 Mon Sep 17 00:00:00 2001 From: ciaochaos <1272777550@qq.com> Date: Mon, 18 May 2020 17:21:32 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=9B=B4=E5=A4=9A=E5=A4=84=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=BB=8B=E7=BB=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Qrcode.css | 47 ++++++++++++++++++++++++++++++++++ src/components/app/PartMore.js | 17 ++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/components/Qrcode.css b/src/components/Qrcode.css index 97b1289..31a77e0 100644 --- a/src/components/Qrcode.css +++ b/src/components/Qrcode.css @@ -1,3 +1,4 @@ + .Qr-titled { background-color: #f5f5f7; box-sizing: border-box; @@ -461,11 +462,57 @@ a:hover { font-size: 12px; } +.Qr-article { + word-wrap: break-word; + margin-top: calc((10px + 1vmin) * 2); + margin-bottom: calc((10px + 2vmin) * 2); + border-spacing: 0; +} + +.Qr-article p { + font-size: 14px; + line-height: 1.7em; + color: #636366; + letter-spacing: 0.05em; +} + +.Qr-article p b { + font-weight: bold; + color: #000000; +} + +.Qr-article p a { + font-weight: bold; + padding: 1px 0; + color: #000000; + border-bottom: 1px solid #3e4ca3; +} + +.Qr-article p a:hover { + color: #000000; + border-bottom: 1px solid #3e4ca3; + text-decoration: none; +} + +.Qr-article h2 { + font-size: 18px; + line-height: 2.5em; + letter-spacing: 0.05em; +} + @media (min-width: 500px) { .note-font { color: #1D1D1F; font-size: 14px; } + + .Qr-article p { + font-size: 16px; + } + + .Qr-article h2 { + font-size: 22px; + } } select { diff --git a/src/components/app/PartMore.js b/src/components/app/PartMore.js index b89b139..ff2a7bf 100644 --- a/src/components/app/PartMore.js +++ b/src/components/app/PartMore.js @@ -7,6 +7,20 @@ const PartMore = () => (
More

更多

+
+

为什么要做一个二维码生成器?

+

看这里,我写的 文章

+

这个生成器的特别之处在哪里?

+

普通的二维码样式单一,不能与环境较好的融合。这一个生成器有着 丰富的参数化样式、基于 SVG 的二维码生成能力,在为我们提供精美样式的同时,不限制参数如数值、颜色、背景图片的选择,又因 SVG 有较好的拓展性,可以完美兼容矢量制图流程。

+

如何使用?

+

从输入 URL 开始。没有确认框,没有额外的页面,选择样式后自动更新,调整参数后下载即可。

+

我应该下载 SVG 还是 JPG?

+

这个工具开发的初衷之一就是便利设计师将其纳入自己的工作流程中。SVG 是一个优秀的、标准的矢量图片格式,各大设计软件如 Adobe Illustrator、Sketch 等都对 SVG 有着很好的支持。用户可以在下载 SVG 后导入这些软件进行二次加工,如删除中央的信息点 放入自己的 Logo 等。如果需要直接分享二维码图像,请直接下载 JPG 格式。

+

使用遇到了问题,怎么反馈?

+

我们是两位大一的学生,忙于学业,可能在设计与开发的过程中有一些疏漏,敬请谅解。如果遇到浏览器兼容问题,请暂时选择更换软件或设备尝试。经常有人问,怎么把已有的公众号二维码上传,很抱歉的是,目前我们并没有开发这个功能,将来一定实现,如有需要请暂时使用第三方软件解码。也有人问,为什么电脑端右边的样式没显示全,不是 bug,只是我们懒得做切换滑动按钮,目前请按住 Shift 使用滚轮在样式区域滚动,一定能行。

+

请注意,应用并不能保证二维码时刻可被识别,需要多加测试。

+

如果你有兴趣和我们一起玩这个项目,设计样式、开发应用,欢迎点击下方的按钮加微信联系我们!

+
@@ -14,8 +28,7 @@ const PartMore = () => (
- - +
From febce0c79e775ee412d69a184363b1dac7d03539 Mon Sep 17 00:00:00 2001 From: ciaochaos <1272777550@qq.com> Date: Mon, 18 May 2020 17:33:16 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E4=BB=8B=E7=BB=8D=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/shenma-site-verification.txt | 1 - src/components/Qrcode.css | 6 +++++- src/components/app/PartMore.js | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) delete mode 100644 public/shenma-site-verification.txt diff --git a/public/shenma-site-verification.txt b/public/shenma-site-verification.txt deleted file mode 100644 index 929a411..0000000 --- a/public/shenma-site-verification.txt +++ /dev/null @@ -1 +0,0 @@ -shenma-site-verification:d4fbd6b4291052fe30f66a678aff6481_1589553349 \ No newline at end of file diff --git a/src/components/Qrcode.css b/src/components/Qrcode.css index 31a77e0..0e70bb3 100644 --- a/src/components/Qrcode.css +++ b/src/components/Qrcode.css @@ -495,9 +495,13 @@ a:hover { } .Qr-article h2 { + word-break: break-all; + word-wrap: break-word; font-size: 18px; - line-height: 2.5em; + line-height: 1.7em; letter-spacing: 0.05em; + margin-top: 1.5em; + margin-bottom: 1.5em; } @media (min-width: 500px) { diff --git a/src/components/app/PartMore.js b/src/components/app/PartMore.js index ff2a7bf..0eafec8 100644 --- a/src/components/app/PartMore.js +++ b/src/components/app/PartMore.js @@ -9,7 +9,7 @@ const PartMore = () => (

更多

为什么要做一个二维码生成器?

-

看这里,我写的 文章

+

看这里,这篇文章 简要介绍了我们的初心与愿景。

这个生成器的特别之处在哪里?

普通的二维码样式单一,不能与环境较好的融合。这一个生成器有着 丰富的参数化样式、基于 SVG 的二维码生成能力,在为我们提供精美样式的同时,不限制参数如数值、颜色、背景图片的选择,又因 SVG 有较好的拓展性,可以完美兼容矢量制图流程。

如何使用?

From 52b2b75f9540e90c18675e2c986c60b3deba1e2e Mon Sep 17 00:00:00 2001 From: ciaochaos <1272777550@qq.com> Date: Mon, 18 May 2020 17:51:44 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E4=BB=8B=E7=BB=8D=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Qrcode.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Qrcode.css b/src/components/Qrcode.css index 0e70bb3..554cdaa 100644 --- a/src/components/Qrcode.css +++ b/src/components/Qrcode.css @@ -485,12 +485,12 @@ a:hover { font-weight: bold; padding: 1px 0; color: #000000; - border-bottom: 1px solid #3e4ca3; + border-bottom: 1px solid #000000; } .Qr-article p a:hover { color: #000000; - border-bottom: 1px solid #3e4ca3; + border-bottom: 1px solid #000000; text-decoration: none; } From e26b286079c8e1d1214ca0860a21b3cee4055ee0 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Tue, 19 May 2020 12:36:23 +0800 Subject: [PATCH 9/9] [QR scan] --- package-lock.json | 5 ++ package.json | 1 + src/components/app/App.js | 8 +-- .../{footer/Footer.js => app/PartFooter.js} | 4 +- .../{header/Header.js => app/PartHeader.js} | 4 +- src/components/renderer/RendererRandRect.js | 2 - src/components/renderer/RendererResImage.js | 2 +- src/constant/ActionTypes.js | 2 +- src/containers/app/InputText.js | 64 +++++++++++++++---- src/containers/app/PartDownloadViewer.js | 1 - src/containers/param/ParamUploadViewer.js | 14 +--- src/containers/style/StyleListViewer.js | 5 +- src/reducers/index.js | 8 +-- src/utils/{qrcode.js => qrcodeEncoder.js} | 3 +- src/utils/qrcodeHandler.js | 30 ++++++++- src/utils/util.js | 13 +++- 16 files changed, 114 insertions(+), 52 deletions(-) rename src/components/{footer/Footer.js => app/PartFooter.js} (95%) rename src/components/{header/Header.js => app/PartHeader.js} (91%) rename src/utils/{qrcode.js => qrcodeEncoder.js} (99%) diff --git a/package-lock.json b/package-lock.json index c7d0a6f..49f28e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8091,6 +8091,11 @@ "verror": "1.10.0" } }, + "jsqr": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/jsqr/download/jsqr-1.3.1.tgz", + "integrity": "sha1-UVp2bliwDIAULzotxLh1EQDO7c8=" + }, "jsx-ast-utils": { "version": "2.2.3", "resolved": "https://registry.npm.taobao.org/jsx-ast-utils/download/jsx-ast-utils-2.2.3.tgz", diff --git a/package.json b/package.json index a5c0897..b91ac60 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", + "jsqr": "^1.3.1", "prop-types": "^15.7.2", "react": "^16.13.1", "react-color": "^2.18.1", diff --git a/src/components/app/App.js b/src/components/app/App.js index 4318bae..be8419b 100644 --- a/src/components/app/App.js +++ b/src/components/app/App.js @@ -1,8 +1,8 @@ import React from 'react'; import './App.css'; import '../Qrcode.css'; -import Footer from "../footer/Footer"; -import Header from "../header/Header"; +import PartFooter from "./PartFooter"; +import PartHeader from "./PartHeader"; import PartMore from "./PartMore"; import PartParams from "./PartParams"; import PartDownloadViewer from "../../containers/app/PartDownloadViewer"; @@ -14,12 +14,12 @@ function App() {
-
+ -
+
diff --git a/src/components/footer/Footer.js b/src/components/app/PartFooter.js similarity index 95% rename from src/components/footer/Footer.js rename to src/components/app/PartFooter.js index 1950b93..fe5bee6 100644 --- a/src/components/footer/Footer.js +++ b/src/components/app/PartFooter.js @@ -3,7 +3,7 @@ import '../Qrcode.css'; const currentYear = new Date().getFullYear(); -const Footer = () => ( +const PartFooter = () => (
@@ -33,4 +33,4 @@ const Footer = () => (
) -export default Footer +export default PartFooter diff --git a/src/components/header/Header.js b/src/components/app/PartHeader.js similarity index 91% rename from src/components/header/Header.js rename to src/components/app/PartHeader.js index d65d5cb..c6870de 100644 --- a/src/components/header/Header.js +++ b/src/components/app/PartHeader.js @@ -9,7 +9,7 @@ const logoStyle = { backgroundPosition: 'left' }; -const Header = () => ( +const PartHeader = () => (

@@ -19,4 +19,4 @@ const Header = () => (
) -export default Header +export default PartHeader diff --git a/src/components/renderer/RendererRandRect.js b/src/components/renderer/RendererRandRect.js index cf357bf..e2a3352 100644 --- a/src/components/renderer/RendererRandRect.js +++ b/src/components/renderer/RendererRandRect.js @@ -1,7 +1,5 @@ import React, { useEffect } from "react"; import {defaultViewBox, rand} from "../../utils/util"; -import {ParamTypes} from "../../constant/ParamTypes"; -import {getTypeTable, QRPointType} from "../../utils/qrcodeHandler"; function listPoints(qrcode, params) { if (!qrcode) return [] diff --git a/src/components/renderer/RendererResImage.js b/src/components/renderer/RendererResImage.js index 345ec6b..6920211 100644 --- a/src/components/renderer/RendererResImage.js +++ b/src/components/renderer/RendererResImage.js @@ -167,7 +167,7 @@ const RendererResImage = ({qrcode, params, setParamInfo}) => { const [gpl, setGPL] = useState([]); useMemo(() => { getGrayPointList(params, qrcode.getModuleCount(), "#S-black", "#S-white").then(res => setGPL(res)); - }, [setGPL, params[0], params[1], params[2], qrcode]) + }, [setGPL, params, qrcode]) return ( ( -