基于 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;
        }
    }
}


目录
相关文章
|
定位技术
基于Leaflet的轨迹模拟回放
在gis场景中,轨迹回放是一个很常见的场景。比如在导航软件中,在行程结束后根据运动轨迹生成运动图,在keep软件中,会自动记录用户的锻炼轨迹,在结束后可以看到自己的运动轨迹等等。这些需求都是设备在运行中自动记录相应的点,在结合gis模拟即可。
1076 0
基于Leaflet的轨迹模拟回放
|
存储 Web App开发 前端开发
Sentry For React 完整接入详解(2021 Sentry v21.8.x)前方高能预警!三万字,慎入!(二)
Sentry For React 完整接入详解(2021 Sentry v21.8.x)前方高能预警!三万字,慎入!(二)
714 0
|
3月前
|
JSON JavaScript 前端开发
震惊!JS如何悄无声息追踪你的每一步?揭秘页面访问与关闭的超级上报大法,让数据说话,优化体验不再难!
【8月更文挑战第4天】在Web开发中,跟踪用户行为对提升体验与留存至关重要。本文以在线学习平台为例,介绍如何用JavaScript监听页面访问及关闭,并上报数据。通过`window.onload`监测页面加载,记录用户访问;利用`navigator.sendBeacon`在用户离开时发送少量数据至服务器,无需担心请求失败。需注意隐私合规、性能影响及浏览器兼容性。此技术有助于深入理解用户行为,为产品迭代提供依据。
148 8
|
4月前
|
定位技术
高德局部刷新标记点,bug解决
将接口返回的经纬集合点在高德地图上标记展示, 如果实时刷新地图标记点,不加优化,则会造成过多的带宽消耗 所以,地图只需加载一次,局部更新标记点就好了。
|
6月前
|
JavaScript 前端开发 定位技术
Vue使用地图以及实现轨迹回放 附完整代码
Vue使用地图以及实现轨迹回放 附完整代码
161 0
Vue使用地图以及实现轨迹回放 附完整代码
|
移动开发 小程序 JavaScript
微信小程序学习实录6(百度经纬度采集、手动调整精度、H5嵌入小程序、百度地图jsAPI、实时定位、H5更新自动刷新)
微信小程序学习实录6(百度经纬度采集、手动调整精度、H5嵌入小程序、百度地图jsAPI、实时定位、H5更新自动刷新)
225 1
|
6月前
|
数据挖掘 定位技术
出租车GPS轨迹、社交软件签到、手机信令数据下载网站整理
出租车GPS轨迹、社交软件签到、手机信令数据下载网站整理
392 2
|
6月前
|
小程序 安全
手机扫一扫即可上报隐患、实时更新整改进度
可以在草料上搭建隐患上报系统,员工扫码即可上报隐患线索,管理人员可实时收到消息提醒,安排对应责任人进行整改。此外,可以在二维码中对隐患问题进行拍照、视频记录,从而体现问题整改前后的对比,确认整改效果。
|
小程序 定位技术
记录一款基于地图标注点展示的微信小程序开发过程纪要
记录整理一款基于地图的微信小程序开发过程,主要涉及标注点展示,可视范围内标注点动态更新,标注点自定义气泡,气泡点击及气泡内容实时更新
124 0
|
定位技术 API
高德地图打点
高德地图打点
154 0