sign-canvas 一个基于canvas开发,封装于Vue组件的通用手写签名板(电子签名板),支持pc端和移动端;

写在前面 :

在项目的开发过程中可能会涉及到手写签名(电子签名)那些,在前端的思路是使用canvas 来签名,导出成图片进行保存。

此轮子是继 https://blog.csdn.net/qq_33270001/article/details/81809535之后,用于vue项目中,为了方便自己与众人和复用而开发;

相比以前:

1. 增加npm 包一件安装并使用,

2. 增加v-model 动态绑定,有人可能觉得有点鸡肋了,但是如果有哪种场景,也是可以适用的.

3. 增加图片一键下载的方法.可以直接导出为png 或者 jpeg的图片.

这是以前的 "注意:在移动端使用的时候, 写竖的时候, 页面会被往下拉, 手写板动了, 写字不顺畅. 建议在移动端的touchmove事件里, 加一行防止页的滑动事件, 代码是: event.preventDefault()" 现在已经处理了.

废话不多说,上项目和代码

 vue-sign-canvas项目地址: https://github.com/langyuxiansheng/vue-sign-canvas

在线演示: https://langyuxiansheng.github.io/vue-sign-canvas/

基础用法

┭┮﹏┭┮ 因为 vue-sign-canvas 的包名被占用了,只好去掉一个前缀了....假如此轮子对你有帮助,请顺手star一下吧.o(* ̄︶ ̄*)o

开始使用! 下载安装npm包

npm i sign-canvas --save
//全局注册 main.js
import SignCanvas from 'sign-canvas';

Vue.use(SignCanvas);

你可以这样使用: 

组件模板使用

<template>
    <div id="app">
        <sign-canvas class="sign-canvas" ref="SignCanvas" :options="options" v-model="value"/>
        <img class="view-image" :src="value" width="150" height="150">
        <div class="sign-btns">
            <span id="clear" @click="canvasClear()">清空</span>
            <span id="save" @click="saveAsImg()">保存</span>
            <span id="save" @click="downloadSignImg()">下载</span>
        </div>
    </div>
</template>
<script>
export default {
    data(){
        return {
            value: null,
            options:{
                isSign: true, //签名模式 [Boolean] 默认为非签名模式,有线框, 当设置为true的时候没有任何线框
                isShowBorder: false, //是否显示边框 [可选]
            }
        }
    },
    methods:{

        /**
         * 清除画板
         */
        canvasClear(){
            this.$refs.SignCanvas.canvasClear();
        },

        /**
         * 保存图片
         */
        saveAsImg(){
            const img = this.$refs.SignCanvas.saveAsImg();
            alert(`image 的base64:${img}`);
        },

        /**
         * 下载图片
         */
        downloadSignImg(){
            this.$refs.SignCanvas.downloadSignImg();
        },

    }
}
</script>
<style lang="less" scoped>
* {
    margin: 0;
    padding: 0;
}
.sign-canvas{
    display: block;
    margin: 0 auto;
    border: 1px dashed #f00;
}
.view-image{
    display: block;
    margin: 20px auto;
}
.sign-btns{
    width: 800px;
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    #clear,
    #clear1,
    #save {
        margin: 0 auto;
        display: inline-block;
        padding: 5px 10px;
        width: 150px;
        height: 40px;
        line-height: 40px;
        border: 1px solid #eee;
        background: #e1e1e1;
        border-radius: 10px;
        text-align: center;
        margin: 20px auto;
        cursor: pointer;
    }
}
</style>

功能与配置

props:{
    options: {  //配置项
        required: false,
        type: [Object],
        default: () => null
    }
}

// 1. options [Object] 可选,非必传

// 2. v-model [String] 可选,非必传
  1. 配置项 options 属性
{
    lastWriteSpeed: 1,  //书写速度 [Number] 可选
    lastWriteWidth: 2,  //下笔的宽度 [Number] 可选
    lineCap: 'round',   //线条的边缘类型 [butt]平直的边缘 [round]圆形线帽 [square]	正方形线帽
    lineJoin: 'round',  //线条交汇时边角的类型  [bevel]创建斜角 [round]创建圆角 [miter]创建尖角。
    canvasWidth: 600, //canvas宽高 [Number] 可选
    canvasHeight: 600,  //高度  [Number] 可选
    isShowBorder: true, //是否显示边框 [可选]   当签名模式处于false的时候此选项才生效
    bgColor: '#fcc', //背景色 [String] 可选
    borderWidth: 1, // 网格线宽度  [Number] 可选
    borderColor: "#ff787f", //网格颜色  [String] 可选
    writeWidth: 5, //基础轨迹宽度  [Number] 可选
    maxWriteWidth: 30, // 写字模式最大线宽  [Number] 可选
    minWriteWidth: 5, // 写字模式最小线宽  [Number] 可选
    writeColor: '#101010', // 轨迹颜色  [String] 可选
    isSign: false, //签名模式 [Boolean] 默认为非签名模式,有线框, 当设置为true的时候没有任何线框
    imgType:'png'   //下载的图片格式  [String] 可选为 jpeg  canvas本是透明背景的
}
  1. 内置方法
//清除画布 无返回值 [Void]
this.$refs.SignCanvas.canvasClear(); 

//清除画布 返回图片的base64编码 [String]
this.$refs.SignCanvas.saveAsImg();

//调用内置的下载图片方法,默认将图片保存为png格式
this.$refs.SignCanvas.downloadSignImg();

二次开发 下载项目

git clone https://github.com/langyuxiansheng/vue-sign-canvas.git

Project setup

cd vue-sign-canvas

npm install

Compiles and hot-reloads for development

npm run dev

Compiles and minifies for production

npm run build

Lints and fixes files

npm run lint

缺陷 & 后期计划

目前还没有撤销回到上一步的操作,一旦输入错了就只有清除重写了(这个是之前去银行的时候,那个签名板是这样设计的); 如果有需要还是可以考虑加上回到上一步的方法.

 

如果您有什么好的建议请留言

项目截图展示:

初始化的非签名模式,

书写展示

保存的base64展示 

 导出的图片展示

 签名模式下的展示

 

 

发布了70 篇原创文章 · 获赞 44 · 访问量 9万+
展开阅读全文

vue使用canvas做横屏手写签名功能,写完后确认生成png图片,但是无法将canvas旋转

03-20

本来打算横屏签完名,然后旋转,然后生成png图片。<br/> 但是做到旋转那一步就死了。 <br/> 在最后的**this.saveEl.addEventListener**方法里将canvas旋转 但是用了ctx.rotate 似乎没有用。。。。 求助啊求助 vue 代码 ``` <template> <div class="container"> <div class="sign-box"> <div id="canvas" ref="canvas"></div> <div class="button-box"> <div id="clearCanvas" ref="clearCanvas"> <p>清除</p> </div> <div id="saveCanvas" ref="saveCanvas"> <p>保存</p> </div> </div> </div> <div class="mySign" v-show="isSign"> <img :src="signSrc" alt /> </div> </div> </template> <script> export default { data() { return { isSign: false, signSrc: "" }; }, created() {}, mounted() { this.lineCanvas({ el: this.$refs.canvas, //绘制canvas的父级div clearEl: this.$refs.clearCanvas, //清除按钮 saveEl: this.$refs.saveCanvas //保存按钮 }); }, methods: { lineCanvas(obj) { for (var i in obj) { this[i] = obj[i]; } this.canvas = document.createElement("canvas"); this.el.appendChild(this.canvas); this.ctx = this.canvas.getContext("2d"); let size = { width: this.el.clientWidth, height: this.el.clientHeight }; this.canvas.width = size.width; this.canvas.height = size.height; this.ctx.fillStyle = "#fff"; this.ctx.fillRect(0, 0, size.width, size.height); this.ctx.strokeStyle = "#000"; //用绝对坐标来创建一条路径 this.ctx.beginPath(); //将这条线绘制到canvas上 this.ctx.stroke(); //只有调用stroke canvas 才会绘制图像显示结果 this.ctx.lineWidth = 2; this.ctx.lineCap = "round"; //开始绘制 this.canvas.addEventListener( "touchstart", function(e) { this.ctx.beginPath(); this.ctx.moveTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY); }.bind(this), false ); //绘制中 this.canvas.addEventListener( "touchmove", function(e) { this.ctx.lineTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY); this.ctx.stroke(); }.bind(this), false ); //结束绘制 // this.canvas.addEventListener( // "touchend", // function() { // this.ctx.closePath(); // // let imgBase64 = this.canvas.toDataURL(); // //console.log(imgBase64); // // this.signSrc= imgBase64; // // this.isSign = true; // }.bind(this), // false // ); // //清除画布 this.clearEl.addEventListener( "click", function() { this.ctx.clearRect(0, 0, size.width, size.height); }.bind(this), false ); //保存图片,直接转base64 this.saveEl.addEventListener( "click", function() { let imgBase64 = this.canvas.toDataURL(); this.signSrc = imgBase64; this.isSign = true; this.ctx.clearRect(0, 0, size.width, size.height); }.bind(this), false ); } } }; </script> <style scoped lang="less"> div.sign-box { display: flex; height: 100%; div.button-box { width: 20%; height: 100%; // border: 1px solid red; display: flex; flex-direction: column; justify-content: space-around; div { text-align: center; // border: 1px solid blue; height: 50%; overflow: hidden; p { line-height: 50vh; transform: rotate(90deg); } } } #canvas { width: 80%; height: 100%; position: relative; // background: bisque; canvas { display: block; } } } .mySign { width: 100%; border: 1px solid red; box-sizing: border-box; img { width: 100%; } } </style> ``` 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览