Browse Source

二维码扫描动画效果优化v0.1

lwx_v6
liwenxuan 10 months ago
parent
commit
8e4fea1cc8
  1. 80
      src/components/lowCode/formItem.vue
  2. 105
      src/views/home/scanQrCode.vue
  3. 212
      src/views/home/scanQrCode1.vue

80
src/components/lowCode/formItem.vue

@ -497,7 +497,7 @@ const currentComponent = computed(() => {
<template #label v-else>
<span :style="getFormItemLableStyle(configStyle)" >{{ getLabel(data.item) }}</span>
</template>
<!-- 单行文本 -->
<el-input
v-bind="control"
v-model="value"
@ -505,7 +505,7 @@ const currentComponent = computed(() => {
:type="data.type === 'password' ? 'password' : 'text'"
:style="getFormItemInputStyle(configStyle,2)"
:input-style="getFormItemInputStyle(configStyle,3)"
v-if="['input', 'password'].includes(data.type)"
v-if="['password'].includes(data.type)"
:placeholder="data.control.placeholder?data.control.placeholder:'请输入'+getLabel(data.item)"
>
<template #prepend v-if="config.prepend">
@ -533,6 +533,82 @@ const currentComponent = computed(() => {
<span v-else>{{ config.append }}</span>
</template>
</el-input>
<!-- input 单行文本 -->
<el-input
v-bind="control"
v-model="value"
:disabled="judgeIsDisabled(data.name)"
:type="data.type === 'password' ? 'password' : 'text'"
:style="getFormItemInputStyle(configStyle,2)"
:input-style="getFormItemInputStyle(configStyle,3)"
v-if="['input'].includes(data.type)&&data.control.scanInputFlag==true&&data.control.scanType=='QrCode'"
:placeholder="data.control.placeholder?data.control.placeholder:'请输入或扫码'+getLabel(data.item)"
>
<template #prepend v-if="config.prepend">
<div v-if="getInputSlot('p')">
<SelectDesign
:data="getInputSlot('p')"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span>
</template>
<template #append v-if="config.append">
<div v-if="getInputSlot()">
<SelectDesign
:data="getInputSlot()"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span><!-- -->
</template>
</el-input>
<el-input
v-bind="control"
v-model="value"
:disabled="judgeIsDisabled(data.name)"
:type="data.type === 'password' ? 'password' : 'text'"
:style="getFormItemInputStyle(configStyle,2)"
:input-style="getFormItemInputStyle(configStyle,3)"
v-if="['input'].includes(data.type)&&data.control.scanInputFlag==true&&data.control.scanType=='OCR'"
:placeholder="data.control.placeholder?data.control.placeholder:'请输入或扫描文字'+getLabel(data.item)"
>
<template #prepend v-if="config.prepend">
<div v-if="getInputSlot('p')">
<SelectDesign
:data="getInputSlot('p')"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span>
</template>
<template #append v-if="config.append">
<div v-if="getInputSlot()">
<SelectDesign
:data="getInputSlot()"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span>
</template>
</el-input>
<!--多行文本-->
<el-input
v-bind="control"

105
src/views/home/scanQrCode.vue

@ -4,6 +4,14 @@
<div class="qrcode">
<!-- 新增扫描线 -->
<div class="scan-line"></div>
<!-- 新增边框装饰 -->
<div class="border-decor top-left"></div>
<div class="border-decor top-right"></div>
<div class="border-decor bottom-left"></div>
<div class="border-decor bottom-right"></div>
<div class="btn">
<div class="left-back" style="float: left;">
@ -171,31 +179,98 @@
</script>
<style lang="scss" scoped>
//
@keyframes scanLine {
0% { transform: translateY(-100%); }
100% { transform: translateY(300%); }
}
@keyframes borderPulse {
0% { opacity: 0.8; }
50% { opacity: 0.2; }
100% { opacity: 0.8; }
}
.scan-line {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 90%;
height: 2px;
background: linear-gradient(180deg, rgba(0,255,255,0) 0%, rgba(51,204,255,1) 50%, rgba(0,255,255,0) 100%);
animation: scanLine 2s infinite linear;
z-index: 2;
}
.border-decor {
position: absolute;
width: 20px;
height: 20px;
border: 2px solid #33ccff;
animation: borderPulse 1.5s infinite ease-in-out;
&.top-left {
top: -1px;
left: -1px;
border-right: none;
border-bottom: none;
}
&.top-right {
top: -1px;
right: -1px;
border-left: none;
border-bottom: none;
}
&.bottom-left {
bottom: -1px;
left: -1px;
border-right: none;
border-top: none;
}
&.bottom-right {
bottom: -1px;
right: -1px;
border-left: none;
border-top: none;
}
}
.scanCode {
height: 100vh;
display: flex;
flex-direction: column;
background: rgba(0, 0, 0);
}
//
.container {
height: 100vh;
position: relative;
width: 100%;
/* border: red solid 7px; */
}
.qrcode {
height: 90%;
/* width: 100%;*/
/* border: white solid 7px; */
position: relative; //
}
#reader {
display: block;
position: relative; //
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: calc(100% - 4px);
height: calc(100% - 4px);
border: 2px solid rgba(255,255,255,0.1);
}
}
height: 90vh;
/* top: 50%;
left: 0;
transform: translateY(-50%); */
/* border: yellow solid 5px; */
.qrcode {
position: relative; //
}
.btn {

212
src/views/home/scanQrCode1.vue

@ -0,0 +1,212 @@
<template>
<div class="scanCode">
<div class="container">
<div class="qrcode">
<div class="btn">
<div class="left-back" style="float: left;">
<el-icon @click="clickBack" style="border: white solid 0px;">
<Back />
</el-icon>
</div>
<!-- <div class="right-file">
<van-uploader
v-model="fileList"
:preview-image="false"
:after-read="dealSelectFiles"
>
<el-icon><Picture /></el-icon>
</van-uploader>
</div> -->
</div>
<div id="reader"></div>
</div>
</div>
<!--<div class="btn">
<div class="left-back">
<el-icon @click="clickBack">
<Back />
</el-icon>
</div>
<div class="right-file">
<van-uploader
v-model="fileList"
:preview-image="false"
:after-read="dealSelectFiles"
>
<el-icon><Picture /></el-icon>
</van-uploader>
</div>
</div> -->
</div>
</template>
<script setup>
import { reactive } from "vue";
import { defineComponent, toRefs, onMounted, onUnmounted } from "vue";
import { Html5Qrcode } from "html5-qrcode";
import { useRouter } from 'vue-router'
const router = useRouter()
const state = reactive({
html5QrCode: null,
fileList: [],
});
const start = () => {
state.html5QrCode
.start(
{ facingMode: "environment" },
{
fps: 5,
qrbox: { width: 300, height: 210 },
aspectRatio: 1.7,//
},
(decodedText, decodedResult) => {
window.location.href = decodedText;
if (state.html5QrCode&&state.html5QrCode.isScanning) {
stop();
}
console.log("decodedText", decodedText);
console.log("decodedResult", decodedResult);
}
)
.catch((err) => {
console.log("扫码错误信息", err);
let message = ""; //
if (typeof err == "string") {
message = "二维码识别失败!";
alert(message)
} else {
if (err.name == "NotAllowedError") {
message = "您需要授予相机访问权限!";
}
if (err.name == "NotFoundError") {
message = "这个设备上没有摄像头!";
}
if (err.name == "NotSupportedError") {
message =
"摄像头访问只支持在安全的上下文中,如https或localhost!";
}
if (err.name == "NotReadableError") {
message = "相机被占用!";
}
if (err.name == "OverconstrainedError") {
message = "安装摄像头不合适!";
}
if (err.name == "StreamApiNotSupportedError") {
message = "此浏览器不支持流API!";
}
alert(message)
}
});
};
const clickBack = () => {
//console.log(1)
if (state.html5QrCode&&state.html5QrCode.isScanning) {
stop();
}
router.back();
}
const getCameras = () => {
Html5Qrcode.getCameras()
.then((devices) => {
if (devices && devices.length) {
state.html5QrCode = new Html5Qrcode("reader");
start();
}
})
.catch((err) => {
console.log(err)
alert("摄像头无访问权限!");
});
};
const stop = () => {
state.html5QrCode
.stop()
.then((ignore) => {
console.log("停止扫码", ignore);
})
.catch((err) => {
console.log(err);
alert("停止扫码失败");
});
};
const dealSelectFiles = () => {
try {
window.qrcode.callback = (result) => {
alert("成功了,结果是:" + result);
}; // get select files.
let file = state.fileList[0].file;
var reader = new FileReader();
reader.onload = (function () {
return function (e) {
window.qrcode.decode(e.target.result);
};
})(file);
reader.readAsDataURL(file);
} catch (error) {
alert("图片识别失败!");
}
};
onMounted(() => {
getCameras();
});
onUnmounted(() => {
//
if (state.html5QrCode&&state.html5QrCode.isScanning) {
stop();
}
});
</script>
<style lang="scss" scoped>
.scanCode {
height: 100vh;
display: flex;
flex-direction: column;
background: rgba(0, 0, 0);
}
.container {
height: 100vh;
position: relative;
width: 100%;
/* border: red solid 7px; */
}
.qrcode {
height: 90%;
/* width: 100%;*/
/* border: white solid 7px; */
}
#reader {
display: block;
height: 90vh;
/* top: 50%;
left: 0;
transform: translateY(-50%); */
/* border: yellow solid 5px; */
}
.btn {
flex: 1;
padding-top: 2vw;
display: flex;
padding-left: 3vw;
color: #fff;
font-size: 6vw;
align-items: flex-start;
/* border: green solid 7px; */
}
</style>
Loading…
Cancel
Save