uniApp使用canvas制作签名板

插件市场大佬封装好的 组件 可以直接拿过去

<template>
  <view
    class="whole canvas-autograph flexc"
    @touchmove.prevent.stop
    @wheel.prevent.stop
    v-show="modelValue"
  >
    <canvas
      class="scroll-view"
      id="mycanvas"
      canvas-id="mycanvas"
      @touchstart="touchstart"
      @touchmove="touchmove"
      @touchend="touchend"
    />
    <view class="fun-box">
      <view
        class="fun-box-btn clear flex"
        @click="clear"
      >
        <text>清空</text>
      </view>
      <view
        class="fun-box-btn confirm flex"
        @click="confirm"
      >
        <text>确认</text>
      </view>
      <view
        class="fun-box-btn cancel flex"
        @click="cancel"
      >
        <text>取消</text>
      </view>
    </view>
  </view>
</template>

<script setup>
/*
		使用如下
		<canvas-autograph v-model="isCanvas" @complete="complete"/>
		
		// 打开、关闭
		let isCanvas = ref(false)
		// 确认事件
		const complete = e=>{
			console.log(e)
		}
	
	*/
import { ref, reactive, watch, getCurrentInstance } from 'vue'
const hasSignature = ref(false) // 新增:记录是否签名
const emits = defineEmits(['update:modelValue', 'complete'])

const props = defineProps({
  modelValue: Boolean
})
const _this = getCurrentInstance()
watch(
  () => props.modelValue,
  (e) => {
    // 这里可进行 tabbar 的 显示、隐藏  不要也可以
    // 自己写
  },
  {
    immediate: true // 是否默认执行一次  默认为false
  }
)

let points = reactive([]) //路径点集合

let canvaCtx = reactive(uni.createCanvasContext('mycanvas', _this)) //创建绘图对象
//设置画笔样式
canvaCtx.lineWidth = 4
canvaCtx.lineCap = 'round'
canvaCtx.lineJoin = 'round'

//触摸开始,获取到起点
const touchstart = (e) => {
  hasSignature.value = true // 有触摸操作则认为有签名
  let startX = e.changedTouches[0].x
  let startY = e.changedTouches[0].y
  let startPoint = { X: startX, Y: startY }
  points.push(startPoint)
  //每次触摸开始,开启新的路径
  canvaCtx.beginPath()
}
//触摸移动,获取到路径点
const touchmove = (e) => {
  let moveX = e.changedTouches[0].x
  let moveY = e.changedTouches[0].y
  let movePoint = { X: moveX, Y: moveY }
  points.push(movePoint) //存点
  let len = points.length
  if (len >= 2) {
    draw()
  }
}
//绘制路径
const draw = () => {
  let point1 = points[0]
  let point2 = points[1]
  points.shift()
  canvaCtx.moveTo(point1.X, point1.Y)
  canvaCtx.lineTo(point2.X, point2.Y)
  canvaCtx.stroke()
  canvaCtx.draw(true)
}
// 触摸结束,将未绘制的点清空防止对后续路径产生干扰
const touchend = (e) => {
  points = []
}
// 清空画布
const clear = () => {
  hasSignature.value = false // 清空时重置签名标志
  return uni
    .getSystemInfo()
    .then((res) => {
      canvaCtx.clearRect(0, 0, res.windowWidth, res.windowHeight)
      canvaCtx.draw(true)
      return res
    })
    .catch((err) => {
      // console.log(err);
    })
}
// 确认
const confirm = () => {
  if (!hasSignature.value) {
    // 如果没有签名,提示用户
    uni.showToast({
      title: '请先签名',
      icon: 'none',
      duration: 2000
    })
    return
  }

  uni.canvasToTempFilePath({ canvasId: 'mycanvas' }, _this, _this.parent).then((res) => {
    console.log(res.tempFilePath)
    emits('complete', res.tempFilePath)
    cancel()
  })
}
// 取消
const cancel = () => {
  clear().then((res) => emits('update:modelValue', false))
}
</script>

<style scoped lang="scss">
.canvas-autograph {
  position: fixed;
  z-index: 99999;
  width: 100vw;
  height: 100vh;
  top: 0;
  left: 0;
  .scroll-view {
    width: 100%;
    height: 100%;
    background-color: #ffffff;
  }
  .fun-box {
    position: absolute;
    right: 0;
    bottom: 10vh;
    height: auto;
    display: flex;
    flex-direction: column;
    .fun-box-btn {
      width: 100rpx;
      height: 160rpx;
      color: #ffffff;
      border-radius: 20rpx;
      border: 1rpx solid #c0c0c0;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-bottom: 20rpx;
      margin-right: 10rpx;
      text {
        transform: rotate(90deg);
      }
    }
    .clear {
      color: #909399;
      background-color: #f4f4f5;
    }
    .confirm {
      background-color: #409eff;
    }
    .cancel {
      background-color: #f67d7d;
    }
  }
}
</style>

子组件使用

    <miliu-autograph
      v-model="isCanvas"
      @complete="complete"
    ></miliu-autograph>

let isCanvas = ref(false)


function toCanvas() {
  isCanvas.value = true
}

// 确认事件
const complete = (e) => {
  console.log(e) // 返回本地生成的base图片路径
  // 上传签名图片
  uni.getImageInfo({
    src: e,
    success: function (res) {
      // uni.uploadFile({
      //   url: baseUrl + '/file/upload', //后端接口地址
      //   name: 'file', //必填 , 此为类型名称
      //   filePath: res.path, //电子签名图片路径
      //   header: {
      //     Authorization: 'Bearer ' + that.token
      //   },
      //   success: (res) => {
      //     console.log(res, '签名信息 ------ res');
      //     //上传成功后逻辑
      //     uni.showToast({
      //       title: '签名成功!'
      //     });
      //   },
      //   fail: (err) => {
      //     console.log(err);
      //     uni.showToast({
      //       title: '签名失败!'
      //     });
      //   }
      // });
    }
  })
}

再具体的我就不描述了 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决Knife4j 接口界面UI中文乱码问题

1、查看乱码情况 2、修改 编码设置 3、删除 target 文件 项目重新启动 被坑死了

FFmpeg 4.3 音视频-多路H265监控录放C++开发八,使用SDLVSQT显示yuv文件 ,使用ffmpeg的AVFrame

一. AVFrame 核心回顾&#xff0c;uint8_t *data[AV_NUM_DATA_POINTERS] 和 int linesize[AV_NUM_DATA_POINTERS] AVFrame 存储的是解码后的数据&#xff0c;&#xff08;包括音频和视频&#xff09;例如&#xff1a;yuv数据&#xff0c;或者pcm数据&#xff0c;参考AVFrame结…

【算法】递归+深搜+哈希表:889.根据前序和后序遍历构造二叉树

目录 1、题目链接 相似题目: 2、题目 ​3、解法&#xff08;针对无重复值&#xff0c;哈希表递归&#xff09; 函数头-----找出重复子问题 函数体---解决子问题 4、代码 1、题目链接 889.根据前序和后序遍历构造二叉树&#xff08;LeetCode&#xff09; 相似题目: 105.…

基于SpringBoot的“乐校园二手书交易管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“乐校园二手书交易管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统首页界面图 用户注册界面图 二手…

“高效开发之路:用Spring MVC构建健壮的企业级应用”

一、SpringMVC框架概念&#xff1a; &#xff08;一&#xff09;概述 SpringMVC是Spring框架的一个模块&#xff0c;Spring和SpringMVC无需中间整合层整合。该模块是一个基于MVC的web框架。 作用&#xff1a;只要需要前后端通信&#xff0c;就需要springMVC帮我完成&#xff…

练习LabVIEW第四十一题

学习目标&#xff1a; 编写一个程序测试自己在程序前面板上输入一段文字“CSDN是一个优秀的网站”所用的时间。 开始编写&#xff1a; 前面板放置一个数值显示控件&#xff0c;程序框图添加顺序结构共三帧&#xff0c;第一帧放一个获取日期/时间&#xff08;秒&#xff09;函…

编程之路:蓝桥杯备赛指南

文章目录 一、蓝桥杯的起源与发展二、比赛的目的与意义三、比赛内容与形式四、比赛前的准备五、获奖与激励六、蓝桥杯的影响力七、蓝桥杯比赛注意事项详解使用Dev-C的注意事项 一、蓝桥杯的起源与发展 蓝桥杯全国软件和信息技术专业人才大赛&#xff0c;简称蓝桥杯&#xff0c…

Cofounder:全栈 AI 应用开发 Agent,基于单一提示生成完整的应用程序

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; &#x1f966; 微信公众号&#xff…

神奇!KMeans也可以进行图像语义分割?基于k-Means的遥感图像语义分割实战

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

2.2、软件生命周期模型介绍

软件生命周期模型 1. 传统软件过程模型1.1 瀑布模型Waterfall model1.2 V模型1.3 原型模型&#xff08;降低需求不明确的风险&#xff09;1.4 增量模型&#xff08;降低需求变化风险&#xff09;1.5 螺旋模型1.6 喷泉模型 2. 现代模型2.1 基于构件的开发模型2.2 统一过程RUP:Ra…

推荐程序员好用的浏览器插件

推荐程序员好用的浏览器插件 1. 网页颜色控制&#xff1a;Dark Reader安装效果 2. 前端助手&#xff1a;FeHelper安装效果 3. markdown可视化&#xff1a;Markdown Reader安装效果 4. ES插件&#xff1a;Multi Elasticsearch Heads安装效果 1. 网页颜色控制&#xff1a;Dark Re…

使用Jest进行JavaScript单元测试

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Jest进行JavaScript单元测试 引言 Jest 简介 安装 Jest 创建基本配置 编写测试用例 运行测试 快照测试 模拟函数 代码覆盖率…

白杨SEO:百度在降低个人备案类网站搜索关键词排名和流量?怎样应对?【参考】

很久没有写百度或者网站这块内容了&#xff0c;一是因为做百度网站朋友越来越少&#xff0c;不管是个人还是企业&#xff1b;二是百度上用户搜索与百度给到网站的流量都越来越少。 为什么想到今天又来写这个呢&#xff1f;因为上个月有个朋友来咨询我说网站百度排名全没了&…

Linux——Shell的运行原理和Linux文件权限

Shell的运行原理和Linux文件权限 文章目录 Shell的运行原理和Linux文件权限1. Shell的运行原理(1) Shell是什么(2) 为什么要有Shell(3) Shell的运行原理(4) 解析命令行 2. Linux文件(1) 文件属性(2) 文件类型(3) 文件权限(4) 文件权限的修改(1) chmod(2) chown(3) chgrp (5) um…

linux守护进程与后台进程的区别

守护进程与后台进程有以下区别&#xff1a; 1. 概念与定义 后台进程&#xff1a; 是指在操作系统后台运行的进程&#xff0c;它不与用户直接交互&#xff08;没有连接到用户的终端&#xff09;。用户在终端中启动一个程序并让其在后台运行&#xff08;如通过在命令后加“&…

Jmeter5.X性能测试

Jmeter5.X性能测试 文章目录 Jmeter5.X性能测试一、掌握Http基础协议1.1 浏览器的B/S架构和C/S架构1.2 HyperText Transfer Protocol 超文本传输协议1.3 超文本传输协议Http消息体拆分讲解1.4 HTTP的九种请求方法和响应码介绍1.5 Http请求头/响应头1.6 Http常见请求/响应头cont…

Spring 配置绑定原理分析

Spring 配置绑定原理分析 前言 Spring 应用中存在诸多配置&#xff0c;有的是系统配置&#xff0c;有的命令行启动参数配置&#xff0c;有的是yaml配置&#xff0c;有的是分布式配置中心配置&#xff0c;但对使用者而言总是可以通过ConfigurationProperties将它关联到一个Java…

爬虫下载网页文夹

爬虫下载网页pdf文件 import os import requests from bs4 import BeautifulSoup from urllib.parse import urljoin from urllib.parse import urljoin, unquote from tqdm import tqdm # 设置网页的URL base_url "http://119/download/dzz/pdf/"# 创建保存文件的…

数据结构-归并排序笔记

【数据结构】八大排序(超详解附动图源码)_数据结构排序-CSDN博客 看这个学思路 一 归并排序介绍: 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法&#xff0c;该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解&#xf…

编译器优化乌龙——记一次死循环不进入问题

记一次死循环不生效问题 看如下代码&#xff0c;本意是我们模拟一次死循环&#xff0c;然后会在中断处理函数中更改waiting的值&#xff0c;更改waiting的值后&#xff0c;跳出死循环。 int waiting 0; while(waiting0){}运行起来发现&#xff0c;程序根本就没有进入这个死循…