基于 Taro 实现签字,轨迹回放 #98

简介: 基于 Taro 实现签字,轨迹回放 #98

前言


最近公司要在小程序上实现签字笔迹追踪,看了下网上关于Taro如何实现的文章,代码都很乱,很杂,所以,想记录下自己是如何实现的,并附上源码。


效果演示



源码


index.js

import Taro, { Component } from '@tarojs/taro';
import { View, Canvas } from '@tarojs/components';
import './index.less';
// 图片url(或filepath)转base64
const fileTobase64 = path => {
    return 'data:image/jpeg;base64,' + Taro.getFileSystemManager().readFileSync(path, 'base64');
};
// 签字轨迹
const historyTrajectory = {
    historyData:[
        {
            //操作时间
            time: 0,
            /**
            * 操作类型
            * 绘图:mapping
            */
            operation: 'mapping',//操作类型
            /**
            * 绘制路径
            * startX:开始x坐标
            * startY:开y纵坐标
            * currentX:目标位置的 x 坐标
            * currentY:目标位置的 y 坐标
            * z:1代表画线时鼠标处于move状态,0代表处于松开状态
            * colorStr:线的填充颜色
            * pen:笔迹大小
            */
            lineArr: {
                startX: 0,
                startY: 0,
                currentX: 0,
                currentY: 0,
                z: 0,
                colorStr: '#000',
                pen: 3
            }
        }
    ]
};
export default class Signature extends Component {
    constructor(props) {
        super(props);
        this.state = { };
        this.pen = 3;
        this.context = '';
        this.signPath = '';
        this.moveToX = 0;
        this.moveToY = 0;
        // 签字开始时间
        this.startDate = new Date().getTime();
        this.timer = '';
        this.colorStr = '#000';
    }
    componentDidMount() {
        const context = Taro.createCanvasContext('myCanvas', this.$scope);
        this.context = context;
        this.context.draw();
        this.context.lineWidth = this.pen;
    }
    // 手指触摸动作开始
    touchStart = (e) => {
        this.context.lineWidth = this.pen;
        this.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y);
        this.moveToX = Math.floor(e.changedTouches[0].x);
        this.moveToY = Math.floor(e.changedTouches[0].y);
        historyTrajectory.historyData.push({
            time: new Date().getTime() - this.startDate,
            operation: 'mapping',
            lineArr: {
                startX: this.moveToX,
                startY: this.moveToY,
                currentX: Math.floor(e.changedTouches[0].x),
                currentY: Math.floor(e.changedTouches[0].y),
                z: 1,
                colorStr: this.colorStr,
                pen: this.pen
            }
        });
    }
    // 手指触摸后移动
    touchMove = (e) => {
        const lineToX = Math.floor(e.changedTouches[0].x);
        const lineToY = Math.floor(e.changedTouches[0].y);
        this.context.lineWidth = this.pen;
        this.context.lineTo(lineToX, lineToY);
        this.context.stroke();
        this.context.draw(true);
        this.context.moveTo(lineToX, lineToY);
        historyTrajectory.historyData.push({
            time: new Date().getTime() - this.startDate,
            operation: 'mapping',
            lineArr: {
                startX: this.moveToX,
                startY: this.moveToY,
                currentX: lineToX,
                currentY: lineToY,
                z: 1,
                colorStr: this.colorStr,
                pen: this.pen
            }
        });
        this.moveToX = lineToX;
        this.moveToY = lineToY;
    }
    onTouchEnd = () => {
    }
    // 清空画布
    clearCanvas = () => {
        this.signPath = '';
        this.context.draw();
        historyTrajectory.historyData = [];
        historyTrajectory.historyData.push({
            time: 0,
            operation: 'mapping',
            lineArr: {
                startX: 0,
                startY: 0,
                currentX: 0,
                currentY: 0,
                z: 0,
                colorStr: this.colorStr,
                pen: this.pen
            }
        });
    }
    replay = () => {
        this.signPath = '';
        this.context.draw();
        clearInterval(this.timer);
        const startDate = new Date().getTime();
        let i = 0;
        let len = historyTrajectory.historyData.length;
        this.timer = setInterval(() => {
            const curTime = new Date().getTime() - startDate;
            if (curTime >= historyTrajectory.historyData[i].time) {
                switch (historyTrajectory.historyData[i].operation) {
                    case 'mapping':
                        this.context.setStrokeStyle(historyTrajectory.historyData[i].lineArr.colorStr);
                        this.context.lineWidth = historyTrajectory.historyData[i].lineArr.pen;
                        this.context.moveTo(historyTrajectory.historyData[i].lineArr.startX, historyTrajectory.historyData[i].lineArr.startY);
                        this.context.lineTo(historyTrajectory.historyData[i].lineArr.currentX, historyTrajectory.historyData[i].lineArr.currentY);
                        this.context.stroke();
                        this.context.draw(true);
                        break;
                }
                i++;
            }
            if(i >= len) {
                clearInterval(this.timer);
            }
        }, 1);
    }
    // 获取签字base64
    confirm() {
        Taro.canvasToTempFilePath({
            x: 0,
            y: 0,
            canvasId: 'myCanvas',
            success: (res) => {
                console.log('cofirm:', fileTobase64(res.tempFilePath));
            },
            fail: (error) => {
                console.error('btnConfirm:', error);
            }
        }, this.$scope);
    }
    render() {
        return (
            <View className="signature-container">
                <View className="canvas-area" style={{ height: (Taro.getSystemInfoSync().screenHeight - 150 + 'px') }}>
                    <Canvas
                        canvasId="myCanvas"
                        className="my-canvas"
                        disableScroll="false"
                        onTouchStart={this.touchStart}
                        onTouchMove={this.touchMove}
                        onTouchEnd={this.onTouchEnd}
                    />
                </View>
                <View className="canvas-btn">
                    <View className="btn" onClick={this.confirm}>确认</View>
                    <View className="btn" onClick={this.clearCanvas}>清除</View>
                    <View className="btn" onClick={this.replay}>回放</View>
                </View>
            </View>
        );
    }
}

index.less

.signature-container {
    padding: 24px;
    .canvas-area {
        overflow: hidden;
        width: 100%;
        border: 2px dashed #dcdcdc;
    }
    .my-canvas {
        width: 100%;
        height: 100%;
    }
    .canvas-btn {
        display: flex;
        justify-content: space-around;
        align-items: center;
        margin-top: 24px;
        .btn {
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 28px;
            border-radius: 5px;
            flex: 1;
            background-color: #359a64;
            color: #fff;
            height: 60px;
            margin: 0 24px;
        }
    }
}


相关文章
|
存储 监控 安全
单点登录的安全性如何保证?有哪些常见的安全风险
单点登录的安全性如何保证?有哪些常见的安全风险
632 2
|
前端开发 NoSQL Java
谷粒学苑笔记整理
谷粒学苑笔记整理
307 0
|
存储 前端开发 JavaScript
ahooks 正式发布:值得拥抱的 React Hooks 工具库
ahook定位于一套基于 React Hooks 的工具库,核心围绕 React Hooks 的逻辑封装能力,降低代码复杂度和避免团队的重复建设为背景,共同建设和维护阿里经济体层面的 React Hooks 库。
23585 1
ahooks 正式发布:值得拥抱的 React Hooks 工具库
|
7月前
|
前端开发 JavaScript API
React 文件下载组件:File Download
本文详细介绍了如何在React应用中实现文件下载组件,包括基本概念、实现步骤和代码示例。同时,探讨了常见问题如文件类型不匹配、文件名乱码等及其解决方法,旨在提升用户体验和代码可维护性。
486 2
|
10月前
|
前端开发
前端使用xlsx模板导出表格
【9月更文挑战第10天】在前端使用 `xlsx` 模板导出表格需完成以下步骤:首先引入 `xlsx` 库,准备数据与模板;接着读取模板文件,选择特定工作表并填充数据;最后将填充后的表格转换为二进制数据,创建 Blob 对象并触发下载。整个过程中可根据需求调整模板格式和数据填充方式。
322 5
|
编解码 开发工具 Android开发
Axure 从入门到够用
Axure 从入门到够用
517 0
|
Web App开发 移动开发 Android开发
解决IOS Safari浏览器H5页面上下滑动时卡顿、页面缺失的问题
解决IOS Safari浏览器H5页面上下滑动时卡顿、页面缺失的问题
|
机器学习/深度学习 运维 算法
利用机器学习进行异常检测的技术实践
【5月更文挑战第16天】本文探讨了利用机器学习进行异常检测的技术实践,强调了在大数据时代异常检测的重要性。机器学习通过无监督、有监督和半监督学习方法自动识别异常,常见算法包括KNN、LOF、K-means和GMM等。异常检测流程包括数据准备、特征工程、选择算法、训练模型、评估优化及部署。机器学习为异常检测提供了灵活性和准确性,但需结合具体问题选择合适方法。
|
小程序 JavaScript Android开发
uniapp开发时可能会遇到的问题及解决方法,uniapp避坑指南!
uniapp开发时可能会遇到的问题及解决方法,uniapp避坑指南!
|
移动开发 前端开发 JavaScript
Web 动画与过渡效果:CSS3、Canvas 和 GreenSock 的比较
Web 动画和过渡效果是现代 Web 开发中常见的重要功能,用于提升用户体验和页面交互效果。在实现 Web 动画和过渡效果时,我们通常可以选择使用 CSS3、Canvas 或 GreenSock(GSAP)等技术。下面对它们进行比较
389 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问