更新记录

1.0.1.5(2024-12-20) 下载此版本

  • 适配4.42

1.0.1.4(2024-12-09) 下载此版本

  • 更新文档

1.0.1.3(2024-12-06) 下载此版本

  • 更新使用文档
查看更多

平台兼容性

Vue2 Vue3
×
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 4.36,Android:6.0,iOS:不支持,HarmonyNext:支持 × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序 鸿蒙元服务
× × × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × × × × × ×

Scan 扫码

该组件可以集成到应用中,提供实时的扫码功能,适用于多种扫码场景。

在线扫一扫体验

<template>
    <t-col @click="rescan">
        <tui-scan style="width: 100%;height: 100%;" ref='nativescan' @scanned="onScanned" @pause="onPause"></tui-scan>
        <slot>
            <t-canvas class='da twh.100%'></t-canvas>
        </slot>
    </t-col>
</template>
<script>
    import { ttc } from '@/uni_modules/tui-plus'
    import { ScanResult } from '@/uni_modules/tui-scan'
    export default {
        name: "t-scan",
        data() {
            return {
                canvasMaskCtx: null as CanvasRenderingContext2D | null,
                animationTaskId: 0,
                pause: false
            };
        },
        props: {
            type: {
                type: String,
                default: 'p'
            },
            mode: {
                type: String,
                default: 'qr'
            },
            rectColor: {
                type: String,
                default: ''
            },
            lineColor: {
                type: String,
                default: ''
            },
            lineHeight: {
                type: Number,
                default: 2
            },
            mask: {
                type: Boolean,
                default: true
            }
        },
        mounted() {
            if (this.animationTaskId != 0) cancelAnimationFrame(this.animationTaskId)
        },
        methods: {
            rescan() {
                const scan = this.$refs['nativescan'] as TuiScanElement
                scan.rescan()
            },
            scanImageByURI(url : string) {
                const scan = this.$refs['nativescan'] as TuiScanElement
                scan.scanImageByURI(url)
            },
            // maskCanvasInit(ctx : CanvasContext) {
            //  this.canvasMaskCtx = ctx.getContext('2d')
            //  this.drawMask()
            // },
            drawMask() {
                const ctx = this.canvasMaskCtx!
                // canvas的宽度和高度
                const canvasWidth = ctx.canvas.offsetWidth;
                const canvasHeight = ctx.canvas.offsetHeight;
                if (!this.mask) {
                    ctx.clearRect(0, 0, canvasWidth, canvasHeight)
                    return
                }
                // 设置矩形框的宽度和高度
                let rectWidth = 300; // 矩形框的宽度
                let rectHeight = 100; // 矩形框的高度
                if (this.mode == 'qr') {
                    rectWidth = 200
                    rectHeight = 200
                }
                // 计算矩形框的起始坐标,使其位于画布中心
                const rectX = (canvasWidth - rectWidth) / 2;
                const rectY = (canvasHeight - rectHeight) / 2;
                // 绘制矩形框
                ctx.lineWidth = 4;
                ctx.globalAlpha = 1;
                ctx.strokeStyle = 'black';
                ctx.globalAlpha = 0.5;
                ctx.fillRect(0, 0, canvasWidth, rectY);
                ctx.fillRect(0, rectY, rectX, rectHeight);
                ctx.fillRect(0, rectY + rectHeight, canvasWidth, canvasHeight - rectHeight - rectY);
                ctx.fillRect(rectX + rectWidth, rectY, canvasWidth - rectWidth - rectX, rectHeight);
                ctx.globalAlpha = 1;
                const rectcolor = ttc(this.type, '', this.rectColor, false)
                ctx.strokeStyle = rectcolor;
                ctx.moveTo(rectX + 15, rectY);
                ctx.lineTo(rectX, rectY);
                ctx.lineTo(rectX, rectY + 15);
                ctx.moveTo(rectX + rectWidth - 15, rectY);
                ctx.lineTo(rectX + rectWidth, rectY);
                ctx.lineTo(rectX + rectWidth, rectY + 15);
                ctx.moveTo(rectX + 15, rectY + rectHeight);
                ctx.lineTo(rectX, rectY + rectHeight);
                ctx.lineTo(rectX, rectY + rectHeight - 15);
                ctx.moveTo(rectX + rectWidth - 15, rectY + rectHeight);
                ctx.lineTo(rectX + rectWidth, rectY + rectHeight);
                ctx.lineTo(rectX + rectWidth, rectY + rectHeight - 15);
                ctx.stroke()
                this.drawScannerLine(rectX, rectY, rectWidth, rectHeight);
            },
            onScanned(e : ScanResult) {
                this.$emit('scanned', e)
            },
            onPause(e : boolean) {
                this.pause = e
                if (!this.pause) {
                    this.drawMask()
                }
            },
            drawScannerLine(rectX : number, rectY : number, rectWidth : number, rectHeight : number) {
                const ctx = this.canvasMaskCtx!;
                const scannerLineHeight = this.lineHeight; // 扫描线的高度
                const scannerLineWidth = rectWidth - 2; // 扫描线的宽度
                let scannerLineY = rectY; // 扫描线的初始Y坐标
                let that = this
                function animateScannerLine() {
                    if (that.animationTaskId != 0) cancelAnimationFrame(that.animationTaskId)
                    if (that.pause) {
                        ctx.clearRect(0, 0, ctx.canvas.offsetWidth, ctx.canvas.offsetHeight)
                        return
                    }
                    ctx.clearRect(rectX + 1, rectY, rectWidth - 1, rectHeight)
                    const linecolor = ttc(that.type, '', that.lineColor, false)
                    ctx.fillStyle = linecolor; // 扫描线的颜色
                    ctx.fillRect(rectX + 1, scannerLineY, scannerLineWidth, scannerLineHeight);

                    // 更新扫描线的位置
                    if (that.mode == 'qr') {
                        scannerLineY += 2; // 扫描线的移动速度
                    } else {
                        scannerLineY += 0.5; // 扫描线的移动速度
                    }
                    if (scannerLineY > rectY + rectHeight - scannerLineHeight) {
                        scannerLineY = rectY; // 重置扫描线的位置
                    }
                    that.animationTaskId = requestAnimationFrame((_ : number) => {
                        animateScannerLine()
                    })
                };
                animateScannerLine()
            }
        }
    }
</script>

支持平台

安卓 ios web 微信小程序 支付宝小程序 QQ小程序
x x x

Props

名称 描述 类型 默认值
mode 扫描模式 String 'qr'
rectColor 矩形颜色 String ''
lineColor 线条颜色 String ''
lineHeight 线条高度 Number 2
mask 是否显示遮罩 Boolean true

Methods

名称 描述
rescan 重新开始扫描
scanImageByURI 通过URI扫描图片
maskCanvasInit 初始化遮罩Canvas
drawMask 绘制遮罩
drawScannerLine 绘制扫描线

Events

名称 描述 参数
scanned 当扫描到结果时触发 result

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问