首页 > 编程语言 >uniapp 小程序 实现 vue 实现手写签名

uniapp 小程序 实现 vue 实现手写签名

时间:2024-05-11 13:20:42浏览次数:27  
标签:uniapp vue dom res height length points 手写 line

方法一

<template>
    <view class="signBox">
        <view class="topHint">请在下方空白书写区域内写出您的名字</view>
        <view class="btn">
            <view class="saveBtn" @click="save">确认</view>
            <view class="cancelBtn" @click="clear">清除</view>
        </view>
        <canvas class="canvas" disable-scroll="true" :style="{'width':width,'height':height}" canvas-id="designature"
            @touchstart="starts" @touchmove="moves" @touchend="end"></canvas>
    </view>
</template>

<script>
    export default {
        components: {},
        data() {
            return {
                dom: null,
                line: [],
                radius: 0,
                width: '0rpx',
                height: '0rpx',
            }
        },
        onl oad() {},
        computed: {},
        created() {
            uni.getSystemInfo({
                success: (res) => {
                    this.width = res.windowWidth - 60 + 'rpx';
                    this.height = res.windowHeight - 56 + 'rpx';
                }
            });
            this.dom = uni.createCanvasContext('designature', this);

        },
        onShow() {},
        methods: {
            end(e) {},
            distance(a, b) {
                let x = b.x - a.x;
                let y = b.y - a.y;
                return Math.sqrt(x * x + y * y);
            },
            // 开始
            starts(e) {
                this.line.push({
                    points: [{
                        time: new Date().getTime(),
                        x: e.touches[0].x,
                        y: e.touches[0].y,
                        dis: 0
                    }]
                })
                let currentPoint = {
                    x: e.touches[0].x,
                    y: e.touches[0].y
                }
                this.currentPoint = currentPoint
                this.drawer(this.line[this.line.length - 1])
            },
            // 滑动
            moves(e) {
                let point = {
                    x: e.touches[0].x,
                    y: e.touches[0].y
                }
                this.lastPoint = this.currentPoint,
                    this.currentPoint = point
                this.line[this.line.length - 1].points.push({
                    time: new Date().getTime(),
                    x: e.touches[0].x,
                    y: e.touches[0].y,
                    dis: this.distance(this.currentPoint, this.lastPoint)
                })
                this.drawer(this.line[this.line.length - 1])
            },
            // 书写
            drawer(item) {
                let x1, x2, y1, y2, len, radius, r, cx, cy, t = 0.5,
                    x, y;
                var time = 0;
                if (item.points.length > 2) {
                    let lines = item.points[item.points.length - 3];
                    let line = item.points[item.points.length - 2];
                    let end = item.points[item.points.length - 1];
                    x = line.x;
                    y = line.y;
                    x1 = lines.x;
                    y1 = lines.y;
                    x2 = end.x;
                    y2 = end.y;
                    var dis = 0;
                    time = (line.time - lines.time) + (end.time - line.time)
                    dis = line.dis + lines.dis + end.dis;
                    var dom = this.dom;
                    var or = Math.min(time / dis * this.linePressure + this.lineMin, this.lineMax);
                    cx = (x - (Math.pow(1 - t, 2) * x1) - Math.pow(t, 2) * x2) / (2 * t * (1 - t))
                    cy = (y - (Math.pow(1 - t, 2) * y1) - Math.pow(t, 2) * y2) / (2 * t * (1 - t))
                    dom.setLineCap('round')
                    dom.beginPath();
                    dom.setStrokeStyle('black')
                    dom.setLineWidth(5)
                    dom.moveTo(x1, y1);
                    dom.quadraticCurveTo(cx, cy, x2, y2);
                    dom.stroke();
                    dom.draw(true)
                }
            },
            // 清除
            clear() {
                this.dom.clearRect(0, 0, 1000, 1000)
                this.dom.draw()
            },
            // 保存图片
            save() {
                var t = this;
                uni.canvasToTempFilePath({
                    canvasId: 'designature',
                    fileType: 'png',
                    quality: 1, //图片质量
                    success: function(res) {
                        t.$emit('getImg', res.tempFilePath)
                        console.log(res.tempFilePath, '148')
                        // uni.navigateBack({
                        //     delta:1
                        // })
                    },
                    fail(e) {
                        console.log(e)
                    }
                }, this)
            }
        }
    }
</script>

<style scoped lang="less">
    .signBox {
        position: relative;
        overflow: hidden;
        background-color: #F6F6F6;
        height: 100vh;
        width: 100vw;
    
        .canvas {
            width: 100% !important;
            background-color: #FFFFFF;
            position: absolute;
            z-index: 9999;
            left: 0rpx;
            top: 25rpx;
            // border: 1rpx solid #d6d6d6;
        }
        .topHint{
            width: 100%;
            height: 25rpx;
            line-height: 25rpx;
            font-size: 15rpx;
            color: #999999;
            text-align: center;
            background: ;
        }
        .btn {
            width: 100%;
            height: 60rpx;
            position: fixed;
            bottom: 0;
            // background-color: red;
            display: flex;
            align-items: center;
            justify-content: center;
            .saveBtn {
                width: 190rpx;
                height: 40rpx;
                line-height: 40rpx;
                background: linear-gradient(306deg, #4281EA 0%, #6363F2 100%);
                border-radius: 10rpx;
                text-align: center;
                font-size: 18rpx;
                color: #FFFFFF;
                margin-right: 10rpx;
            }
            .cancelBtn {
                width: 190rpx;
                height: 40rpx;
                line-height: 40rpx;
                background: #FFFFFF;
                border-radius: 10rpx;
                text-align: center;
                font-size: 18rpx;
                color: #222222;
                margin-left: 10rpx;
            }
        }
    }
</style>

json文件
{
    "path": "pages/clientDitch/sign",
    "style": {
        "navigationBarTitleText": "签字手签",
        "pageOrientation": "landscape",    //控制横屏
        // "navigationStyle": "custom"
    }
}, 

方法二

<template>
    <view class="signBox column-me">
        <!-- 这个是自定义的title-可根据自己封装的title的作为调整 -->
        <status-bar title="电子签名" :bgColor="null"></status-bar>
        <view class="topHint">请绘制清晰可辨的签名并保存</view>
        <canvas class="canvas flex1" :canvas-id="cid" :id="cid" @touchstart="touchstart" @touchmove="touchmove"
            @touchend="touchend" :disable-scroll="true"></canvas>
        <view class="btn margin-top10 margin-bottom10">
            <view class="cancelBtn" @click="reWrite">重写</view>
            <view class="saveBtn margin-left30" @click="save">保存</view>
        </view>
    </view>
</template>

<script>
    export default {
        components: {},
        data() {
            return {
                line: [],
                radius: 0,
                taskId: '',
                //以下与签名有关参数
                dom: null,
                cid: 'canvas', //画布id
                Strokes: [],
                showCanvasDialog: false,
                canvasImg: '', //签名图片
            }
        },
        onl oad(e) {
            this.taskId = e.taskId
        },
        computed: {},
        mounted: function() {
            let that = this
            this.initCanvas()
        },
        methods: {
            initCanvas() {
                let that = this
                this.$nextTick(function() {
                    this.dom = uni.createCanvasContext(this.cid, this);
                    var query = wx.createSelectorQuery();
                    query.select('#canvas').boundingClientRect();
                    query.exec(function(res) {
                        let widths = res[0].width
                        let heights = res[0].height
                        that.dom.rect(0, 0, widths, heights)
                        that.dom.setFillStyle('#FFFFFF')
                        that.dom.fill()
                        that.dom.draw()
                    })
                });
            },
            touchstart(e) {
                this.Strokes.push({
                    imageData: null,
                    style: {
                        color: '#000000',
                        lineWidth: '3',
                    },
                    points: [{
                        x: e.touches[0].x,
                        y: e.touches[0].y,
                        type: e.type,
                    }]
                })
                this.drawLine(this.Strokes[this.Strokes.length - 1], e.type);
            },
            touchmove(e) {
                this.Strokes[this.Strokes.length - 1].points.push({
                    x: e.touches[0].x,
                    y: e.touches[0].y,
                    type: e.type,
                })
                this.drawLine(this.Strokes[this.Strokes.length - 1], e.type);
            },
            touchend(e) {
                if (this.Strokes[this.Strokes.length - 1].points.length < 2) { //当此路径只有一个点的时候
                    this.Strokes.pop();
                }
            },
            drawLine(StrokesItem, type) {
                if (StrokesItem.points.length > 1) {
                    this.dom.setLineCap('round')
                    this.dom.setStrokeStyle(StrokesItem.style.color);
                    this.dom.setLineWidth(StrokesItem.style.lineWidth);
                    this.dom.moveTo(StrokesItem.points[StrokesItem.points.length - 2].x, StrokesItem.points[StrokesItem
                        .points.length -
                        2].y);
                    this.dom.lineTo(StrokesItem.points[StrokesItem.points.length - 1].x, StrokesItem.points[StrokesItem
                        .points.length -
                        1].y);
                    this.dom.stroke();
                    this.dom.draw(true);
                }
            },
            //重写签名
            reWrite() {
                this.Strokes = [];
                this.dom.draw();
                this.initCanvas()
            },
            // 保存图片
            save() {
                let that = this
                uni.canvasToTempFilePath({
                    canvasId: 'canvas',
                    fileType: 'png',
                    quality: 1, //图片质量
                    success: function(res) {
                        let imgs = [res.tempFilePath]
                        that.$.upload_img(imgs, 0, res => {
                            let imgUrl = res.data //签名图片
                            let mediaUrl = that.$.get_data('mediaUrl') //采集图片
                            if (that.$.isEmpty(mediaUrl)) {
                                mediaUrl = ''
                            }
                            that.$.ajax("POST", "/customer/user/checkTask", {
                                taskId: that.taskId,
                                status: 1, //状态:1同意2拒绝    
                                signImage: imgUrl,
                                userVideo: mediaUrl,
                            }, (res) => {
                                if (res.code === 1000) {
                                    that.$.ti_shi(res.message)
                                    setTimeout(() => {
                                        uni.$emit('signOk')
                                        that.$.back()
                                    }, 1000)
                                } else {
                                    that.$.ti_shi(res.message)
                                }
                            });
                        })
                    },
                    fail(e) {
                        console.log(e)
                    }
                })
            }
        }
    }
</script>

<style scoped lang="less">
    .signBox {
        position: relative;
        overflow: hidden;
        background-color: #F6F6F6;
        height: 100vh;
        width: 100vw;

        .canvas {
            width: 100%;
            background: #FFFFFF;
        }

        .topHint {
            width: 100%;
            height: 60rpx;
            line-height: 60rpx;
            font-size: 28rpx;
            color: #6D7984;
            text-align: center;
            background: ;
        }

        .btn {
            width: 100%;
            height: 132rpx;
            display: flex;
            align-items: center;
            justify-content: center;

            .saveBtn {
                width: 300rpx;
                height: 88rpx;
                line-height: 88rpx;
                background: #215AA0;
                border-radius: 20rpx;
                text-align: center;
                font-size: 32rpx;
                color: #FFFFFF;
            }

            .cancelBtn {
                width: 298rpx;
                height: 86rpx;
                line-height: 86rpx;
                background: #FFFFFF;
                border-radius: 20rpx;
                text-align: center;
                font-size: 32rpx;
                color: #202233;
                border: 1px solid #BBC4CC;
            }
        }
    }
</style>

 

标签:uniapp,vue,dom,res,height,length,points,手写,line
From: https://www.cnblogs.com/qqqq122418812/p/18186302

相关文章

  • vue和react的相同点和不同点
    Vue和React作为现代前端开发中流行的两个JavaScript框架,它们有诸多相似之处,同时也存在一些关键性的不同。以下是Vue和React的一些主要相同点和不同点:相同点:虚拟DOM:Vue和React都使用虚拟DOM(VirtualDOM)来提高性能,减少直接操作真实DOM的频率,从而加快页面渲染速度。组件化开发:两......
  • Vue+elementUI-创建项目
    创建VUE项目vuecreatemy-project后会出现选项,反正我选择的是自定义创建,第三个  之后选2.X选一堆配置,案子自己需求配置然后 然后进入到我们的项目目录,可以运行   这个安装好了以后,到element.ui的官方文档地址:https://element.eleme.cn/#/zh-CN/compo......
  • Vue3 项目
    创建Vue3项目的步骤如下:安装Node.jsVue3需要依赖Node.js环境,因此需要先安装Node.js。可以从官网下载Node.js的安装包并安装,也可以使用包管理器安装,例如在Ubuntu上可以使用以下命令安装:sudoapt-getupdatesudoapt-getinstallnodejssudoapt-getinstallnpm......
  • 使用vue ui新建一个vue项目
    参考:https://blog.csdn.net/weixin_46932840/article/details/114590107@目录一、安装环境二、使用vueui初始化步骤1.我的是到C盘的ProgramFiles\nodejs\node_global目录下执行以下命令2.执行命令后会自动跳转到初始化项目的页面,如下图操作3.最后我一开始执行npmrunserve页......
  • 从零手写实现 tomcat-09-servlet 处理类
    创作缘由平时使用tomcat等web服务器不可谓不多,但是一直一知半解。于是想着自己实现一个简单版本,学习一下tomcat的精髓。系列教程从零手写实现apacheTomcat-01-入门介绍从零手写实现apacheTomcat-02-web.xml入门详细介绍从零手写实现tomcat-03-基本的socket实......
  • 【vue3入门】-【22】 组件attribute透传
    透传Attribute透传Attribute指的是传递给一个组件,却没有被该组件声明为props或emits的attribute或者v-on事件监听器。最常见的列子就是class、style和id。当一个组件以单个元素为根路径渲染时,透传的attribute会自动被添加到根元素上app.vue<template><!--在引用的组件上使......
  • springboot+vue快速部署前后台项目,无需服务器
    问题前言我们都知道,现在的主流开发大多数为,前后端分离,目前流行的框架,大多数是springboot+elementui这些框架,这无疑是给开发部署项目带来了便利,我们后台开发无需关心前端如何部署的,前端同样也无需关系后台如何部署,只需要确认能够访问即可。存在有如下问题:当由于条件有限,我......
  • wps加载项在vue2项目中的应用(publish模式)
    wps加载项在vue2项目中的应用应用代码:wps.js/***WPSOA助手-WPS启动方法入口*/varpluginsMode=location.search.split("=")[1];//截取url中的参数值varpluginType=WpsInvoke.ClientType.wps;//加载项类型wps,et,wppvarpluginName="WpsOAAssist";//加载项名......
  • Vue中Tabs标签页的使用
    本案例的优点是给每个tab标签的标题设置了状态值,并给不同的状态值设置了不同的背景颜色。效果:代码:1、父组件<template><el-containerclass="container"><el-tabsv-model="activeName"type="border-card"style="width:100%;height:100%">......
  • vue3 vite项目H5页面 ios13进入页面出现白屏问题
    项目中碰见IOS系统进入页面出现白屏问题,记录一下问题排查过程一、页面可能报错进入页面是白屏,页面的 vconsole 也没有显示,首先想到的是页面是不是有什么报错,然后查看了别的机型,都没有问题,定位到只有IOS13有问题,想着会不会是什么语法在IOS13不兼容(这个问题之前出现过一个......