vue3项目引入电子签名(可横屏竖屏)

news2024/9/26 1:18:43

实现效果:(左边横屏,右边竖屏)

前言:【使用开源项目smooth-signature 实现签名的功能。Gitee 地址是 :GitHub - linjc/smooth-signature: H5带笔锋手写签名,支持PC端和移动端,任何前端框架均可使用

以下代码可复制粘贴直接用,改下文件路径即可】

1.在项目中安装依赖包:npm install --save smooth-signature

2.我是放到一个dialog里,可根据需求自行开发。

弹框代码:

 <!--签名-->
  <Dialog
    v-model="signatureVisible"
    title="电子签名"
    width="100%"
    destroy-on-close
    draggable
    :append-to-body="true"
    @close="handleClose"
  >
    <div v-loading="endLoading">
      <ESign @closeson="closeVisi" />
    </div>
    <button v-show="false" @click="closeVisi">关闭</button>
  </Dialog>

引入模块:

import ESign from '@/views/officeDocument/office/components/packages/ESign/src/index2.vue'

使用方法:

//电子签名
const signatureVisible = ref(false)
const signatureBtn = () => {
  signatureVisible.value = true
}
//子组件关闭调用此方法
const closeVisi = () => {
  signatureVisible.value = false
}

2.开发电子签名功能及样式

电子签名文件目录(src/index.vue省略,主要是index2.vue文件):

packages/index.ts文件代码:

import { App, Plugin } from 'vue'

import { ESignPlugin } from './ESign'
const XiPlugin: Plugin = {
  install(app: App) {
    ESignPlugin.install?.(app)
  }
}

export default XiPlugin

export * from './ESign'

packages/Esign/index.ts文件代码:

import { App, Plugin } from 'vue'
import ESign from './src/index.vue'

export const ESignPlugin: Plugin = {
  install(app: App) {
    app.component('ESign', ESign)
  }
}

export { ESign }

 packages/Edign/src/index2.vue文件代码(主要代码):

<template>
  <div class="sign-finish">
    <div class="wrap1" v-show="showFull">
      <span class="sign-title">请在区域内签字</span>
      <canvas class="canvas1" ref="canvas1"></canvas>
      <div class="actions">
        <button class="danger" @click="handleClear1">清除</button>
        <button class="warning" @click="handleUndo1">撤销</button>
        <button class="primary" @click="handleFull">横屏</button>
        <button class="success" @click="handlePreview1">保存</button>
      </div>
    </div>
    <div class="wrap2" v-show="!showFull">
      <div class="actionsWrap">
        <div class="actions">
          <button class="danger" @click="handleClear2">清除</button>
          <button class="warning" @click="handleUndo2">撤销</button>
          <button class="primary" @click="handleFull">竖屏</button>
          <button class="success" @click="handlePreview2">保存</button>
        </div>
      </div>
      <canvas class="canvas" ref="canvas2"></canvas>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { emit } from 'process'
import { ref, watch, onMounted, onUnmounted } from 'vue'
import SmoothSignature from 'smooth-signature'

//组件电子签名
const canvas = document.querySelector('canvas')
// const signature = new SmoothSignature(canvas)
const showFull = ref(true)
const canvas2 = ref<any>(null)
const canvas1 = ref<any>(null)
const signature1 = ref<any>(null)
const signature2 = ref<any>(null)
const emit = defineEmits(['closeson'])

//坚屏横屏
const handleFull = () => {
  showFull.value = !showFull.value
}
const initSignature1 = () => {
  // const canvas = this.$refs["canvas1"]
  const canvas = canvas1.value as any
  const options = {
    width: window.innerWidth - 30,
    height: 200,
    minWidth: 2,
    maxWidth: 6,
    openSmooth: true,
    // color: "#1890ff",
    bgColor: '#f6f6f6'
  }
  signature1.value = new SmoothSignature(canvas, options)
}
const initSignture2 = () => {
  // const canvas = this.$refs["canvas2"]
  const canvas = canvas2.value as any
  const options = {
    width: window.innerWidth - 120,
    height: window.innerHeight - 80,
    minWidth: 3,
    maxWidth: 10,
    openSmooth: true,
    // color: "#1890ff",
    bgColor: '#f6f6f6'
  }
  signature2.value = new SmoothSignature(canvas, options)
}

const handleClear1 = () => {
  const sgn = signature1.value
  sgn.clear()
}
const handleClear2 = () => {
  const sgn2 = signature2.value
  sgn2.clear()
}
const handleUndo1 = () => {
  const sgn = signature1.value
  sgn.undo()
}
const handleUndo2 = () => {
  const sgn2 = signature2.value
  sgn2.undo()
}
const handlePreview1 = () => {
  const sgn = signature1.value
  const isEmpty = sgn.isEmpty()
  if (isEmpty) {
    alert('isEmpty')
    return
  }
  // const pngUrl = sgn.getPNG()
  const pngUrl = sgn.getJPG()
  console.log(pngUrl)
  emit('closeson')
  // window.previewImage(pngUrl);
}
const handlePreview2 = () => {
  const sgn2 = signature2.value
  const isEmpty = sgn2.isEmpty()
  if (isEmpty) {
    alert('isEmpty')
    return
  }
  const canvas = sgn2.getRotateCanvas(-90)
  const pngUrl = canvas.toDataURL()
  console.log('pngUrl', pngUrl)
  // 生成JPG
  //signature.getJPG() // 或者 signature.toDataURL('image/jpeg')
}

onMounted(() => {
  initSignature1()
  initSignture2()
})

// onUnmounted(() => {
//   removeEventListener()
// })
</script>

<style scoped lang="less">
.sign-finish {
  height: 100vh;
  width: 100vw;
  button {
    height: 32px;
    padding: 0 8px;
    font-size: 12px;
    border-radius: 2px;
  }
  .danger {
    color: #fff;
    background: #ee0a24;
    border: 1px solid #ee0a24;
  }
  .warning {
    color: #fff;
    background: #ff976a;
    border: 1px solid #ff976a;
  }
  .primary {
    color: #fff;
    background: #1989fa;
    border: 1px solid #1989fa;
  }
  .success {
    color: #fff;
    background: #07c160;
    border: 1px solid #07c160;
  }
  canvas {
    border-radius: 10px;
    border: 2px dashed #ccc;
  }
  .wrap1 {
    height: 100%;
    width: 96%;
    margin: auto;
    margin-top: 100px;
    .actions {
      display: flex;
      justify-content: space-around;
    }
  }
  .wrap2 {
    padding: 15px;
    height: 100%;
    display: flex;
    justify-content: center;
    .actionsWrap {
      width: 50px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .canvas {
      flex: 1;
    }
    .actions {
      margin-right: 10px;
      white-space: nowrap;
      transform: rotate(90deg);
      button {
        margin-right: 20px;
      }
    }
  }
}
</style>

最后就实现啦!本人因项目 使用比较复杂,可根据个人情况减少代码。参考前面的开源项目地址即可。

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

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

相关文章

局域网其他pc如何访问宿主机虚拟机IP?

文章目录 背景贝瑞蒲公英设置虚拟机网络连接测试 背景 使用贝瑞蒲公英异地组网&#xff0c;将家里的pc作为pgsql服务器在公司使用&#xff0c;但是虚拟机的ip和端口访问不了 贝瑞蒲公英 设置虚拟机网络 就是添加端口转发规则 连接测试 公网内其他pc连接测试 可以看到已经连接成…

【python基础】-- yarn add 添加依赖的各种类型

目录 1、安装 yarn 1.1 使用npm安装 1.2 查看版本 1.3 yarn 淘宝源配置 2、安装命令说明 2.1 yarn add&#xff08;会更新package.json和yarn.lock&#xff09; 2.2 yarn install 2.3 一些操作 2.3.1 发布包 2.3.2 移除一个包 2.3.3 更新一个依赖 2.3.4 运行脚本 …

知乎上高频提问:Redis到底是单线程还是多线程程序?

1.概述 这里我们先给出问题的全面回答&#xff1a;Redis到底是多线程还是单线程程序要看是针对哪个功能而言&#xff0c;对于核心业务功能部分(命令操作处理数据)&#xff0c;Redis是单线程的&#xff0c;主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的&#xff…

Potplayer播放器远程访问群晖WebDav本地资源【内网穿透】

文章目录 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是&#xff1a;1 使用环境要求&#xff1a;2 配置webdav3 测试局域网使用potplayer访问webdav3 内网穿透&#xff0c;映射至公网4 使用固定地址在potplayer访问webdav 国内流媒体平台的内容…

node.js mongoose aggregate

目录 官方文档 简述 Aggregate的原型方法 aggregate进行操作 官方文档 Mongoose v8.0.3: Aggregate 简述 在 Mongoose 中&#xff0c;Aggregate 是用于执行 MongoDB 聚合操作的类。MongoDB 聚合操作是一种强大的数据处理工具&#xff0c;可以用于对集合中的文档进行变换和…

智慧安防视频监控EasyCVR如何通过回调接口向第三方平台推送RTSP视频通道离线通知

安防视频监控系统EasyCVR能在局域网、公网、专网等复杂的网络环境中部署&#xff0c;可支持4G、5G、WiFi、有线等方式进行视频的接入与传输、处理和分发。平台能将接入的视频流进行汇聚、转码、多格式输出和分发&#xff0c;具体包括&#xff1a;RTMP、RTSP、HTTP-FLV、WebSock…

微信视频号本地生活服务商如何申请,最新方法来了

随着某平台的本地生活服务商被清退&#xff0c;大量的服务商开始想着如何转型&#xff0c;但辛苦一年打下来的商家资源&#xff0c;如何才能效果最大化&#xff1f;最好的方式就是重新找一个平台进行接盘。 随着视频号本地生活业务的开展&#xff0c;这一下就受到广大创业者&a…

linux运维面试题

linux运维面试题 面试 K8S篇(高可用) Q&#xff1a;k8s是什么&#xff1f;架构&#xff1f; Kubenetes是一个开源的容器集群管理系统。主要用于容器编排&#xff0c;解决容器调度问题。当应用请求时&#xff0c;k8s需要合理分配请求到空闲node节点上去。k8s使用的主从模式&…

《Linux C编程实战》笔记:进程操作之ID,优先级

获得进程ID getpid函数 这个函数都用了很多次了&#xff0c;看一下定义和例子就行了 #include<sys/types.h> #include <unistd.h> pid_t getpid(void); 示例程序1 #include<cstdlib> #include<malloc.h> #include<cstring> #include <cs…

中国社科院与新加坡新跃社科联合培养工商管理博士

全球经济正在经历由科技进步与创新、政治和人口的剧烈变化所带来的巨大不确定性与挑战。企业的领导者和管理者需要发展出战略性思维和全球洞察力以便面对越来越大的经济波动。中国社科院与新加坡新跃社科联合培养工商管理博士项目的训练能够让学生在一个企业和组织的改变和发展…

快速给SOLIDWORKS工程图添加水印

水印常见于电子文档或纸质上的文字或图案&#xff0c;日常生活中&#xff0c;一些特殊的水印只能在特定的条件下才能看到。水印可以作为一个品牌的象征&#xff0c;有的软件生成文档就会有水印&#xff0c;可以作为宣传&#xff0c;让更多的人熟知。 作品水印&#xff0c;就是…

app测试必掌握的核心测试:UI、功能测试!

一、UI测试 UI即User Interface (用户界面)的简称。UI 设计则是指对软件的人机交互、操作逻辑、界面美观的整体设计。好的UI设计不仅是让软件变得有个性有品味,还要让软件的操作变得舒适、简单、自由、充分体现软件的定位和特点。手机APP从启动界面开始, 到运行过程,直至退出,…

为什么要编写测试用例,测试用例写给谁看?

“为什么要编写测试用例&#xff0c;测试用例写给谁看”&#xff0c;这个问题看似简单&#xff0c;但却涵盖了一系列复杂的考虑因素&#xff0c;并不太好回答。 为了向各位学测试的同学们解释清楚“为什么编写测试用例是至关重要的”&#xff0c;我将通过以下5个方面进行展开&…

【工具使用-ADB】小米手机如何使用adb传输文件

一&#xff0c;简介 本文主要介绍&#xff0c;如何使用小米手机&#xff0c;打开adb设置进行文件的传输。供参考 二&#xff0c;操作步骤 2.1 进入开发者模式 “设置”->“我的设备”->“全部参数信息” 连续多次点击“MIUI 版本”&#xff0c;直到提示“您已处于开…

英码科技受邀参加2023计算产业生态大会,分享智慧轨道交通创新解决方案

12月13-14日&#xff0c;“凝心聚力&#xff0c;共赢计算新时代”——2023计算产业生态大会在北京香格里拉饭店成功举办。英码科技受邀参加行业数字化分论坛活动&#xff0c;市场总监李甘来先生现场发表了题为《AI哨兵&#xff0c;为铁路安全运营站好第一道岗》的精彩主题演讲&…

计算机网络 运输层上 | 运输层概述 UDP协议 端口 套接字

文章目录 1 运输层概述1.1 运输层存在的意义1.2 运输层协议概述1.3 主要端口号 2 运输层主要协议 UDP2.1 UDP的特点2.2 UDP首部格式2.3 UDP工作流 1 运输层概述 1.1 运输层存在的意义 之前我们讲网络层的时候&#xff0c;已经可以将信息从一个主机传递到另一个主机了。 那么…

轻推API无代码集成:创新电商CRM与客服系统

无代码API集成的力量&#xff1a;电商与CRM无缝对接 随着电子商务的快速发展&#xff0c;电商平台与客户关系管理&#xff08;CRM&#xff09;系统的高效对接成为商家竞争力的关键。无代码API集成平台如轻推&#xff0c;提供了简单易用的解决方案&#xff0c;使得电商企业能够…

机器学习中的一些经典理论定理

PAC学习理论 当使用机器学习方法来解决某个特定问题时&#xff0c;通常靠经验或者多次试验来选择合适的模型、训练样本数量以及学习算法收敛的速度等。但是经验判断或多次试验往往成本比较高&#xff0c;也不太可靠&#xff0c;因此希望有一套理论能够分析问题难度、计算模型能…

Axure中如何使用交互样式交互事件交互动作情形

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《产品经理如何画泳道图&流程图》 ⛺️ 越努力 &#xff0c;越幸运 目录 一、Axure中交互样式 1、什么是交互样式&#xff1f; 2、交互样式的作用&#xff1f; 3、Axure中如何…