基于 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模拟即可。
828 0
基于Leaflet的轨迹模拟回放
|
存储 Web App开发 前端开发
Sentry For React 完整接入详解(2021 Sentry v21.8.x)前方高能预警!三万字,慎入!(二)
Sentry For React 完整接入详解(2021 Sentry v21.8.x)前方高能预警!三万字,慎入!(二)
572 0
|
3天前
|
小程序 安全
手机扫一扫即可上报隐患、实时更新整改进度
可以在草料上搭建隐患上报系统,员工扫码即可上报隐患线索,管理人员可实时收到消息提醒,安排对应责任人进行整改。此外,可以在二维码中对隐患问题进行拍照、视频记录,从而体现问题整改前后的对比,确认整改效果。
|
10月前
|
移动开发 小程序 JavaScript
微信小程序学习实录6(百度经纬度采集、手动调整精度、H5嵌入小程序、百度地图jsAPI、实时定位、H5更新自动刷新)
微信小程序学习实录6(百度经纬度采集、手动调整精度、H5嵌入小程序、百度地图jsAPI、实时定位、H5更新自动刷新)
149 1
|
10月前
|
小程序 定位技术
记录一款基于地图标注点展示的微信小程序开发过程纪要
记录整理一款基于地图的微信小程序开发过程,主要涉及标注点展示,可视范围内标注点动态更新,标注点自定义气泡,气泡点击及气泡内容实时更新
102 0
|
11月前
|
定位技术 API
高德地图打点
高德地图打点
111 0
|
监控 前端开发
前端数据周报草稿
前端数据周报草稿
67 0
前端数据周报草稿
|
JavaScript 定位技术
VUE之高德地图轨迹绘制与轨迹回放
VUE之高德地图轨迹绘制与轨迹回放
783 0
VUE之高德地图轨迹绘制与轨迹回放
|
Dubbo Cloud Native Java
数据变更白屏化利器-推送轨迹上线
微服务引擎MSE面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持Nacos/ZooKeeper/Eureka)、云原生网关(原生支持Ingress/Envoy)、微服务治理(原生支持Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。
数据变更白屏化利器-推送轨迹上线
|
数据采集 存储 Python
Python爬虫系列9-非诚勿扰等婚恋网数据批量抓取!
一般当大家遇到不顺心的时候,总是会焦虑,抱怨,我知道,这也是人软弱的一面,但是我们越是遇到困难,越是要振作起来,不要放弃自己,然后悄悄努力,只有这样才能让自己越来越好,如果一直沉浸在痛苦中,只会越来越糟。 适当的逼一逼自己,你会发现,人的潜力是无限的。
Python爬虫系列9-非诚勿扰等婚恋网数据批量抓取!