Canvas鼠标手写签名-vue

转载含JavaScript与Python相关内容
此博客为转载内容,原链接为https://juejin.im/post/5ce3cfd5e51d4577565366f0 ,标签涉及JavaScript和Python两种信息技术领域的编程语言。

<template>
  <div>
    <!-- <div class="container">
      <input type="radio" name="tool" id="huabi" checked>
      <label for="huabi">画笔</label>
    </div> -->
    <canvas style="z-index:9999" width="800" height="600"></canvas>
    <p @click="clear" >重画</p>
    <p @click="toImg">转化</p>
  </div>
</template>
<script>
// import draw from './draw.js'
export default {
  data() {
    return {
      canvas:{}
    }
  },
  mounted() {
    this.do()
  },
  methods: {
    do() {
      var tool = "huabi";
      // debugger
      this.canvas = document.querySelector("canvas");
      var x, y;
      // var canvas = document.querySelector("canvas");
      var ctx = this.canvas.getContext("2d");
      ctx.fillStyle = 'red'

      const _this = this

      this.canvas.onmousedown = function(event) {
        x = event.clientX - this.offsetLeft;
        y = event.clientY - this.offsetTop;
        document.onmousemove = function(event) {
          var x1 = event.clientX - _this.canvas.offsetLeft;
          var y1 = event.clientY - _this.canvas.offsetTop;
          // this.huabi(x, y, x1, y1, ctx);
          ctx.beginPath();
      ctx.globalAlpha = 1;
      ctx.lineWidth = 2;
      ctx.strokeStyle = "#000";
      ctx.moveTo(x, y);
      ctx.lineTo(x1, y1);
      ctx.closePath();
      ctx.stroke();
          x = x1;
          y = y1;
        };
      };

      document.onmouseup = function() {
        this.onmousemove = null;
      };
    },
    clear(){
      document.querySelector("canvas").getContext("2d").clearRect(0,0,800,600)
    },
    toImg(){
      var image = new Image();
      image.src = this.canvas.toDataURL("image/png");
      return image;
    }
    // huabi(startX, startY, endX, endY, ctx) {
    //   ctx.beginPath();
    //   ctx.globalAlpha = 1;
    //   ctx.lineWidth = 2;
    //   ctx.strokeStyle = "#000";
    //   ctx.moveTo(startX, startY);
    //   ctx.lineTo(endX, endY);
    //   ctx.closePath();
    //   ctx.stroke();
    // }
  }
};
</script>
复制代码

转载于:https://juejin.im/post/5ce3cfd5e51d4577565366f0

### 通过 Vue3 和 Canvas 实现 UniApp 签名功能 在 UniApp 中使用 Vue3 开发手写签名功能,可以通过 `<canvas>` 组件来实现用户的手写输入,并将其转换为图片或 Base64 格式的字符串以便后续处理。以下是详细的实现方式: #### 功能描述 1. **创建画布区域**:提供一个可以绘制的 `canvas` 区域供用户书写。 2. **监听触摸事件**:捕获用户的触控操作(如手指移动),并将轨迹记录到画布上。 3. **导出签名数据**:将画布上的内容转化为 Base64 或者文件形式的数据,方便上传至服务器或其他用途。 --- #### HTML 结构 定义一个简单的页面布局,其中包含用于书写的 `canvas` 元素以及清除和保存按钮。 ```html <template> <view class="signature-container"> <canvas type="2d" id="myCanvas" :style="{ width: '100%', height: '300px' }"></canvas> <button @click="clearSignature">清空</button> <button @click="saveSignature">保存</button> </view> </template> ``` --- #### JavaScript 部分 (Vue3 Composition API) 利用 Vue3 的组合式 API 来管理逻辑状态和交互行为。 ```javascript <script setup> import { ref, onMounted } from 'vue'; // 定义变量 const canvasRef = ref(null); let ctx = null; let isDrawing = false; // 是否正在绘图 let lastX = 0; let lastY = 0; onMounted(() => { const canvasElement = document.getElementById('myCanvas'); if (!canvasElement) return; // 初始化画布上下文 ctx = canvasElement.getContext('2d'); ctx.strokeStyle = '#000'; // 设置线条颜色 ctx.lineWidth = 2; // 设置线宽 ctx.lineCap = 'round'; // 圆形笔尖效果 // 添加触摸事件监听器 canvasElement.addEventListener('touchstart', startDraw); canvasElement.addEventListener('touchmove', draw); canvasElement.addEventListener('touchend', stopDraw); // PC 测试环境下的鼠标事件支持 canvasElement.addEventListener('mousedown', startDraw); canvasElement.addEventListener('mousemove', draw); canvasElement.addEventListener('mouseup', stopDraw); }); function startDraw(event) { event.preventDefault(); isDrawing = true; [lastX, lastY] = getTouchPosition(event); } function draw(event) { if (!isDrawing) return; let [currentX, currentY] = getTouchPosition(event); ctx.beginPath(); // 开始路径 ctx.moveTo(lastX, lastY); // 移动起点位置 ctx.lineTo(currentX, currentY); // 连接到当前点 ctx.stroke(); // 执行绘制命令 [lastX, lastY] = [currentX, currentY]; } function stopDraw() { isDrawing = false; } function clearSignature() { ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); } function saveSignature() { const base64Image = canvasRef.value.toDataURL('image/png'); // 转化为Base64编码 console.log(base64Image); // 输出调试信息 // 如果需要上传,则调用函数进行转化并发送请求 uploadToServer(base64Image).then((result) => { console.log(result); }).catch((error) => { console.error(error); }); } async function uploadToServer(dataUrl) { const file = dataURLtoFile(dataUrl, 'signature.png'); // 将Base64转为文件对象[^2] const formData = new FormData(); formData.append('file', file); try { const response = await fetch('/upload-endpoint', { method: 'POST', body: formData, }); if (response.ok) { return await response.json(); } throw new Error('Upload failed.'); } catch (e) { throw e; } } /** * Helper Function to convert Data URL into a File Object. */ function 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 }); // 创建文件对象 } function getTouchPosition(e) { const rect = e.target.getBoundingClientRect(); if (e.touches && e.touches[0]) { // 处理移动端触摸事件 return [ Math.floor(e.touches[0].clientX - rect.left), Math.floor(e.touches[0].clientY - rect.top) ]; } else if (e.clientX || e.clientY) { // 处理PC端鼠标事件 return [ Math.floor(e.clientX - rect.left), Math.floor(e.clientY - rect.top) ]; } return [0, 0]; // 默认返回原点坐标 } </script> ``` --- #### CSS 样式调整 可以根据实际需求自定义签名字体框的颜色、边距等属性。 ```css <style scoped> .signature-container { display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 20px; } #myCanvas { border: 1px solid black; background-color: white; } button { margin-top: 10px; padding: 10px 20px; font-size: 16px; } </style> ``` --- #### 数据传输与存储 当用户完成签名后,可通过上述代码中的 `dataURLtoFile()` 方法将 Base64 图片数据转化为标准文件格式后再上传至 OSS 或其他云服务中。 --- ### 性能优化建议 - 对于 Android 设备可能出现的卡顿现象,尝试降低采样频率或者减少每次渲染的操作复杂度[^3]。 - 提高用户体验时,可以在加载动画期间显示进度条以告知用户正在进行的操作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值