Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
csdou
QRCode
提交
bdf8a42c
Q
QRCode
项目概览
csdou
/
QRCode
与 Fork 源项目一致
Fork自
yu5025 / QRCode
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
QRCode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bdf8a42c
编写于
2月 26, 2021
作者:
MuGuiLin
🏡
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update
上级
7fb834e8
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
224 addition
and
163 deletion
+224
-163
HtmlQRCode/css/base.css
HtmlQRCode/css/base.css
+39
-19
HtmlQRCode/img/qrcode.png
HtmlQRCode/img/qrcode.png
+0
-0
HtmlQRCode/index.html
HtmlQRCode/index.html
+31
-16
HtmlQRCode/js/base.js
HtmlQRCode/js/base.js
+137
-125
README.md
README.md
+17
-3
未找到文件。
HtmlQRCode/css/base.css
浏览文件 @
bdf8a42c
...
...
@@ -3,28 +3,36 @@
padding
:
0
;
}
.h2
{
.h1
{
padding
:
10px
;
text-align
:
center
;
}
.reader
{
.menu
{
text-align
:
center
;
font-size
:
16px
;
}
.canvas
{
display
:
none
;
box-sizing
:
border-box
;
position
:
fixed
;
top
:
0
;
right
:
0
;
bottom
:
0
;
left
:
0
;
width
:
100vw
;
height
:
100vh
;
.menu
nav
{
display
:
inline-block
;
padding
:
20px
;
font-size
:
20px
;
font-weight
:
bold
;
cursor
:
pointer
;
}
.menu
nav
.active
{
color
:
#42b983
;
}
.main
{
}
.reader
.sweep
{
.main
.reader
{
text-align
:
center
;
font-size
:
16px
;
}
.main
.reader
.sweep
{
position
:
relative
;
margin
:
20px
;
padding
:
12px
;
...
...
@@ -37,18 +45,18 @@
overflow
:
hidden
;
}
.reader
.sweep
input
{
.
main
.
reader
.sweep
input
{
position
:
absolute
;
font-size
:
100px
;
opacity
:
0
;
}
.reader
.imgurl
{
.
main
.
reader
.imgurl
{
margin
:
20px
;
text-align
:
center
;
}
.reader
.imgurl
img
{
.
main
.
reader
.imgurl
img
{
margin
:
20px
;
padding
:
10px
;
border
:
1px
solid
gray
;
...
...
@@ -57,10 +65,22 @@
height
:
260px
;
}
.reader
.result
{
.
main
.
reader
.result
{
box-sizing
:
border-box
;
padding
:
10px
;
border
:
1px
solid
gray
;
border-radius
:
8px
;
font-size
:
16px
;
}
.canvas
{
display
:
none
;
box-sizing
:
border-box
;
position
:
fixed
;
top
:
0
;
right
:
0
;
bottom
:
0
;
left
:
0
;
width
:
100vw
;
height
:
100vh
;
}
\ No newline at end of file
HtmlQRCode/img/qrcode.png
0 → 100644
浏览文件 @
bdf8a42c
30.5 KB
HtmlQRCode/index.html
浏览文件 @
bdf8a42c
...
...
@@ -10,18 +10,27 @@
</head>
<body>
<h2
class=
"h2"
>
纯前端 JS :二维码:生成、扫描、识别 (HTML版)
</h2>
<menu
class=
"menu"
id=
"menu"
>
<nav>
二维码生成
</nav>
|
<nav
class=
"active"
>
二维码识别
</nav>
</menu>
<h1
class=
"h1"
>
纯前端 JS :二维码:生成、扫描、识别 (HTML版)
</h1>
<hr
/>
<main
class=
"reader"
>
<button
class=
"sweep"
onclick=
"sweep()"
>
扫一扫
</button>
<button
class=
"sweep"
>
<input
type=
"file"
id=
"file"
onchange=
"upload()"
/>
从相册选择
</button>
<div
class=
"imgurl"
>
<img
id=
"imgurl"
src=
"https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/github.com.png"
alt=
"当前识别的二维码"
/>
<main
class=
"main"
>
<div
class=
"reader"
>
<button
class=
"sweep"
onclick=
"sweep()"
>
扫一扫
</button>
<button
class=
"sweep"
>
<input
type=
"file"
id=
"file"
onchange=
"upload()"
/>
从相册选择
</button>
<div
class=
"imgurl"
>
<img
id=
"imgurl"
src=
"https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/github.com.png"
alt=
"当前识别的二维码"
/>
</div>
<textarea
class=
"result"
id=
"result"
cols=
"32"
rows=
"6"
placeholder=
"二维码识别结果!"
></textarea>
</div>
<textarea
class=
"result"
id=
"result"
cols=
"32"
rows=
"6"
placeholder=
"二维码识别结果!"
></textarea>
</main>
<canvas
class=
"canvas"
id=
"canvas"
></canvas>
...
...
@@ -31,22 +40,28 @@
<script
src=
"./js/base.js"
></script>
<script>
const
result
=
document
.
querySelector
(
'
#result
'
);
const
QrCode
=
new
QrCodeRecognition
({
id
:
'
#canvas
'
,
seuccess
:
function
(
res
)
{
document
.
querySelector
(
'
#result
'
).
value
=
res
.
data
;
},
sweepId
:
'
#canvas
'
,
// 扫一扫
uploadId
:
'
#file
'
,
// 从相册选择
error
:
function
(
err
)
{
document
.
querySelector
(
'
#result
'
).
value
=
err
;
console
.
error
(
err
);
// 识别错误反馈
result
.
value
=
err
;
},
seuccess
:
function
(
res
)
{
// 识别成功反馈
result
.
value
=
res
.
data
;
}
});
function
sweep
()
{
QrCode
.
init
();
result
.
value
=
''
;
QrCode
.
sweep
();
}
function
upload
()
{
result
.
value
=
''
;
QrCode
.
upload
();
}
...
...
HtmlQRCode/js/base.js
浏览文件 @
bdf8a42c
class
QrCodeRecognition
{
constructor
(
opts
=
{})
{
this
.
timer
=
null
;
this
.
result
=
""
;
this
.
isAnimation
=
true
;
this
.
lineWidth
=
opts
.
borderWidth
||
3
;
this
.
strokeStyle
=
opts
.
lineColor
||
'
red
'
;
this
.
audio
=
new
Audio
(
opts
.
audio
||
'
./js/tone.mp3
'
);
this
.
video
=
document
.
createElement
(
'
video
'
);
this
.
cvsele
=
document
.
querySelector
(
opts
.
id
);
this
.
canvas
=
this
.
cvsele
.
getContext
(
'
2d
'
);
this
.
seuccess
=
opts
.
seuccess
||
Function
;
this
.
error
=
opts
.
error
||
Function
;
};
;
(
function
(
window
,
QrCodeRecognition
)
{
"
use strict
"
;
draw
(
begin
,
end
)
{
this
.
canvas
.
beginPath
();
this
.
canvas
.
moveTo
(
begin
.
x
,
begin
.
y
);
this
.
canvas
.
lineTo
(
end
.
x
,
end
.
y
);
this
.
canvas
.
lineWidth
=
this
.
lineWidth
;
this
.
canvas
.
strokeStyle
=
this
.
strokeStyle
;
this
.
canvas
.
stroke
();
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
define
(
QrCodeRecognition
());
}
else
if
(
typeof
exports
===
'
object
'
)
{
module
.
exports
=
QrCodeRecognition
();
}
else
{
window
.
QrCodeRecognition
=
QrCodeRecognition
();
};
sweep
()
{
if
(
this
.
video
.
readyState
===
this
.
video
.
HAVE_ENOUGH_DATA
)
{
const
{
videoWidth
,
videoHeight
}
=
this
.
video
;
this
.
cvsele
.
width
=
videoWidth
;
this
.
cvsele
.
height
=
videoHeight
;
this
.
canvas
.
drawImage
(
this
.
video
,
0
,
0
,
videoWidth
,
videoHeight
);
try
{
const
img
=
this
.
canvas
.
getImageData
(
0
,
0
,
videoWidth
,
videoHeight
);
document
.
querySelector
(
'
#imgurl
'
).
src
=
img
;
const
obj
=
jsQR
(
img
.
data
,
img
.
width
,
img
.
height
,
{
inversionAttempts
:
'
dontInvert
'
});
if
(
obj
)
{
const
loc
=
obj
.
location
;
this
.
draw
(
loc
.
topLeftCorner
,
loc
.
topRightCorner
);
this
.
draw
(
loc
.
topRightCorner
,
loc
.
bottomRightCorner
);
this
.
draw
(
loc
.
bottomRightCorner
,
loc
.
bottomLeftCorner
);
this
.
draw
(
loc
.
bottomLeftCorner
,
loc
.
topLeftCorner
);
if
(
this
.
result
!=
obj
.
data
)
{
this
.
audio
.
play
();
this
.
seuccess
(
obj
);
this
.
isAnimation
=
false
;
cancelAnimationFrame
(
this
.
timer
);
console
.
info
(
"
识别结果:
"
,
obj
.
data
);
setTimeout
(()
=>
{
this
.
cvsele
.
style
.
display
=
"
none
"
;
},
1000
);
}
}
else
{
this
.
error
(
"
识别失败,请检查二维码是否正确!
"
);
console
.
error
(
"
识别失败,请检查二维码是否正确!
"
);
}
}
catch
(
err
)
{
this
.
error
(
err
);
console
.
error
(
"
识别失败,请检查二维码是否正确!
"
,
err
);
};
}(
typeof
window
!==
"
undefined
"
?
window
:
this
,
()
=>
{
"
use strict
"
;
return
class
QrCodeRecognition
{
constructor
(
opts
=
{})
{
this
.
timer
=
null
;
this
.
result
=
""
;
this
.
isAnimation
=
true
;
this
.
lineWidth
=
opts
.
borderWidth
||
3
;
this
.
strokeStyle
=
opts
.
lineColor
||
'
red
'
;
this
.
audio
=
new
Audio
(
opts
.
audio
||
'
./js/tone.mp3
'
);
this
.
video
=
document
.
createElement
(
'
video
'
);
this
.
file
=
document
.
querySelector
(
opts
.
uploadId
);
this
.
cvsele
=
document
.
querySelector
(
opts
.
sweepId
);
this
.
canvas
=
this
.
cvsele
.
getContext
(
'
2d
'
);
this
.
seuccess
=
opts
.
seuccess
||
Function
;
this
.
error
=
opts
.
error
||
Function
;
};
if
(
this
.
isAnimation
)
{
this
.
timer
=
requestAnimationFrame
(()
=>
{
this
.
sweep
();
});
}
};
upload
()
{
const
ele
=
document
.
querySelector
(
'
#file
'
);
const
file
=
ele
.
files
[
0
];
const
createObjectURL
=
window
.
createObjectURL
||
window
.
URL
.
createObjectURL
||
window
.
webkitURL
.
createObjectUR
;
document
.
querySelector
(
'
#result
'
).
value
=
''
;
draw
(
begin
,
end
)
{
this
.
canvas
.
beginPath
();
this
.
canvas
.
moveTo
(
begin
.
x
,
begin
.
y
);
this
.
canvas
.
lineTo
(
end
.
x
,
end
.
y
);
this
.
canvas
.
lineWidth
=
this
.
lineWidth
;
this
.
canvas
.
strokeStyle
=
this
.
strokeStyle
;
this
.
canvas
.
stroke
();
};
cance
()
{
this
.
isAnimation
=
false
;
cancelAnimationFrame
(
this
.
timer
);
setTimeout
(()
=>
{
this
.
cvsele
.
style
.
display
=
"
none
"
;
},
1000
);
};
const
fReader
=
new
FileReader
();
fReader
.
readAsDataURL
(
file
);
// Base64 8Bit字节码
// fReader.readAsBinaryString(file); // Binary 原始二进制
// fReader.readAsArrayBuffer(file); // ArrayBuffer 文件流
fReader
.
onload
=
(
e
)
=>
{
document
.
querySelector
(
'
#imgurl
'
).
src
=
e
.
target
.
result
||
createObjectURL
(
file
);
e
.
target
.
result
&&
Jimp
.
read
(
e
.
target
.
result
).
then
(
async
(
res
)
=>
{
const
{
data
,
width
,
height
}
=
res
.
bitmap
;
untie
()
{
if
(
this
.
video
.
readyState
===
this
.
video
.
HAVE_ENOUGH_DATA
)
{
const
{
videoWidth
,
videoHeight
}
=
this
.
video
;
this
.
cvsele
.
width
=
videoWidth
;
this
.
cvsele
.
height
=
videoHeight
;
this
.
canvas
.
drawImage
(
this
.
video
,
0
,
0
,
videoWidth
,
videoHeight
);
try
{
const
resolve
=
await
jsQR
(
data
,
width
,
height
);
this
.
audio
.
play
();
this
.
seuccess
(
resolve
);
console
.
info
(
"
识别结果:
"
,
resolve
.
data
);
const
img
=
this
.
canvas
.
getImageData
(
0
,
0
,
videoWidth
,
videoHeight
);
document
.
querySelector
(
'
#imgurl
'
).
src
=
img
;
const
obj
=
jsQR
(
img
.
data
,
img
.
width
,
img
.
height
,
{
inversionAttempts
:
'
dontInvert
'
});
if
(
obj
)
{
const
loc
=
obj
.
location
;
this
.
draw
(
loc
.
topLeftCorner
,
loc
.
topRightCorner
);
this
.
draw
(
loc
.
topRightCorner
,
loc
.
bottomRightCorner
);
this
.
draw
(
loc
.
bottomRightCorner
,
loc
.
bottomLeftCorner
);
this
.
draw
(
loc
.
bottomLeftCorner
,
loc
.
topLeftCorner
);
if
(
this
.
result
!=
obj
.
data
)
{
this
.
audio
.
play
();
this
.
cance
();
this
.
seuccess
(
obj
);
}
}
else
{
this
.
error
(
"
识别失败,请检查二维码是否正确!
"
);
}
}
catch
(
err
)
{
this
.
error
(
"
识别失败,请检查二维码是否正确!
"
);
console
.
error
(
"
识别失败,请检查二维码是否正确!
"
,
err
);
}
finally
{
console
.
info
(
"
读取到的文件:
"
,
res
);
}
}).
catch
((
err
)
=>
{
this
.
error
(
"
文件读取错误:
"
,
err
);
console
.
error
(
"
文件读取错误:
"
,
err
);
});
this
.
error
(
"
识别失败,请检查二维码是否正确!
"
,
err
);
};
};
if
(
this
.
isAnimation
)
{
this
.
timer
=
requestAnimationFrame
(()
=>
{
this
.
untie
();
});
}
};
};
init
()
{
this
.
isAnimation
=
true
;
this
.
cvsele
.
style
.
display
=
"
block
"
;
navigator
.
getUserMedia
=
navigator
.
getUserMedia
||
navigator
.
webkitGetUserMedia
||
navigator
.
mozGetUserMedia
||
navigator
.
msGetUserMedia
;
if
(
navigator
.
mediaDevices
)
{
navigator
.
mediaDevices
.
getUserMedia
({
video
:
{
facingMode
:
"
environment
"
}
}).
then
(
stream
=>
{
this
.
video
.
srcObject
=
stream
;
this
.
video
.
setAttribute
(
'
playsinline
'
,
true
);
this
.
video
.
setAttribute
(
'
webkit-playsinline
'
,
true
);
this
.
video
.
addEventListener
(
'
loadedmetadata
'
,
()
=>
{
this
.
video
.
play
();
this
.
sweep
();
sweep
()
{
this
.
isAnimation
=
true
;
this
.
cvsele
.
style
.
display
=
"
block
"
;
navigator
.
getUserMedia
=
navigator
.
getUserMedia
||
navigator
.
webkitGetUserMedia
||
navigator
.
mozGetUserMedia
||
navigator
.
msGetUserMedia
;
if
(
navigator
.
mediaDevices
)
{
navigator
.
mediaDevices
.
getUserMedia
({
video
:
{
facingMode
:
"
environment
"
}
}).
then
(
stream
=>
{
this
.
video
.
srcObject
=
stream
;
this
.
video
.
setAttribute
(
'
playsinline
'
,
true
);
this
.
video
.
setAttribute
(
'
webkit-playsinline
'
,
true
);
this
.
video
.
addEventListener
(
'
loadedmetadata
'
,
()
=>
{
this
.
video
.
play
();
this
.
untie
();
});
}).
catch
(
error
=>
{
console
.
error
(
error
.
name
+
"
:
"
+
error
.
message
+
"
,
"
+
error
.
constraint
);
});
}
).
catch
(
error
=>
{
console
.
error
(
error
.
name
+
"
:
"
+
error
.
message
+
"
,
"
+
error
.
constraint
);
});
}
else
if
(
navigator
.
getUserMedia
)
{
navigator
.
getUserMedia
({
video
:
{
facingMode
:
"
environment
"
}
},
(
stream
)
=>
{
this
.
video
.
srcObject
=
stream
;
this
.
video
.
setAttribute
(
'
playsinline
'
,
true
);
this
.
video
.
setAttribute
(
'
webkit-playsinline
'
,
true
);
this
.
video
.
addEventListener
(
'
loadedmetadata
'
,
()
=>
{
this
.
video
.
play
();
this
.
sweep
(
);
}
else
if
(
navigator
.
getUserMedia
)
{
navigator
.
getUserMedia
({
video
:
{
facingMode
:
"
environment
"
}
},
(
stream
)
=>
{
this
.
video
.
srcObject
=
stream
;
this
.
video
.
setAttribute
(
'
playsinline
'
,
true
);
this
.
video
.
setAttribute
(
'
webkit-playsinline
'
,
true
);
this
.
video
.
addEventListener
(
'
loadedmetadata
'
,
()
=>
{
this
.
video
.
play
(
);
this
.
untie
(
);
});
},
(
error
)
=>
{
console
.
error
(
error
.
name
+
"
:
"
+
error
.
message
+
"
,
"
+
error
.
constraint
);
});
},
(
error
)
=>
{
console
.
error
(
error
.
name
+
"
:
"
+
error
.
message
+
"
,
"
+
error
.
constraint
);
});
}
else
{
if
(
navigator
.
userAgent
.
toLowerCase
().
match
(
/chrome/
)
&&
location
.
origin
.
indexOf
(
'
https://
'
)
<
0
)
{
console
.
error
(
'
获取浏览器录音功能,因安全性问题,需要在localhost 或 127.0.0.1 或 https 下才能获取权限!
'
);
}
else
{
alert
(
'
对不起:未识别到扫描设备!
'
);
}
if
(
navigator
.
userAgent
.
toLowerCase
().
match
(
/chrome/
)
&&
location
.
origin
.
indexOf
(
'
https://
'
)
<
0
)
{
console
.
error
(
'
获取浏览器录音功能,因安全性问题,需要在localhost 或 127.0.0.1 或 https 下才能获取权限!
'
);
}
else
{
alert
(
'
对不起:未识别到扫描设备!
'
);
}
};
};
upload
()
{
this
.
cance
();
const
file
=
this
.
file
.
files
[
0
];
const
createObjectURL
=
window
.
createObjectURL
||
window
.
URL
.
createObjectURL
||
window
.
webkitURL
.
createObjectUR
;
const
fReader
=
new
FileReader
();
fReader
.
readAsDataURL
(
file
);
// Base64 8Bit字节码
// fReader.readAsBinaryString(file); // Binary 原始二进制
// fReader.readAsArrayBuffer(file); // ArrayBuffer 文件流
fReader
.
onload
=
(
e
)
=>
{
document
.
querySelector
(
'
#imgurl
'
).
src
=
e
.
target
.
result
||
createObjectURL
(
file
);
e
.
target
.
result
&&
Jimp
.
read
(
e
.
target
.
result
).
then
(
async
(
res
)
=>
{
const
{
data
,
width
,
height
}
=
res
.
bitmap
;
try
{
const
resolve
=
await
jsQR
(
data
,
width
,
height
);
this
.
audio
.
play
();
this
.
seuccess
(
resolve
);
}
catch
(
err
)
{
this
.
error
(
"
识别失败,请检查二维码是否正确!
"
,
err
);
}
finally
{
console
.
info
(
"
读取到的文件:
"
,
res
);
}
}).
catch
((
err
)
=>
{
this
.
error
(
"
文件读取错误:
"
,
err
);
});
};
};
}
};
\ No newline at end of file
};
}));
\ No newline at end of file
README.md
浏览文件 @
bdf8a42c
...
...
@@ -2,16 +2,30 @@
GitHub:
[
https://github.com/MuGuiLin/QRCode
](
https://github.com/MuGuiLin/QRCode
)
### 纯前端 HTML / Vue :二维码:生成、扫描、识别
### 纯前端 HTML / Vue :二维码:生成、扫描、识别
、解析、扫一扫
> 该Demo功能共分为:HTML版 和 Vue版 两个版本!
>
> 不依赖任何关于微信环境、微信JS-SDK,微信受权等!
>
> 支持二维码生成,实时动态生成和渲染!
>
> 支持扫一扫识别,从相册选择二维码识别!
>
> 支持PC端,手机移动端等!
### HTML版 Demo实例效果:
![
二维码识别
](
https://raw.githubusercontent.com/MuGuiLin/QRCode/master/HtmlQRCode/img/qrcode.png
)
### Vue.js版 Demo实例效果:
![
二维生成
](
https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/create.png
)
![
二维
码
生成
](
https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/create.png
)
------
![
二维生成
](
https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/qrcode.png
)
\ No newline at end of file
![
二维码识别
](
https://raw.githubusercontent.com/MuGuiLin/QRCode/master/VueQRCode/src/assets/qrcode.png
)
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录