h5实现扫码二维码和识别相册二维码

1.vue组件

<template>

<qrcode-stream class="js-qr" :camera="camera" :torch="torchActive" @decode="onDecode" @init="onInit">

<div v-show="qrcode">

<div class="qr-scanner">

<div class="qr-scanner-top">

<span class="close" @click="$emit('oncloseJsQr', true)">&times;</span>

<van-uploader class="pictures" :after-read="afterRead">

<span>相册</span>

</van-uploader>

</div>

<div class="box">

<div class="line"></div>

<div class="angle"></div>

</div>

<div class="txt">

将二维码放入框内,即自动扫描

</div>

</div>

</div>

</qrcode-stream>

</template>

<script>

// 引入

import { QrcodeStream } from 'vue-qrcode-reader' // "vue-qrcode-reader": "3.1.8"

import compression from '@/utils/compression'

import QrcodeDecoder from 'qrcode-decoder' // 0.1.2

export default {

// 注册

components: { QrcodeStream },

data() {

return {

result: '', // 扫码结果信息

error: '', // 错误信息

// show: false,

// qrcode: false,

qrcode: false,

torchActive: false,

camera: 'auto'

}

},

mounted() {},

methods: {

onDecode(result) {

// alert(result)

this.result = result

this.checkCode(result)

},

checkCode(code) {

clearTimeout(this.backTimer)

this.backTimer = setTimeout(() => {

// const validated = validERC20(code) || validOMNI(code) || validTRC20(code)

// console.log(validated)

// if (validated) {

this.$emit('onsuccess', code)

this.$emit('oncloseJsQr', true)

// } else {

// console.log('不支持的二维码')

// this.$toast('不支持的二维码')

// }

}, 50)

},

afterRead(uploadRes) {

// const base64Img = file.content

compression(uploadRes.content, 500, this.dealImg)

},

dealImg(base64Img) {

const qr = new QrcodeDecoder()

qr.decodeFromImage(base64Img).then(decodeRes => {

const code = decodeRes.data

this.checkCode(code)

})

},

async onInit(promise) {

const { capabilities } = await promise

const TORCH_IS_SUPPORTED = !!capabilities.torch

try {

await promise

this.qrcode = true

} catch (error) {

if (error.name === 'NotAllowedError') {

this.error = 'ERROR: 您需要授予相机访问权限'

} else if (error.name === 'NotFoundError') {

this.error = 'ERROR: 这个设备上没有摄像头'

} else if (error.name === 'NotSupportedError') {

this.error = 'ERROR: 所需的安全上下文(HTTPS、本地主机)'

} else if (error.name === 'NotReadableError') {

this.error = 'ERROR: 相机被占用'

} else if (error.name === 'OverconstrainedError') {

this.error = 'ERROR: 安装摄像头不合适'

} else if (error.name === 'StreamApiNotSupportedError') {

this.error = 'ERROR: 此浏览器不支持流API'

}

this.$toast(this.error)

}

}

}

}

</script>

<style lang="scss" scoped>

.js-qr {

width: 100%;

height: 100vh;

position: fixed !important;

top: 0;

left: 0;

z-index: 1000 !important;

}

.error {

font-weight: bold;

color: red;

}

.cameraMessage {

width: 100%;

height: 60px;

}

.qr-scanner {

position: fixed;

top: 0;

left: 0;

z-index: 1000;

background-size: 3rem 3rem;

background-position: -1rem -1rem;

width: 100%;

height: 100vh;

background-color: #1110;

.qr-scanner-top {

margin-top: 30px;

padding: 0 30px;

display: flex;

justify-content: space-between;

align-items: center;

color: #fff;

font-size: 18px;

.close {

font-size: 36px;

}

}

.box {

width: 213px;

height: 213px;

position: absolute;

left: 50%;

top: 50%;

transform: translate(-50%, -50%);

overflow: hidden;

border: 0.1rem solid rgba(0, 255, 51, 0.2);

}

.txt {

width: 100%;

height: 35px;

line-height: 35px;

font-size: 16px;

text-align: center;

margin: 0 auto;

position: absolute;

top: 70%;

left: 0;

color: #fff;

}

.myQrcode {

text-align: center;

color: #00ae10;

}

.line {

height: calc(100% - 2px);

width: 100%;

background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #00ff33 211%);

border-bottom: 3px solid #00ff33;

transform: translateY(-100%);

animation: radar-beam 2s infinite alternate;

animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);

animation-delay: 1.4s;

}

.box:after,

.box:before,

.angle:after,

.angle:before {

content: '';

display: block;

position: absolute;

width: 3vw;

height: 3vw;

border: 0.2rem solid transparent;

}

.box:after,

.box:before {

top: 0;

border-top-color: #00ff33;

}

.angle:after,

.angle:before {

bottom: 0;

border-bottom-color: #00ff33;

}

.box:before,

.angle:before {

left: 0;

border-left-color: #00ff33;

}

.box:after,

.angle:after {

right: 0;

border-right-color: #00ff33;

}

}

@keyframes radar-beam {

0% {

transform: translateY(-100%);

}

100% {

transform: translateY(0);

}

}

</style>

2.compression

export default function(base64, w, callback) {

const newImage = new Image()

let quality = 0.6 // 压缩系数0-1之间

newImage.src = base64

newImage.setAttribute('crossOrigin', 'Anonymous') // url为外域时需要

let imgWidth, imgHeight

newImage.onload = function() {

imgWidth = this.width

imgHeight = this.height

const canvas = document.createElement('canvas')

const ctx = canvas.getContext('2d')

if (Math.max(imgWidth, imgHeight) > w) {

if (imgWidth > imgHeight) {

canvas.width = w

canvas.height = (w * imgHeight) / imgWidth

} else {

canvas.height = w

canvas.width = (w * imgWidth) / imgHeight

}

} else {

canvas.width = imgWidth

canvas.height = imgHeight

quality = 0.6

console.log(11)

}

ctx.clearRect(0, 0, canvas.width, canvas.height)

ctx.drawImage(this, 0, 0, canvas.width, canvas.height)

const base641 = canvas.toDataURL('image/png', quality) // 压缩语句

// 如想确保图片压缩到自己想要的尺寸,如要求在50-150kb之间,请加以下语句,quality初始值根据情况自定

// while (base64.length / 1024 > 150) {

// quality -= 0.01;

// base64 = canvas.toDataURL("image/jpeg", quality);

// }

// 防止最后一次压缩低于最低尺寸,只要quality递减合理,无需考虑

// while (base64.length / 1024 < 50) {

// quality += 0.001;

// base64 = canvas.toDataURL("image/jpeg", quality);

// }

callback(base641) // 必须通过回调函数返回,否则无法及时拿到该值

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值