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/Qrcode.css b/src/components/Qrcode.css index 97b1289..554cdaa 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,61 @@ 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 #000000; +} + +.Qr-article p a:hover { + color: #000000; + border-bottom: 1px solid #000000; + text-decoration: none; +} + +.Qr-article h2 { + word-break: break-all; + word-wrap: break-word; + font-size: 18px; + line-height: 1.7em; + letter-spacing: 0.05em; + margin-top: 1.5em; + margin-bottom: 1.5em; +} + @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/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/app/PartMore.js b/src/components/app/PartMore.js index b89b139..0eafec8 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 = () => (
- - +
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 6633206..6920211 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]/100; + let exposure = params[2]/100; 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) + exposure - 0.5) * (contrast + 1) + 0.5 && ( 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, qrcode]) return ( ( -