vue2实现手写签批

news2024/11/27 12:33:46

手写签名

    • 一、安装
    • 二、引入
    • 三、使用 vue-signature-pad 完成签批功能
    • 四、解构出data为base64编码的图片
    • 一、图片实现横屏

  1. 使用案例图

在这里插入图片描述

一、安装

npm i vue-signature-pad.0.5   // vue2适用的版本

二、引入

*mian.js*
import VueSignaturePad from 'vue-signature-pad'

Vue.use(VueSignaturePad)

三、使用 vue-signature-pad 完成签批功能

<template>
  <div id="app">
    <div style="background: #fff">
      <vue-signature-pad
        id="signature"
        width="95%"
        height="400px"
        ref="signaturePad"
        :options="options"
      />
    </div>

    <button ="save">保存</button>
    <button ="resume">重置</button>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      options: {
        penColor: '#000',
      },
    }
  },
  methods: {
    save() {
      const { isEmpty, data } = this.$refs.signaturePad.saveSignature()
      console.log(isEmpty)
      console.log(data)
    },

    //清除重置
    resume() {
      this.$refs.signaturePad.clearSignature()
    },
  },
}
</script>

<style lang="scss">
html,
body {
  padding: 0;
  margin: 0;
}
#app {
  width: 100vw;
  height: 100vh;
  background: #ececec;
}
</style>

四、解构出data为base64编码的图片

<template>
  <div id="app">
    <div style="background: #fff">
      <vue-signature-pad
        id="signature"
        width="95%"
        height="300px"
        ref="signaturePad"
        :options="options"
      />
    </div>

    <div v-for="(item, index) in imgList" :key="index">
      <img :src="item.src" alt="" width="100" />
    </div>

    <button ="save" class="btn">保存</button>
    <button ="resume" class="btn">重置</button>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      options: {
        penColor: '#000',
      },
      imgList: [],
    }
  },
  methods: {
    save() {
      const { isEmpty, data } = this.$refs.signaturePad.saveSignature()
      this.imgList.push({
        src: data,
      })
      let res = this.dataURLtoFile(data, 'demo')
      console.log(res)
    },

    // 清除重置
    resume() {
      this.$refs.signaturePad.clearSignature()
    },

    // 将base64转换为文件
    dataURLtoFile(dataurl, filename) {
      var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)

      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }

      return new File([u8arr], filename, { type: mime })
    },
  },
}
</script>

<style lang="scss">
html,
body {
  padding: 0;
  margin: 0;
}
#app {
  width: 100vw;
  height: 100vh;
  background: #ececec;
}

.btn {
  width: 35%;
  color: #fff;
  background: #5daaf3;
  border: none;
  height: 40px;
  border-radius: 20px;
  margin-top: 20px;
  margin-left: 40px;
}
</style>

一、图片实现横屏

<template>
  <div id="app">
    <div style="background: #fff">
      <vue-signature-pad
        id="signature"
        width="95%"
        height="300px"
        ref="signaturePad"
        :options="options"
      />
    </div>

    <div v-for="(item, index) in imgList" :key="index">
      <img :src="item.src" alt="" width="100" />
    </div>

    <div class="buttons">
      <button ="save" class="btn">保存</button>
      <button ="resume" class="btn">重置</button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      options: {
        penColor: '#000',
      },
      imgList: [],
      fileList: [],
    }
  },
  methods: {
    save() {
      const { isEmpty, data } = this.$refs.signaturePad.saveSignature()

      this.rotateBase64Img(data, 90, (res) => {
        console.log(res) // 旋转后的base64图片src
        this.fileList.push({
          file: this.dataURLtoFile(res, 'sign'),
          name: 'sign',
        })
        this.imgList.push({
          src: res,
        })
      })
    },

    // 清除重置
    resume() {
      this.$refs.signaturePad.clearSignature()
    },

    // 将base64转换为文件
    dataURLtoFile(dataurl, filename) {
      var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)

      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }

      return new File([u8arr], filename, { type: mime })
    },

    // 通过canvas旋转图片
    rotateBase64Img(src, edg, callback) {
      var canvas = document.createElement('canvas')
      var ctx = canvas.getContext('2d')

      var imgW //图片宽度
      var imgH //图片高度
      var size //canvas初始大小

      if (edg % 90 != 0) {
        console.error('旋转角度必须是90的倍数!')
        throw '旋转角度必须是90的倍数!'
      }
      edg < 0 && (edg = (edg % 360) + 360)
      const quadrant = (edg / 90) % 4 //旋转象限
      const cutCoor = { sx: 0, sy: 0, ex: 0, ey: 0 } //裁剪坐标

      var image = new Image()

      image.crossOrigin = 'anonymous'
      image.src = src

      image.onload = function () {
        imgW = image.width
        imgH = image.height
        size = imgW > imgH ? imgW : imgH

        canvas.width = size * 2
        canvas.height = size * 2
        switch (quadrant) {
          case 0:
            cutCoor.sx = size
            cutCoor.sy = size
            cutCoor.ex = size + imgW
            cutCoor.ey = size + imgH
            break
          case 1:
            cutCoor.sx = size - imgH
            cutCoor.sy = size
            cutCoor.ex = size
            cutCoor.ey = size + imgW
            break
          case 2:
            cutCoor.sx = size - imgW
            cutCoor.sy = size - imgH
            cutCoor.ex = size
            cutCoor.ey = size
            break
          case 3:
            cutCoor.sx = size
            cutCoor.sy = size - imgW
            cutCoor.ex = size + imgH
            cutCoor.ey = size + imgW
            break
        }

        ctx.translate(size, size)
        ctx.rotate((edg * Math.PI) / 180)
        ctx.drawImage(image, 0, 0)

        var imgData = ctx.getImageData(
          cutCoor.sx,
          cutCoor.sy,
          cutCoor.ex,
          cutCoor.ey
        )

        if (quadrant % 2 == 0) {
          canvas.width = imgW
          canvas.height = imgH
        } else {
          canvas.width = imgH
          canvas.height = imgW
        }
        ctx.putImageData(imgData, 0, 0)
        callback(canvas.toDataURL())
      }
    },
  },
}
</script>

<style lang="scss">
html,
body {
  padding: 0;
  margin: 0;
}
#app {
  width: 100vw;
  height: 100vh;
  background: #ececec;
}

.btn {
  width: 35%;
  color: #fff;
  background: #5daaf3;
  border: none;
  height: 40px;
  border-radius: 20px;
  margin-top: 20px;
  margin-left: 40px;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1341833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI时代下,如何看待“算法利维坦”?

ChatGPT的浪潮从2022年袭来后&#xff0c;至今热度不减&#xff0c;呈现出蓬勃发展的趋势。AI家居、医疗、教育、金融、公益、农业、艺术......AI真的已经走进了生活的方方面面&#xff0c;我们仿佛已经进入了AI时代&#xff0c;势不可挡。人工智能水平如此之高&#xff0c;不禁…

【每日一题】收集巧克力

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;枚举操作数 写在最后 Tag 【枚举】【数组】【2023-12-28】 题目来源 2735. 收集巧克力 题目解读 有长度为 n, 下标从 0 开始的整数数组 nums, 表示收集不同类型的巧克力的成本. nums[i] 表示收集类型 i 巧克力的成本…

机器视觉——cv2窗口

1、窗口控制 1.1 创建窗口 cv2.imshow()函数在显示图像时&#xff0c;指定的窗口如果不存在&#xff0c;则会按默认设置创建一个窗口&#xff0c;窗口大小由图像大小决定&#xff0c;且不能更改。 cv2.nameWindow()函数用于创建窗口&#xff0c;格式如下&#xff1a; cv2.n…

CodeWhisperer:编码世界中的声音启迪者

人烟 导语&#xff1a; 在数字化时代&#xff0c;编码已经成为了一种不可或缺的技能。而 CodeWhisperer&#xff08;编码世界中的声音启迪者&#xff09;则以其卓越的技术和深厚的知识为人们带来了独特的启发和指导。本文将介绍 CodeWhisperer 的背景和成就&#xff0c;探讨他是…

未来编程语言什么样?编译解释兼容方为王

○、编程语言的未来&#xff1f; 随着科技的飞速发展&#xff0c;编程语言在计算机领域中扮演着至关重要的角色。它们是软件开发的核心&#xff0c;为程序员提供了与机器沟通的桥梁。那么&#xff0c;在技术不断进步的未来&#xff0c;编程语言的走向又将如何呢&#xff1f; …

HCIA-Datacom题库(自己整理分类的)——OSPF协议判断

1.路由表中某条路由信息的Proto为OSPF则此路由的优先级一定为10。√ 2.如果网络管理员没有配置骨干区域,则路由器会自动创建骨干区域&#xff1f; 路由表中某条路由信息的Proto为OSPF&#xff0c;则此路由的优先级一定为10。 当两台OSPF路由器形成2-WAY邻居关系时&#xff0…

【Android】使用android studio查看内置数据库信息

背景 需要用到android db 逻辑存储用户信息等等。 使用 在 App inspection 工具中查看该 app 内的 db 数据 sql执行 在新的查询框内解析查询即可知道当前的数据信息。 官方文档-使用 Database Inspector 调试数据库

k8s-cni网络 10

Flannel vxlan模式跨主机通信原理 在同一个节点上的pod 流量通过cni网桥可以直接进行转发&#xff1b; 在需要跨主机访问时&#xff0c;数据包通过flannel(隧道) 知道另一边的mac地址&#xff0c;就可以拿到另一边的ip地址&#xff0c;然后构建常规的以太网数据包&#xff0c;…

文件下载输出zip文件

文件下载输出成zip文件&#xff1a; 1、前端整个按钮&#xff0c;调js方法&#xff1a;&#xff08;参数&#xff1a;param,需要下载的id&#xff0c;用逗号拼接&#xff09; var param "?dto.id";//需要自己拼接param window.location.href "<%basePat…

C++ 函数模板 template

现在的C编译器实现了C新增的一项特性一一函数模板. 函数模板是通用的函数描述&#xff0c;也就是说它们使用泛型来定义函数&#xff0c;其中的泛型可用具体的类型(如int或double)替换。 通过将类型作为参数传递给模板&#xff0c;可使编译器生成该类型的函数。由于模板允许以泛…

【2023 CCF 大数据与计算智能大赛】基于TPU平台实现超分辨率重建模型部署 基于预训练ESPCN的轻量化图像超分辨率模型TPU部署方案

2023 CCF 大数据与计算智能大赛 《基于TPU平台实现超分辨率重建模型部署》 作品名&#xff1a;基于预训练ESPCN的轻量化图像超分辨率模型TPU部署方案 队伍名&#xff1a;Absofastlutely 蒋松儒 计算机科学与技术系 硕士 南京大学 中国-江苏 kahsoltqq.com 吕欢欢 计算…

Windows搭建RTMP视频流服务(Nginx服务器版)

文章目录 引言1、安装FFmpeg2、安装Nginx服务器3、实现本地视频推流服务4、使用VLC或PotPlayer可视化播放器播放视频5、RTSP / RTMP系列文章 引言 RTSP和RTMP视频流的区别 RTSP &#xff08;Real-Time Streaming Protocol&#xff09;实时流媒体协议。 RTSP定义流格式&#xff…

26K star! 跨平台的开源AirDrop 替品

现在大家的设备都很多&#xff0c;平时在家里手机&#xff0c;电脑&#xff0c;平板之间怎么传文件&#xff1f;如果你是苹果党&#xff0c;那肯定AirDrop最方便。但是当你需要跨平台来传输内容时&#xff0c;怎么样能更方便呢&#xff1f;各种网盘们都需要网络&#xff0c;如果…

MySQL 数据库系列课程 03:MySQL数据库相关软件的下载和安装

俗话说&#xff1a;“工欲善其事&#xff0c;必先利其器”&#xff0c;开始学习 MySQL 之前我们一定是要做环境准备的&#xff0c;接下来我们来讲解一下 MySQL 的安装。 一、MySQL下载 步骤一&#xff1a;官方入口的寻找 &#xff08;1&#xff09;大家可以尝试在官网寻找 M…

java基础-回忆性记录

java基础 Java概括 jaava是一种计算机交流的高级编程语言&#xff0c;1995年java衍生&#xff0c;詹姆斯高斯林被世人称之为java之父。 java语言具有跨平台性 java程序并非可以直接运行的&#xff0c;在java程序编译完成后会形成与编译无关的class文件。Java具有跨平台性&a…

【前端学习指南】第一站 Vue 生命周期初探

&#x1f36d; Hello&#xff0c;我是爱吃糖的范同学 &#x1f534; 想把自己学习技术的经历和一些总结分享给大家&#xff01; &#x1f534; 通过这样的方式记录自己成长&#xff0c;同时沉淀自己的技术&#xff0c;我会把所有额外的时间和经历投放到CSDN和公众号&#xff0…

Flink1.17实战教程(第四篇:处理函数)

系列文章目录 Flink1.17实战教程&#xff08;第一篇&#xff1a;概念、部署、架构&#xff09; Flink1.17实战教程&#xff08;第二篇&#xff1a;DataStream API&#xff09; Flink1.17实战教程&#xff08;第三篇&#xff1a;时间和窗口&#xff09; Flink1.17实战教程&…

DDR终端匹配电阻的长度多少合适?

上次我们对不加端接电阻和加端接电阻之后的仿真结果做了分析之后我们得出在DDR采用菊花链拓扑结构的时候是需要加端接电阻的&#xff0c;这次我们看看DDR末端的端接电阻距离最后一片DDR远一点效果好一些还是近一点效果好一些。 本次采用的案例依旧是我们上期的DDR3一拖八正反贴…

Kali Linux中的十大WiFi攻击工具介绍

在这十大WiFi攻击黑客工具中&#xff0c;我们将讨论一个非常受欢迎的主题&#xff1a;无线网络攻击以及如何防止黑客入侵。无线网络通常是网络的一个弱点&#xff0c;因为WiFi信号可以随处可见&#xff0c;任何人都可以使用。还有很多路由器包含漏洞&#xff0c;可以利用正确的…

【Web API系列】使用getDisplayMedia来实现录屏功能

文章目录 前言一、认识getD该处使用的url网络请求的数据。二、使用步骤1.使用方法一实现录屏2.使用方法二实现录屏3. 运行效果 延伸 前言 Web API经过长期的发展&#xff0c;尤其是最近&#xff0c;发展相当迅猛&#xff0c;现在已经支持很多功能了&#xff0c;一些原生就支持…