canvas实现手写签名并旋转base64图片

思路:

1. touchstart:当手指触摸屏幕时,获取初始坐标,lastPos.x,lastPos.y。
2. touchmove: 当手指在屏幕上滑动的时,获取当前坐标,curLoc.x,curLoc.y。
起始位置为鼠标落下的位置(lastPos.x,lastPos.y), 结束位置为当前位置(curLoc.x,curLoc.y),从新设置初始坐标(lastPos.x,lastPos.y)canvas

元素相对于视窗的位置集&点击位置距离当前body可视区域的x,y坐标

若是直接用鼠标点击的坐标在canvas上绘图的话,会发现,画出来的线,坐标永远都是有误差的。后端

如图,鼠标的坐标系原点,和canvas的坐标系原点,不是同一个。就形成了差异。红色矩形在canvas上起始坐标,是鼠标落下的x轴距离,减去画布离页面的距离pageX-left. bash

getBoundingClientRect()

getBoundingClientRect用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性。你了解getBoundingClientRect()?post

完整代码

// 获取鼠标位置在画布上的距离
      windowToCanvas(x,y){
        let rect = this.can.getBoundingClientRect()
        // x和y参数分别传入的是鼠标距离窗口的坐标,而后减去canvas距离窗口左边和顶部的距离。
        return {
         x: x - rect.left 
         y: y - rect.top
        };
      },
        touchStart(e) {
        // 上一次的坐标
        this.lastPos = this.windowToCanvas(e.touches[0].clientX,e.touches[0].clientY);
      },
       touchMove(e) {
        // 得到当前坐标
        let curLoc =this.windowToCanvas(e.touches[0].clientX,e.touches[0].clientY);
        let lineWidth = 5;
        this.ctx.lineWidth=lineWidth;
        this.ctx.beginPath();
        // 起始位置为鼠标落下的位置
        this.ctx.moveTo(this.lastPos.x,this.lastPos.y);
        // 结束位置为当前位置
        this.ctx.lineTo(curLoc.x,curLoc.y);
        this.ctx.strokeStyle= 'black';
        this.ctx.stroke();
        // 将当前坐标赋值给上一次坐标
        this.lastPos = curLoc;
      },
复制代码
<canvas id='canvas' class="canvas"
            @touchstart="touchStart"
            @touchmove="touchMove"
    ></canvas>  
复制代码

旋转base64图片

调用toDataURL,把canvas转为base64发送给后端。发现发送过去的base64图片是反的。 ui

但愿是这样的this

思路

  1. 画布旋转合适的角度,把传入的base64图片,画在新建的画布上
  2. getImageData() 提取裁剪后图像数据
  3. putImageData()把提取的图像数据画到画布上
  4. 调用toDataURL,生成最终的base64字符串

如图,

1.为了方便计算,新建画布的宽高都设为base64图片的高度的两倍
2.画笔位移到画布中心,如图灰色的矩形
3.画笔旋转90度,如图蓝色矩形
4.设定裁剪坐标,{sx: 0, sy: 0, ex: 0, ey: 0}
sx:开始复制的左上角位置的 ,如图,image.heihgt
sy:开始复制的左上角位置的 y 坐标,如图,image.heihgt-image.width
ex:将要复制的矩形区域的宽度。如图,image.height,
ey:将要复制的矩形区域的高度。url

rotateBase64(data){   //传入须要旋转的base64图片
        return new Promise((resolve, reject) => {
          const imgView = new Image();
          imgView.src = data;
          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');
          const cutCoor = {sx: 0, sy: 0, ex: 0, ey: 0}; // 裁剪坐标
          imgView.onload = () => {
            const imgW = imgView.width;
            const imgH = imgView.height;
            const size = imgH;
            canvas.width = size * 2;
            canvas.height = size * 2;
            cutCoor.sx = size;
            cutCoor.sy = size - imgW;
            cutCoor.ex = size + imgH;
            cutCoor.ey = size + imgW;
            context.translate(size, size);
            context.rotate(Math.PI/2*3);
            context.drawImage(imgView, 0, 0);
            const imgData = context.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey);
            canvas.width = imgH;
            canvas.height = imgW;
            context.putImageData(imgData, 0, 0);
            resolve(canvas.toDataURL('image/png'));
          };
        });
      },
复制代码

能够这样调用spa

rotateBase64(imgData)
            .then((img) => {
            console.log(`旋转后的base64图片:${img}`)
            });
复制代码

延伸

后台要求的是发送base64格式的图片,若是,后台要求其余格式的呢。因而,我在想到底图片有多少种显示形式,之间又是怎样切换的。 图片的三种表现形式url、base6四、blob,三者之间是否能够转化以知足需求呢?3d

相关文章
相关标签/搜索